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
copy_sg_data(scsi_ccb * ccb,uint offset,uint allocationLength,void * buffer,int size,bool toBuffer)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
swap_words(void * data,size_t size)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