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:
25: 26: 27:
28: EXPORT void ataSelDrv(DrvTab *drv)
29: {
30:
31: sdSetIntWait(drv);
32:
33:
34: ataStatusIn(drv);
35: }
36:
37: 38: 39:
40: EXPORT void ataIntHdr(DrvTab *drv)
41: {
42: if (drv->EnbInt) {
43: DIS_INT(drv);
44: drv->wrk.ub[0] = ataStatusIn(drv);
45: tk_wup_tsk(drv->WaitTskId);
46: } else {
47:
48: ataStatusIn(drv);
49: }
50: }
51:
52: 53: 54:
55: LOCAL ER WaitInt(DrvTab *drv, W dcnt, W cmd)
56: {
57: ER er;
58: W sts;
59:
60: 61:
62: er = (drv->Aborted) ? E_RLWAI : tk_slp_tsk(TMO_ATACMD);
63:
64:
65: DIS_INT(drv);
66:
67:
68: sts = drv->wrk.ub[0];
69:
70:
71: if (er == E_TMOUT) {
72: return ERR_TMOUT;
73: }
74: if (er == E_RLWAI) {
75: return ERR_ABORT;
76: }
77:
78:
79: if (er < E_OK) return er;
80:
81: if ((sts & stBSY) != 0) {
82: return E_OK;
83: }
84:
85:
86: if ((sts & (stERR | stDRQ)) != (dcnt > 0 ? stDRQ : 0)) {
87: if ((sts & stERR) == 0) {
88: er = ERR_HARD;
89: } else {
90:
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: 101:
102: EXPORT void ataAbort(DrvTab *drv)
103: {
104: ER er;
105:
106: 107:
108: drv->Aborted = TRUE;
109:
110:
111: er = tk_rel_wai(drv->WaitTskId);
112: }
113:
114: 115: 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:
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:
141: if (drv->UseLBA) {
142: sc = lba & 0xFF,
143: cy = (lba >> 8) & 0xFFFF;
144: hd = ((lba >> 24) & 0xF) | drLBA;
145: } else {
146: sc = (lba % drv->nSec) + 1;
147: cy = lba / drv->nSec;
148: hd = cy % drv->nHead;
149: cy /= drv->nHead;
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:
163: er = ataCommandOut(drv, cm, cnt, sc, cy, hd);
164: if (er < E_OK) return er;
165:
166: if (wrt == TRUE) {
167:
168: er = ataWaitData(drv);
169: if (er < E_OK) return er;
170:
171:
172: while (len > 0) {
173: ENB_INT(drv);
174:
175:
176: if (len < nsec) nsec = len;
177: ataDataOut(drv, (UH*)buf, nsec * ATA_HSECSZ);
178: if (buf != NULL) buf += ATA_SECSZ * nsec;
179:
180:
181: er = WaitInt(drv, len -= nsec, cmd);
182: if (er < E_OK) {
183: if (ERR_ATAMSK(er, erABRT) == ERR_ATA(erABRT))
184: er = ERR_RONLY;
185: break;
186: }
187: }
188: } else {
189: do {
190:
191: er = WaitInt(drv, len, cmd);
192: if (er < E_OK || len == 0) break;
193:
194: if (len > nsec) ENB_INT(drv);
195: else nsec = len;
196:
197:
198: ataDataIn(drv, (UH*)buf, nsec * ATA_HSECSZ);
199: buf += ATA_SECSZ * nsec;
200: } while ((len -= nsec) > 0);
201: }
202:
203:
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);
209: }
210: }
211: return er;
212: }