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

4.104.115
Last change on this file since be72045 was be72045, checked in by Chris Johns <chrisj@…>, on 06/12/09 at 03:06:33

2009-06-12 Chris Johns <chrisj@…>

  • ide/ide.c: Format the data output in DEBUG mode.
  • Property mode set to 100644
File size: 18.8 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#ifdef DEBUG_OUT
364  int i32 = 0;
365#endif
366  while (cnt < block_size)
367  {
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);
371      /* FIXME: add an error here. */
372      return;
373    }
374   
375    if (status_val & IDE_REGISTER_STATUS_ERR)
376      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    }
388#endif
389   
390    lbuf++;
391    cnt    += sizeof(*lbuf);
392    (*pos) += sizeof(*lbuf);
393    if ((*pos) == llength) {
394      (*pos) = 0;
395      (*cbuf)++;
396      lbuf = bufs[(*cbuf)].buffer;
397      llength = bufs[(*cbuf)].length;
398    }
399  }
400}
401
402/*=========================================================================*\
403| Function:                                                                 |
404\*-------------------------------------------------------------------------*/
405void pc386_ide_write_block
406(
407/*-------------------------------------------------------------------------*\
408| Purpose:                                                                  |
409|  write a IDE controller data block                                        |
410+---------------------------------------------------------------------------+
411| Input Parameters:                                                         |
412\*-------------------------------------------------------------------------*/
413 int minor,
414 uint16_t                block_size,
415 rtems_blkdev_sg_buffer *bufs,
416 uint32_t               *cbuf,
417 uint32_t               *pos
418 )
419/*-------------------------------------------------------------------------*\
420| Return Value:                                                             |
421|    <none>                                                                 |
422\*=========================================================================*/
423{
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");
433#endif
434
435  while (cnt < block_size)
436  {
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);
440      /* FIXME: add an error here. */
441      return;
442    }
443   
444    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);
449#endif
450    outport_word(port+IDE_REGISTER_DATA,*lbuf);
451    lbuf++;
452    cnt    += sizeof(*lbuf);
453    (*pos) += sizeof(*lbuf);
454    if ((*pos) == llength) {
455      (*pos) = 0;
456      (*cbuf)++;
457      lbuf = bufs[(*cbuf)].buffer;
458      llength = bufs[(*cbuf)].length;
459    }
460  }
461}
462
463/*=========================================================================*\
464| Function:                                                                 |
465\*-------------------------------------------------------------------------*/
466int pc386_ide_control
467(
468/*-------------------------------------------------------------------------*\
469| Purpose:                                                                  |
470|  control interface for controller                                         |
471+---------------------------------------------------------------------------+
472| Input Parameters:                                                         |
473\*-------------------------------------------------------------------------*/
474 int  minor,                        /* controller minor number       */
475 uint32_t   cmd,                    /* command to send               */
476 void * arg                         /* optional argument             */
477 )
478/*-------------------------------------------------------------------------*\
479| Return Value:                                                             |
480|    <none>                                                                 |
481\*=========================================================================*/
482{
483  return 0;
484}
485
486/*=========================================================================*\
487| Function:                                                                 |
488\*-------------------------------------------------------------------------*/
489rtems_status_code pc386_ide_config_io_speed
490(
491/*-------------------------------------------------------------------------*\
492| Purpose:                                                                  |
493|  set up transfer speed, if possible                                       |
494+---------------------------------------------------------------------------+
495| Input Parameters:                                                         |
496\*-------------------------------------------------------------------------*/
497 int        minor,                   /* controller minor number       */
498 uint16_t   modes_avail              /* optional argument             */
499 )
500/*-------------------------------------------------------------------------*\
501| Return Value:                                                             |
502|    rtems_status_code                                                      |
503\*=========================================================================*/
504{
505  return RTEMS_SUCCESSFUL;
506}
507
508/*
509 * The following table configures the functions used for IDE drivers
510 * in this BSP.
511 */
512
513ide_ctrl_fns_t pc386_ide_ctrl_fns = {
514  pc386_ide_probe,
515  pc386_ide_initialize,
516  pc386_ide_control,
517  pc386_ide_read_reg,
518  pc386_ide_write_reg,
519  pc386_ide_read_block,
520  pc386_ide_write_block,
521  pc386_ide_config_io_speed
522};
Note: See TracBrowser for help on using the repository browser.