xref: /haiku/src/add-ons/kernel/busses/ata/ide_isa/ide_isa.c (revision 22440f4105cafc95cc1d49f9bc65bb395c527d86)
1 /*
2  * Copyright 2002/03, Thomas Kurschel. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 /*
7 	IDE ISA controller driver
8 
9 	This is a testing-only driver. In reality, you want to use
10 	the IDE PCI controller driver, but at least under Bochs, there's not
11 	much choice as PCI support is very limited there.
12 */
13 
14 
15 #include <KernelExport.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include <ata_adapter.h>
20 #include <bus/ISA.h>
21 
22 
23 //#define TRACE_IDE_ISA
24 #ifdef TRACE_IDE_ISA
25 #	define TRACE(x...) dprintf("ide_isa: " x)
26 #else
27 #	define TRACE(x...) ;
28 #endif
29 
30 
31 #define ATA_ISA_MODULE_NAME "busses/ata/ide_isa/driver_v1"
32 
33 // private node item:
34 // io address of command block
35 #define ATA_ISA_COMMAND_BLOCK_BASE "ide_isa/command_block_base"
36 // io address of control block
37 #define ATA_ISA_CONTROL_BLOCK_BASE "ide_isa/control_block_base"
38 // interrupt number
39 #define ATA_ISA_INTNUM "ide_isa/irq"
40 
41 
42 ata_for_controller_interface *sATA;
43 device_manager_info *sDeviceManager;
44 
45 
46 // info about one channel
47 typedef struct channel_info {
48 	isa2_module_info	*isa;
49 	uint16	command_block_base;	// io address command block
50 	uint16	control_block_base; // io address control block
51 	int		intnum;			// interrupt number
52 
53 	uint32	lost;			// != 0 if device got removed, i.e. if it must not
54 							// be accessed anymore
55 
56 	ata_channel ataChannel;
57 	device_node *node;
58 } channel_info;
59 
60 
61 /*! publish node of an ata channel */
62 static status_t
63 publish_channel(device_node *parent, uint16 command_block_base,
64 	uint16 control_block_base, uint8 intnum, const char *name)
65 {
66 	device_attr attrs[] = {
67 		{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE, { string: ATA_FOR_CONTROLLER_MODULE_NAME }},
68 
69 		// properties of this controller for ata bus manager
70 		{ ATA_CONTROLLER_MAX_DEVICES_ITEM, B_UINT8_TYPE, { ui8: 2 }},
71 		{ ATA_CONTROLLER_CAN_DMA_ITEM, B_UINT8_TYPE, { ui8: 0 }},
72 		{ ATA_CONTROLLER_CONTROLLER_NAME_ITEM, B_STRING_TYPE, { string: name }},
73 
74 		// DMA properties; the 16 bit alignment is not necessary as
75 		// the ata bus manager handles that very efficiently, but why
76 		// not use the block device manager for doing that?
77 		{ B_DMA_ALIGNMENT, B_UINT32_TYPE, { ui32: 1 }},
78 		{ B_DMA_HIGH_ADDRESS, B_UINT64_TYPE, { ui64: 0x100000000LL }},
79 
80 		// private data to identify device
81 		{ ATA_ISA_COMMAND_BLOCK_BASE, B_UINT16_TYPE, { ui16: command_block_base }},
82 		{ ATA_ISA_CONTROL_BLOCK_BASE, B_UINT16_TYPE, { ui16: control_block_base }},
83 		{ ATA_ISA_INTNUM, B_UINT8_TYPE, { ui8: intnum }},
84 		{ NULL }
85 	};
86 	io_resource resources[3] = {
87 		{ B_IO_PORT, command_block_base, 8 },
88 		{ B_IO_PORT, control_block_base, 1 },
89 		{}
90 	};
91 
92 	TRACE("publishing %s, resources %#x %#x %d\n",
93 		  name, command_block_base, control_block_base, intnum);
94 
95 	return sDeviceManager->register_node(parent, ATA_ISA_MODULE_NAME, attrs, resources,
96 		NULL);
97 }
98 
99 
100 //	#pragma mark -
101 
102 
103 static void
104 set_channel(void *cookie, ata_channel ataChannel)
105 {
106 	channel_info *channel = cookie;
107 	channel->ataChannel = ataChannel;
108 }
109 
110 
111 static status_t
112 write_command_block_regs(void *channel_cookie, ata_task_file *tf,
113 	ata_reg_mask mask)
114 {
115 	channel_info *channel = channel_cookie;
116 	uint16 ioaddr = channel->command_block_base;
117 	int i;
118 
119 	if (channel->lost)
120 		return B_ERROR;
121 
122 	for (i = 0; i < 7; i++) {
123 		if (((1 << (i-7)) & mask) != 0) {
124 			TRACE("write_command_block_regs(): %x->HI(%x)\n",
125 				tf->raw.r[i + 7], i);
126 			channel->isa->write_io_8(ioaddr + 1 + i, tf->raw.r[i + 7]);
127 		}
128 
129 		if (((1 << i) & mask) != 0 ) {
130 			TRACE("write_comamnd_block_regs(): %x->LO(%x)\n", tf->raw.r[i], i);
131 			channel->isa->write_io_8(ioaddr + 1 + i, tf->raw.r[i]);
132 		}
133 	}
134 
135 	return B_OK;
136 }
137 
138 
139 static status_t
140 read_command_block_regs(void *channel_cookie, ata_task_file *tf,
141 	ata_reg_mask mask)
142 {
143 	channel_info *channel = channel_cookie;
144 	uint16 ioaddr = channel->command_block_base;
145 	int i;
146 
147 	if (channel->lost)
148 		return B_ERROR;
149 
150 	for (i = 0; i < 7; i++) {
151 		if (((1 << i) & mask) != 0) {
152 			tf->raw.r[i] = channel->isa->read_io_8(ioaddr + 1 + i);
153 			TRACE("read_command_block_regs(%x): %x\n", i, (int)tf->raw.r[i]);
154 		}
155 	}
156 
157 	return B_OK;
158 }
159 
160 
161 static uint8
162 get_altstatus(void *channel_cookie)
163 {
164 	channel_info *channel = channel_cookie;
165 	uint16 altstatusaddr = channel->control_block_base;
166 
167 	if (channel->lost)
168 		return B_ERROR;
169 
170 	return channel->isa->read_io_8(altstatusaddr);
171 }
172 
173 
174 static status_t
175 write_device_control(void *channel_cookie, uint8 val)
176 {
177 	channel_info *channel = channel_cookie;
178 	uint16 device_control_addr = channel->control_block_base;
179 
180 	TRACE("write_device_control(%x)\n", (int)val);
181 
182 	if (channel->lost)
183 		return B_ERROR;
184 
185 	channel->isa->write_io_8(device_control_addr, val);
186 
187 	return B_OK;
188 }
189 
190 
191 static status_t
192 write_pio_16(void *channel_cookie, uint16 *data, int count, bool force_16bit)
193 {
194 	channel_info *channel = channel_cookie;
195 	uint16 ioaddr = channel->command_block_base;
196 
197 	if (channel->lost)
198 		return B_ERROR;
199 
200 	// Bochs doesn't support 32 bit accesses;
201 	// no real performance impact as this driver is for Bochs only anyway
202 	force_16bit = true;
203 
204 	if ((count & 1) != 0 || force_16bit) {
205 		for (; count > 0; --count)
206 			channel->isa->write_io_16(ioaddr, *(data++));
207 	} else {
208 		uint32 *cur_data = (uint32 *)data;
209 
210 		for (; count > 0; count -= 2)
211 			channel->isa->write_io_32(ioaddr, *(cur_data++));
212 	}
213 
214 	return B_OK;
215 }
216 
217 
218 static status_t
219 read_pio_16(void *channel_cookie, uint16 *data, int count, bool force_16bit)
220 {
221 	channel_info *channel = channel_cookie;
222 	uint16 ioaddr = channel->command_block_base;
223 
224 	if (channel->lost)
225 		return B_ERROR;
226 
227 	force_16bit = true;
228 
229 	if ((count & 1) != 0 || force_16bit) {
230 		for (; count > 0; --count)
231 			*(data++) = channel->isa->read_io_16(ioaddr);
232 	} else {
233 		uint32 *cur_data = (uint32 *)data;
234 
235 		for (; count > 0; count -= 2)
236 			*(cur_data++) = channel->isa->read_io_32(ioaddr);
237 	}
238 
239 	return B_OK;
240 }
241 
242 
243 static int32
244 inthand(void *arg)
245 {
246 	channel_info *channel = (channel_info *)arg;
247 	uint8 status;
248 
249 	TRACE("interrupt handler()\n");
250 
251 	if (channel->lost)
252 		return B_UNHANDLED_INTERRUPT;
253 
254 	// acknowledge IRQ
255 	status = channel->isa->read_io_8(channel->command_block_base + 7);
256 
257 	return sATA->interrupt_handler(channel->ataChannel, status);
258 }
259 
260 
261 static status_t
262 prepare_dma(void *channel_cookie, const physical_entry *sg_list,
263 	size_t sg_list_count, bool write)
264 {
265 	return B_NOT_ALLOWED;
266 }
267 
268 
269 static status_t
270 start_dma(void *channel_cookie)
271 {
272 	return B_NOT_ALLOWED;
273 }
274 
275 
276 static status_t
277 finish_dma(void *channel_cookie)
278 {
279 	return B_NOT_ALLOWED;
280 }
281 
282 
283 //	#pragma mark -
284 
285 
286 static float
287 supports_device(device_node *parent)
288 {
289 	const char *bus;
290 
291 	// make sure parent is really the ISA bus manager
292 	if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
293 		return B_ERROR;
294 
295 	if (strcmp(bus, "isa"))
296 		return 0.0;
297 
298 	// we assume that every modern PC has an IDE controller, so no
299 	// further testing is done (well - I don't really know how to detect the
300 	// controller, but who cares ;)
301 
302 	return 0.6;
303 }
304 
305 
306 static status_t
307 init_channel(device_node *node, void **_cookie)
308 {
309 	channel_info *channel;
310 	device_node *parent;
311 	isa2_module_info *isa;
312 	uint16 command_block_base, control_block_base;
313 	uint8 irq;
314 	status_t res;
315 
316 	TRACE("ISA-IDE: channel init\n");
317 
318 	// get device data
319 	if (sDeviceManager->get_attr_uint16(node, ATA_ISA_COMMAND_BLOCK_BASE, &command_block_base, false) != B_OK
320 		|| sDeviceManager->get_attr_uint16(node, ATA_ISA_CONTROL_BLOCK_BASE, &control_block_base, false) != B_OK
321 		|| sDeviceManager->get_attr_uint8(node, ATA_ISA_INTNUM, &irq, false) != B_OK)
322 		return B_ERROR;
323 
324 	parent = sDeviceManager->get_parent_node(node);
325 	sDeviceManager->get_driver(parent, (driver_module_info **)&isa, NULL);
326 	sDeviceManager->put_node(parent);
327 
328 	channel = (channel_info *)malloc(sizeof(channel_info));
329 	if (channel == NULL)
330 		return B_NO_MEMORY;
331 
332 	TRACE("ISA-IDE: channel init, resources %#x %#x %d\n",
333 		  command_block_base, control_block_base, irq);
334 
335 	channel->isa = isa;
336 	channel->node = node;
337 	channel->lost = false;
338 	channel->command_block_base = command_block_base;
339 	channel->control_block_base = control_block_base;
340 	channel->intnum = irq;
341 	channel->ataChannel = NULL;
342 
343 	res = install_io_interrupt_handler(channel->intnum,
344 		inthand, channel, 0);
345 
346 	if (res < 0) {
347 		TRACE("ISA-IDE: couldn't install irq handler for int %d\n", irq);
348 		goto err;
349 	}
350 
351 	// enable interrupts so the channel is ready to run
352 	write_device_control(channel, ATA_DEVICE_CONTROL_BIT3);
353 
354 	*_cookie = channel;
355 	return B_OK;
356 
357 err:
358 	free(channel);
359 	return res;
360 }
361 
362 
363 static void
364 uninit_channel(void *channel_cookie)
365 {
366 	channel_info *channel = channel_cookie;
367 
368 	TRACE("ISA-IDE: channel uninit\n");
369 
370 	// disable IRQs
371 	write_device_control(channel, ATA_DEVICE_CONTROL_BIT3 | ATA_DEVICE_CONTROL_DISABLE_INTS);
372 
373 	// catch spurious interrupt
374 	// (some controllers generate an IRQ when you _disable_ interrupts,
375 	//  they are delayed by less then 40 µs, so 1 ms is safe)
376 	snooze(1000);
377 
378 	remove_io_interrupt_handler(channel->intnum, inthand, channel);
379 
380 	free(channel);
381 }
382 
383 
384 static status_t
385 register_device(device_node *parent)
386 {
387 	status_t primaryStatus;
388 	status_t secondaryStatus;
389 	TRACE("register_device()\n");
390 
391 	// our parent device is the isa bus and all device drivers are Universal,
392 	// so the pnp_manager tries each ISA driver in turn
393 	primaryStatus = publish_channel(parent, 0x1f0, 0x3f6, 14,
394 		"primary IDE channel");
395 	secondaryStatus = publish_channel(parent, 0x170, 0x376, 15,
396 		"secondary IDE channel");
397 
398 	if (primaryStatus == B_OK || secondaryStatus == B_OK)
399 		return B_OK;
400 
401 	return primaryStatus;
402 }
403 
404 
405 static void
406 channel_removed(void *cookie)
407 {
408 	channel_info *channel = cookie;
409 	TRACE("channel_removed()\n");
410 
411 	// disable access instantly
412 	atomic_or((int32*)&channel->lost, 1);
413 }
414 
415 
416 module_dependency module_dependencies[] = {
417 	{ ATA_FOR_CONTROLLER_MODULE_NAME, (module_info **)&sATA },
418 	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
419 	{}
420 };
421 
422 // exported interface
423 static ata_controller_interface sISAControllerInterface = {
424 	{
425 		{
426 			ATA_ISA_MODULE_NAME,
427 			0,
428 			NULL
429 		},
430 
431 		supports_device,
432 		register_device,
433 		init_channel,
434 		uninit_channel,
435 		NULL,	// register child devices
436 		NULL,	// rescan
437 		channel_removed,
438 	},
439 
440 	&set_channel,
441 
442 	&write_command_block_regs,
443 	&read_command_block_regs,
444 
445 	&get_altstatus,
446 	&write_device_control,
447 
448 	&write_pio_16,
449 	&read_pio_16,
450 
451 	&prepare_dma,
452 	&start_dma,
453 	&finish_dma,
454 };
455 
456 module_info *modules[] = {
457 	(module_info *)&sISAControllerInterface,
458 	NULL
459 };
460