xref: /haiku/src/add-ons/kernel/bus_managers/ata/ATAModule.cpp (revision 52c4471a3024d2eb81fe88e2c3982b9f8daa5e56)
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 
13 scsi_for_sim_interface *gSCSIModule = NULL;
14 device_manager_info *gDeviceManager = NULL;
15 
16 
17 static status_t
18 ata_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 
36 static void
37 ata_sim_uninit_bus(void *cookie)
38 {
39 	ATAChannel *channel = (ATAChannel *)cookie;
40 	delete channel;
41 }
42 
43 
44 static void
45 ata_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 
55 static void
56 ata_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 
64 static void
65 ata_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 
79 static uchar
80 ata_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 
91 static uchar
92 ata_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 
103 static uchar
104 ata_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 
115 static uchar
116 ata_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 
127 static uchar
128 ata_sim_rescan_bus(scsi_sim_cookie cookie)
129 {
130 	// TODO: implement
131 	return SCSI_REQ_CMP;
132 }
133 
134 
135 static uchar
136 ata_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 
148 static void
149 ata_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 
157 static status_t
158 ata_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 
166 status_t
167 ata_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 
208 status_t
209 ata_interrupt_handler(void *cookie, uint8 status)
210 {
211 	ATAChannel *channel = (ATAChannel *)cookie;
212 	return channel->Interrupt(status);
213 }
214 
215 
216 static status_t
217 std_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 
232 scsi_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 
263 ata_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 
282 module_dependency module_dependencies[] = {
283 	{ SCSI_FOR_SIM_MODULE_NAME, (module_info **)&gSCSIModule },
284 	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
285 	{}
286 };
287 
288 module_info *modules[] = {
289 	(module_info *)&ata_for_controller_module,
290 	(module_info *)&ata_sim_module,
291 	NULL
292 };
293