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 "ATAPrivate.h"
10
11#include <vm/vm.h>
12#include <string.h>
13
14
15/*!	Copy data between ccb data and buffer
16	ccb			- ccb to copy data from/to
17	offset			- offset of data in ccb
18	allocation_length- limit of ccb's data buffer according to CDB
19	buffer			- data to copy data from/to
20	size			- number of bytes to copy
21	to_buffer		- true: copy from ccb to buffer
22					  false: copy from buffer to ccb
23	return: true, if data of ccb was large enough
24*/
25bool
26copy_sg_data(scsi_ccb *ccb, uint offset, uint allocationLength,
27	void *buffer, int size, bool toBuffer)
28{
29	const physical_entry *sgList = ccb->sg_list;
30	int sgCount = ccb->sg_count;
31
32	// skip unused S/G entries
33	while (sgCount > 0 && offset >= sgList->size) {
34		offset -= sgList->size;
35		++sgList;
36		--sgCount;
37	}
38
39	if (sgCount == 0)
40		return false;
41
42	// remaining bytes we are allowed to copy from/to ccb
43	int requestSize = MIN(allocationLength, ccb->data_length) - offset;
44
45	// copy one S/G entry at a time
46	for (; size > 0 && requestSize > 0 && sgCount > 0; ++sgList, --sgCount) {
47		size_t bytes;
48
49		bytes = MIN(size, requestSize);
50		bytes = MIN(bytes, sgList->size);
51
52		if (toBuffer) {
53			vm_memcpy_from_physical(buffer, sgList->address + offset, bytes,
54				false);
55		} else {
56			vm_memcpy_to_physical(sgList->address + offset, buffer, bytes,
57				false);
58		}
59
60		buffer = (char *)buffer + bytes;
61		size -= bytes;
62		offset = 0;
63	}
64
65	return size == 0;
66}
67
68
69void
70swap_words(void *data, size_t size)
71{
72	uint16 *word = (uint16 *)data;
73	size_t count = size / 2;
74	while (count--) {
75		*word = B_BENDIAN_TO_HOST_INT16(*word);
76		word++;
77	}
78}
79