1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15:
16:
17: 18: 19: 20: 21:
22:
23: #include "sdisk.h"
24:
25: 26: 27:
28: LOCAL DrvTab *CheckDrvTab(DrvTab *drv, INT devid)
29: {
30: for (; drv != NULL; drv = drv->Next) {
31: if (devid >= drv->DevId &&
32: devid <= drv->DevId + drv->nSUnit) break;
33: }
34: if (drv != NULL) {
35:
36: drv->CurSUnit = devid - drv->DevId;
37: }
38: return drv;
39: }
40:
41: 42: 43:
44: EXPORT INT CheckSize(W datacnt, W size)
45: {
46: if (datacnt >= size) return E_OK;
47: return (datacnt == 0) ? size : E_PAR;
48: }
49:
50: 51: 52:
53: LOCAL INT accDISKEVENT(DrvTab *drv, T_DEVREQ *req)
54: {
55: if (req->cmd == TDC_READ) *((ID*)req->buf) = drv->MbfId;
56: else drv->MbfId = *((ID*)req->buf);
57: return sizeof(ID);
58: }
59:
60: 61: 62:
63: LOCAL INT accDISKINFO(DrvTab *drv, T_DEVREQ *req)
64: {
65: sdMakeDiskInfo(drv, (DiskInfo*)req->buf);
66: return sizeof(DiskInfo);
67: }
68:
69: 70: 71:
72: LOCAL INT accDISKFORMAT(DrvTab *drv, T_DEVREQ *req)
73: {
74: ER er, err;
75:
76:
77: if (drv->Spec.readonly) return E_RONLY;
78:
79:
80: er = (*(drv->Format))(drv, ((DiskFormat*)req->buf), req->size);
81:
82: 83:
84: if (er != E_PAR && drv->CurSUnit == 0) {
85: err = sdRegistDevice(drv);
86: if (er == E_OK) er = err;
87: }
88: return (er >= E_OK) ? sizeof(DiskFormat) : er;
89: }
90:
91: 92: 93:
94: LOCAL INT accDISKINIT(DrvTab *drv, T_DEVREQ *req)
95: {
96: ER er;
97:
98:
99: if (*((DiskInit*)req->buf) != DISKINIT) return E_PAR;
100:
101:
102: if (drv->CurSUnit == 0) {
103:
104: if ((er = sdRegistDevice(drv)) < E_OK) return er;
105: }
106: return sizeof(DiskInit);
107: }
108:
109: 110: 111:
112: LOCAL INT accDISKMEMADR(DrvTab *drv, T_DEVREQ *req)
113: {
114:
115: if (drv->Spec.accif != MEM_ACCIF) return E_NOSPT;
116:
117: *((void**)req->buf) = (void*)drv->IOB;
118: return sizeof(void*);
119: }
120:
121: 122: 123:
124: LOCAL INT accDISKPARTINFO(DrvTab *drv, T_DEVREQ *req)
125: {
126:
127: if (drv->CurSUnit == 0) return E_PAR;
128:
129: ((DiskPartInfo*)req->buf)->systemid =
130: drv->s.SUnit[drv->CurSUnit].SystemId;
131: ((DiskPartInfo*)req->buf)->startblock =
132: drv->s.SUnit[drv->CurSUnit].StartBlock;
133: ((DiskPartInfo*)req->buf)->endblock =
134: drv->s.SUnit[drv->CurSUnit].EndBlock - 1;
135: return sizeof(DiskPartInfo);
136: }
137:
138: 139: 140:
141: LOCAL INT accDISKCHSINFO(DrvTab *drv, T_DEVREQ *req)
142: {
143: ((DiskCHSInfo*)req->buf)->cylinder = drv->nXCyl;
144: ((DiskCHSInfo*)req->buf)->head = drv->nXHead;
145: ((DiskCHSInfo*)req->buf)->sector = drv->nXSec;
146: return sizeof(DiskCHSInfo);
147: }
148:
149: 150: 151:
152: LOCAL INT accDISKIDINFO(DrvTab *drv, T_DEVREQ *req)
153: {
154:
155: if (drv->Spec.accif != ATA_ACCIF &&
156: drv->Spec.accif != MMC_ACCIF) return E_NOSPT;
157:
158: MEMCPY(req->buf, drv->Ident, IDENT_DTSZ);
159: return IDENT_DTSZ;
160: }
161:
162: 163: 164:
165: LOCAL INT accDISKCMD(DrvTab *drv, T_DEVREQ *req)
166: {
167:
168: return E_NOSPT;
169: }
170:
171: 172: 173:
174: #define MBR_DTSZ (512 + 4)
175:
176: LOCAL INT accDISKMBR(DrvTab *drv, T_DEVREQ *req)
177: {
178: ER er;
179: UW *mp;
180: BOOL write;
181:
182:
183: if (!drv->SuptMBR || drv->CurSUnit != 0) return E_PAR;
184:
185: if (req->size != MBR_DTSZ) return E_PAR;
186:
187:
188: mp = (UW*)req->buf;
189: if (*mp == (UW)CH4toW('M','B','R','R')) write = FALSE;
190: else if (*mp == (UW)CH4toW('M','B','R','W')
191: && !drv->Spec.readonly) write = TRUE;
192: else return E_PAR;
193:
194:
195: er = (*(drv->ReadWrite))(drv, 0, 1, (void*)(++mp), write);
196:
197: if (er >= E_OK && write) {
198:
199: (*(drv->DiskInit))(drv);
200: }
201: return (er >= E_OK) ? MBR_DTSZ : er;
202: }
203:
204: 205: 206:
207: LOCAL ER ReadWriteReq(DrvTab *drv, T_DEVREQ *req)
208: {
209: #define nDnT 10
210: static const struct {
211: W dn;
212: UW dsz:16;
213: UW nomedia:1;
214: UW readable:1;
215: UW writable:1;
216: INT (*acc)(DrvTab*, T_DEVREQ*);
217: } DnT[nDnT] = {
218: { DN_DISKEVENT,
219: sizeof(ID), 1, 1, 1, accDISKEVENT },
220: { DN_DISKINFO,
221: sizeof(DiskInfo), 0, 1, 0, accDISKINFO },
222: { DN_DISKFORMAT,
223: sizeof(DiskFormat), 0, 0, 1, accDISKFORMAT },
224: { DN_DISKINIT,
225: sizeof(DiskInit), 0, 0, 1, accDISKINIT },
226: { DN_DISKMEMADR,
227: sizeof(void*), 0, 1, 0, accDISKMEMADR },
228: { DN_DISKPARTINFO,
229: sizeof(DiskPartInfo), 0, 1, 0, accDISKPARTINFO },
230: { DN_DISKCHSINFO,
231: sizeof(DiskCHSInfo), 0, 1, 0, accDISKCHSINFO },
232: { DN_DISKIDINFO,
233: IDENT_DTSZ, 1, 1, 0, accDISKIDINFO },
234: { (-999999),
235: MBR_DTSZ, 0, 1, 0, accDISKMBR },
236: { DN_DISKCMD,
237: sizeof(DiskCmd), 0, 0, 1, accDISKCMD }
238: };
239: ER er;
240: W cnt, dn, i, edn;
241:
242:
243: if ((cnt = req->size) < 0)
244: {er = E_PAR; goto E_EXIT;}
245:
246:
247: er = tk_set_tsp(TSK_SELF, &req->tskspc);
248: if (er < E_OK) goto E_EXIT;
249:
250: if ((dn = req->start) >= 0) {
251: if (!drv->MediaOK) {
252: er = ERR_NOMEDIA;
253: } else if (req->cmd == TDC_WRITE && drv->Spec.readonly) {
254: er = E_RONLY;
255: } else {
256:
257: dn += drv->s.SUnit[drv->CurSUnit].StartBlock;
258: edn = drv->s.SUnit[drv->CurSUnit].EndBlock;
259:
260: if (dn >= edn || (edn - dn) < cnt) {
261: er = E_PAR;
262: } else if (cnt == 0) {
263: er = edn - dn;
264: } else {
265: er = (*(drv->ReadWrite))(drv, dn, cnt,
266: req->buf, req->cmd == TDC_WRITE);
267: }
268: }
269:
270: } else {
271: for (i = 0; i < nDnT && DnT[i].dn != dn; i++);
272:
273: if (i >= nDnT) {
274: er = E_PAR;
275: } else if (DnT[i].acc == NULL) {
276: er = E_NOSPT;
277: } else if (!drv->MediaOK && DnT[i].nomedia == 0) {
278: er = ERR_NOMEDIA;
279: } else if (((req->cmd == TDC_READ) ?
280: DnT[i].readable : DnT[i].writable) == 0) {
281: er = E_PAR;
282: } else if ((er = CheckSize(cnt, DnT[i].dsz)) == E_OK) {
283: er = (*(DnT[i].acc))(drv, req);
284: }
285: }
286:
287: if (er < E_OK) goto E_EXIT;
288: req->asize = (INT)er;
289: return E_OK;
290:
291: E_EXIT:
292: return er;
293: }
294:
295: 296: 297:
298: EXPORT ER sdAbortFn(T_DEVREQ *req, GDI gdi)
299: {
300: DrvTab *drv;
301:
302: drv = CheckDrvTab(GDI_exinf(gdi), req->devid);
303: if (! drv) return E_OK;
304:
305:
306: if (!drv->Suspended) {
307:
308:
309: if (drv->CurReq && drv->CurReq == req) {
310:
311: (*(drv->Abort))(drv);
312:
313: 314:
315: Lock(&drv->ProcLock);
316: Unlock(&drv->ProcLock);
317: }
318: }
319: return E_OK;
320: }
321:
322: 323: 324:
325: LOCAL ER SuspendReq(DrvTab *drv)
326: {
327:
328: if (!drv->Suspended) {
329:
330: 331: 332:
333:
334: Lock(&drv->ProcLock);
335:
336: drv->Suspended = TRUE;
337:
338:
339: sdPowerOff(drv, CP_SUSPEND);
340:
341:
342: drv->Reset = TRUE;
343:
344:
345: }
346: return E_OK;
347: }
348:
349: 350: 351:
352: LOCAL ER ResumeReq(DrvTab *drv)
353: {
354:
355: if (drv->Suspended) {
356:
357: sdPowerOn(drv, CP_RESUME);
358:
359:
360: drv->Suspended = FALSE;
361: Unlock(&drv->ProcLock);
362: }
363: return E_OK;
364: }
365:
366: 367: 368:
369: EXPORT INT sdEventFn(INT evttyp, void *evtinf, GDI gdi)
370: {
371: ER er;
372: DrvTab *drv;
373:
374: drv = CheckDrvTab(GDI_exinf(gdi), GDI_devid(gdi));
375: if (! drv) return E_NOEXS;
376:
377: switch (evttyp) {
378: case TDV_SUSPEND:
379: er = SuspendReq(drv);
380: break;
381: case TDV_RESUME:
382: er = ResumeReq(drv);
383: break;
384: case TDV_CARDEVT:
385: Lock(&drv->ProcLock);
386: drv->CurSUnit = 0;
387: er = sdCardEvent(evttyp, evtinf, gdi);
388: Unlock(&drv->ProcLock);
389: break;
390: case TDV_USBEVT:
391: er = E_NOSPT;
392: break;
393: default:
394: er = E_PAR;
395: }
396: return er;
397: }
398:
399: 400: 401:
402: EXPORT ER sdOpenFn(ID devid, UINT omode, GDI gdi)
403: {
404: ER er;
405: DrvTab *drv;
406:
407: drv = CheckDrvTab(GDI_exinf(gdi), devid);
408: if (! drv) return E_NOEXS;
409:
410: Lock(&drv->ProcLock);
411:
412:
413: if (drv->DriveOK && drv->OpenCnt == 0) {
414: er = (*(drv->Misc))(drv, (W)DC_OPEN);
415: if (er < E_OK) goto E_EXIT;
416: }
417:
418: er = ERR_NOMEDIA;
419:
420:
421: if (!drv->DriveOK) goto E_EXIT;
422:
423:
424: if (!drv->MediaOK) {
425:
426: if (drv->CurSUnit != 0) goto E_EXIT;
427: }
428:
429: 430: 431:
432: if (drv->CurSUnit != 0 &&
433: drv->s.SUnit[drv->CurSUnit].StartBlock >=
434: drv->s.SUnit[drv->CurSUnit].EndBlock) goto E_EXIT;
435:
436:
437: drv->s.SUnit[drv->CurSUnit].OpenCnt++;
438:
439:
440: er = E_OK;
441: if (drv->OpenCnt++ == 0) {
442: if ((er = sdPowerOn(drv, CP_POWERON)) < E_OK) {
443: drv->OpenCnt--;
444: drv->s.SUnit[drv->CurSUnit].OpenCnt--;
445: }
446: }
447: E_EXIT:
448: Unlock(&drv->ProcLock);
449: return er;
450: }
451:
452: 453: 454:
455: EXPORT ER sdCloseFn(ID devid, UINT option, GDI gdi)
456: {
457: DrvTab *drv;
458:
459: drv = CheckDrvTab(GDI_exinf(gdi), devid);
460: if (! drv) return E_NOEXS;
461:
462: Lock(&drv->ProcLock);
463:
464:
465: if (drv->s.SUnit[drv->CurSUnit].OpenCnt > 0) {
466: drv->s.SUnit[drv->CurSUnit].OpenCnt--;
467: }
468:
469:
470: if (--drv->OpenCnt <= 0) {
471: drv->OpenCnt = 0;
472: if (drv->DriveOK) {
473:
474: (*(drv->Misc))(drv, (option & TD_EJECT) ?
475: DC_CLOSEALL : DC_CLOSE);
476:
477: sdPowerOff(drv, CP_POFF);
478: }
479: }
480:
481: Unlock(&drv->ProcLock);
482: return E_OK;
483: }
484:
485: 486: 487:
488: EXPORT void sdAcceptRequest(DrvTab *drv)
489: {
490: T_DEVREQ *req;
491: INT er;
492:
493:
494: for (;;) {
495:
496: er = GDI_Accept(&req, NORMAL_REQPTN, drv->ReqTmout, drv->Gdi);
497:
498: if (er < E_OK || (er & DRP_NORMREQ) == 0) {
499: if(er >= E_OK || er == E_TMOUT) {
500:
501: (*(drv->Misc))(drv, DC_TSKTMO);
502: }
503: continue;
504: }
505:
506: drv = CheckDrvTab(drv, req->devid);
507: if (! drv) er = E_NOEXS;
508: else {
509: Lock(&drv->ProcLock);
510: if (!drv->DriveOK) er = ERR_NOMEDIA;
511: else {
512: drv->CurReq = req;
513: er = ReadWriteReq(drv, req);
514: drv->CurReq = NULL;
515: drv->Aborted = FALSE;
516: }
517: Unlock(&drv->ProcLock);
518: }
519:
520:
521: req->error = er;
522: GDI_Reply(req, drv->Gdi);
523: }
524: }