1/*
2 * Copyright 2009, Michael Lotz, mmlr@mlotz.ch.
3 * Copyright 2008, Marcus Overhagen.
4 * Copyright 2004-2008, Axel D��rfler, axeld@pinc-software.de.
5 * Copyright 2002-2003, Thomas Kurschel.
6 *
7 * Distributed under the terms of the MIT License.
8 */
9
10#include "ATAPrivate.h"
11
12
13scsi_for_sim_interface *gSCSIModule = NULL;
14device_manager_info *gDeviceManager = NULL;
15
16
17static status_t
18ata_sim_init_bus(device_node *node, void **cookie)
19{
20	ATAChannel *channel = new(std::nothrow) ATAChannel(node);
21	if (channel == NULL)
22		return B_NO_MEMORY;
23
24	status_t result = channel->InitCheck();
25	if (result != B_OK) {
26		TRACE_ERROR("failed to set up ata channel object\n");
27		delete channel;
28		return result;
29	}
30
31	*cookie = channel;
32	return B_OK;
33}
34
35
36static void
37ata_sim_uninit_bus(void *cookie)
38{
39	ATAChannel *channel = (ATAChannel *)cookie;
40	delete channel;
41}
42
43
44static void
45ata_sim_bus_removed(void *cookie)
46{
47	ATAChannel *channel = (ATAChannel *)cookie;
48	if (channel->Bus() != NULL) {
49		gSCSIModule->block_bus(channel->Bus());
50		channel->SetBus(NULL);
51	}
52}
53
54
55static void
56ata_sim_set_scsi_bus(scsi_sim_cookie cookie, scsi_bus bus)
57{
58	ATAChannel *channel = (ATAChannel *)cookie;
59	channel->SetBus(bus);
60	channel->ScanBus();
61}
62
63
64static void
65ata_sim_scsi_io(scsi_sim_cookie cookie, scsi_ccb *ccb)
66{
67	ATAChannel *channel = (ATAChannel *)cookie;
68	if (channel->Bus() == NULL) {
69		ccb->subsys_status = SCSI_NO_HBA;
70		gSCSIModule->finished(ccb, 1);
71		return;
72	}
73
74	if (channel->ExecuteIO(ccb) == B_BUSY)
75		gSCSIModule->requeue(ccb, true);
76}
77
78
79static uchar
80ata_sim_abort(scsi_sim_cookie cookie, scsi_ccb *ccb)
81{
82	ATAChannel *channel = (ATAChannel *)cookie;
83	if (channel->Bus() == NULL)
84		return SCSI_NO_HBA;
85
86	// aborting individual commands is not possible
87	return SCSI_REQ_CMP;
88}
89
90
91static uchar
92ata_sim_reset_device(scsi_sim_cookie cookie, uchar targetId, uchar targetLun)
93{
94	ATAChannel *channel = (ATAChannel *)cookie;
95	if (channel->Bus() == NULL)
96		return SCSI_NO_HBA;
97
98	// TODO: implement
99	return SCSI_REQ_INVALID;
100}
101
102
103static uchar
104ata_sim_term_io(scsi_sim_cookie cookie, scsi_ccb *ccb)
105{
106	ATAChannel *channel = (ATAChannel *)cookie;
107	if (channel->Bus() == NULL)
108		return SCSI_NO_HBA;
109
110	// we don't terminate commands, ignore
111	return SCSI_REQ_CMP;
112}
113
114
115static uchar
116ata_sim_path_inquiry(scsi_sim_cookie cookie, scsi_path_inquiry *info)
117{
118	ATAChannel *channel = (ATAChannel *)cookie;
119	if (channel->Bus() == NULL)
120		return SCSI_NO_HBA;
121
122	channel->PathInquiry(info);
123	return SCSI_REQ_CMP;
124}
125
126
127static uchar
128ata_sim_rescan_bus(scsi_sim_cookie cookie)
129{
130	// TODO: implement
131	return SCSI_REQ_CMP;
132}
133
134
135static uchar
136ata_sim_reset_bus(scsi_sim_cookie cookie)
137{
138	ATAChannel *channel = (ATAChannel *)cookie;
139	if (channel->Bus() == NULL)
140		return SCSI_NO_HBA;
141
142	//channel->Reset();
143	panic("asking for trouble");
144	return SCSI_REQ_CMP;
145}
146
147
148static void
149ata_sim_get_restrictions(scsi_sim_cookie cookie, uchar targetID,
150	bool *isATAPI, bool *noAutoSense, uint32 *maxBlocks)
151{
152	ATAChannel *channel = (ATAChannel *)cookie;
153	channel->GetRestrictions(targetID, isATAPI, noAutoSense, maxBlocks);
154}
155
156
157static status_t
158ata_sim_control(scsi_sim_cookie cookie, uchar targetID, uint32 op, void *buffer,
159	size_t length)
160{
161	ATAChannel *channel = (ATAChannel *)cookie;
162	return channel->Control(targetID, op, buffer, length);
163}
164
165
166status_t
167ata_channel_added(device_node *parent)
168{
169	const char *controllerName;
170	if (gDeviceManager->get_attr_string(parent,
171		ATA_CONTROLLER_CONTROLLER_NAME_ITEM, &controllerName, true) != B_OK) {
172		TRACE_ERROR("controller name missing\n");
173		return B_ERROR;
174	}
175
176	int32 channelID = gDeviceManager->create_id(ATA_CHANNEL_ID_GENERATOR);
177	if (channelID < 0) {
178		TRACE_ERROR("out of channel ids\n");
179		return B_ERROR;
180	}
181
182	device_attr attributes[] = {
183		{
184			B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
185				{ .string = SCSI_FOR_SIM_MODULE_NAME }
186		},
187
188		{
189			SCSI_DESCRIPTION_CONTROLLER_NAME, B_STRING_TYPE,
190				{ .string = controllerName }
191		},
192
193		// maximum number of blocks per transmission:
194		// - ATAPI uses packets, i.e. normal SCSI limits apply
195		//   but I'm not sure about controller restrictions
196		// - ATA allows up to 256 blocks for LBA28 and 65535 for LBA48
197		// to fix specific drive bugs use ATAChannel::GetRestrictions()
198		{ B_DMA_MAX_TRANSFER_BLOCKS, B_UINT32_TYPE, { .ui32 = 0xffff } },
199		{ ATA_CHANNEL_ID_ITEM, B_UINT32_TYPE, { .ui32 = (uint32)channelID } },
200		{ NULL }
201	};
202
203	return gDeviceManager->register_node(parent, ATA_SIM_MODULE_NAME,
204		attributes, NULL, NULL);
205}
206
207
208status_t
209ata_interrupt_handler(void *cookie, uint8 status)
210{
211	ATAChannel *channel = (ATAChannel *)cookie;
212	return channel->Interrupt(status);
213}
214
215
216static status_t
217std_ops(int32 op, ...)
218{
219	switch (op) {
220		case B_MODULE_INIT:
221		case B_MODULE_UNINIT:
222			return B_OK;
223
224		default:
225			break;
226	}
227
228	return B_ERROR;
229}
230
231
232scsi_sim_interface ata_sim_module = {
233	{
234		{
235			ATA_SIM_MODULE_NAME,
236			0,
237			std_ops
238		},
239
240		NULL, // supported devices
241		NULL, // register node
242		ata_sim_init_bus,
243		ata_sim_uninit_bus,
244		NULL, // register child devices
245		NULL, // rescan
246		ata_sim_bus_removed,
247		NULL, // suspend
248		NULL, // resume
249	},
250
251	ata_sim_set_scsi_bus,
252	ata_sim_scsi_io,
253	ata_sim_abort,
254	ata_sim_reset_device,
255	ata_sim_term_io,
256	ata_sim_path_inquiry,
257	ata_sim_rescan_bus,
258	ata_sim_reset_bus,
259	ata_sim_get_restrictions,
260	ata_sim_control
261};
262
263ata_for_controller_interface ata_for_controller_module = {
264	{
265		{
266			ATA_FOR_CONTROLLER_MODULE_NAME,
267			0,
268			&std_ops
269		},
270
271		NULL, // supported devices
272		ata_channel_added,
273		NULL,
274		NULL,
275		NULL
276	},
277
278	ata_interrupt_handler
279};
280
281
282module_dependency module_dependencies[] = {
283	{ SCSI_FOR_SIM_MODULE_NAME, (module_info **)&gSCSIModule },
284	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
285	{}
286};
287
288module_info *modules[] = {
289	(module_info *)&ata_for_controller_module,
290	(module_info *)&ata_sim_module,
291	NULL
292};
293