gonzui


Format: Advanced Search

tkernel_2/driver/tef_em1d/sysdsk/src/ataio.cbare sourcepermlink (0.04 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    T-Kernel 2.0 Software Package
    4:  *
    5:  *    Copyright 2011 by Ken Sakamura.
    6:  *    This software is distributed under the latest version of T-License 2.x.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by T-Engine Forum(http://www.t-engine.org/) at 2011/05/17.
   10:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/01.
   11:  *
   12:  *----------------------------------------------------------------------
   13:  */
   14: 
   15: 
   16: /*
   17:  *      ataio.c              System disk driver
   18:  *
   19:  *      ATA (IDE) Drive I/O processing
   20:  */
   21: 
   22: #include "sdisk.h"
   23: #include "ata.h"
   24: #include "pccardio.h"
   25: 
   26: /*
   27:  *      Time-out time
   28:  */
   29: #define STATUS_TMO      (50 * 1000)          /* x usec = 50 msec     */
   30: #define READY_TMO       (10 * 1000)           /* x msec = 10 sec       */
   31: #define RESET_TMO       (31 * 1000)           /* x msec = 31 sec       */
   32: 
   33: /*
   34:  *      Status input
   35:  */
   36: EXPORT  W        ataStatusIn(DrvTab *drv)
   37: {
   38:         return InForceB(drv->IOB, REG_STS);
   39: }
   40: 
   41: /*
   42:  *      Error information input
   43:  */
   44: EXPORT  W        ataErrorIn(DrvTab *drv)
   45: {
   46:         UW     iob = drv->IOB;
   47: 
   48:         return InB(REG_ERR);
   49: }
   50: 
   51: /*
   52:  *      Cylinder register input
   53:  */
   54: EXPORT  W        ataCylIn(DrvTab *drv)
   55: {
   56:         UW     iob = drv->IOB;
   57: 
   58:         return (InB(REG_CYL_H) << 8) | InB(REG_CYL_L);
   59: }
   60: 
   61: /*
   62:  *      Status check
   63:  */
   64: LOCAL   W ataChkSts(DrvTab *drv, UB chk, UB ok)
   65: {
   66:         UW     iob = drv->IOB;
   67:         W      i;
   68: 
   69:         for (i = 0; i < STATUS_TMO; i += 10, WaitUsec(10)) {
   70:                 if ((InB(REG_STS) & chk) == ok) return E_OK;
   71:         }
   72:         return ERR_DATABUSY;
   73: }
   74: 
   75: /*
   76:  *      Drive setting
   77:  */
   78: EXPORT  ER       ataSetDrive(DrvTab *drv, W drvno)
   79: {
   80:         UW     iob = drv->IOB;
   81:         UB     dno;
   82: 
   83:         if (drvno < 0) drvno = drv->DrvNo;
   84: 
   85:         OutB(REG_DRVHEAD, dno = drDRV(drvno));
   86:         WaitUsec(4);           /* Waiting is necessary depending on drive */
   87:         if (InB(REG_DRVHEAD) == dno) return E_OK;
   88:         return ERR_NOPORT;
   89: }
   90: 
   91: /*
   92:  *      Interrupt-enabled
   93:  */
   94: EXPORT  void     ataEnbInt(DrvTab *drv)
   95: {
   96:         UW     iob = drv->IOB;
   97:         UW     reg;
   98: 
   99:         reg = (drv->d.pcc.IOConf[0] & IOC_IO2_NONE)? REG_DEVCTL : REG_DEVCTL2;
  100:         OutB(reg, dcNORM);
  101: }
  102: 
  103: /*
  104:  *      Wait until a data transfer is OK
  105:  */
  106: EXPORT  ER       ataWaitData(DrvTab *drv)
  107: {
  108:         /* Wait until a data transfer is OK ("BSY=0", "DRDY=1", and "DRQ=1")  */
  109:         return ataChkSts(drv, stBSY | stDRDY | stDRQ, stDRDY | stDRQ);
  110: }
  111: 
  112: /*
  113:  *      Wait for a long time until it becomes ready-status (BUSY = 0)
  114:  */
  115: EXPORT  ER       ataWaitReady(DrvTab *drv)
  116: {
  117:         UW     tm, st;
  118: 
  119:         for (tm = 0;;) {
  120:                 st = ataStatusIn(drv);
  121:                 if ((st & stBSY) == 0) return E_OK;
  122:                 if (drv->Spec.pccard && st == 0xff) break;   /* There is no card */
  123:                 if (sdChkTmout(&tm, READY_TMO, 10)) break;
  124:         }
  125:         return ERR_CMDBUSY;
  126: }
  127: 
  128: /*
  129:  *      ATA (soft) reset
  130:  */
  131: EXPORT  void     ataReset(DrvTab *drv)
  132: {
  133:         UW     iob = drv->IOB;
  134:         UW     reg, tm;
  135:         BOOL   master;
  136: 
  137:         /* Set it to drive 0 */
  138:         ataSetDrive(drv, 0);
  139: 
  140:         /* Check the existence of drive 0 (Master) */
  141:         master = (InB(REG_DRVHEAD) == 0xff && InB(REG_STS) == 0xff) ?
  142:                                                         FALSE : TRUE;
  143: 
  144:         /* Reset pulse output */
  145:         reg = (drv->d.pcc.IOConf[0] & IOC_IO2_NONE)? REG_DEVCTL : REG_DEVCTL2;
  146:         OutB(reg, dcSRST);
  147:         WaitUsec(20);                          /* Wait for "20 usec" */
  148:         OutB(reg, dcNORM);
  149: 
  150:         /* Wait until it becomes ready status:
  151:                         Firstly set it to drive 1 when there is no "Master" */
  152:         for (tm = 0;;) {
  153:                 if (master == TRUE || ataSetDrive(drv, 0x100) == E_OK) {
  154:                         if ((ataStatusIn(drv) & stBSY) == 0) break;
  155:                 }
  156:                 if (drv->Spec.pccard && ataStatusIn(drv) == 0xff) break;
  157:                                                         /* There is no card */
  158:                 if (sdChkTmout(&tm, RESET_TMO, 10)) break;
  159:         }
  160:         /* Set Drive (Master & Slave) to the reset status */
  161:         if (drv->Top != NULL) drv = drv->Top;
  162:         for (; drv != NULL; drv = drv->Next) drv->Reset = TRUE;
  163: }
  164: 
  165: /*
  166:  *      ATA command output
  167:  */
  168: EXPORT  ER       ataCommandOut(DrvTab *drv, W cmd, W cnt, W sec, W cyl, W head)
  169: {
  170:         UW     iob = drv->IOB;
  171: 
  172:         /* Wait for a while until it becomes ready status (BSY = 0) */
  173:         if (ataChkSts(drv, stBSY, 0) != E_OK) goto EEXIT;
  174: 
  175:         /* The drive/header number register setting */
  176:         OutB(REG_DRVHEAD, drDRV(drv->DrvNo) | head);
  177: 
  178:         /* Wait for a while until It gets to "BSY = 0" and "DRDY = 1" */
  179:         if (ataChkSts(drv, stBSY | stDRDY, stDRDY) != E_OK) goto EEXIT;
  180: 
  181:         /* Register setting of the number of sectors */
  182:         if (cnt != NOSET) {
  183:                 OutB(REG_SECCNT, cnt);
  184:         }
  185: 
  186:         /* Register setting of sector number */
  187:         if (sec != NOSET) {
  188:                 OutB(REG_SECNO, sec);
  189:         }
  190: 
  191:         /* Register setting of cylinder number */
  192:         if (cyl != NOSET) {
  193:                 OutB(REG_CYL_L, cyl);
  194:                 OutB(REG_CYL_H, cyl >> 8);
  195:         }
  196: 
  197:         /* Future register setting */
  198:         if ((cmd & 0xFF00) != 0) OutB(REG_FEATURE, cmd >> 8);
  199: 
  200:         /*  Enable interrupt:
  201:                 Interrupt may be caused immediately after the command setting.
  202:                 Therefore, the interrupt shall be enabled at this point. However, the interrupt
  203:                 is not caused yet at the time of writing, so it shall be enabled later.*/
  204: 
  205:         if (cmd != ATA_WRITE && cmd != ATA_MWRITE) ENB_INT(drv);
  206: 
  207:         /* Command register setting */
  208:         OutB(REG_CMD, cmd);
  209:         return E_OK;
  210: 
  211: EEXIT:
  212:         ataReset(drv);                 /* ATA reset*/
  213:         return ERR_CMDBUSY;
  214: }
  215: 
  216: /*
  217:  *      Data input : H unit
  218:  */
  219: EXPORT  void     ataDataIn(DrvTab *drv, UH *buf, W cnt)
  220: {
  221:         UW     iob = drv->IOB;
  222:         UH     d;
  223: 
  224:         pcIO_16bits(); /* 16 bits I/O */
  225:         while (--cnt >= 0) {d = InH(REG_DATA); *buf++ = CnvHIO(d);}
  226:         pcIO_8bits();  /* 8 bits I/O */
  227: }
  228: 
  229: /*
  230:  *      Skip the data input : H unit
  231:  */
  232: EXPORT  void     ataDataSkip(DrvTab *drv, W cnt)
  233: {
  234:         UW     iob = drv->IOB;
  235: 
  236:         pcIO_16bits(); /* 16 bits I/O */
  237:         while (--cnt >= 0) InH(REG_DATA);
  238:         pcIO_8bits();  /* 8 bits I/O */
  239: }
  240: 
  241: /*
  242:  *      Data output : H unit
  243:  *              Output the "0xFFFF" when "buf == NULL"
  244:  */
  245: EXPORT  void     ataDataOut(DrvTab *drv, UH *buf, W cnt)
  246: {
  247:         UW     iob = drv->IOB;
  248: 
  249:         pcIO_16bits(); /* 16 bits I/O */
  250:         if (buf != NULL) {
  251:                 UH    d;
  252:                 while (--cnt >= 0) {d = *buf++;       OutH(REG_DATA, CnvHIO(d));}
  253:         } else {
  254:                 while (--cnt >= 0) OutH(REG_DATA, 0xffff);
  255:         }
  256:         pcIO_8bits();  /* 8 bits I/O */
  257: }