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