gonzui


Format: Advanced Search

tkernel_2/driver/tef_em1d/sysdsk/src/atacmd.cbare sourcepermlink (0.02 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:  *      atacmd.c     System disk driver
   18:  *
   19:  *      ATA (IDE) Disk command processing
   20:  */
   21: 
   22: #include "sdisk.h"
   23: #include "ata.h"
   24: 
   25: /*
   26:  *      Set the wait-for-interrupt
   27:  */
   28: EXPORT  void     ataSelDrv(DrvTab *drv)
   29: {
   30:         /* Set the wait-for-interrupt */
   31:         sdSetIntWait(drv);
   32: 
   33:         /* Reset the interrupt */
   34:         ataStatusIn(drv);
   35: }
   36: 
   37: /*
   38:  *      Interrupt handler
   39:  */
   40: EXPORT  void     ataIntHdr(DrvTab *drv)
   41: {
   42:         if (drv->EnbInt) {                     /* Valid interrupt?       */
   43:                 DIS_INT(drv);                 /* Disable the interrupt      */
   44:                 drv->wrk.ub[0] = ataStatusIn(drv); /* Clear the interrupt     */
   45:                 tk_wup_tsk(drv->WaitTskId);   /* Wake up the idle task  */
   46:         } else {
   47:                 /* Illegal interrupt : Clear the interrupt */
   48:                 ataStatusIn(drv);
   49:         }
   50: }
   51: 
   52: /*
   53:  *      Wait-for-interrupt
   54:  */
   55: LOCAL   ER        WaitInt(DrvTab *drv, W dcnt, W cmd)
   56: {
   57:         ER     er;
   58:         W      sts;
   59: 
   60:         /* Waken up from the interrupt handler, or wait until the time-out.
   61:                 However, do no wait if it is already aborted */
   62:         er = (drv->Aborted) ? E_RLWAI : tk_slp_tsk(TMO_ATACMD);
   63: 
   64:         /* Disable interrupt */
   65:         DIS_INT(drv);
   66: 
   67:         /* Fetch the status */
   68:         sts = drv->wrk.ub[0];
   69: 
   70:         /* Time-out or abort request */
   71:         if (er == E_TMOUT) {
   72:                 return ERR_TMOUT;
   73:         }
   74:         if (er == E_RLWAI) {
   75:                 return ERR_ABORT;
   76:         }
   77: 
   78:         /* Other errors */
   79:         if (er < E_OK) return er;
   80: 
   81:         if ((sts & stBSY) != 0) {
   82:                 return E_OK;
   83:         }
   84: 
   85:         /* Error occurs when error exit(ERR = 1) or "DRQ != drq" */
   86:         if ((sts & (stERR | stDRQ)) != (dcnt > 0 ? stDRQ : 0)) {
   87:                 if ((sts & stERR) == 0) {
   88:                         er = ERR_HARD;
   89:                 } else {
   90:                         /* er = DF UNC MC IDNF MCR ABRT TK0 AMNF */
   91:                         er = (ataErrorIn(drv) & 0x7F) | ((sts << 2) & 0x80);
   92:                         er = ERR_ATA(er);
   93:                 }
   94:                 return er;
   95:         }
   96:         return E_OK;
   97: }
   98: 
   99: /*
  100:  *      Abort processing
  101:  */
  102: EXPORT  void     ataAbort(DrvTab *drv)
  103: {
  104:         ER     er;
  105: 
  106:         /* Main task may be in "READY" status.
  107:                         Therefore, an abort flag shall be set up. */
  108:         drv->Aborted = TRUE;
  109: 
  110:         /* Forcibly release the wait-for-main task (WaitInt)  */
  111:         er = tk_rel_wai(drv->WaitTskId);
  112: }
  113: 
  114: /*
  115:  *      ATA command execution
  116:  */
  117: EXPORT  ER       ataCmd(DrvTab *drv, W cmd, UW lba, W len, void *buf)
  118: {
  119:         ER     er;
  120:         W      cm, cnt, nsec, sc, cy, hd;
  121:         BOOL   wrt;
  122: 
  123: #define ATA_HSECSZ      (ATA_SECSZ / sizeof(H))
  124: 
  125:         wrt = FALSE;
  126:         nsec = 1;
  127:         cnt = sc = cy = NOSET;
  128:         hd = 0;
  129: 
  130:         switch(cm = cmd) {
  131:         case ATA_WRITE:
  132:                 wrt = TRUE;
  133:         case ATA_READ:
  134:                 /* Count setting for "R/W-MULTIPLE" */
  135:                 nsec = drv->MultiCnt;
  136:                 if (nsec == 0 || len == 1) nsec = 1;
  137:                 else if (nsec > 1) {
  138:                         cm = (wrt) ? ATA_MWRITE : ATA_MREAD;
  139:                 }
  140:                 /* Logical block number -> Conversion to  CHS / LBA number */
  141:                 if (drv->UseLBA) {                    /* Use LBA */
  142:                         sc = lba & 0xFF,             /* sec: LBA 00-07 */
  143:                         cy = (lba >> 8) & 0xFFFF;    /* cyl: LBA 08-23 */
  144:                         hd = ((lba >> 24) & 0xF) | drLBA; /* head:LBA 24-27 */
  145:                 } else {                              /*  Use CHS*/
  146:                         sc = (lba % drv->nSec) + 1;  /* sec */
  147:                         cy = lba / drv->nSec;
  148:                         hd = cy % drv->nHead;                /* head */
  149:                         cy /= drv->nHead;            /* cyl */
  150:                 }
  151:                 cnt = len;
  152:                 break;
  153:         case ATA_SETMULTI:
  154:                 cnt = drv->MultiCnt;
  155:                 break;
  156:         case ATA_IDENTIFY:
  157:                 break;
  158:         default:
  159:                 return ERR_ATA(erABRT);
  160:         }
  161: 
  162:         /* ATA command output */
  163:         er = ataCommandOut(drv, cm, cnt, sc, cy, hd);
  164:         if (er < E_OK) return er;
  165: 
  166:         if (wrt == TRUE) {
  167:                 /* Wait to initially transfer for "nsec" sector  */
  168:                 er = ataWaitData(drv);
  169:                 if (er < E_OK) return er;
  170: 
  171:                 /* Write data by each "nsec" sector and receive an interrupt */
  172:                 while (len > 0) {
  173:                         ENB_INT(drv);                        /* Enable interrupt */
  174: 
  175:                         /* Writing of data : There is also "buf == NULL" */
  176:                         if (len < nsec) nsec = len;
  177:                         ataDataOut(drv, (UH*)buf, nsec * ATA_HSECSZ);
  178:                         if (buf != NULL) buf += ATA_SECSZ * nsec;
  179: 
  180:                         /* Wait-for-interrupt of completion of writing */
  181:                         er = WaitInt(drv, len -= nsec, cmd);
  182:                         if (er < E_OK) {     /* "ABRT" shall be "ERR_RONLY" */
  183:                                 if (ERR_ATAMSK(er, erABRT) == ERR_ATA(erABRT))
  184:                                         er = ERR_RONLY;
  185:                                 break;
  186:                         }
  187:                 }
  188:         } else {
  189:                 do {
  190:                         /* Wait-for-interrupt of completion of reading */
  191:                         er = WaitInt(drv, len, cmd);
  192:                         if (er < E_OK || len == 0) break;
  193: 
  194:                         if (len > nsec)      ENB_INT(drv);        /* Enable the next interrupt */
  195:                         else         nsec = len;    /* Exit    */
  196: 
  197:                         /* Read data */
  198:                         ataDataIn(drv, (UH*)buf, nsec * ATA_HSECSZ);
  199:                         buf += ATA_SECSZ * nsec;
  200:                 } while ((len -= nsec) > 0);
  201:         }
  202: 
  203:         /* Post-error processing*/
  204:         if (er < E_OK) {
  205:                 if (((ERR_ATAMSK(er, erABRT) == ERR_ATA(erABRT))
  206:                                                 && cmd == ATA_READ) ||
  207:                                 er == ERR_TMOUT || er == ERR_HARD) {
  208:                         ataReset(drv);               /* ATA-reset */
  209:                 }
  210:         }
  211:         return er;
  212: }