1:     2:     3:     4:     5:     6:     7:     8:     9:    10:    11:    12:    13: 
   14: 
   15: 
   16:    17:    18:    19:    20: 
   21: 
   22: #include "sdisk.h"
   23: #include "ata.h"
   24: #include "pccardio.h"
   25: 
   26:    27:    28: 
   29: #define STATUS_TMO      (50 * 1000)          
   30: #define READY_TMO       (10 * 1000)           
   31: #define RESET_TMO       (31 * 1000)           
   32: 
   33:    34:    35: 
   36: EXPORT  W        ataStatusIn(DrvTab *drv)
   37: {
   38:         return InForceB(drv->IOB, REG_STS);
   39: }
   40: 
   41:    42:    43: 
   44: EXPORT  W        ataErrorIn(DrvTab *drv)
   45: {
   46:         UW     iob = drv->IOB;
   47: 
   48:         return InB(REG_ERR);
   49: }
   50: 
   51:    52:    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:    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:    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);           
   87:         if (InB(REG_DRVHEAD) == dno) return E_OK;
   88:         return ERR_NOPORT;
   89: }
   90: 
   91:    92:    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:   105: 
  106: EXPORT  ER       ataWaitData(DrvTab *drv)
  107: {
  108:         
  109:         return ataChkSts(drv, stBSY | stDRDY | stDRQ, stDRDY | stDRQ);
  110: }
  111: 
  112:   113:   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;   
  123:                 if (sdChkTmout(&tm, READY_TMO, 10)) break;
  124:         }
  125:         return ERR_CMDBUSY;
  126: }
  127: 
  128:   129:   130: 
  131: EXPORT  void     ataReset(DrvTab *drv)
  132: {
  133:         UW     iob = drv->IOB;
  134:         UW     reg, tm;
  135:         BOOL   master;
  136: 
  137:         
  138:         ataSetDrive(drv, 0);
  139: 
  140:         
  141:         master = (InB(REG_DRVHEAD) == 0xff && InB(REG_STS) == 0xff) ?
  142:                                                         FALSE : TRUE;
  143: 
  144:         
  145:         reg = (drv->d.pcc.IOConf[0] & IOC_IO2_NONE)? REG_DEVCTL : REG_DEVCTL2;
  146:         OutB(reg, dcSRST);
  147:         WaitUsec(20);                          
  148:         OutB(reg, dcNORM);
  149: 
  150:           151: 
  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:                                                         
  158:                 if (sdChkTmout(&tm, RESET_TMO, 10)) break;
  159:         }
  160:         
  161:         if (drv->Top != NULL) drv = drv->Top;
  162:         for (; drv != NULL; drv = drv->Next) drv->Reset = TRUE;
  163: }
  164: 
  165:   166:   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:         
  173:         if (ataChkSts(drv, stBSY, 0) != E_OK) goto EEXIT;
  174: 
  175:         
  176:         OutB(REG_DRVHEAD, drDRV(drv->DrvNo) | head);
  177: 
  178:         
  179:         if (ataChkSts(drv, stBSY | stDRDY, stDRDY) != E_OK) goto EEXIT;
  180: 
  181:         
  182:         if (cnt != NOSET) {
  183:                 OutB(REG_SECCNT, cnt);
  184:         }
  185: 
  186:         
  187:         if (sec != NOSET) {
  188:                 OutB(REG_SECNO, sec);
  189:         }
  190: 
  191:         
  192:         if (cyl != NOSET) {
  193:                 OutB(REG_CYL_L, cyl);
  194:                 OutB(REG_CYL_H, cyl >> 8);
  195:         }
  196: 
  197:         
  198:         if ((cmd & 0xFF00) != 0) OutB(REG_FEATURE, cmd >> 8);
  199: 
  200:           201:   202:   203: 
  204: 
  205:         if (cmd != ATA_WRITE && cmd != ATA_MWRITE) ENB_INT(drv);
  206: 
  207:         
  208:         OutB(REG_CMD, cmd);
  209:         return E_OK;
  210: 
  211: EEXIT:
  212:         ataReset(drv);                 
  213:         return ERR_CMDBUSY;
  214: }
  215: 
  216:   217:   218: 
  219: EXPORT  void     ataDataIn(DrvTab *drv, UH *buf, W cnt)
  220: {
  221:         UW     iob = drv->IOB;
  222:         UH     d;
  223: 
  224:         pcIO_16bits(); 
  225:         while (--cnt >= 0) {d = InH(REG_DATA); *buf++ = CnvHIO(d);}
  226:         pcIO_8bits();  
  227: }
  228: 
  229:   230:   231: 
  232: EXPORT  void     ataDataSkip(DrvTab *drv, W cnt)
  233: {
  234:         UW     iob = drv->IOB;
  235: 
  236:         pcIO_16bits(); 
  237:         while (--cnt >= 0) InH(REG_DATA);
  238:         pcIO_8bits();  
  239: }
  240: 
  241:   242:   243:   244: 
  245: EXPORT  void     ataDataOut(DrvTab *drv, UH *buf, W cnt)
  246: {
  247:         UW     iob = drv->IOB;
  248: 
  249:         pcIO_16bits(); 
  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();  
  257: }