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
145typedef enum _io_direction {
146  is_read,
147  is_write,
148} io_direction;
149
150
151enum {
152  nr_ide_controllers = 2,
153  nr_ide_drives_per_controller = 2,
154  nr_fifo_entries = 8192,
155};
156
157enum {
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
186typedef 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
196static const char *
197ide_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
211typedef struct _ide_geometry {
212  int head;
213  int sector;
214  int byte;
215} ide_geometry;
216
217typedef struct _ide_drive {
218  int nr;
219  device *device;
220  ide_geometry geometry;
221  ide_geometry default_geometry;
222} ide_drive;
223
224typedef struct _ide_controller {
225  int nr;
226  ide_states state;
227  uint8_t reg[nr_ide_registers];
228  uint8_t 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  int64_t ready_delay;
239} ide_controller;
240
241
242
243static void
244set_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
255static void
256clear_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
267static void
268do_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
292static void
293schedule_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
305static void
306do_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
348static void
349do_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
391static void
392setup_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
474static void
475do_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
491static uint8_t
492get_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
514enum {
515  nr_address_blocks = 6,
516};
517
518typedef 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
526typedef struct _address_decoder {
527  address_block block[nr_address_blocks];
528} address_decoder;
529
530static void
531decode_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
564static void
565build_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
648typedef struct _hw_ide_device {
649  ide_controller controller[nr_ide_controllers];
650  address_decoder decoder;
651} hw_ide_device;
652
653
654static void
655hw_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
682static void
683hw_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
722static unsigned
723hw_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    *(uint8_t*)dest = get_status(me, controller);
748    clear_interrupt(me, controller);
749    break;
750  case ide_alternate_status_reg:
751    *(uint8_t*)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    *(uint8_t*)dest = controller->reg[reg];
767    break;
768  default:
769    device_error(me, "bus-error at address 0x%lx", (unsigned long)addr);
770    break;
771  }
772  return nr_bytes;
773}
774
775
776static unsigned
777hw_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, *(uint8_t*)source);
801    break;
802  case ide_control_reg:
803    controller->reg[reg] = *(uint8_t*)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] = *(uint8_t*)source;
821    break;
822  default:
823    device_error(me, "bus-error at 0x%lx", (unsigned long)addr);
824    break;
825  }
826  return nr_bytes;
827}
828
829
830static 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
840static 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
853static void *
854hw_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
863const device_descriptor hw_ide_device_descriptor[] = {
864  { "ide", hw_ide_create, &hw_ide_callbacks },
865  { NULL, },
866};
867
868#endif /* _HW_IDE_ */
869