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: }