Update
[gdb.git] / sim / ppc / hw_ide.c
blob00d54b32e1e3a497f5c51ea12ba13447e07f5702
1 /* This file is part of the program psim.
3 Copyright (C) 1996, Andrew Cagney <cagney@highland.com.au>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #ifndef _HW_IDE_C_
23 #define _HW_IDE_C_
25 #include "device_table.h"
29 /* DEVICE
32 ide - Integrated Disk Electronics
35 DESCRIPTION
38 This device models the primary/secondary <<ide>> controller
39 described in the [CHRPIO] document.
41 The controller has separate independant interrupt outputs for each
42 <<ide>> bus.
45 PROPERTIES
48 reg = ... (required)
50 The <<reg>> property is described in the document [CHRPIO].
53 ready-delay = <integer> (optional)
55 If present, this specifies the time that the <<ide>> device takes
56 to complete an I/O operation.
59 disk@?/ide-byte-count = <integer> (optional)
61 disk@?/ide-sector-count = <integer> (optional)
63 disk@?/ide-head-count = <integer> (optional)
65 The <<ide>> device checks each child (disk device) node to see if
66 it has the above properties. If present, these values will be used
67 to compute the <<LBA>> address in <<CHS>> addressing mode.
70 EXAMPLES
73 Enable tracing:
75 | -t ide-device \
78 Attach the <<ide>> device to the <<pci>> bus at slot one. Specify
79 legacy I/O addresses:
81 | -o '/phb/ide@1/assigned-addresses \
82 | ni0,0,10,1f0 8 \
83 | ni0,0,14,3f8 8 \
84 | ni0,0,18,170 8 \
85 | ni0,0,1c,378 8 \
86 | ni0,0,20,200 8' \
87 | -o '/phb@0x80000000/ide@1/reg \
88 | 1 0 \
89 | i0,0,10,0 8 \
90 | i0,0,18,0 8 \
91 | i0,0,14,6 1 \
92 | i0,0,1c,6 1 \
93 | i0,0,20,0 8' \
95 Note: the fouth and fifth reg entries specify that the register is
96 at an offset into the address specified by the base register
97 (<<assigned-addresses>>); Apart from restrictions placed by the
98 <<pci>> specification, no restrictions are placed on the number of
99 base registers specified by the <<assigned-addresses>> property.
101 Attach a <<disk>> to the primary and a <<cdrom>> to the secondary
102 <<ide>> controller.
104 | -o '/phb@0x80000000/ide@1/disk@0/file "zero' \
105 | -o '/phb@0x80000000/ide@1/cdrom@2/file "/dev/cdrom"' \
107 Connect the two interrupt outputs (a and b) to a <<glue>> device to
108 allow testing of the interrupt port. In a real simulation they
109 would be wired to the interrupt controller.
111 | -o '/phb@0x80000000/glue@2/reg 2 0 ni0,0,0,0 8' \
112 | -o '/phb@0x80000000/ide@1 > a 0 /phb@0x80000000/glue@2' \
113 | -o '/phb@0x80000000/ide@1 > b 1 /phb@0x80000000/glue@2'
116 BUGS
119 While the DMA registers are present, DMA support has not yet been
120 implemented.
122 The number of supported commands is very limited.
124 The standards documents appear to be vague on how to specify the
125 <<unit-address>> of disk devices devices being attached to the
126 <<ide>> controller. I've chosen to use integers with devices zero
127 and one going to the primary controller while two and three are
128 connected to the secondary controller.
131 REFERENCES
134 [CHRPIO] PowerPC(tm) Microprocessor Common Hardware Reference
135 Platform: I/O Device Reference. http://chrp.apple.com/???.
137 [SCHMIDT] The SCSI Bus and IDE Interface - Protocols, Applications
138 and Programming. Friedhelm Schmidt (translated by Michael
139 Schultz). ISBN 0-201-42284-0. Addison-Wesley Publishing Company.
146 typedef enum _io_direction {
147 is_read,
148 is_write,
149 } io_direction;
152 enum {
153 nr_ide_controllers = 2,
154 nr_ide_drives_per_controller = 2,
155 nr_fifo_entries = 8192,
158 enum {
159 /* command register block - read */
160 ide_data_reg,
161 ide_error_reg, /*ide_feature_reg*/
162 ide_sector_count_reg,
163 ide_sector_number_reg,
164 ide_cylinder_reg0,
165 ide_cylinder_reg1,
166 ide_drive_head_reg,
167 ide_status_reg, /*ide_command_reg*/
168 /* command register block - write */
169 ide_feature_reg, /*ide_error_reg*/
170 ide_command_reg, /*ide_status_reg*/
171 /* control register block - read */
172 ide_alternate_status_reg, /*ide_control_reg*/
173 ide_control_reg, /*ide_alternate_status_reg*/
174 /* dma register block */
175 ide_dma_command_reg,
176 ide_dma_unused_1_reg,
177 ide_dma_status_reg,
178 ide_dma_unused_3_reg,
179 ide_dma_prd_table_address_reg0,
180 ide_dma_prd_table_address_reg1,
181 ide_dma_prd_table_address_reg2,
182 ide_dma_prd_table_address_reg3,
183 nr_ide_registers,
187 typedef enum _ide_states {
188 idle_state,
189 busy_loaded_state,
190 busy_drained_state,
191 busy_dma_state,
192 busy_command_state,
193 loading_state,
194 draining_state,
195 } ide_states;
197 static const char *
198 ide_state_name(ide_states state)
200 switch (state) {
201 case idle_state: return "idle";
202 case busy_loaded_state: return "busy_loaded_state";
203 case busy_drained_state: return "busy_drained_state";
204 case busy_dma_state: return "busy_dma_state";
205 case busy_command_state: return "busy_command_state";
206 case loading_state: return "loading_state";
207 case draining_state: return "draining_state";
208 default: return "illegal-state";
212 typedef struct _ide_geometry {
213 int head;
214 int sector;
215 int byte;
216 } ide_geometry;
218 typedef struct _ide_drive {
219 int nr;
220 device *device;
221 ide_geometry geometry;
222 ide_geometry default_geometry;
223 } ide_drive;
225 typedef struct _ide_controller {
226 int nr;
227 ide_states state;
228 unsigned8 reg[nr_ide_registers];
229 unsigned8 fifo[nr_fifo_entries];
230 int fifo_pos;
231 int fifo_size;
232 ide_drive *current_drive;
233 int current_byte;
234 int current_transfer;
235 ide_drive drive[nr_ide_drives_per_controller];
236 device *me;
237 event_entry_tag event_tag;
238 int is_interrupting;
239 signed64 ready_delay;
240 } ide_controller;
244 static void
245 set_interrupt(device *me,
246 ide_controller *controller)
248 if ((controller->reg[ide_control_reg] & 0x2) == 0) {
249 DTRACE(ide, ("controller %d - interrupt set\n", controller->nr));
250 device_interrupt_event(me, controller->nr, 1, NULL, 0);
251 controller->is_interrupting = 1;
256 static void
257 clear_interrupt(device *me,
258 ide_controller *controller)
260 if (controller->is_interrupting) {
261 DTRACE(ide, ("controller %d - interrupt clear\n", controller->nr));
262 device_interrupt_event(me, controller->nr, 0, NULL, 0);
263 controller->is_interrupting = 0;
268 static void
269 do_event(void *data)
271 ide_controller *controller = data;
272 device *me = controller->me;
273 controller->event_tag = 0;
274 switch (controller->state) {
275 case busy_loaded_state:
276 case busy_drained_state:
277 if (controller->current_transfer > 0) {
278 controller->state = (controller->state == busy_loaded_state
279 ? loading_state : draining_state);
281 else {
282 controller->state = idle_state;
284 set_interrupt(me, controller);
285 break;
286 default:
287 device_error(me, "controller %d - unexpected event", controller->nr);
288 break;
293 static void
294 schedule_ready_event(device *me,
295 ide_controller *controller)
297 if (controller->event_tag != 0)
298 device_error(me, "controller %d - attempting to schedule multiple events",
299 controller->nr);
300 controller->event_tag =
301 device_event_queue_schedule(me, controller->ready_delay,
302 do_event, controller);
306 static void
307 do_fifo_read(device *me,
308 ide_controller *controller,
309 void *dest,
310 int nr_bytes)
312 if (controller->state != draining_state)
313 device_error(me, "controller %d - reading fifo when not ready (%s)",
314 controller->nr,
315 ide_state_name(controller->state));
316 if (controller->fifo_pos + nr_bytes > controller->fifo_size)
317 device_error(me, "controller %d - fifo underflow", controller->nr);
318 if (nr_bytes > 0) {
319 memcpy(dest, &controller->fifo[controller->fifo_pos], nr_bytes);
320 controller->fifo_pos += nr_bytes;
322 if (controller->fifo_pos == controller->fifo_size) {
323 controller->current_transfer -= 1;
324 if (controller->current_transfer > 0
325 && controller->current_drive != NULL) {
326 DTRACE(ide, ("controller %d:%d - reading %d byte block at 0x%x\n",
327 controller->nr,
328 controller->current_drive->nr,
329 controller->fifo_size,
330 controller->current_byte));
331 if (device_io_read_buffer(controller->current_drive->device,
332 controller->fifo,
333 0, controller->current_byte,
334 controller->fifo_size,
335 NULL, 0)
336 != controller->fifo_size)
337 device_error(me, "controller %d - disk %s io read error",
338 controller->nr,
339 device_path(controller->current_drive->device));
341 controller->state = busy_drained_state;
342 controller->fifo_pos = 0;
343 controller->current_byte += controller->fifo_size;
344 schedule_ready_event(me, controller);
349 static void
350 do_fifo_write(device *me,
351 ide_controller *controller,
352 const void *source,
353 int nr_bytes)
355 if (controller->state != loading_state)
356 device_error(me, "controller %d - writing fifo when not ready (%s)",
357 controller->nr,
358 ide_state_name(controller->state));
359 if (controller->fifo_pos + nr_bytes > controller->fifo_size)
360 device_error(me, "controller %d - fifo overflow", controller->nr);
361 if (nr_bytes > 0) {
362 memcpy(&controller->fifo[controller->fifo_pos], source, nr_bytes);
363 controller->fifo_pos += nr_bytes;
365 if (controller->fifo_pos == controller->fifo_size) {
366 if (controller->current_transfer > 0
367 && controller->current_drive != NULL) {
368 DTRACE(ide, ("controller %d:%d - writing %d byte block at 0x%x\n",
369 controller->nr,
370 controller->current_drive->nr,
371 controller->fifo_size,
372 controller->current_byte));
373 if (device_io_write_buffer(controller->current_drive->device,
374 controller->fifo,
375 0, controller->current_byte,
376 controller->fifo_size,
377 NULL, 0)
378 != controller->fifo_size)
379 device_error(me, "controller %d - disk %s io write error",
380 controller->nr,
381 device_path(controller->current_drive->device));
383 controller->current_transfer -= 1;
384 controller->fifo_pos = 0;
385 controller->current_byte += controller->fifo_size;
386 controller->state = busy_loaded_state;
387 schedule_ready_event(me, controller);
392 static void
393 setup_fifo(device *me,
394 ide_controller *controller,
395 int is_simple,
396 int is_with_disk,
397 io_direction direction)
399 /* find the disk */
400 if (is_with_disk) {
401 int drive_nr = (controller->reg[ide_drive_head_reg] & 0x10) != 0;
402 controller->current_drive = &controller->drive[drive_nr];
404 else {
405 controller->current_drive = NULL;
408 /* number of transfers */
409 if (is_simple)
410 controller->current_transfer = 1;
411 else {
412 int sector_count = controller->reg[ide_sector_count_reg];
413 if (sector_count == 0)
414 controller->current_transfer = 256;
415 else
416 controller->current_transfer = sector_count;
419 /* the transfer size */
420 if (controller->current_drive == NULL)
421 controller->fifo_size = 512;
422 else
423 controller->fifo_size = controller->current_drive->geometry.byte;
425 /* empty the fifo */
426 controller->fifo_pos = 0;
428 /* the starting address */
429 if (controller->current_drive == NULL)
430 controller->current_byte = 0;
431 else if (controller->reg[ide_drive_head_reg] & 0x40) {
432 /* LBA addressing mode */
433 controller->current_byte = controller->fifo_size
434 * (((controller->reg[ide_drive_head_reg] & 0xf) << 24)
435 | (controller->reg[ide_cylinder_reg1] << 16)
436 | (controller->reg[ide_cylinder_reg0] << 8)
437 | (controller->reg[ide_sector_number_reg]));
439 else if (controller->current_drive->geometry.head != 0
440 && controller->current_drive->geometry.sector != 0) {
441 /* CHS addressing mode */
442 int head_nr = controller->reg[ide_drive_head_reg] & 0xf;
443 int cylinder_nr = ((controller->reg[ide_cylinder_reg1] << 8)
444 | controller->reg[ide_cylinder_reg0]);
445 int sector_nr = controller->reg[ide_sector_number_reg];
446 controller->current_byte = controller->fifo_size
447 * ((cylinder_nr * controller->current_drive->geometry.head + head_nr)
448 * controller->current_drive->geometry.sector + sector_nr - 1);
450 else
451 device_error(me, "controller %d:%d - CHS addressing disabled",
452 controller->nr, controller->current_drive->nr);
453 DTRACE(ide, ("controller %ld:%ld - transfer (%s) %ld blocks of %ld bytes from 0x%lx\n",
454 (long)controller->nr,
455 controller->current_drive == NULL ? -1L : (long)controller->current_drive->nr,
456 direction == is_read ? "read" : "write",
457 (long)controller->current_transfer,
458 (long)controller->fifo_size,
459 (unsigned long)controller->current_byte));
460 switch (direction) {
461 case is_read:
462 /* force a primeing read */
463 controller->current_transfer += 1;
464 controller->state = draining_state;
465 controller->fifo_pos = controller->fifo_size;
466 do_fifo_read(me, controller, NULL, 0);
467 break;
468 case is_write:
469 controller->state = loading_state;
470 break;
475 static void
476 do_command(device *me,
477 ide_controller *controller,
478 int command)
480 if (controller->state != idle_state)
481 device_error(me, "controller %d - command when not idle", controller->nr);
482 switch (command) {
483 case 0x20: case 0x21: /* read-sectors */
484 setup_fifo(me, controller, 0/*is_simple*/, 1/*is_with_disk*/, is_read);
485 break;
486 case 0x30: case 0x31: /* write */
487 setup_fifo(me, controller, 0/*is_simple*/, 1/*is_with_disk*/, is_write);
488 break;
492 static unsigned8
493 get_status(device *me,
494 ide_controller *controller)
496 switch (controller->state) {
497 case loading_state:
498 case draining_state:
499 return 0x08; /* data req */
500 case busy_loaded_state:
501 case busy_drained_state:
502 return 0x80; /* busy */
503 case idle_state:
504 return 0x40; /* drive ready */
505 default:
506 device_error(me, "internal error");
507 return 0;
512 /* The address presented to the IDE controler is decoded and then
513 mapped onto a controller:reg pair */
515 enum {
516 nr_address_blocks = 6,
519 typedef struct _address_block {
520 int space;
521 unsigned_word base_addr;
522 unsigned_word bound_addr;
523 int controller;
524 int base_reg;
525 } address_block;
527 typedef struct _address_decoder {
528 address_block block[nr_address_blocks];
529 } address_decoder;
531 static void
532 decode_address(device *me,
533 address_decoder *decoder,
534 int space,
535 unsigned_word address,
536 int *controller,
537 int *reg,
538 io_direction direction)
540 int i;
541 for (i = 0; i < nr_address_blocks; i++) {
542 if (space == decoder->block[i].space
543 && address >= decoder->block[i].base_addr
544 && address <= decoder->block[i].bound_addr) {
545 *controller = decoder->block[i].controller;
546 *reg = (address
547 - decoder->block[i].base_addr
548 + decoder->block[i].base_reg);
549 if (direction == is_write) {
550 switch (*reg) {
551 case ide_error_reg: *reg = ide_feature_reg; break;
552 case ide_status_reg: *reg = ide_command_reg; break;
553 case ide_alternate_status_reg: *reg = ide_control_reg; break;
554 default: break;
557 return;
560 device_error(me, "address %d:0x%lx invalid",
561 space, (unsigned long)address);
565 static void
566 build_address_decoder(device *me,
567 address_decoder *decoder)
569 int reg;
570 for (reg = 1; reg < 6; reg++) {
571 reg_property_spec unit;
572 int space;
573 unsigned_word address;
574 unsigned size;
575 /* find and decode the reg property */
576 if (!device_find_reg_array_property(me, "reg", reg, &unit))
577 device_error(me, "missing or invalid reg entry %d", reg);
578 device_address_to_attach_address(device_parent(me), &unit.address,
579 &space, &address, me);
580 device_size_to_attach_size(device_parent(me), &unit.size, &size, me);
581 /* insert it into the address decoder */
582 switch (reg) {
583 case 1:
584 case 2:
585 /* command register block */
586 if (size != 8)
587 device_error(me, "reg entry %d must have a size of 8", reg);
588 decoder->block[reg-1].space = space;
589 decoder->block[reg-1].base_addr = address;
590 decoder->block[reg-1].bound_addr = address + size - 1;
591 decoder->block[reg-1].controller = (reg + 1) % nr_ide_controllers;
592 decoder->block[reg-1].base_reg = ide_data_reg;
593 DTRACE(ide, ("controller %d command register block at %d:0x%lx..0x%lx\n",
594 decoder->block[reg-1].controller,
595 decoder->block[reg-1].space,
596 (unsigned long)decoder->block[reg-1].base_addr,
597 (unsigned long)decoder->block[reg-1].bound_addr));
598 break;
599 case 3:
600 case 4:
601 /* control register block */
602 if (size != 1)
603 device_error(me, "reg entry %d must have a size of 1", reg);
604 decoder->block[reg-1].space = space;
605 decoder->block[reg-1].base_addr = address;
606 decoder->block[reg-1].bound_addr = address + size - 1;
607 decoder->block[reg-1].controller = (reg + 1) % nr_ide_controllers;
608 decoder->block[reg-1].base_reg = ide_alternate_status_reg;
609 DTRACE(ide, ("controller %d control register block at %d:0x%lx..0x%lx\n",
610 decoder->block[reg-1].controller,
611 decoder->block[reg-1].space,
612 (unsigned long)decoder->block[reg-1].base_addr,
613 (unsigned long)decoder->block[reg-1].bound_addr));
614 break;
615 case 5:
616 /* dma register block */
617 if (size != 8)
618 device_error(me, "reg entry %d must have a size of 8", reg);
619 decoder->block[reg-1].space = space;
620 decoder->block[reg-1].base_addr = address;
621 decoder->block[reg-1].bound_addr = address + 4 - 1;
622 decoder->block[reg-1].base_reg = ide_dma_command_reg;
623 decoder->block[reg-1].controller = 0;
624 DTRACE(ide, ("controller %d dma register block at %d:0x%lx..0x%lx\n",
625 decoder->block[reg-1].controller,
626 decoder->block[reg-1].space,
627 (unsigned long)decoder->block[reg-1].base_addr,
628 (unsigned long)decoder->block[reg-1].bound_addr));
629 decoder->block[reg].space = space;
630 decoder->block[reg].base_addr = address + 4;
631 decoder->block[reg].bound_addr = address + 8 - 1;
632 decoder->block[reg].controller = 1;
633 decoder->block[reg].base_reg = ide_dma_command_reg;
634 DTRACE(ide, ("controller %d dma register block at %d:0x%lx..0x%lx\n",
635 decoder->block[reg].controller,
636 decoder->block[reg-1].space,
637 (unsigned long)decoder->block[reg].base_addr,
638 (unsigned long)decoder->block[reg].bound_addr));
639 break;
640 default:
641 device_error(me, "internal error - bad switch");
642 break;
649 typedef struct _hw_ide_device {
650 ide_controller controller[nr_ide_controllers];
651 address_decoder decoder;
652 } hw_ide_device;
655 static void
656 hw_ide_init_address(device *me)
658 hw_ide_device *ide = device_data(me);
659 int controller;
660 int drive;
662 /* zero some things */
663 for (controller = 0; controller < nr_ide_controllers; controller++) {
664 memset(&ide->controller[controller], 0, sizeof(ide_controller));
665 for (drive = 0; drive < nr_ide_drives_per_controller; drive++) {
666 ide->controller[controller].drive[drive].nr = drive;
668 ide->controller[controller].me = me;
669 if (device_find_property(me, "ready-delay") != NULL)
670 ide->controller[controller].ready_delay =
671 device_find_integer_property(me, "ready-delay");
674 /* attach this device to its parent */
675 generic_device_init_address(me);
677 /* determine our own address map */
678 build_address_decoder(me, &ide->decoder);
683 static void
684 hw_ide_attach_address(device *me,
685 attach_type type,
686 int space,
687 unsigned_word addr,
688 unsigned nr_bytes,
689 access_type access,
690 device *client) /*callback/default*/
692 hw_ide_device *ide = (hw_ide_device*)device_data(me);
693 int controller_nr = addr / nr_ide_drives_per_controller;
694 int drive_nr = addr % nr_ide_drives_per_controller;
695 ide_controller *controller;
696 ide_drive *drive;
697 if (controller_nr >= nr_ide_controllers)
698 device_error(me, "no controller for disk %s",
699 device_path(client));
701 controller = &ide->controller[controller_nr];
702 drive = &controller->drive[drive_nr];
703 drive->device = client;
704 if (device_find_property(client, "ide-byte-count") != NULL)
705 drive->geometry.byte = device_find_integer_property(client, "ide-byte-count");
706 else
707 drive->geometry.byte = 512;
708 if (device_find_property(client, "ide-sector-count") != NULL)
709 drive->geometry.sector = device_find_integer_property(client, "ide-sector-count");
710 if (device_find_property(client, "ide-head-count") != NULL)
711 drive->geometry.head = device_find_integer_property(client, "ide-head-count");
712 drive->default_geometry = drive->geometry;
713 DTRACE(ide, ("controller %d:%d %s byte-count %d, sector-count %d, head-count %d\n",
714 controller_nr,
715 drive->nr,
716 device_path(client),
717 drive->geometry.byte,
718 drive->geometry.sector,
719 drive->geometry.head));
723 static unsigned
724 hw_ide_io_read_buffer(device *me,
725 void *dest,
726 int space,
727 unsigned_word addr,
728 unsigned nr_bytes,
729 cpu *processor,
730 unsigned_word cia)
732 hw_ide_device *ide = (hw_ide_device *)device_data(me);
733 int control_nr;
734 int reg;
735 ide_controller *controller;
737 /* find the interface */
738 decode_address(me, &ide->decoder, space, addr, &control_nr, &reg, is_read);
739 controller = & ide->controller[control_nr];
741 /* process the transfer */
742 memset(dest, 0, nr_bytes);
743 switch (reg) {
744 case ide_data_reg:
745 do_fifo_read(me, controller, dest, nr_bytes);
746 break;
747 case ide_status_reg:
748 *(unsigned8*)dest = get_status(me, controller);
749 clear_interrupt(me, controller);
750 break;
751 case ide_alternate_status_reg:
752 *(unsigned8*)dest = get_status(me, controller);
753 break;
754 case ide_error_reg:
755 case ide_sector_count_reg:
756 case ide_sector_number_reg:
757 case ide_cylinder_reg0:
758 case ide_cylinder_reg1:
759 case ide_drive_head_reg:
760 case ide_control_reg:
761 case ide_dma_command_reg:
762 case ide_dma_status_reg:
763 case ide_dma_prd_table_address_reg0:
764 case ide_dma_prd_table_address_reg1:
765 case ide_dma_prd_table_address_reg2:
766 case ide_dma_prd_table_address_reg3:
767 *(unsigned8*)dest = controller->reg[reg];
768 break;
769 default:
770 device_error(me, "bus-error at address 0x%lx", addr);
771 break;
773 return nr_bytes;
777 static unsigned
778 hw_ide_io_write_buffer(device *me,
779 const void *source,
780 int space,
781 unsigned_word addr,
782 unsigned nr_bytes,
783 cpu *processor,
784 unsigned_word cia)
786 hw_ide_device *ide = (hw_ide_device *)device_data(me);
787 int control_nr;
788 int reg;
789 ide_controller *controller;
791 /* find the interface */
792 decode_address(me, &ide->decoder, space, addr, &control_nr, &reg, is_write);
793 controller = &ide->controller[control_nr];
795 /* process the access */
796 switch (reg) {
797 case ide_data_reg:
798 do_fifo_write(me, controller, source, nr_bytes);
799 break;
800 case ide_command_reg:
801 do_command(me, controller, *(unsigned8*)source);
802 break;
803 case ide_control_reg:
804 controller->reg[reg] = *(unsigned8*)source;
805 /* possibly cancel interrupts */
806 if ((controller->reg[reg] & 0x02) == 0x02)
807 clear_interrupt(me, controller);
808 break;
809 case ide_feature_reg:
810 case ide_sector_count_reg:
811 case ide_sector_number_reg:
812 case ide_cylinder_reg0:
813 case ide_cylinder_reg1:
814 case ide_drive_head_reg:
815 case ide_dma_command_reg:
816 case ide_dma_status_reg:
817 case ide_dma_prd_table_address_reg0:
818 case ide_dma_prd_table_address_reg1:
819 case ide_dma_prd_table_address_reg2:
820 case ide_dma_prd_table_address_reg3:
821 controller->reg[reg] = *(unsigned8*)source;
822 break;
823 default:
824 device_error(me, "bus-error at 0x%lx", addr);
825 break;
827 return nr_bytes;
831 static const device_interrupt_port_descriptor hw_ide_interrupt_ports[] = {
832 { "a", 0, 0 },
833 { "b", 1, 0 },
834 { "c", 2, 0 },
835 { "d", 3, 0 },
836 { NULL }
841 static device_callbacks const hw_ide_callbacks = {
842 { hw_ide_init_address, },
843 { hw_ide_attach_address, }, /* attach */
844 { hw_ide_io_read_buffer, hw_ide_io_write_buffer, },
845 { NULL, }, /* DMA */
846 { NULL, NULL, hw_ide_interrupt_ports }, /* interrupt */
847 { generic_device_unit_decode,
848 generic_device_unit_encode,
849 generic_device_address_to_attach_address,
850 generic_device_size_to_attach_size },
854 static void *
855 hw_ide_create(const char *name,
856 const device_unit *unit_address,
857 const char *args)
859 hw_ide_device *ide = ZALLOC(hw_ide_device);
860 return ide;
864 const device_descriptor hw_ide_device_descriptor[] = {
865 { "ide", hw_ide_create, &hw_ide_callbacks },
866 { NULL, },
869 #endif /* _HW_IDE_ */