ideDrv.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:28k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* ideDrv.c - IDE disk device driver */
  2. /* Copyright 1989-1999 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01p,30jul99,jkf  fixed SPR 9729, retryRW condition loses data.
  8. 01o,11jan99,aeg  removed redundant semBInit () in ideInit ().
  9. 01n,03mar97,dat  fixed SPR 8084, previous edit needed tweeking.
  10. 01m,28feb97,dat  fixed SPR 8084, incorrect block number check
  11. 01l,17dec96,dat  fixed SPR 3273, incorrect block count
  12. 01k,14jun95,hdn  removed function declarations defined in sysLib.h.
  13. 01j,24jan95,jdi  doc cleanup.
  14. 01i,07dec94,rhp  man page cleanups to ideDrvCreate(), ideRawio() (SPR3734).
  15. 01h,25oct94,hdn  cleaned up ideRawio().
  16.  changed ideSemSec and ideWdSec back to 5.
  17. 01g,06oct94,hdn  changed ideSemSec to 10, ideWdSec to 10.
  18.  added ideRawio() to provide physical IO.
  19. 01f,03jun94,hdn  changed DESCRIPTION, 386 to 386/486.
  20.  added an explanation of parameters for ideDevCreate().
  21. 01e,18nov93,hdn  added watchdog to check ideInit() in ideDrv().
  22. 01d,11nov93,hdn  added ideWait() in end of each primitive functions.
  23.  implemented semaphore timeout and watchdog.
  24. 01c,10nov93,hdn  separated ideDiagnose() from ideInit().
  25. 01b,04nov93,hdn  cleaned up.
  26. 01a,18oct93,hdn  written.
  27. */
  28. /*
  29. DESCRIPTION
  30. This is the driver for the IDE used on the PC 386/486.
  31. USER-CALLABLE ROUTINES
  32. Most of the routines in this driver are accessible only through the I/O
  33. system.  However, two routines must be called directly:  ideDrv() to
  34. initialize the driver, and ideDevCreate() to create devices.
  35. Before the driver can be used, it must be initialized by calling ideDrv().
  36. This routine should be called exactly once, before any reads, writes, or
  37. calls to ideDevCreate().  Normally, it is called from usrRoot() in
  38. usrConfig.c.
  39. The routine ideRawio() provides physical I/O access.  Its first
  40. argument is a drive number, 0 or 1; the second argument is a pointer
  41. to an IDE_RAW structure.
  42. NOTE
  43. Format is not supported, because IDE disks are already formatted, and bad
  44. sectors are mapped.
  45. SEE ALSO:
  46. .pG "I/O System"
  47. */
  48. #include "vxWorks.h"
  49. #include "taskLib.h"
  50. #include "ioLib.h"
  51. #include "iosLib.h"
  52. #include "memLib.h"
  53. #include "stdlib.h"
  54. #include "errnoLib.h"
  55. #include "stdio.h"
  56. #include "string.h"
  57. #include "private/semLibP.h"
  58. #include "intLib.h"
  59. #include "iv.h"
  60. #include "wdLib.h"
  61. #include "sysLib.h"
  62. #include "sys/fcntlcom.h"
  63. #include "drv/hdisk/ideDrv.h"
  64. /* imports */
  65. IMPORT IDE_TYPE ideTypes[];
  66. /* global */
  67. BOOL ideDebug  = FALSE; /* debug flag */
  68. BOOL ideDebugErr = FALSE; /* debug flag */
  69. int  ideIntCount = 0; /* interrupt count */
  70. int  ideStatus  = 0; /* status register in interrupt level */
  71. int  ideDrives  = 0; /* number of IDE drives */
  72. int  ideRetry  = 3; /* max retry count */
  73. int  ideSemSec  = 5; /* timeout seconds for semaphore */
  74. int  ideWdSec  = 5; /* timeout seconds for watchdog */
  75. BOOL ideWaitForever = TRUE; /* watchdog: wait forever in ideInit() */
  76. WDOG_ID   ideWid; /* watchdog */
  77. SEMAPHORE ideSyncSem; /* binary semaphore for syncronization */
  78. SEMAPHORE ideMuteSem; /* mutex  semaphore for mutual-exclusion */
  79. IDE_PARAM ideParams[IDE_MAX_DRIVES];
  80. /* local */
  81. LOCAL BOOL ideDrvInstalled = FALSE;   /* TRUE = facility installed */
  82. /* function prototypes */
  83.       void   ideShow (int drive);
  84. LOCAL STATUS ideBlkRd (IDE_DEV *pIdeDev, int startBlk, int nBlks, char *pBuf);
  85. LOCAL STATUS ideBlkWrt (IDE_DEV *pIdeDev, int startBlk, int nBlks, char *pBuf);
  86. LOCAL STATUS ideReset (IDE_DEV *pIdeDev);
  87. LOCAL STATUS ideIoctl (IDE_DEV *pIdeDev, int function, int arg);
  88. LOCAL STATUS ideBlkRW (IDE_DEV *pIdeDev, int startBlk, int nBlks, char *pBuf,
  89.  int direction);
  90. LOCAL void   ideIntr (int ctrl);
  91. LOCAL void   ideWdog (int ctrl);
  92. LOCAL void   ideWait (int request);
  93. LOCAL void   ideInit (void);
  94. LOCAL STATUS ideDiagnose(void);
  95. LOCAL STATUS idePinit (int drive);
  96. LOCAL STATUS idePread (int drive, void *buffer);
  97. LOCAL STATUS ideRecalib (int drive);
  98. LOCAL STATUS ideSeek (int drive, int cylinder, int head);
  99. LOCAL STATUS ideRW (int drive, int cylinder, int head, int sector, 
  100.    void *pBuf, int nSecs, int direction);
  101. LOCAL STATUS ideFormat (int drive, int cylinder, int head, int interleave);
  102. /*******************************************************************************
  103. *
  104. * ideDrv - initialize the IDE driver
  105. *
  106. * This routine initializes the IDE driver, sets up interrupt vectors,
  107. * and performs hardware initialization of the IDE chip.
  108. *
  109. * This routine should be called exactly once, before any reads, writes,
  110. * or calls to ideDevCreate().  Normally, it is called by usrRoot()
  111. * in usrConfig.c.
  112. *
  113. * The ideDrv() call requires a configuration type, <manualConfig>.  If
  114. * this argument is 1, the driver will initialize drive parameters; if
  115. * the argument is 0, the driver will not initialize drive parameters.
  116. *
  117. * The drive parameters are the number of sectors per track, the number of
  118. * heads, and the number of cylinders.  They are stored in the structure
  119. * table `ideTypes[]' in sysLib.c.  The table has two entries:  the first is
  120. * for drive 0; the second is for drive 1.  The table has two other members
  121. * which are used by the driver: the number of bytes per sector and
  122. * the precompensation cylinder.  These two members should be set properly.
  123. * Definitions of the structure members are:
  124. * .CS
  125. *     int cylinders;              /@ number of cylinders @/
  126. *     int heads;                  /@ number of heads @/
  127. *     int sectorsTrack;           /@ number of sectors per track @/
  128. *     int bytesSector;            /@ number of bytes per sector @/
  129. *     int precomp;                /@ precompensation cylinder @/
  130. * .CE
  131. *
  132. * RETURNS: OK, or ERROR if initialization fails.
  133. *
  134. * SEE ALSO: ideDevCreate()
  135. */
  136. STATUS ideDrv
  137.     (
  138.     int vector, /* interrupt vector */
  139.     int level, /* interrupt level */
  140.     BOOL manualConfig /* 1 = initialize drive parameters */
  141.     )
  142.     {
  143.     int drive;
  144.     IDE_PARAM *pParam;
  145.     IDE_TYPE *pType;
  146.     if (!ideDrvInstalled)
  147. {
  148.         semBInit (&ideSyncSem, SEM_Q_FIFO, SEM_EMPTY);
  149.         semMInit (&ideMuteSem, SEM_Q_PRIORITY | SEM_DELETE_SAFE |
  150. SEM_INVERSION_SAFE);
  151.         (void) intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (vector),
  152.        (VOIDFUNCPTR)ideIntr, 0);
  153. ideWid = wdCreate ();
  154.         sysIntEnablePIC (level); /* unmask the interrupt level */
  155. wdStart (ideWid, (sysClkRateGet() * ideWdSec), (FUNCPTR)ideWdog, 0);
  156.         ideInit ();
  157. wdCancel (ideWid);
  158.         if (!ideWaitForever)
  159.     {
  160.     ideWaitForever = TRUE;
  161.     return (ERROR);
  162.     }
  163.         if (ideDiagnose () != OK)
  164.     return (ERROR);
  165.         for (drive = 0; drive < IDE_MAX_DRIVES; drive++)
  166.     {
  167.     pType = &ideTypes[drive];
  168.     pParam = &ideParams[drive];
  169.     if (pType->cylinders == 0)
  170.         break;
  171.     ideDrives += 1;
  172.     if (manualConfig)
  173.         {
  174.         (void) idePinit (drive);
  175.                 (void) idePread (drive, (char *)pParam);
  176.         }
  177.     else
  178.         {
  179.                 (void) idePread (drive, (char *)pParam);
  180.         pType->cylinders = pParam->cylinders - 1;
  181.         pType->heads = pParam->heads;
  182.         pType->sectorsTrack = pParam->sectorsTrack;
  183.         }
  184.     (void) ideRecalib (drive);
  185.     }
  186. ideDrvInstalled = TRUE;
  187. }
  188.     return (OK);
  189.     }
  190. /*******************************************************************************
  191. *
  192. * ideDevCreate - create a device for a IDE disk
  193. *
  194. * This routine creates a device for a specified IDE disk.
  195. *
  196. * <drive> is a drive number for the hard drive: it must be 0 or 1.
  197. *
  198. * The <nBlocks> parameter specifies the size of the device, in blocks.
  199. * If <nBlocks> is zero, the whole disk is used.
  200. *
  201. * The <blkOffset> parameter specifies an offset, in blocks, from the start
  202. * of the device to be used when writing or reading the hard disk.  This
  203. * offset is added to the block numbers passed by the file system during
  204. * disk accesses.  (VxWorks file systems always use block numbers beginning
  205. * at zero for the start of a device.)
  206. *
  207. *
  208. * RETURNS:
  209. * A pointer to a block device structure (BLK_DEV), or NULL if memory cannot
  210. * be allocated for the device structure.
  211. *
  212. * SEE ALSO: dosFsMkfs(), dosFsDevInit(), rt11FsDevInit(), rt11FsMkfs(),
  213. * rawFsDevInit()
  214. */
  215. BLK_DEV *ideDevCreate
  216.     (
  217.     int drive, /* drive number for hard drive (0 or 1) */
  218.     int nBlocks, /* device size in blocks (0 = whole disk) */
  219.     int blkOffset /* offset from start of device */
  220.     )
  221.     {
  222.     IDE_DEV *pIdeDev;
  223.     BLK_DEV *pBlkDev;
  224.     IDE_TYPE *pType;
  225.     if (!ideDrvInstalled)
  226. return (NULL);
  227.     if ((UINT)drive > ideDrives)
  228. return (NULL);
  229.     if ((pIdeDev = (IDE_DEV *)calloc(sizeof (IDE_DEV), 1)) == NULL)
  230. return (NULL);
  231.     pType = &ideTypes[drive];
  232.     pBlkDev = &pIdeDev->blkDev;
  233.     if (nBlocks == 0)
  234. nBlocks = pType->cylinders * pType->heads * pType->sectorsTrack
  235.   - blkOffset;
  236.     pBlkDev->bd_nBlocks = nBlocks;
  237.     pBlkDev->bd_bytesPerBlk = pType->bytesSector;
  238.     pBlkDev->bd_blksPerTrack = pType->sectorsTrack;
  239.     pBlkDev->bd_nHeads = pType->heads;
  240.     pBlkDev->bd_removable = FALSE;
  241.     pBlkDev->bd_retry = 1;
  242.     pBlkDev->bd_mode = O_RDWR;
  243.     pBlkDev->bd_readyChanged = TRUE;
  244.     pBlkDev->bd_blkRd = ideBlkRd;
  245.     pBlkDev->bd_blkWrt = ideBlkWrt;
  246.     pBlkDev->bd_ioctl = ideIoctl;
  247.     pBlkDev->bd_reset = ideReset;
  248.     pBlkDev->bd_statusChk = NULL;
  249.     pIdeDev->drive = drive;
  250.     pIdeDev->blkOffset = blkOffset;
  251.     return (&pIdeDev->blkDev);
  252.     }
  253. /*******************************************************************************
  254. *
  255. * ideShow - show IDE disk parameters
  256. *
  257. * Show IDE disk parameters
  258. *
  259. * RETURNS: N/A
  260. *
  261. * NOMANUAL
  262. */
  263. void ideShow
  264.     (
  265.     int drive
  266.     )
  267.     {
  268.     int ix;
  269.     IDE_PARAM *pParam = &ideParams[drive];
  270.     IDE_TYPE *pType = &ideTypes[drive];
  271.     if ((UINT)drive > ideDrives)
  272. {
  273. printErr ("drive should be 0 - %dn",ideDrives);
  274. return;
  275. }
  276.     printf ("ideTypes    cylinders   =%dn", pType->cylinders);
  277.     printf ("            heads       =%dn", pType->heads);
  278.     printf ("            sectorsTrack=%dn", pType->sectorsTrack);
  279.     printf ("            bytesSector =%dn", pType->bytesSector);
  280.     printf ("            precomp     =0x%04xn",pType->precomp);
  281.     printf ("parameters  config      =0x%04xn",(USHORT)pParam->config);
  282.     printf ("            cylinders   =%dn", (USHORT)pParam->cylinders);
  283.     printf ("            removcyl    =0x%04xn",(USHORT)pParam->removcyl);
  284.     printf ("            heads       =%dn", (USHORT)pParam->heads);
  285.     printf ("            bytesTrack  =0x%04xn",(USHORT)pParam->bytesTrack);
  286.     printf ("            bytesSec    =0x%04xn",(USHORT)pParam->bytesSec);
  287.     printf ("            sectorsTrack=%dn", (USHORT)pParam->sectorsTrack);
  288.     printf ("            bytesGap    =0x%04xn",(USHORT)pParam->bytesGap);
  289.     printf ("            bytesSync   =0x%04xn",(USHORT)pParam->bytesSync);
  290.     printf ("            vendstat    =0x%04xn",(USHORT)pParam->vendstat);
  291.     printf ("            serial      =");
  292.     for (ix = 0; ix < 10; ix++)
  293. {
  294.         printf ("%c", pParam->serial[ix * 2 + 1]);
  295.         printf ("%c", pParam->serial[ix * 2]);
  296. }
  297.     printf ("n");
  298.     printf ("            type        =0x%04xn",(USHORT)pParam->type);
  299.     printf ("            size        =0x%04xn",(USHORT)pParam->size);
  300.     printf ("            bytesEcc    =0x%04xn",(USHORT)pParam->bytesEcc);
  301.     printf ("            rev         =");
  302.     for (ix = 0; ix < 4; ix++)
  303. {
  304.         printf ("%c", pParam->rev[ix * 2 + 1]);
  305.         printf ("%c", pParam->rev[ix * 2]);
  306. }
  307.     printf ("n");
  308.     printf ("            model       =");
  309.     for (ix = 0; ix < 20; ix++)
  310. {
  311.         printf ("%c", pParam->model[ix * 2 + 1]);
  312.         printf ("%c", pParam->model[ix * 2]);
  313. }
  314.     printf ("n");
  315.     printf ("            nsecperint  =0x%04xn",(USHORT)pParam->nsecperint);
  316.     printf ("            usedmovsd   =0x%04xn",(USHORT)pParam->usedmovsd);
  317.     }
  318. /*******************************************************************************
  319. *
  320. * ideRawio - provide raw I/O access
  321. *
  322. * This routine is called when the raw I/O access is necessary.
  323. *
  324. * <drive> is a drive number for the hard drive: it must be 0 or 1.
  325. *
  326. * The <pIdeRaw> is a pointer to the structure IDE_RAW which is defined in 
  327. * ideDrv.h
  328. *
  329. * RETURNS: OK or ERROR.
  330. *
  331. */
  332. STATUS ideRawio
  333.     (
  334.     int        drive, /* drive number for hard drive (0 or 1) */
  335.     IDE_RAW *  pIdeRaw /* pointer to IDE_RAW structure */
  336.     )
  337.     {
  338.     IDE_DEV ideDev;
  339.     BLK_DEV *pBlkDev = &ideDev.blkDev;
  340.     IDE_TYPE *pType = &ideTypes[drive];
  341.     UINT startBlk;
  342.     if (!ideDrvInstalled)
  343. return (ERROR);
  344.     if ((UINT)drive > ideDrives)
  345. return (ERROR);
  346.     if ((pIdeRaw->cylinder >= pType->cylinders) ||
  347.         (pIdeRaw->head >= pType->heads) ||
  348.         (pIdeRaw->sector >  pType->sectorsTrack) ||
  349.         (pIdeRaw->sector == 0))
  350. return (ERROR);
  351.     pBlkDev->bd_nBlocks = pType->cylinders * pType->heads * 
  352.   pType->sectorsTrack;
  353.     pBlkDev->bd_bytesPerBlk = pType->bytesSector;
  354.     pBlkDev->bd_blksPerTrack = pType->sectorsTrack;
  355.     pBlkDev->bd_nHeads = pType->heads;
  356.     pBlkDev->bd_removable = FALSE;
  357.     pBlkDev->bd_retry = 1;
  358.     pBlkDev->bd_mode = O_RDWR;
  359.     pBlkDev->bd_readyChanged = TRUE;
  360.     pBlkDev->bd_blkRd = ideBlkRd;
  361.     pBlkDev->bd_blkWrt = ideBlkWrt;
  362.     pBlkDev->bd_ioctl = ideIoctl;
  363.     pBlkDev->bd_reset = ideReset;
  364.     pBlkDev->bd_statusChk = NULL;
  365.     ideDev.drive = drive;
  366.     ideDev.blkOffset = 0;
  367.     startBlk = pIdeRaw->cylinder * (pType->sectorsTrack * pType->heads) +
  368.        pIdeRaw->head * pType->sectorsTrack +
  369.        pIdeRaw->sector - 1;
  370.     return (ideBlkRW (&ideDev, startBlk, pIdeRaw->nSecs, pIdeRaw->pBuf,
  371.      pIdeRaw->direction));
  372.     }
  373. /*******************************************************************************
  374. *
  375. * ideBlkRd - read one or more blocks from a IDE disk
  376. *
  377. * This routine reads one or more blocks from the specified device,
  378. * starting with the specified block number.
  379. *
  380. * If any block offset was specified during ideDevCreate(), it is added
  381. * to <startBlk> before the transfer takes place.
  382. *
  383. * RETURNS: OK, ERROR if the read command didn't succeed.
  384. */
  385. LOCAL STATUS ideBlkRd
  386.     (
  387.     IDE_DEV *pIdeDev,
  388.     int startBlk,
  389.     int nBlks,
  390.     char *pBuf
  391.     )
  392.     {
  393.     return (ideBlkRW (pIdeDev, startBlk, nBlks, pBuf, O_RDONLY));
  394.     }
  395. /*******************************************************************************
  396. *
  397. * ideBlkWrt - write one or more blocks to a IDE disk
  398. *
  399. * This routine writes one or more blocks to the specified device,
  400. * starting with the specified block number.
  401. *
  402. * If any block offset was specified during ideDevCreate(), it is added
  403. * to <startBlk> before the transfer takes place.
  404. *
  405. * RETURNS: OK, ERROR if the write command didn't succeed.
  406. */
  407. LOCAL STATUS ideBlkWrt
  408.     (
  409.     IDE_DEV *pIdeDev,
  410.     int startBlk,
  411.     int nBlks,
  412.     char *pBuf
  413.     )
  414.     {
  415.     return (ideBlkRW (pIdeDev, startBlk, nBlks, pBuf, O_WRONLY));
  416.     }
  417. /*******************************************************************************
  418. *
  419. * ideReset - reset a IDE disk controller
  420. *
  421. * This routine resets a IDE disk controller.
  422. *
  423. * RETURNS: OK, always.
  424. */
  425. LOCAL STATUS ideReset
  426.     (
  427.     IDE_DEV *pIdeDev
  428.     )
  429.     {
  430.     
  431.     semTake (&ideMuteSem, WAIT_FOREVER);
  432.     ideInit ();
  433.     semGive (&ideMuteSem);
  434.     return (OK);
  435.     }
  436. /*******************************************************************************
  437. *
  438. * ideIoctl - do device specific control function
  439. *
  440. * This routine is called when the file system cannot handle an ioctl()
  441. * function.
  442. *
  443. * RETURNS:  OK or ERROR.
  444. */
  445. LOCAL STATUS ideIoctl
  446.     (
  447.     IDE_DEV *pIdeDev,
  448.     int function,
  449.     int arg
  450.     )
  451.     {
  452.     FAST int status = ERROR;
  453.     FAST int cylinder;
  454.     FAST int head;
  455.     int retryCount;
  456.     IDE_TYPE *pType = &ideTypes[pIdeDev->drive];
  457.     semTake (&ideMuteSem, WAIT_FOREVER);
  458.     switch (function)
  459. {
  460. case FIODISKFORMAT:
  461.     (void) ideRecalib (pIdeDev->drive);
  462.     for (cylinder = 0; cylinder < pType->cylinders; cylinder++)
  463.         for (head = 0; head < pType->heads; head++)
  464.     {
  465.     retryCount = 0;
  466.     while (ideSeek(pIdeDev->drive, cylinder, head) != OK)
  467.              if (++retryCount > ideRetry)
  468.     {
  469.          (void) errnoSet (S_ioLib_DEVICE_ERROR);
  470.     goto doneIoctl;
  471.     }
  472.     retryCount = 0;
  473.     while (ideFormat(pIdeDev->drive, cylinder, head, arg)
  474.    != OK)
  475.              if (++retryCount > ideRetry)
  476.     {
  477.          (void) errnoSet (S_ioLib_DEVICE_ERROR);
  478.     goto doneIoctl;
  479.     }
  480.     }
  481.     status = OK;
  482.     break;
  483. default:
  484.     (void) errnoSet (S_ioLib_UNKNOWN_REQUEST);
  485. }
  486. doneIoctl:
  487.     semGive (&ideMuteSem);
  488.     return (status);
  489.     }
  490. /*******************************************************************************
  491. *
  492. * ideBlkRW - read or write sectors to a IDE disk.
  493. *
  494. * Read or write sectors to a IDE disk.
  495. *
  496. * RETURNS: OK, ERROR if the command didn't succeed.
  497. */
  498. LOCAL STATUS ideBlkRW
  499.     (
  500.     IDE_DEV *pIdeDev,
  501.     int startBlk,
  502.     int nBlks,
  503.     char *pBuf,
  504.     int direction
  505.     )
  506.     {
  507.     BLK_DEV *pBlkDev = &pIdeDev->blkDev;
  508.     int cylinder;
  509.     int head;
  510.     int sector;
  511.     int ix;
  512.     int nSecs;
  513.     int retryRW0 = 0;
  514.     int retryRW1 = 0;
  515.     int retrySeek = 0;
  516.     int status = ERROR;
  517.     IDE_TYPE *pType = &ideTypes[pIdeDev->drive];
  518.     /* sanity check */
  519.     nSecs =  pBlkDev->bd_nBlocks;
  520.     if ((startBlk + nBlks) > nSecs)
  521. {
  522.         if (ideDebugErr)
  523.     printErr ("startBlk=%d nBlks=%d: 0 - %dn", startBlk, nBlks, nSecs);
  524. return (ERROR);
  525. }
  526.     startBlk += pIdeDev->blkOffset;
  527.     semTake (&ideMuteSem, WAIT_FOREVER);
  528.     for (ix = 0; ix < nBlks; ix += nSecs)
  529. {
  530. cylinder = startBlk / (pType->sectorsTrack * pType->heads);
  531. sector   = startBlk % (pType->sectorsTrack * pType->heads);
  532. head     = sector / pType->sectorsTrack;
  533. sector   = sector % pType->sectorsTrack + 1;
  534. nSecs    = min (nBlks - ix, pType->sectorsTrack - sector + 1);
  535. retrySeek = 0;
  536. while (ideSeek(pIdeDev->drive, cylinder, head) != OK)
  537.     if (++retrySeek > ideRetry)
  538. goto done;
  539. retryRW1 = 0;
  540. retryRW0 = 0;
  541. while (ideRW (pIdeDev->drive, cylinder, head, sector, 
  542.   pBuf, nSecs, direction) != OK)
  543.     {
  544.     if (++retryRW0 > ideRetry)
  545. {
  546.         (void) ideRecalib (pIdeDev->drive);
  547.         if (++retryRW1 > ideRetry)
  548.     goto done;
  549.         retrySeek = 0;
  550.         while (ideSeek(pIdeDev->drive, cylinder, head) != OK)
  551.             if (++retrySeek > ideRetry)
  552.         goto done;
  553.         retryRW0 = 0;
  554. }
  555.     }
  556.         startBlk += nSecs;
  557.         pBuf += pBlkDev->bd_bytesPerBlk * nSecs;
  558. }
  559.     status = OK;
  560. done:
  561.     if (status == ERROR)
  562.         (void)errnoSet (S_ioLib_DEVICE_ERROR);
  563.     semGive (&ideMuteSem);
  564.     return (status);
  565.     }
  566. /*******************************************************************************
  567. *
  568. * ideIntr - IDE controller interrupt handler.
  569. *
  570. * RETURNS: N/A
  571. */
  572. LOCAL void ideIntr
  573.     (
  574.     int ctrl
  575.     )
  576.     {
  577.     ideIntCount++; /* XXX */
  578.     ideStatus = sysInByte (IDE_STATUS);
  579.     semGive (&ideSyncSem);
  580.     }
  581. /*******************************************************************************
  582. *
  583. * ideIntr - IDE controller watchdog handler.
  584. *
  585. * RETURNS: N/A
  586. */
  587. LOCAL void ideWdog
  588.     (
  589.     int ctrl
  590.     )
  591.     {
  592.     ideWaitForever = FALSE;
  593.     }
  594. /*******************************************************************************
  595. *
  596. * ideWait - wait the drive ready
  597. *
  598. * Wait the drive ready
  599. *
  600. * RETURNS: OK, ERROR if the drive didn't become ready in certain period of time.
  601. */
  602. LOCAL void ideWait
  603.     (
  604.     int request
  605.     )
  606.     {
  607.     switch (request)
  608. {
  609. case STAT_READY:
  610.     wdStart (ideWid, (sysClkRateGet() * ideWdSec), (FUNCPTR)ideInit, 0);
  611.             while (sysInByte (IDE_STATUS) & STAT_BUSY)
  612.         ;
  613.             while ((sysInByte (IDE_STATUS) & STAT_READY) == 0)
  614.         ;
  615.     wdCancel (ideWid);
  616.     break;
  617. case STAT_DRQ:
  618.             while ((sysInByte (IDE_STATUS) & STAT_DRQ) == 0)
  619.         ;
  620.     break;
  621. case STAT_SEEKCMPLT:
  622.             while ((sysInByte (IDE_STATUS) & STAT_SEEKCMPLT) == 0)
  623.         ;
  624.     break;
  625. }
  626.     if (ideDebug)
  627. printErr ("ideWait end: n");
  628.     }
  629. /*******************************************************************************
  630. *
  631. * ideInit - init a IDE disk controller
  632. *
  633. * This routine initializes a IDE disk controller.
  634. *
  635. * RETURNS: OK, ERROR if the command didn't succeed.
  636. */
  637. LOCAL void ideInit (void)
  638.     {
  639.     int ix;
  640.     sysOutByte (IDE_D_CONTROL, CTL_RST | CTL_IDS);
  641.     for (ix = 0; ix < 100; ix++)
  642.         sysDelay ();
  643.     sysOutByte (IDE_D_CONTROL, CTL_IDS);
  644.     for (ix = 0; ix < 100; ix++)
  645.         sysDelay ();
  646.     while ((sysInByte (IDE_STATUS) & STAT_BUSY) && (ideWaitForever))
  647. ;
  648.     sysOutByte (IDE_D_CONTROL, CTL_4BIT);
  649.     for (ix = 0; ix < 100; ix++)
  650.         sysDelay ();
  651.     while (((sysInByte (IDE_STATUS) & STAT_READY) == 0) && (ideWaitForever))
  652. ;
  653.     if (ideDebug)
  654. printErr ("ideInit end: n");
  655.     }
  656. /*******************************************************************************
  657. *
  658. * ideDiagnose - diagnose the drive
  659. *
  660. * Diagnose the drive
  661. *
  662. * RETURNS: OK, ERROR if the command didn't succeed.
  663. */
  664. LOCAL STATUS ideDiagnose (void)
  665.     {
  666.     int error;
  667.     int semStatus;
  668.     sysOutByte (IDE_SDH, SDH_IBM);
  669.     ideWait (STAT_READY);
  670.     sysOutByte (IDE_COMMAND, CMD_DIAGNOSE);
  671.     semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
  672.     if (((error = sysInByte(IDE_ERROR)) != DIAG_OK) || (semStatus == ERROR))
  673. {
  674. if (ideDebugErr)
  675.     printErr ("ideDiagnose: status=0x%x error=0x%xn", 
  676.       ideStatus, error);
  677. return (ERROR);
  678. }
  679.     ideWait (STAT_READY);
  680.     if (ideDebug)
  681. printErr ("ideDiagnose end: n");
  682.     return (OK);
  683.     }
  684. /*******************************************************************************
  685. *
  686. * idePinit - Initialize drive parameters
  687. *
  688. * Initialize drive parameters.
  689. *
  690. * RETURNS: OK, ERROR if the command didn't succeed.
  691. */
  692. LOCAL STATUS idePinit
  693.     (
  694.     int drive
  695.     )
  696.     {
  697.     int status;
  698.     int error;
  699.     int semStatus;
  700.     int retryCount = 0;
  701.     IDE_TYPE *pType = &ideTypes[drive];
  702. retryPinit:
  703.     sysOutByte (IDE_CYL_LO, pType->cylinders);
  704.     sysOutByte (IDE_CYL_HI, pType->cylinders >> 8);
  705.     sysOutByte (IDE_SECCNT, pType->sectorsTrack);
  706.     sysOutByte (IDE_SDH, SDH_IBM | (drive << 4) | ((pType->heads & 0xf) - 1));
  707.     ideWait (STAT_READY);
  708.     sysOutByte (IDE_COMMAND, CMD_INITP);
  709.     semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
  710.     if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
  711. {
  712. error = sysInByte (IDE_ERROR);
  713. status = sysInByte (IDE_STATUS);
  714. ideInit ();
  715. if (ideDebugErr)
  716.             printErr ("idePinit%d err: stat=0x%x 0x%x error=0x%xn",
  717.               drive, ideStatus, status, error);
  718. if (++retryCount < ideRetry)
  719.     goto retryPinit;
  720. return (ERROR);
  721. }
  722.     ideWait (STAT_READY);
  723.     if (ideDebug)
  724. printErr ("idePinit%d end: n", drive);
  725.     return (OK);
  726.     }
  727. /*******************************************************************************
  728. *
  729. * idePread - Read drive parameters
  730. *
  731. * Read drive parameters.
  732. *
  733. * RETURNS: OK, ERROR if the command didn't succeed.
  734. */
  735. LOCAL STATUS idePread
  736.     (
  737.     int drive,
  738.     void *buffer
  739.     )
  740.     {
  741.     int status;
  742.     int error;
  743.     int semStatus;
  744.     int retryCount = 0;
  745. retryPread:
  746.     sysOutByte (IDE_SDH, SDH_IBM | (drive << 4));
  747.     ideWait (STAT_READY);
  748.     sysOutByte (IDE_COMMAND, CMD_READP);
  749.     semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
  750.     if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
  751. {
  752. error = sysInByte (IDE_ERROR);
  753. status = sysInByte (IDE_STATUS);
  754. ideInit ();
  755. if (ideDebugErr)
  756.             printErr ("idePread%d err: stat=0x%x 0x%x error=0x%xn",
  757.               drive, ideStatus, status, error);
  758. if (++retryCount < ideRetry)
  759.     goto retryPread;
  760. return (ERROR);
  761. }
  762.     ideWait (STAT_DRQ);
  763.     sysInWordString (IDE_DATA, (short *)buffer, 256);
  764.     ideWait (STAT_READY);
  765.     if (ideDebug)
  766. printErr ("idePread%d end: n", drive);
  767.     return (OK);
  768.     }
  769. /*******************************************************************************
  770. *
  771. * ideRecalib - recalibrate the drive
  772. *
  773. * Recalibrate the drive
  774. *
  775. * RETURNS: OK, ERROR if the command didn't succeed.
  776. */
  777. LOCAL STATUS ideRecalib
  778.     (
  779.     int drive
  780.     )
  781.     {
  782.     int status;
  783.     int error;
  784.     int semStatus;
  785.     int retryCount = 0;
  786. retryRecalib:
  787.     sysOutByte (IDE_SDH, SDH_IBM | (drive << 4));
  788.     ideWait (STAT_READY);
  789.     sysOutByte (IDE_COMMAND, CMD_RECALIB);
  790.     semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
  791.     if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
  792. {
  793. error = sysInByte (IDE_ERROR);
  794. status = sysInByte (IDE_STATUS);
  795. ideInit ();
  796. if (ideDebugErr)
  797.     printErr ("ideRecalib%d err: status=0x%x 0x%x error=0x%xn",
  798.               drive, ideStatus, status, error);
  799. if (++retryCount < ideRetry)
  800.     goto retryRecalib;
  801. return (ERROR);
  802. }
  803.     
  804.     ideWait (STAT_READY);
  805.     if (ideDebug)
  806. printErr ("ideRecalib%d end: n", drive);
  807.     return (OK);
  808.     }
  809. /*******************************************************************************
  810. *
  811. * ideSeek - seek the drive heads to the specified cylinder
  812. *
  813. * Seek the drive heads to the specified cylinder
  814. *
  815. * RETURNS: OK, ERROR if the command didn't succeed.
  816. */
  817. LOCAL STATUS ideSeek
  818.     (
  819.     int drive,
  820.     int cylinder,
  821.     int head
  822.     )
  823.     {
  824.     int status;
  825.     int error;
  826.     int semStatus;
  827.     int retryCount = 0;
  828. retrySeek:
  829.     sysOutByte (IDE_CYL_LO, cylinder);
  830.     sysOutByte (IDE_CYL_HI, cylinder>>8);
  831.     sysOutByte (IDE_SDH, SDH_IBM | (drive << 4) | (head & 0xf));
  832.     ideWait (STAT_READY);
  833.     sysOutByte (IDE_COMMAND, CMD_SEEK);
  834.     semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
  835.     if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
  836. {
  837. error = sysInByte (IDE_ERROR);
  838. status = sysInByte (IDE_STATUS);
  839. ideInit ();
  840. if (ideDebugErr)
  841.     printErr ("ideSeek%d err: c=%d h=%d status=0x%x 0x%x error=0x%xn",
  842.       drive, cylinder, head, ideStatus, status, error);
  843. if (++retryCount < ideRetry)
  844.     goto retrySeek;
  845. return (ERROR);
  846. }
  847.     ideWait (STAT_SEEKCMPLT);
  848.     ideWait (STAT_READY);
  849.     if (ideDebug)
  850. printErr ("ideSeek%d end: c=%d h=%dn", drive, cylinder, head);
  851.     return (OK);
  852.     }
  853. /*******************************************************************************
  854. *
  855. * ideRW - read/write a number of sectors on the current track
  856. *
  857. * Read/write a number of sectors on the current track
  858. *
  859. * RETURNS: OK, ERROR if the command didn't succeed.
  860. */
  861. LOCAL STATUS ideRW
  862.     (
  863.     int drive,
  864.     int cylinder,
  865.     int head,
  866.     int sector,
  867.     void *buffer,
  868.     int nSecs,
  869.     int direction
  870.     )
  871.     {
  872.     int ix;
  873.     int status;
  874.     int error;
  875.     int semStatus;
  876.     int retryCount = 0;
  877.     short *pBuf; 
  878.     IDE_TYPE *pType = &ideTypes[drive];
  879.     int nWords = pType->bytesSector >> 1;
  880. retryRW:
  881.     pBuf = (short *)buffer;
  882.     sysOutByte (IDE_PRECOMP, pType->precomp);
  883.     sysOutByte (IDE_SECCNT, nSecs);
  884.     sysOutByte (IDE_SECTOR, sector);
  885.     sysOutByte (IDE_CYL_LO, cylinder);
  886.     sysOutByte (IDE_CYL_HI, cylinder>>8);
  887.     sysOutByte (IDE_SDH, SDH_IBM | (drive << 4) | (head & 0xf));
  888.     ideWait (STAT_READY);
  889.     if (direction == O_WRONLY)
  890. {
  891. sysOutByte (IDE_COMMAND, CMD_WRITE);
  892. for (ix = 0; ix < nSecs; ix++)
  893.     {
  894.             ideWait (STAT_DRQ);
  895.     sysOutWordString (IDE_DATA, pBuf, nWords);
  896.             semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
  897.          if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
  898.         goto errorRW;
  899.     pBuf += nWords;
  900.             }
  901. }
  902.     else
  903. {
  904. sysOutByte (IDE_COMMAND, CMD_READ);
  905. for (ix = 0; ix < nSecs; ix++)
  906.     {
  907.             semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
  908.          if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
  909.         goto errorRW;
  910.             ideWait (STAT_DRQ);
  911.     sysInWordString (IDE_DATA, pBuf, nWords);
  912.     pBuf += nWords;
  913.     }
  914. }
  915.     ideWait (STAT_READY);
  916.     if (ideDebug)
  917. printErr ("ideRW%d end: c=%d h=%d s=%d buf=0x%x n=%d dir=%dn",
  918.                   drive, cylinder, head, sector, (int)buffer, nSecs, direction);
  919.     return (OK);
  920. errorRW:
  921.     error = sysInByte (IDE_ERROR);
  922.     status = sysInByte (IDE_STATUS);
  923.     ideInit ();
  924.     if (ideDebugErr)
  925. {
  926.         printErr ("ideRW%d err: c=%d h=%d s=%d buf=0x%x n=%d dir=%d ",
  927.                   drive, cylinder, head, sector, (int)buffer, nSecs, direction);
  928.         printErr ("stat=0x%x 0x%x error=0x%xn", ideStatus, status, error);
  929. }
  930.     if (++retryCount < ideRetry)
  931. goto retryRW;
  932.     return (ERROR);
  933.     }
  934. /*******************************************************************************
  935. *
  936. * ideFormat - format the current track
  937. *
  938. * format the current track; not supported.
  939. *
  940. * RETURNS: ERROR always.
  941. */
  942. LOCAL STATUS ideFormat
  943.     (
  944.     int drive,
  945.     int cylinder,
  946.     int head,
  947.     int interleave
  948.     )
  949.     {
  950.     return (ERROR);
  951.     }