Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:40

0001 /*
0002  * RTEMS PC386 IDE harddisc driver
0003  *
0004  * This file contains the BSP layer for IDE access below the
0005  * libchip IDE harddisc driver.
0006  * based on a board specific driver from
0007  * Eugeny S. Mints, Oktet
0008  */
0009 
0010 /*
0011  * Copyright (c) 2003 IMD Ingenieurbuero fuer Microcomputertechnik
0012  * All rights reserved.
0013  *
0014  * The license and distribution terms for this file may be
0015  * found in the file LICENSE in this distribution or at
0016  * http://www.rtems.org/license/LICENSE.
0017  */
0018 
0019 #include <inttypes.h>
0020 
0021 #include <rtems.h>
0022 
0023 #include <bsp.h>
0024 #include <libchip/ide_ctrl.h>
0025 #include <libchip/ide_ctrl_cfg.h>
0026 #include <libchip/ide_ctrl_io.h>
0027 
0028 #define ATA_SECTOR_SIZE (512)
0029 
0030 /*
0031  * Use during initialisation.
0032  */
0033 extern void Wait_X_ms(unsigned int msecs);
0034 
0035 bool pc386_ide_show;
0036 uint32_t pc386_ide_timeout;
0037 
0038 #define PC386_IDE_DEBUG_OUT 0
0039 
0040 #if PC386_IDE_DEBUG_OUT
0041 bool pc386_ide_trace;
0042 #define pc386_ide_printk if (pc386_ide_trace) printk
0043 #endif
0044 
0045 #define PC386_IDE_PROBE_TIMEOUT    (500)
0046 #define PC386_IDE_PRESTART_TIMEOUT (1000)
0047 #define PC386_IDE_TASKING_TIMEOUT  (2000)
0048 
0049 /*
0050  * Prestart sleep using a calibrated timing loop.
0051  */
0052 static void pc386_ide_prestart_sleep (void)
0053 {
0054   Wait_X_ms (10);
0055 }
0056 
0057 /*
0058  * Once tasking has started we use a task sleep.
0059  */
0060 static void pc386_ide_tasking_sleep (void)
0061 {
0062   rtems_task_wake_after (RTEMS_MICROSECONDS_TO_TICKS (10000) ?
0063                          RTEMS_MICROSECONDS_TO_TICKS (10000) : 1);
0064 }
0065 
0066 typedef void (*pc386_ide_sleeper)(void);
0067 
0068 static void pc386_ide_sleep (pc386_ide_sleeper sleeper)
0069 {
0070   sleeper ();
0071 }
0072 
0073 static void wait(volatile uint32_t loops)
0074 {
0075   while (loops)
0076     loops--;
0077 }
0078 
0079 static bool pc386_ide_status_busy (uint32_t          port,
0080                                    volatile uint32_t timeout,
0081                                    uint8_t*          status_val,
0082                                    pc386_ide_sleeper sleeper)
0083 {
0084   volatile uint8_t status;
0085   int              polls;
0086 
0087   do
0088   {
0089     polls = 500;
0090     while (polls)
0091     {
0092       inport_byte (port + IDE_REGISTER_STATUS, status);
0093       if ((status & IDE_REGISTER_STATUS_BSY) == 0)
0094       {
0095         *status_val = status;
0096         return true;
0097       }
0098       polls--;
0099     }
0100 
0101     if (timeout)
0102     {
0103       timeout--;
0104       pc386_ide_sleep (sleeper);
0105     }
0106   }
0107   while (timeout);
0108 
0109   *status_val = status;
0110   return false;
0111 }
0112 
0113 static bool pc386_ide_status_data_ready (uint32_t          port,
0114                                          volatile uint32_t timeout,
0115                                          uint8_t*          status_val,
0116                                          pc386_ide_sleeper sleeper)
0117 {
0118   volatile uint8_t status;
0119   int              polls;
0120 
0121   do
0122   {
0123     polls = 1000;
0124     while (polls)
0125     {
0126       inport_byte (port + IDE_REGISTER_STATUS, status);
0127 
0128       if (((status & IDE_REGISTER_STATUS_BSY) == 0) &&
0129           (status & IDE_REGISTER_STATUS_DRQ))
0130       {
0131         *status_val = status;
0132         return true;
0133       }
0134 
0135       polls--;
0136     }
0137 
0138     if (timeout)
0139     {
0140       timeout--;
0141       pc386_ide_sleep (sleeper);
0142     }
0143   }
0144   while (timeout);
0145 
0146   *status_val = status;
0147   return false;
0148 }
0149 
0150 /*
0151  * support functions for IDE harddisk IF
0152  */
0153 /*=========================================================================*\
0154 | Function:                                                                 |
0155 \*-------------------------------------------------------------------------*/
0156 static bool pc386_ide_probe
0157 (
0158 /*-------------------------------------------------------------------------*\
0159 | Purpose:                                                                  |
0160 |  This function should probe, whether a IDE disk is available              |
0161 +---------------------------------------------------------------------------+
0162 | Input Parameters:                                                         |
0163 \*-------------------------------------------------------------------------*/
0164  int minor
0165  )
0166 /*-------------------------------------------------------------------------*\
0167 | Return Value:                                                             |
0168 |    true, when flash disk available                                        |
0169 \*=========================================================================*/
0170 {
0171   bool ide_card_plugged = true; /* assume: we have a disk here */
0172 
0173   return ide_card_plugged;
0174 }
0175 
0176 /*=========================================================================*\
0177 | Function:                                                                 |
0178 \*-------------------------------------------------------------------------*/
0179 static void pc386_ide_initialize
0180 (
0181 /*-------------------------------------------------------------------------*\
0182   | Purpose:                                                                  |
0183   |  initialize IDE access                                                    |
0184   +---------------------------------------------------------------------------+
0185   | Input Parameters:                                                         |
0186   \*-------------------------------------------------------------------------*/
0187   int  minor                              /* controller minor number       */
0188  )
0189 /*-------------------------------------------------------------------------*\
0190   | Return Value:                                                             |
0191   |    <none>                                                                 |
0192   \*=========================================================================*/
0193 {
0194   uint32_t port = IDE_Controller_Table[minor].port1;
0195   uint8_t  dev = 0;
0196 
0197   if (pc386_ide_show)
0198     printk("IDE%d: port base: %04" PRIu32 "\n", minor, port);
0199 
0200   outport_byte(port+IDE_REGISTER_DEVICE_HEAD,
0201                (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | 0xE0);
0202   wait(10000);
0203   outport_byte(port+IDE_REGISTER_DEVICE_CONTROL,
0204                IDE_REGISTER_DEVICE_CONTROL_SRST | IDE_REGISTER_DEVICE_CONTROL_nIEN);
0205   wait(10000);
0206   outport_byte(port+IDE_REGISTER_DEVICE_CONTROL,
0207                IDE_REGISTER_DEVICE_CONTROL_nIEN);
0208   wait(10000);
0209 
0210   for (dev = 0; dev < 2; dev++)
0211   {
0212     uint16_t    capabilities = 0;
0213     uint32_t    byte;
0214     uint8_t     status;
0215     uint8_t     error;
0216     uint8_t     cyllsb;
0217     uint8_t     cylmsb;
0218     const char* label = dev ? " slave" : "master";
0219     int         max_multiple_sectors = 0;
0220     int         cur_multiple_sectors = 0;
0221     uint32_t    cylinders = 0;
0222     uint32_t    heads = 0;
0223     uint32_t    sectors = 0;
0224     uint32_t    lba_sectors = 0;
0225     char        model_number[41];
0226     char*       p = &model_number[0];
0227     bool        data_ready;
0228 
0229     (void) cur_multiple_sectors; /* avoid set but not used warning */
0230 
0231     memset(model_number, 0, sizeof(model_number));
0232 
0233     outport_byte(port+IDE_REGISTER_DEVICE_HEAD,
0234                  (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | 0xE0);
0235     /*
0236       outport_byte(port+IDE_REGISTER_SECTOR_NUMBER,
0237       (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | IDE_REGISTER_LBA3_L);
0238     */
0239 
0240     outport_byte(port+IDE_REGISTER_COMMAND, 0x00);
0241 
0242     if (!pc386_ide_status_busy (port, PC386_IDE_PROBE_TIMEOUT,
0243                                 &status, pc386_ide_prestart_sleep))
0244       continue;
0245 
0246     inport_byte(port+IDE_REGISTER_STATUS,        status);
0247     inport_byte(port+IDE_REGISTER_ERROR,         error);
0248     inport_byte(port+IDE_REGISTER_CYLINDER_LOW,  cyllsb);
0249     inport_byte(port+IDE_REGISTER_CYLINDER_HIGH, cylmsb);
0250 
0251     if (pc386_ide_show)
0252     {
0253       printk("IDE%d:%s: status=%02x\n", minor, label, status);
0254       printk("IDE%d:%s: error=%02x\n", minor, label, error);
0255       printk("IDE%d:%s: cylinder-low=%02x\n", minor, label, cyllsb);
0256       printk("IDE%d:%s: cylinder-high=%02x\n", minor, label, cylmsb);
0257     }
0258 
0259     outport_byte(port+IDE_REGISTER_COMMAND, 0xec);
0260 
0261     if (!pc386_ide_status_busy (port, PC386_IDE_PRESTART_TIMEOUT,
0262                                 &status, pc386_ide_prestart_sleep))
0263     {
0264       if (pc386_ide_show)
0265         printk("IDE%d:%s: device busy: %02x\n", minor, label, status);
0266       continue;
0267     }
0268 
0269     data_ready = pc386_ide_status_data_ready (port,
0270                                               250,
0271                                               &status,
0272                                               pc386_ide_prestart_sleep);
0273 
0274     if (status & IDE_REGISTER_STATUS_ERR)
0275     {
0276       inport_byte(port+IDE_REGISTER_ERROR, error);
0277       if (error != 4)
0278       {
0279         if (pc386_ide_show)
0280           printk("IDE%d:%s: error=%04x\n", minor, label, error);
0281         continue;
0282       }
0283       /*
0284        * The device is an ATAPI device.
0285        */
0286       outport_byte(port+IDE_REGISTER_COMMAND, 0xa1);
0287       data_ready = pc386_ide_status_data_ready (port,
0288                                                 250,
0289                                                 &status,
0290                                                 pc386_ide_prestart_sleep);
0291     }
0292 
0293     if (!data_ready)
0294       continue;
0295 
0296     byte = 0;
0297     while (byte < 512)
0298     {
0299       uint16_t word;
0300 
0301       if (pc386_ide_show && ((byte % 16) == 0))
0302         printk("\n %04" PRIx32 " : ", byte);
0303 
0304       inport_word(port+IDE_REGISTER_DATA, word);
0305 
0306       if (pc386_ide_show)
0307         printk ("%04x ", word);
0308 
0309       if (byte == 2)
0310         cylinders = word;
0311       if (byte == 6)
0312         heads = word;
0313       if (byte == 12)
0314         sectors = word;
0315 
0316       if (byte >= 54 && byte < (54 + 40))
0317       {
0318         *p = word >> 8;
0319         p++;
0320         *p = word;
0321         p++;
0322       }
0323 
0324       if (byte == (47 * 2))
0325         max_multiple_sectors = word & 0xff;
0326 
0327       if (byte == (49 * 2))
0328         capabilities = word;
0329 
0330       if (byte == (59 * 2))
0331       {
0332         if (word & (1 << 8))
0333           cur_multiple_sectors = word & 0xff;
0334       }
0335 
0336       if (byte == (60 * 2))
0337         lba_sectors = word;
0338       if (byte == (61 * 2))
0339         lba_sectors |= word << 16;
0340 
0341       byte += 2;
0342     }
0343 
0344     if (pc386_ide_show)
0345       printk("\nbytes read = %" PRIu32 "\n", byte);
0346 
0347     if (p != &model_number[0])
0348     {
0349       uint32_t size;
0350       uint32_t left;
0351       uint32_t right;
0352       char     units;
0353 
0354       if (capabilities & (1 << 9))
0355         size = lba_sectors;
0356       else
0357         size = cylinders * heads * sectors;
0358 
0359       size /= 2;
0360 
0361       if (size > (1024 * 1024))
0362       {
0363         size = (size * 10) / (1000 * 1000);
0364         units = 'G';
0365       }
0366       else if (size > 1024)
0367       {
0368         size = (size * 10) / 1000;
0369         units = 'M';
0370       }
0371       else
0372       {
0373         size = size * 10;
0374         units = 'K';
0375       }
0376 
0377       left = size / 10;
0378       right = size % 10;
0379 
0380       p--;
0381       while (*p == ' ')
0382       {
0383         *p = '\0';
0384         p--;
0385       }
0386 
0387       printk("IDE%d:%s:%s, %" PRIu32 ".%" PRIu32 "%c (%" PRIu32 "/%" PRIu32 "/%" PRIu32 "), max blk size:%d\n",
0388              minor, label, model_number, left, right, units,
0389              heads, cylinders, sectors, max_multiple_sectors * 512);
0390     }
0391 
0392 #if IDE_CLEAR_MULTI_SECTOR_COUNT
0393     if (max_multiple_sectors)
0394     {
0395       outport_byte(port+IDE_REGISTER_SECTOR_COUNT, 0);
0396       outport_byte(port+IDE_REGISTER_COMMAND, 0xc6);
0397 
0398       if (!pc386_ide_status_busy (port, PC386_IDE_PRESTART_TIMEOUT,
0399                                   &status, pc386_ide_prestart_sleep))
0400       {
0401         if (pc386_ide_show)
0402           printk("IDE%d:%s: device busy: %02x\n", minor, label, status);
0403         continue;
0404       }
0405 
0406       inport_byte(port+IDE_REGISTER_STATUS, status);
0407       if (status & IDE_REGISTER_STATUS_ERR)
0408       {
0409         inport_byte(port+IDE_REGISTER_ERROR, error);
0410         if (error & IDE_REGISTER_ERROR_ABRT)
0411           printk("IDE%d:%s: disable multiple failed\n", minor, label);
0412         else
0413           printk("IDE%d:%s: unknown error on disable multiple: %02x\n",
0414                  minor, label, error);
0415       }
0416     }
0417 #endif
0418 
0419     outport_byte(port+IDE_REGISTER_DEVICE_CONTROL,
0420                  IDE_REGISTER_DEVICE_CONTROL_nIEN);
0421     wait(10000);
0422   }
0423 
0424   pc386_ide_timeout = PC386_IDE_TASKING_TIMEOUT;
0425 
0426   /*
0427    * FIXME: enable interrupts, if needed
0428    */
0429 }
0430 
0431 /*=========================================================================*\
0432 | Function:                                                                 |
0433 \*-------------------------------------------------------------------------*/
0434 static void pc386_ide_read_reg
0435 (
0436 /*-------------------------------------------------------------------------*\
0437 | Purpose:                                                                  |
0438 |  read a IDE controller register                                           |
0439 +---------------------------------------------------------------------------+
0440 | Input Parameters:                                                         |
0441 \*-------------------------------------------------------------------------*/
0442  int                        minor,  /* controller minor number       */
0443  int                        reg,    /* register index to access      */
0444  uint16_t                  *value   /* ptr to return value location  */
0445  )
0446 /*-------------------------------------------------------------------------*\
0447 | Return Value:                                                             |
0448 |    <none>                                                                 |
0449 \*=========================================================================*/
0450 {
0451   uint32_t    port = IDE_Controller_Table[minor].port1;
0452   uint8_t   bval1,bval2;
0453 
0454   if (reg == IDE_REGISTER_DATA_WORD) {
0455     inport_byte(port+reg, bval1);
0456     inport_byte(port+reg+1, bval2);
0457     *value = bval1 + (bval2 << 8);
0458   }
0459   else {
0460     inport_byte(port+reg, bval1);
0461     *value = bval1;
0462   }
0463 #if PC386_IDE_DEBUG_OUT
0464   pc386_ide_printk("pc386_ide_read_reg (0x%x)=0x%x\r\n",reg,*value & 0xff);
0465 #endif
0466 }
0467 
0468 /*=========================================================================*\
0469 | Function:                                                                 |
0470 \*-------------------------------------------------------------------------*/
0471 static void pc386_ide_write_reg
0472 (
0473 /*-------------------------------------------------------------------------*\
0474 | Purpose:                                                                  |
0475 |  write a IDE controller register                                          |
0476 +---------------------------------------------------------------------------+
0477 | Input Parameters:                                                         |
0478 \*-------------------------------------------------------------------------*/
0479  int                        minor,  /* controller minor number       */
0480  int                        reg,    /* register index to access      */
0481  uint16_t                   value   /* value to write                */
0482  )
0483 /*-------------------------------------------------------------------------*\
0484 | Return Value:                                                             |
0485 |    <none>                                                                 |
0486 \*=========================================================================*/
0487 {
0488   uint32_t    port = IDE_Controller_Table[minor].port1;
0489 
0490 #if PC386_IDE_DEBUG_OUT
0491   pc386_ide_printk("pc386_ide_write_reg(0x%x,0x%x)\r\n",reg,value & 0xff);
0492 #endif
0493   if (reg == IDE_REGISTER_DATA_WORD) {
0494     outport_word(port+reg,value);
0495   }
0496   else {
0497     outport_byte(port+reg,value);
0498   }
0499 }
0500 
0501 /*=========================================================================*\
0502 | Function:                                                                 |
0503 \*-------------------------------------------------------------------------*/
0504 static void pc386_ide_read_block
0505 (
0506 /*-------------------------------------------------------------------------*\
0507 | Purpose:                                                                  |
0508 |  read a IDE controller data block                                         |
0509 +---------------------------------------------------------------------------+
0510 | Input Parameters:                                                         |
0511 \*-------------------------------------------------------------------------*/
0512  int                     minor,
0513  uint32_t                block_size,
0514  rtems_blkdev_sg_buffer *bufs,
0515  uint32_t               *cbuf,
0516  uint32_t               *pos
0517  )
0518 /*-------------------------------------------------------------------------*\
0519 | Return Value:                                                             |
0520 |    <none>                                                                 |
0521 \*=========================================================================*/
0522 {
0523   uint32_t port = IDE_Controller_Table[minor].port1;
0524   uint32_t cnt = 0;
0525 #if PC386_IDE_DEBUG_OUT
0526   int i32 = 0;
0527   pc386_ide_printk("pc386_ide_read_block(bs=%u,bn=%u,bl=%u,cb=%d,p=%d)\n",
0528                    block_size, bufs[(*cbuf)].block, llength, *cbuf, *pos);
0529 #endif
0530 
0531   while (cnt < block_size)
0532   {
0533     uint16_t *lbuf;
0534     uint8_t  status_val;
0535     int      b;
0536 
0537     if (!pc386_ide_status_data_ready (port, pc386_ide_timeout,
0538                                       &status_val, pc386_ide_tasking_sleep))
0539     {
0540       printk ("pc386_ide_read_block: block=%" PRIu32 \
0541               " cbuf=%" PRIu32 " status=%02x, cnt=%" PRIu32 " bs=%" PRIu32 "\n",
0542               bufs[*cbuf].block, *cbuf, status_val, cnt, block_size);
0543       /* FIXME: add an error here. */
0544       return;
0545     }
0546 
0547     if (status_val & IDE_REGISTER_STATUS_ERR)
0548     {
0549       inport_byte(port+IDE_REGISTER_ERROR, status_val);
0550       printk("pc386_ide_read_block: error: %02x\n", status_val);
0551       return;
0552     }
0553 
0554     lbuf = (uint16_t*)((uint8_t*)(bufs[(*cbuf)].buffer) + (*pos));
0555 
0556     for (b = 0; b < (ATA_SECTOR_SIZE / 2); b++)
0557     {
0558       inport_word(port+IDE_REGISTER_DATA,*lbuf);
0559 
0560 #if PC386_IDE_DEBUG_OUT
0561       pc386_ide_printk("%04x ",*lbuf);
0562       i32++;
0563       if (i32 >= 16)
0564       {
0565         pc386_ide_printk("\n");
0566         i32 = 0;
0567       }
0568 #endif
0569       lbuf++;
0570     }
0571     cnt    += ATA_SECTOR_SIZE;
0572     (*pos) += ATA_SECTOR_SIZE;
0573     if ((*pos) == bufs[(*cbuf)].length) {
0574       (*pos) = 0;
0575       (*cbuf)++;
0576       lbuf = bufs[(*cbuf)].buffer;
0577     }
0578   }
0579 }
0580 
0581 /*=========================================================================*\
0582 | Function:                                                                 |
0583 \*-------------------------------------------------------------------------*/
0584 static void pc386_ide_write_block
0585 (
0586 /*-------------------------------------------------------------------------*\
0587 | Purpose:                                                                  |
0588 |  write a IDE controller data block                                        |
0589 +---------------------------------------------------------------------------+
0590 | Input Parameters:                                                         |
0591 \*-------------------------------------------------------------------------*/
0592  int minor,
0593  uint32_t                block_size,
0594  rtems_blkdev_sg_buffer *bufs,
0595  uint32_t               *cbuf,
0596  uint32_t               *pos
0597  )
0598 /*-------------------------------------------------------------------------*\
0599 | Return Value:                                                             |
0600 |    <none>                                                                 |
0601 \*=========================================================================*/
0602 {
0603   uint32_t port = IDE_Controller_Table[minor].port1;
0604   uint32_t cnt = 0;
0605 #if PC386_IDE_DEBUG_OUT
0606   int i32 = 0;
0607   pc386_ide_printk("pc386_ide_write_block(bs=%u,bn=%u,bl=%u,cb=%d,p=%d)\n",
0608                    block_size, bufs[(*cbuf)].block, llength, *cbuf, *pos);
0609 #endif
0610 
0611   while (cnt < block_size)
0612   {
0613     uint16_t *lbuf;
0614     uint8_t  status_val;
0615     int      b;
0616 
0617     if (!pc386_ide_status_data_ready (port, pc386_ide_timeout,
0618                                       &status_val, pc386_ide_tasking_sleep))
0619     {
0620       printk ("pc386_ide_write_block: block=%" PRIu32 " status=%02x, cnt=%" PRIu32 " bs=%" PRIu32 "\n",
0621               bufs[*cbuf].block, status_val, cnt, block_size);
0622       /* FIXME: add an error here. */
0623       return;
0624     }
0625 
0626     if (status_val & IDE_REGISTER_STATUS_ERR)
0627     {
0628       inport_byte(port+IDE_REGISTER_ERROR, status_val);
0629       printk ("pc386_ide_write_block: error: %02x\n", status_val);
0630       return;
0631     }
0632 
0633     lbuf = (uint16_t*)(((uint8_t*)bufs[*cbuf].buffer) + (*pos));
0634 
0635     for (b = 0; b < (ATA_SECTOR_SIZE / 2); b++)
0636     {
0637 #if PC386_IDE_DEBUG_OUT
0638       pc386_ide_printk("%04x ",*lbuf);
0639       i32++;
0640       if (i32 >= 16)
0641       {
0642         pc386_ide_printk("\n");
0643         i32 = 0;
0644       }
0645 #endif
0646       outport_word(port+IDE_REGISTER_DATA,*lbuf);
0647       lbuf++;
0648     }
0649     cnt    += ATA_SECTOR_SIZE;
0650     (*pos) += ATA_SECTOR_SIZE;
0651     if ((*pos) == bufs[(*cbuf)].length) {
0652       (*pos) = 0;
0653       (*cbuf)++;
0654       lbuf = bufs[(*cbuf)].buffer;
0655     }
0656   }
0657 }
0658 
0659 /*=========================================================================*\
0660 | Function:                                                                 |
0661 \*-------------------------------------------------------------------------*/
0662 static int pc386_ide_control
0663 (
0664 /*-------------------------------------------------------------------------*\
0665 | Purpose:                                                                  |
0666 |  control interface for controller                                         |
0667 +---------------------------------------------------------------------------+
0668 | Input Parameters:                                                         |
0669 \*-------------------------------------------------------------------------*/
0670  int  minor,                        /* controller minor number       */
0671  uint32_t   cmd,                    /* command to send               */
0672  void * arg                         /* optional argument             */
0673  )
0674 /*-------------------------------------------------------------------------*\
0675 | Return Value:                                                             |
0676 |    <none>                                                                 |
0677 \*=========================================================================*/
0678 {
0679   return 0;
0680 }
0681 
0682 /*=========================================================================*\
0683 | Function:                                                                 |
0684 \*-------------------------------------------------------------------------*/
0685 static rtems_status_code pc386_ide_config_io_speed
0686 (
0687 /*-------------------------------------------------------------------------*\
0688 | Purpose:                                                                  |
0689 |  set up transfer speed, if possible                                       |
0690 +---------------------------------------------------------------------------+
0691 | Input Parameters:                                                         |
0692 \*-------------------------------------------------------------------------*/
0693  int        minor,                   /* controller minor number       */
0694  uint16_t   modes_avail              /* optional argument             */
0695  )
0696 /*-------------------------------------------------------------------------*\
0697 | Return Value:                                                             |
0698 |    rtems_status_code                                                      |
0699 \*=========================================================================*/
0700 {
0701   return RTEMS_SUCCESSFUL;
0702 }
0703 
0704 /*
0705  * The following table configures the functions used for IDE drivers
0706  * in this BSP.
0707  */
0708 
0709 ide_ctrl_fns_t pc386_ide_ctrl_fns = {
0710   pc386_ide_probe,
0711   pc386_ide_initialize,
0712   pc386_ide_control,
0713   pc386_ide_read_reg,
0714   pc386_ide_write_reg,
0715   pc386_ide_read_block,
0716   pc386_ide_write_block,
0717   pc386_ide_config_io_speed
0718 };