1 /* 2 * Copyright 2009, Michael Lotz, mmlr@mlotz.ch. 3 * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. 4 * Copyright 2002/03, Thomas Kurschel. All rights reserved. 5 * 6 * Distributed under the terms of the MIT License. 7 */ 8 9 #include "VirtioSCSIPrivate.h" 10 11 #include <string.h> 12 13 #include <vm/vm.h> 14 15 16 /*! Copy data between ccb data and buffer 17 ccb - ccb to copy data from/to 18 offset - offset of data in ccb 19 allocation_length- limit of ccb's data buffer according to CDB 20 buffer - data to copy data from/to 21 size - number of bytes to copy 22 to_buffer - true: copy from ccb to buffer 23 false: copy from buffer to ccb 24 return: true, if data of ccb was large enough 25 */ 26 bool 27 copy_sg_data(scsi_ccb *ccb, uint offset, uint allocationLength, 28 void *buffer, int size, bool toBuffer) 29 { 30 const physical_entry *sgList = ccb->sg_list; 31 int sgCount = ccb->sg_count; 32 33 // skip unused S/G entries 34 while (sgCount > 0 && offset >= sgList->size) { 35 offset -= sgList->size; 36 ++sgList; 37 --sgCount; 38 } 39 40 if (sgCount == 0) 41 return false; 42 43 // remaining bytes we are allowed to copy from/to ccb 44 int requestSize = MIN(allocationLength, ccb->data_length) - offset; 45 46 // copy one S/G entry at a time 47 for (; size > 0 && requestSize > 0 && sgCount > 0; ++sgList, --sgCount) { 48 size_t bytes; 49 50 bytes = MIN(size, requestSize); 51 bytes = MIN(bytes, sgList->size); 52 53 if (toBuffer) { 54 vm_memcpy_from_physical(buffer, sgList->address + offset, bytes, 55 false); 56 } else { 57 vm_memcpy_to_physical(sgList->address + offset, buffer, bytes, 58 false); 59 } 60 61 buffer = (char *)buffer + bytes; 62 size -= bytes; 63 offset = 0; 64 } 65 66 return size == 0; 67 } 68 69 70 void 71 swap_words(void *data, size_t size) 72 { 73 uint16 *word = (uint16 *)data; 74 size_t count = size / 2; 75 while (count--) { 76 *word = B_BENDIAN_TO_HOST_INT16(*word); 77 word++; 78 } 79 } 80