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