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