xref: /haiku/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIHelper.cpp (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
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