Changeset c1fc5d4 in rtems


Ignore:
Timestamp:
Oct 8, 2009, 7:15:08 AM (10 years ago)
Author:
Chris Johns <chrisj@…>
Branches:
4.10, 4.11, master
Children:
7357f566
Parents:
eb649786
Message:

2009-10-08 Chris Johns <chrisj@…>

  • ide/ide.c: Fixed more IDE driver bugs. The driver can transfer 64K in a single write on my test PC and qemu with this driver. The driver only checks the data ready bit at the start of each 512 block being transfered. This has speed the transfer loop up. Fixed the timing so the BSP timer is used until RTEMS has started.
Location:
c/src/lib/libbsp/i386/pc386
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/i386/pc386/ChangeLog

    reb649786 rc1fc5d4  
     12009-10-08      Chris Johns <chrisj@rtems.org>
     2
     3        * ide/ide.c: Fixed more IDE driver bugs. The driver can transfer
     4        64K in a single write on my test PC and qemu with this driver. The
     5        driver only checks the data ready bit at the start of each 512
     6        block being transfered. This has speed the transfer loop up. Fixed
     7        the timing so the BSP timer is used until RTEMS has started.
     8
    192009-09-30      Ralf Corsépius <ralf.corsepius@rtems.org>
    210
  • c/src/lib/libbsp/i386/pc386/ide/ide.c

    reb649786 rc1fc5d4  
    3030#include <libchip/ide_ctrl_io.h>
    3131
     32#define ATA_SECTOR_SIZE (512)
     33
     34/*
     35 * Use during initialisation.
     36 */
     37extern void Wait_X_ms(unsigned int msecs);
     38
    3239bool pc386_ide_show;
    33 
    34 /* #define DEBUG_OUT */
    35 
    36 static bool pc386_ide_status_busy (uint32_t port,
    37                                    uint32_t timeout,
    38                                    uint8_t* status_val)
    39 {
     40uint32_t pc386_ide_timeout;
     41
     42#define PC386_IDE_DEBUG_OUT 0
     43
     44#if PC386_IDE_DEBUG_OUT
     45bool pc386_ide_trace;
     46#define pc386_ide_printk if (pc386_ide_trace) printk
     47#endif
     48
     49#define PC386_IDE_PROBE_TIMEOUT    (500)
     50#define PC386_IDE_PRESTART_TIMEOUT (1000)
     51#define PC386_IDE_TASKING_TIMEOUT  (2000)
     52
     53/*
     54 * Prestart sleep using a calibrated timing loop.
     55 */
     56static void pc386_ide_prestart_sleep (void)
     57{
     58  Wait_X_ms (10);
     59}
     60
     61/*
     62 * Once tasking has started we use a task sleep.
     63 */
     64static void pc386_ide_tasking_sleep (void)
     65{
     66  rtems_task_wake_after (TOD_MICROSECONDS_TO_TICKS (10000) ?
     67                         TOD_MICROSECONDS_TO_TICKS (10000) : 1);
     68}
     69
     70typedef void (*pc386_ide_sleeper)(void);
     71
     72static void pc386_ide_sleep (pc386_ide_sleeper sleeper)
     73{
     74  sleeper ();
     75}
     76
     77static void wait(volatile uint32_t loops)
     78{
     79  while (loops)
     80    loops--;
     81}
     82
     83static bool pc386_ide_status_busy (uint32_t          port,
     84                                   volatile uint32_t timeout,
     85                                   uint8_t*          status_val,
     86                                   pc386_ide_sleeper sleeper)
     87{
     88  volatile uint8_t status;
     89  int              polls;
     90 
    4091  do
    4192  {
    42     inport_byte (port + IDE_REGISTER_STATUS, *status_val);
    43     if ((*status_val & IDE_REGISTER_STATUS_BSY) == 0)
    44       return true;
     93    polls = 500;
     94    while (polls)
     95    {
     96      inport_byte (port + IDE_REGISTER_STATUS, status);
     97      if ((status & IDE_REGISTER_STATUS_BSY) == 0)
     98      {
     99        *status_val = status;
     100        return true;
     101      }
     102      polls--;
     103    }
    45104
    46105    if (timeout)
    47106    {
    48107      timeout--;
    49       rtems_task_wake_after (TOD_MICROSECONDS_TO_TICKS (1000));
     108      pc386_ide_sleep (sleeper);
    50109    }
    51110  }
    52111  while (timeout);
    53112
     113  *status_val = status;
    54114  return false;
    55115}
    56116
    57 static bool pc386_ide_status_data_ready (uint32_t port,
    58                                          uint32_t timeout,
    59                                          uint8_t* status_val)
    60 {
     117static bool pc386_ide_status_data_ready (uint32_t          port,
     118                                         volatile uint32_t timeout,
     119                                         uint8_t*          status_val,
     120                                         pc386_ide_sleeper sleeper)
     121{
     122  volatile uint8_t status;
     123  int              polls;
     124 
    61125  do
    62126  {
    63     inport_byte (port + IDE_REGISTER_STATUS, *status_val);
    64    
    65     if (((*status_val & IDE_REGISTER_STATUS_BSY) == 0) &&
    66         (*status_val & IDE_REGISTER_STATUS_DRQ))
    67       return true;
     127    polls = 1000;
     128    while (polls)
     129    {
     130      inport_byte (port + IDE_REGISTER_STATUS, status);
     131   
     132      if (((status & IDE_REGISTER_STATUS_BSY) == 0) &&
     133          (status & IDE_REGISTER_STATUS_DRQ))
     134      {
     135        *status_val = status;
     136        return true;
     137      }
     138
     139      polls--;
     140    }
    68141
    69142    if (timeout)
    70143    {
    71144      timeout--;
    72       rtems_task_wake_after (TOD_MICROSECONDS_TO_TICKS (1000));
     145      pc386_ide_sleep (sleeper);
    73146    }
    74147  }
    75148  while (timeout);
    76149
     150  *status_val = status;
    77151  return false;
    78152}
     
    102176
    103177  return ide_card_plugged;
    104 }
    105 
    106 static void wait(volatile uint32_t loops)
    107 {
    108   while (loops)
    109     loops--;
    110178}
    111179
     
    152220    uint8_t     cylmsb;
    153221    const char* label = dev ? " slave" : "master";
     222    int         max_multiple_sectors = 0;
     223    int         cur_multiple_sectors = 0;
     224    uint32_t    cylinders = 0;
     225    uint32_t    heads = 0;
     226    uint32_t    sectors = 0;
    154227    char        model_number[41];
    155228    char*       p = &model_number[0];
    156 
     229   
    157230    memset(model_number, 0, sizeof(model_number));
    158231
     
    166239    outport_byte(port+IDE_REGISTER_COMMAND, 0x00);
    167240   
    168     if (!pc386_ide_status_busy (port, 6000, &status))
     241    if (!pc386_ide_status_busy (port, PC386_IDE_PROBE_TIMEOUT,
     242                                &status, pc386_ide_prestart_sleep))
    169243      continue;
    170244   
     
    182256    }
    183257
    184 #if 0
    185     /*
    186      * Filter based on the cylinder values and the status.
    187      * Taken from grub's ata.c.
    188      */
    189     if (cyllsb != 0x14 || cylmsb != 0xeb)
    190       if (status == 0 || (cyllsb != 0 && cylmsb != 0 &&
    191                           cyllsb != 0xc3 && cylmsb != 0x3c))
    192       {
    193         if (pc386_ide_show)
    194           printk("IDE%d:%s: bad device\n", minor, label);
    195       }
    196 #endif
    197    
    198258    outport_byte(port+IDE_REGISTER_COMMAND, 0xec);
    199259
    200     if (!pc386_ide_status_busy (port, 6000, &status))
     260    if (!pc386_ide_status_busy (port, PC386_IDE_PRESTART_TIMEOUT,
     261                                &status, pc386_ide_prestart_sleep))
    201262    {
    202263      if (pc386_ide_show)
     
    204265      continue;
    205266    }
    206    
     267
    207268    byte = 0;
    208269    while (byte < 512)
     
    211272      bool     data_ready;
    212273
    213       if (pc386_ide_show && ((byte % 16) == 0))
    214         printk("\n %04x : ", byte);
    215      
    216       data_ready = pc386_ide_status_data_ready (port, 100, &status);
     274      data_ready = pc386_ide_status_data_ready (port,
     275                                                250,
     276                                                &status,
     277                                                pc386_ide_prestart_sleep);
    217278
    218279      if (status & IDE_REGISTER_STATUS_ERR)
     
    235296        break;
    236297     
     298      if (pc386_ide_show && ((byte % 16) == 0))
     299        printk("\n %04x : ", byte);
     300     
    237301      inport_word(port+IDE_REGISTER_DATA, word);
    238302
     
    240304        printk ("%04x ", word);
    241305
     306      if (byte == 2)
     307        cylinders = word;
     308      if (byte == 6)
     309        heads = word;
     310      if (byte == 12)
     311        sectors = word;
     312     
    242313      if (byte >= 54 && byte < (54 + 40))
    243314      {
     
    247318        p++;
    248319      }
    249        
     320
     321      if (byte == 94)
     322        max_multiple_sectors = word & 0xff;
     323     
     324      if (byte == (47 * 2))
     325        max_multiple_sectors = word & 0xff;
     326     
     327      if (byte == (59 * 2))
     328      {
     329        if (word & (1 << 8))
     330          cur_multiple_sectors = word & 0xff;
     331      }
     332     
    250333      byte += 2;
    251334    }
     
    255338
    256339    if (p != &model_number[0])
    257       printk("IDE%d:%s: %s\n", minor, label, model_number);
    258   }
     340    {
     341      uint32_t size;
     342      uint32_t left;
     343      uint32_t right;
     344      char     units;
     345     
     346      size = ((((uint64_t) cylinders) * heads) * sectors * 512) / 1024;
     347
     348      if (size > (1024 * 1024))
     349      {
     350        size = (size * 10) / (1000 * 1000);
     351        units = 'G';
     352      }
     353      else if (size > 1024)
     354      {
     355        size = (size * 10) / 1000;
     356        units = 'M';
     357      }
     358      else
     359      {
     360        size = size * 10;
     361        units = 'K';
     362      }
     363
     364      left = size / 10;
     365      right = size % 10;
     366     
     367      p--;
     368      while (*p == ' ')
     369      {
     370        *p = '\0';
     371        p--;
     372      }
     373
     374      printk("IDE%d:%s:%s, %u.%u%c (%u/%u/%u), max blk size:%d\n",
     375             minor, label, model_number, left, right, units,
     376             heads, cylinders, sectors, max_multiple_sectors * 512);
     377    }
     378
     379#if IDE_CLEAR_MULTI_SECTOR_COUNT
     380    if (max_multiple_sectors)
     381    {
     382      outport_byte(port+IDE_REGISTER_SECTOR_COUNT, 0);
     383      outport_byte(port+IDE_REGISTER_COMMAND, 0xc6);
     384
     385      if (!pc386_ide_status_busy (port, PC386_IDE_PRESTART_TIMEOUT,
     386                                  &status, pc386_ide_prestart_sleep))
     387      {
     388        if (pc386_ide_show)
     389          printk("IDE%d:%s: device busy: %02x\n", minor, label, status);
     390        continue;
     391      }
     392
     393      inport_byte(port+IDE_REGISTER_STATUS, status);
     394      if (status & IDE_REGISTER_STATUS_ERR)
     395      {
     396        inport_byte(port+IDE_REGISTER_ERROR, error);
     397        if (error & IDE_REGISTER_ERROR_ABRT)
     398          printk("IDE%d:%s: disable multiple failed\n", minor, label);
     399        else
     400          printk("IDE%d:%s: unknown error on disable multiple: %02x\n",
     401                 minor, label, error);
     402      }
     403    }
     404#endif
     405   
     406    outport_byte(port+IDE_REGISTER_DEVICE_CONTROL,
     407                 IDE_REGISTER_DEVICE_CONTROL_nIEN);
     408    wait(10000);
     409  }
     410
     411  pc386_ide_timeout = PC386_IDE_TASKING_TIMEOUT;
    259412 
    260413  /*
     
    295448    *value = bval1;
    296449  }
    297 #ifdef DEBUG_OUT
    298   printk("pc386_ide_read_reg (0x%x)=0x%x\r\n",reg,*value & 0xff);
     450#if PC386_IDE_DEBUG_OUT
     451  pc386_ide_printk("pc386_ide_read_reg (0x%x)=0x%x\r\n",reg,*value & 0xff);
    299452#endif
    300453}
     
    322475  uint32_t    port = IDE_Controller_Table[minor].port1;
    323476
    324 #ifdef DEBUG_OUT
    325   printk("pc386_ide_write_reg(0x%x,0x%x)\r\n",reg,value & 0xff);
     477#if PC386_IDE_DEBUG_OUT
     478  pc386_ide_printk("pc386_ide_write_reg(0x%x,0x%x)\r\n",reg,value & 0xff);
    326479#endif
    327480  if (reg == IDE_REGISTER_DATA_WORD) {
     
    344497| Input Parameters:                                                         |
    345498\*-------------------------------------------------------------------------*/
    346  int minor,
    347  uint16_t                block_size,
     499 int                     minor,
     500 uint32_t                block_size,
    348501 rtems_blkdev_sg_buffer *bufs,
    349502 uint32_t               *cbuf,
     
    355508\*=========================================================================*/
    356509{
    357   uint32_t    port = IDE_Controller_Table[minor].port1;
    358   uint16_t    cnt = 0;
    359   uint32_t    llength = bufs[(*cbuf)].length;
    360   uint8_t     status_val;
    361   uint16_t   *lbuf = (uint16_t*)
    362     ((uint8_t*)(bufs[(*cbuf)].buffer) + (*pos));
    363 #ifdef DEBUG_OUT
     510  uint32_t port = IDE_Controller_Table[minor].port1;
     511  uint32_t cnt = 0;
     512#if PC386_IDE_DEBUG_OUT
    364513  int i32 = 0;
     514  pc386_ide_printk("pc386_ide_read_block(bs=%u,bn=%u,bl=%u,cb=%d,p=%d)\n",
     515                   block_size, bufs[(*cbuf)].block, llength, *cbuf, *pos);
    365516#endif
     517
    366518  while (cnt < block_size)
    367519  {
    368     if (!pc386_ide_status_data_ready (port, 100, &status_val))
    369     {
    370       printk ("pc386_ide_read_block: status=%02x, cnt=%d bs=%d\n", status_val, cnt, block_size);
     520    uint16_t *lbuf;
     521    uint8_t  status_val;
     522    int      b;
     523   
     524    if (!pc386_ide_status_data_ready (port, pc386_ide_timeout,
     525                                      &status_val, pc386_ide_tasking_sleep))
     526    {
     527      printk ("pc386_ide_read_block: block=%u cbuf=%u status=%02x, cnt=%d bs=%d\n",
     528              bufs[*cbuf].block, *cbuf, status_val, cnt, block_size);
    371529      /* FIXME: add an error here. */
    372530      return;
     
    374532   
    375533    if (status_val & IDE_REGISTER_STATUS_ERR)
     534    {
     535      inport_byte(port+IDE_REGISTER_ERROR, status_val);
    376536      printk("pc386_ide_read_block: error: %02x\n", status_val);
    377    
    378     inport_word(port+IDE_REGISTER_DATA,*lbuf);
    379 
    380 #ifdef DEBUG_OUT
    381     printk("%04x ",*lbuf);
    382     i32++;
    383     if (i32 >= 16)
    384     {
    385       printk("\n");
    386       i32 = 0;
    387     }
     537      return;
     538    }
     539
     540    lbuf = (uint16_t*)((uint8_t*)(bufs[(*cbuf)].buffer) + (*pos));
     541 
     542    for (b = 0; b < (ATA_SECTOR_SIZE / 2); b++)
     543    {
     544      inport_word(port+IDE_REGISTER_DATA,*lbuf);
     545
     546#if PC386_IDE_DEBUG_OUT
     547      pc386_ide_printk("%04x ",*lbuf);
     548      i32++;
     549      if (i32 >= 16)
     550      {
     551        pc386_ide_printk("\n");
     552        i32 = 0;
     553      }
    388554#endif
    389    
    390     lbuf++;
    391     cnt    += sizeof(*lbuf);
    392     (*pos) += sizeof(*lbuf);
    393     if ((*pos) == llength) {
     555      lbuf++;
     556    }
     557    cnt    += ATA_SECTOR_SIZE;
     558    (*pos) += ATA_SECTOR_SIZE;
     559    if ((*pos) == bufs[(*cbuf)].length) {
    394560      (*pos) = 0;
    395561      (*cbuf)++;
    396562      lbuf = bufs[(*cbuf)].buffer;
    397       llength = bufs[(*cbuf)].length;
    398563    }
    399564  }
     
    412577\*-------------------------------------------------------------------------*/
    413578 int minor,
    414  uint16_t                block_size,
     579 uint32_t                block_size,
    415580 rtems_blkdev_sg_buffer *bufs,
    416581 uint32_t               *cbuf,
     
    422587\*=========================================================================*/
    423588{
    424   uint32_t    port = IDE_Controller_Table[minor].port1;
    425   uint16_t    cnt = 0;
    426   uint32_t    llength = bufs[(*cbuf)].length;
    427   uint8_t     status_val;
    428   uint16_t   *lbuf = (uint16_t*)
    429     ((uint8_t*)(bufs[(*cbuf)].buffer) + (*pos));
    430  
    431 #ifdef DEBUG_OUT
    432   printk("pc386_ide_write_block()\n");
     589  uint32_t port = IDE_Controller_Table[minor].port1;
     590  uint32_t cnt = 0;
     591#if PC386_IDE_DEBUG_OUT
     592  int i32 = 0;
     593  pc386_ide_printk("pc386_ide_write_block(bs=%u,bn=%u,bl=%u,cb=%d,p=%d)\n",
     594                   block_size, bufs[(*cbuf)].block, llength, *cbuf, *pos);
    433595#endif
    434596
    435597  while (cnt < block_size)
    436598  {
    437     if (!pc386_ide_status_data_ready (port, 100, &status_val))
    438     {
    439       printk ("pc386_ide_write_block: status=%02x, cnt=%d bs=%d\n", status_val, cnt, block_size);
     599    uint16_t *lbuf;
     600    uint8_t  status_val;
     601    int      b;
     602   
     603    if (!pc386_ide_status_data_ready (port, pc386_ide_timeout,
     604                                      &status_val, pc386_ide_tasking_sleep))
     605    {
     606      printk ("pc386_ide_write_block: block=%u status=%02x, cnt=%d bs=%d\n",
     607              bufs[*cbuf].block, status_val, cnt, block_size);
    440608      /* FIXME: add an error here. */
    441609      return;
     
    443611   
    444612    if (status_val & IDE_REGISTER_STATUS_ERR)
    445       printk("pc386_ide_write_block: error: %02x\n", status_val);
    446    
    447 #ifdef DEBUG_OUT
    448     printk("0x%x ",*lbuf);
     613    {
     614      inport_byte(port+IDE_REGISTER_ERROR, status_val);
     615      printk ("pc386_ide_write_block: error: %02x\n", status_val);
     616      return;
     617    }
     618   
     619    lbuf = (uint16_t*)(((uint8_t*)bufs[*cbuf].buffer) + (*pos));
     620 
     621    for (b = 0; b < (ATA_SECTOR_SIZE / 2); b++)
     622    {
     623#if PC386_IDE_DEBUG_OUT
     624      pc386_ide_printk("%04x ",*lbuf);
     625      i32++;
     626      if (i32 >= 16)
     627      {
     628        pc386_ide_printk("\n");
     629        i32 = 0;
     630      }
    449631#endif
    450     outport_word(port+IDE_REGISTER_DATA,*lbuf);
    451     lbuf++;
    452     cnt    += sizeof(*lbuf);
    453     (*pos) += sizeof(*lbuf);
    454     if ((*pos) == llength) {
     632      outport_word(port+IDE_REGISTER_DATA,*lbuf);
     633      lbuf++;
     634    }
     635    cnt    += ATA_SECTOR_SIZE;
     636    (*pos) += ATA_SECTOR_SIZE;
     637    if ((*pos) == bufs[(*cbuf)].length) {
    455638      (*pos) = 0;
    456639      (*cbuf)++;
    457640      lbuf = bufs[(*cbuf)].buffer;
    458       llength = bufs[(*cbuf)].length;
    459641    }
    460642  }
Note: See TracChangeset for help on using the changeset viewer.