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