xref: /netbsd/external/gpl3/gdb/dist/sim/ppc/hw_ide.c (revision 48596154)
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 *
ide_state_name(ide_states state)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
set_interrupt(device * me,ide_controller * controller)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
clear_interrupt(device * me,ide_controller * controller)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
do_event(void * data)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
schedule_ready_event(device * me,ide_controller * controller)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
do_fifo_read(device * me,ide_controller * controller,void * dest,int nr_bytes)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
do_fifo_write(device * me,ide_controller * controller,const void * source,int nr_bytes)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
setup_fifo(device * me,ide_controller * controller,int is_simple,int is_with_disk,io_direction direction)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
do_command(device * me,ide_controller * controller,int command)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
get_status(device * me,ide_controller * controller)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
decode_address(device * me,address_decoder * decoder,int space,unsigned_word address,int * controller,int * reg,io_direction direction)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
build_address_decoder(device * me,address_decoder * decoder)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
hw_ide_init_address(device * me)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
hw_ide_attach_address(device * me,attach_type type,int space,unsigned_word addr,unsigned nr_bytes,access_type access,device * client)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
hw_ide_io_read_buffer(device * me,void * dest,int space,unsigned_word addr,unsigned nr_bytes,cpu * processor,unsigned_word cia)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
hw_ide_io_write_buffer(device * me,const void * source,int space,unsigned_word addr,unsigned nr_bytes,cpu * processor,unsigned_word cia)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 *
hw_ide_create(const char * name,const device_unit * unit_address,const char * args)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_ */
869