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