source: rtems/c/src/lib/libbsp/i386/pc386/ide/ide.c @ 57be444

4.104.11
Last change on this file since 57be444 was 57be444, checked in by Chris Johns <chrisj@…>, on May 30, 2009 at 4:49:26 AM

2009-05-30 Chris Johns <chrisj@…>

  • ide/ide.c: Add initialisation code to reset the IDE devices and to probe them and display their model numbers. Also add code to display the probing to aid bring up new hardware.
  • ide/idecfg.c: Add the --ide-show command to show probing type accessing when finding devices on the configured IDE buses.
  • Property mode set to 100644
File size: 18.7 KB
Line 
1/*===============================================================*\
2| Project: RTEMS PC386 IDE harddisc driver                        |
3+-----------------------------------------------------------------+
4| File: ide.c                                                     |
5+-----------------------------------------------------------------+
6|                    Copyright (c) 2003 IMD                       |
7|      Ingenieurbuero fuer Microcomputertechnik Th. Doerfler      |
8|               <Thomas.Doerfler@imd-systems.de>                  |
9|                       all rights reserved                       |
10+-----------------------------------------------------------------+
11| this file contains the BSP layer for IDE access below the       |
12| libchip IDE harddisc driver                                     |
13| based on a board specific driver from                           |
14| Eugeny S. Mints, Oktet                                          |
15|                                                                 |
16|  The license and distribution terms for this file may be        |
17|  found in the file LICENSE in this distribution or at           |
18|  http://www.rtems.com/license/LICENSE.                     |
19|                                                                 |
20+-----------------------------------------------------------------+
21|   date                      history                        ID   |
22| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
23| 01.14.03  creation                                         doe  |
24\*===============================================================*/
25
26#include <rtems.h>
27#include <bsp.h>
28#include <libchip/ide_ctrl.h>
29#include <libchip/ide_ctrl_cfg.h>
30#include <libchip/ide_ctrl_io.h>
31
32bool pc386_ide_show;
33
34/* #define DEBUG_OUT */
35
36static bool pc386_ide_status_busy (uint32_t port,
37                                   uint32_t timeout,
38                                   uint8_t* status_val)
39{
40  do
41  {
42    inport_byte (port + IDE_REGISTER_STATUS, *status_val);
43    if ((*status_val & IDE_REGISTER_STATUS_BSY) == 0)
44      return true;
45
46    if (timeout)
47    {
48      timeout--;
49      rtems_task_wake_after (TOD_MICROSECONDS_TO_TICKS (1000));
50    }
51  }
52  while (timeout);
53
54  return false;
55}
56
57static bool pc386_ide_status_data_ready (uint32_t port,
58                                         uint32_t timeout,
59                                         uint8_t* status_val)
60{
61  do
62  {
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;
68
69    if (timeout)
70    {
71      timeout--;
72      rtems_task_wake_after (TOD_MICROSECONDS_TO_TICKS (1000));
73    }
74  }
75  while (timeout);
76
77  return false;
78}
79
80/*
81 * support functions for IDE harddisk IF
82 */
83/*=========================================================================*\
84| Function:                                                                 |
85\*-------------------------------------------------------------------------*/
86bool pc386_ide_probe
87(
88/*-------------------------------------------------------------------------*\
89| Purpose:                                                                  |
90|  This function should probe, whether a IDE disk is available              |
91+---------------------------------------------------------------------------+
92| Input Parameters:                                                         |
93\*-------------------------------------------------------------------------*/
94 int minor
95 )
96/*-------------------------------------------------------------------------*\
97| Return Value:                                                             |
98|    true, when flash disk available                                        |
99\*=========================================================================*/
100{
101  bool ide_card_plugged = true; /* assume: we have a disk here */
102
103  return ide_card_plugged;
104}
105
106static void wait(volatile uint32_t loops)
107{
108  while (loops)
109    loops--;
110}
111
112/*=========================================================================*\
113| Function:                                                                 |
114\*-------------------------------------------------------------------------*/
115void pc386_ide_initialize
116(
117/*-------------------------------------------------------------------------*\
118| Purpose:                                                                  |
119|  initialize IDE access                                                    |
120+---------------------------------------------------------------------------+
121| Input Parameters:                                                         |
122\*-------------------------------------------------------------------------*/
123 int  minor                              /* controller minor number       */
124 )
125/*-------------------------------------------------------------------------*\
126| Return Value:                                                             |
127|    <none>                                                                 |
128\*=========================================================================*/
129{
130  uint32_t port = IDE_Controller_Table[minor].port1;
131  uint8_t  dev = 0;
132
133  if (pc386_ide_show)
134    printk("IDE%d: port base: %04x\n", minor, port);
135
136  outport_byte(port+IDE_REGISTER_DEVICE_HEAD,
137               (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | 0xE0);
138  wait(10000);
139  outport_byte(port+IDE_REGISTER_DEVICE_CONTROL,
140               IDE_REGISTER_DEVICE_CONTROL_SRST | IDE_REGISTER_DEVICE_CONTROL_nIEN);
141  wait(10000);
142  outport_byte(port+IDE_REGISTER_DEVICE_CONTROL,
143               IDE_REGISTER_DEVICE_CONTROL_nIEN);
144  wait(10000);
145
146  for (dev = 0; dev < 2; dev++)
147  {
148    uint32_t    byte;
149    uint8_t     status;
150    uint8_t     error;
151    uint8_t     cyllsb;
152    uint8_t     cylmsb;
153    const char* label = dev ? " slave" : "master";
154    char        model_number[41];
155    char*       p = &model_number[0];
156
157    memset(model_number, 0, sizeof(model_number));
158
159    outport_byte(port+IDE_REGISTER_DEVICE_HEAD,
160                 (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | 0xE0);
161    /*
162    outport_byte(port+IDE_REGISTER_SECTOR_NUMBER,
163                 (dev << IDE_REGISTER_DEVICE_HEAD_DEV_POS) | IDE_REGISTER_LBA3_L);
164    */
165
166    outport_byte(port+IDE_REGISTER_COMMAND, 0x00);
167   
168    if (!pc386_ide_status_busy (port, 6000, &status))
169      continue;
170   
171    inport_byte(port+IDE_REGISTER_STATUS,        status);
172    inport_byte(port+IDE_REGISTER_ERROR,         error);
173    inport_byte(port+IDE_REGISTER_CYLINDER_LOW,  cyllsb);
174    inport_byte(port+IDE_REGISTER_CYLINDER_HIGH, cylmsb);
175
176    if (pc386_ide_show)
177    {
178      printk("IDE%d:%s: status=%02x\n", minor, label, status);
179      printk("IDE%d:%s: error=%02x\n", minor, label, error);
180      printk("IDE%d:%s: cylinder-low=%02x\n", minor, label, cyllsb);
181      printk("IDE%d:%s: cylinder-high=%02x\n", minor, label, cylmsb);
182    }
183
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   
198    outport_byte(port+IDE_REGISTER_COMMAND, 0xec);
199
200    if (!pc386_ide_status_busy (port, 6000, &status))
201    {
202      if (pc386_ide_show)
203        printk("IDE%d:%s: device busy: %02x\n", minor, label, status);
204      continue;
205    }
206   
207    byte = 0;
208    while (byte < 512)
209    {
210      uint16_t word;
211      bool     data_ready;
212
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);
217
218      if (status & IDE_REGISTER_STATUS_ERR)
219      {
220        inport_byte(port+IDE_REGISTER_ERROR, error);
221        if (error != 4)
222        {
223          if (pc386_ide_show)
224            printk("IDE%d:%s: error=%04x\n", minor, label, error);
225          break;
226        }
227        /*
228         * The device is an ATAPI device.
229         */
230        outport_byte(port+IDE_REGISTER_COMMAND, 0xa1);
231        continue;
232      }
233
234      if (!data_ready)
235        break;
236     
237      inport_word(port+IDE_REGISTER_DATA, word);
238
239      if (pc386_ide_show)
240        printk ("%04x ", word);
241
242      if (byte >= 54 && byte < (54 + 40))
243      {
244        *p = word >> 8;
245        p++;
246        *p = word;
247        p++;
248      }
249       
250      byte += 2;
251    }
252   
253    if (pc386_ide_show)
254      printk("\nbytes read = %d\n", byte);
255
256    if (p != &model_number[0])
257      printk("IDE%d:%s: %s\n", minor, label, model_number);
258  }
259 
260  /*
261   * FIXME: enable interrupts, if needed
262   */
263}
264
265/*=========================================================================*\
266| Function:                                                                 |
267\*-------------------------------------------------------------------------*/
268void pc386_ide_read_reg
269(
270/*-------------------------------------------------------------------------*\
271| Purpose:                                                                  |
272|  read a IDE controller register                                           |
273+---------------------------------------------------------------------------+
274| Input Parameters:                                                         |
275\*-------------------------------------------------------------------------*/
276 int                        minor,  /* controller minor number       */
277 int                        reg,    /* register index to access      */
278 uint16_t                  *value   /* ptr to return value location  */
279 )
280/*-------------------------------------------------------------------------*\
281| Return Value:                                                             |
282|    <none>                                                                 |
283\*=========================================================================*/
284{
285  uint32_t    port = IDE_Controller_Table[minor].port1;
286  uint8_t   bval1,bval2;
287
288  if (reg == IDE_REGISTER_DATA_WORD) {
289    inport_byte(port+reg, bval1);
290    inport_byte(port+reg+1, bval2);
291    *value = bval1 + (bval2 << 8);
292  }
293  else {
294    inport_byte(port+reg, bval1);
295    *value = bval1;
296  }
297#ifdef DEBUG_OUT
298  printk("pc386_ide_read_reg (0x%x)=0x%x\r\n",reg,*value & 0xff);
299#endif
300}
301
302/*=========================================================================*\
303| Function:                                                                 |
304\*-------------------------------------------------------------------------*/
305void pc386_ide_write_reg
306(
307/*-------------------------------------------------------------------------*\
308| Purpose:                                                                  |
309|  write a IDE controller register                                          |
310+---------------------------------------------------------------------------+
311| Input Parameters:                                                         |
312\*-------------------------------------------------------------------------*/
313 int                        minor,  /* controller minor number       */
314 int                        reg,    /* register index to access      */
315 uint16_t                   value   /* value to write                */
316 )
317/*-------------------------------------------------------------------------*\
318| Return Value:                                                             |
319|    <none>                                                                 |
320\*=========================================================================*/
321{
322  uint32_t    port = IDE_Controller_Table[minor].port1;
323
324#ifdef DEBUG_OUT
325  printk("pc386_ide_write_reg(0x%x,0x%x)\r\n",reg,value & 0xff);
326#endif
327  if (reg == IDE_REGISTER_DATA_WORD) {
328    outport_word(port+reg,value);
329  }
330  else {
331    outport_byte(port+reg,value);
332  }
333}
334
335/*=========================================================================*\
336| Function:                                                                 |
337\*-------------------------------------------------------------------------*/
338void pc386_ide_read_block
339(
340/*-------------------------------------------------------------------------*\
341| Purpose:                                                                  |
342|  read a IDE controller data block                                         |
343+---------------------------------------------------------------------------+
344| Input Parameters:                                                         |
345\*-------------------------------------------------------------------------*/
346 int minor,
347 uint16_t                block_size,
348 rtems_blkdev_sg_buffer *bufs,
349 uint32_t               *cbuf,
350 uint32_t               *pos
351 )
352/*-------------------------------------------------------------------------*\
353| Return Value:                                                             |
354|    <none>                                                                 |
355\*=========================================================================*/
356{
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
364  while (cnt < block_size)
365  {
366    if (!pc386_ide_status_data_ready (port, 100, &status_val))
367    {
368      printk ("pc386_ide_read_block: status=%02x, cnt=%d bs=%d\n", status_val, cnt, block_size);
369      /* FIXME: add an error here. */
370      return;
371    }
372   
373    if (status_val & IDE_REGISTER_STATUS_ERR)
374      printk("pc386_ide_read_block: error: %02x\n", status_val);
375   
376    inport_word(port+IDE_REGISTER_DATA,*lbuf);
377
378#ifdef DEBUG_OUT
379    printk("0x%x ",*lbuf);
380#endif
381
382    lbuf++;
383    cnt    += sizeof(*lbuf);
384    (*pos) += sizeof(*lbuf);
385    if ((*pos) == llength) {
386      (*pos) = 0;
387      (*cbuf)++;
388      lbuf = bufs[(*cbuf)].buffer;
389      llength = bufs[(*cbuf)].length;
390    }
391  }
392}
393
394/*=========================================================================*\
395| Function:                                                                 |
396\*-------------------------------------------------------------------------*/
397void pc386_ide_write_block
398(
399/*-------------------------------------------------------------------------*\
400| Purpose:                                                                  |
401|  write a IDE controller data block                                        |
402+---------------------------------------------------------------------------+
403| Input Parameters:                                                         |
404\*-------------------------------------------------------------------------*/
405 int minor,
406 uint16_t                block_size,
407 rtems_blkdev_sg_buffer *bufs,
408 uint32_t               *cbuf,
409 uint32_t               *pos
410 )
411/*-------------------------------------------------------------------------*\
412| Return Value:                                                             |
413|    <none>                                                                 |
414\*=========================================================================*/
415{
416  uint32_t    port = IDE_Controller_Table[minor].port1;
417  uint16_t    cnt = 0;
418  uint32_t    llength = bufs[(*cbuf)].length;
419  uint8_t     status_val;
420  uint16_t   *lbuf = (uint16_t*)
421    ((uint8_t*)(bufs[(*cbuf)].buffer) + (*pos));
422 
423#ifdef DEBUG_OUT
424  printk("pc386_ide_write_block()\n");
425#endif
426
427  while (cnt < block_size)
428  {
429    if (!pc386_ide_status_data_ready (port, 100, &status_val))
430    {
431      printk ("pc386_ide_write_block: status=%02x, cnt=%d bs=%d\n", status_val, cnt, block_size);
432      /* FIXME: add an error here. */
433      return;
434    }
435   
436    if (status_val & IDE_REGISTER_STATUS_ERR)
437      printk("pc386_ide_write_block: error: %02x\n", status_val);
438   
439#ifdef DEBUG_OUT
440    printk("0x%x ",*lbuf);
441#endif
442    outport_word(port+IDE_REGISTER_DATA,*lbuf);
443    lbuf++;
444    cnt    += sizeof(*lbuf);
445    (*pos) += sizeof(*lbuf);
446    if ((*pos) == llength) {
447      (*pos) = 0;
448      (*cbuf)++;
449      lbuf = bufs[(*cbuf)].buffer;
450      llength = bufs[(*cbuf)].length;
451    }
452  }
453}
454
455/*=========================================================================*\
456| Function:                                                                 |
457\*-------------------------------------------------------------------------*/
458int pc386_ide_control
459(
460/*-------------------------------------------------------------------------*\
461| Purpose:                                                                  |
462|  control interface for controller                                         |
463+---------------------------------------------------------------------------+
464| Input Parameters:                                                         |
465\*-------------------------------------------------------------------------*/
466 int  minor,                        /* controller minor number       */
467 uint32_t   cmd,                    /* command to send               */
468 void * arg                         /* optional argument             */
469 )
470/*-------------------------------------------------------------------------*\
471| Return Value:                                                             |
472|    <none>                                                                 |
473\*=========================================================================*/
474{
475  return 0;
476}
477
478/*=========================================================================*\
479| Function:                                                                 |
480\*-------------------------------------------------------------------------*/
481rtems_status_code pc386_ide_config_io_speed
482(
483/*-------------------------------------------------------------------------*\
484| Purpose:                                                                  |
485|  set up transfer speed, if possible                                       |
486+---------------------------------------------------------------------------+
487| Input Parameters:                                                         |
488\*-------------------------------------------------------------------------*/
489 int        minor,                   /* controller minor number       */
490 uint16_t   modes_avail              /* optional argument             */
491 )
492/*-------------------------------------------------------------------------*\
493| Return Value:                                                             |
494|    rtems_status_code                                                      |
495\*=========================================================================*/
496{
497  return RTEMS_SUCCESSFUL;
498}
499
500/*
501 * The following table configures the functions used for IDE drivers
502 * in this BSP.
503 */
504
505ide_ctrl_fns_t pc386_ide_ctrl_fns = {
506  pc386_ide_probe,
507  pc386_ide_initialize,
508  pc386_ide_control,
509  pc386_ide_read_reg,
510  pc386_ide_write_reg,
511  pc386_ide_read_block,
512  pc386_ide_write_block,
513  pc386_ide_config_io_speed
514};
Note: See TracBrowser for help on using the repository browser.