1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16:
17: 18: 19: 20:
21:
22: #include "sysmgr.h"
23: #include <sys/rominfo.h>
24: #include <sys/ssid.h>
25:
26: LOCAL OpnCB *OpnCBtbl;
27: LOCAL QUEUE FreeOpnCB;
28: LOCAL INT MaxOpnDev;
29:
30: #define DD(opncb) ( (opncb) - OpnCBtbl + 1 )
31: #define OPNCB(dd) ( OpnCBtbl + ((dd) - 1) )
32:
33: LOCAL ReqCB *ReqCBtbl;
34: LOCAL QUEUE FreeReqCB;
35: LOCAL INT MaxReqDev;
36:
37: #define REQID(reqcb) ( (reqcb) - ReqCBtbl + 1 )
38: #define REQCB(reqid) ( ReqCBtbl + ((reqid) - 1) )
39:
40: #define DEVREQ_REQCB(devreq) ((ReqCB*)((B*)(devreq) - offsetof(ReqCB, req)))
41:
42: 43: 44:
45: LOCAL ResCB* GetResCB( ID ssid, ID tskid )
46: {
47: ResCB *rescb;
48:
49: rescb = GetResBlk(ssid, tskid);
50: if ( rescb == NULL ) {
51: return NULL;
52: }
53:
54: LockDM();
55:
56:
57: if ( rescb->openq.next == NULL ) {
58:
59: QueInit(&rescb->openq);
60: }
61:
62: UnlockDM();
63:
64: return rescb;
65: }
66:
67: 68: 69:
70: EXPORT ER check_devdesc( ID dd, UINT mode, OpnCB **p_opncb )
71: {
72: OpnCB *opncb;
73:
74: if ( dd < 1 || dd > MaxOpnDev ) {
75: return E_ID;
76: }
77: opncb = OPNCB(dd);
78: if ( opncb->resid <= 0 ) {
79: return E_ID;
80: }
81:
82: if ( opncb->resid != tk_get_rid(TSK_SELF) ) {
83: return E_OACV;
84: }
85:
86: if ( mode != 0 ) {
87: if ( (opncb->omode & mode) == 0 ) {
88: return E_OACV;
89: }
90: }
91:
92: *p_opncb = opncb;
93: return E_OK;
94: }
95:
96: 97: 98:
99: LOCAL ReqCB* check_reqid( ID reqid, OpnCB *opncb )
100: {
101: ReqCB *reqcb;
102:
103: if ( reqid < 1 || reqid > MaxReqDev ) {
104: return NULL;
105: }
106: reqcb = REQCB(reqid);
107: if ( reqcb->opncb != opncb ) {
108: return NULL;
109: }
110:
111: return reqcb;
112: }
113:
114: 115: 116:
117: LOCAL OpnCB* newOpnCB( DevCB *devcb, INT unitno, UINT omode, ResCB *rescb )
118: {
119: OpnCB *opncb;
120:
121:
122: opncb = (OpnCB*)QueRemoveNext(&FreeOpnCB);
123: if ( opncb == NULL ) {
124: return NULL;
125: }
126:
127:
128: QueInsert(&opncb->q, &devcb->openq);
129: QueInsert(&opncb->resq, &rescb->openq);
130:
131: opncb->devcb = devcb;
132: opncb->unitno = unitno;
133: opncb->omode = omode;
134: QueInit(&opncb->requestq);
135: opncb->syncreq = 0;
136: opncb->waitone = 0;
137: opncb->nwaireq = 0;
138: opncb->abort_tskid = 0;
139:
140: opncb->resid = 0;
141:
142: return opncb;
143: }
144:
145: 146: 147:
148: LOCAL void delOpnCB( OpnCB *opncb )
149: {
150: QueRemove(&opncb->q);
151: QueRemove(&opncb->resq);
152:
153: QueInsert(&opncb->q, &FreeOpnCB);
154:
155: opncb->resid = 0;
156: }
157:
158: 159: 160:
161: LOCAL ReqCB* newReqCB( OpnCB *opncb )
162: {
163: ReqCB *reqcb;
164:
165:
166: reqcb = (ReqCB*)QueRemoveNext(&FreeReqCB);
167: if ( reqcb == NULL ) {
168: return NULL;
169: }
170:
171:
172: QueInsert(&reqcb->q, &opncb->requestq);
173:
174: reqcb->opncb = opncb;
175:
176: return reqcb;
177: }
178:
179: 180: 181:
182: LOCAL void delReqCB( ReqCB *reqcb )
183: {
184: QueRemove(&reqcb->q);
185:
186: QueInsert(&reqcb->q, &FreeReqCB);
187: reqcb->opncb = NULL;
188: }
189:
190:
191:
192: 193: 194: 195: 196: 197: 198: 199:
200: LOCAL BOOL enterSyncWait( QUEUE *syncq, WaitQ *entry )
201: {
202: BOOL wait;
203:
204: wait = !isQueEmpty(syncq);
205:
206: entry->tskid = tk_get_tid();
207: QueInsert(&entry->q, syncq);
208:
209: return wait;
210: }
211:
212: 213: 214: 215: 216:
217: LOCAL void leaveSyncWait( QUEUE *syncq, WaitQ *entry )
218: {
219: QueRemove(&entry->q);
220:
221: if ( !isQueEmpty(syncq) ) {
222: SyncSignalDM(((WaitQ*)syncq->next)->tskid);
223: }
224: }
225:
226: 227: 228:
229: LOCAL ER chkopenmode( DevCB *devcb, INT unitno, UINT omode )
230: {
231: QUEUE *q;
232: OpnCB *opncb;
233: INT read, write, rexcl, wexcl;
234:
235: if ( (omode & TD_UPDATE) == 0 ) {
236: return E_PAR;
237: }
238:
239:
240: read = write = rexcl = wexcl = 0;
241: for ( q = devcb->openq.next; q != &devcb->openq; q = q->next ) {
242: opncb = (OpnCB*)q;
243:
244: if ( unitno == 0 || opncb->unitno == 0
245: || opncb->unitno == unitno ) {
246: if ( (opncb->omode & TD_READ) != 0 ) {
247: read++;
248: }
249: if ( (opncb->omode & TD_WRITE) != 0 ) {
250: write++;
251: }
252: if ( (opncb->omode & (TD_EXCL|TD_REXCL)) != 0) {
253: rexcl++;
254: }
255: if ( (opncb->omode & (TD_EXCL|TD_WEXCL)) != 0) {
256: wexcl++;
257: }
258: }
259: }
260:
261:
262: if ( (omode & (TD_EXCL|TD_REXCL)) != 0 && read > 0 ) {
263: return E_BUSY;
264: }
265: if ( (omode & (TD_EXCL|TD_WEXCL)) != 0 && write > 0 ) {
266: return E_BUSY;
267: }
268: if ( (omode & TD_READ) != 0 && rexcl > 0 ) {
269: return E_BUSY;
270: }
271: if ( (omode & TD_WRITE) != 0 && wexcl > 0 ) {
272: return E_BUSY;
273: }
274:
275: return E_OK;
276: }
277:
278: 279: 280: 281: 282: 283:
284: LOCAL BOOL chkopen( DevCB *devcb, INT unitno, OpnCB *opncb )
285: {
286: QUEUE *q;
287:
288: for ( q = devcb->openq.next; q != &devcb->openq; q = q->next ) {
289: if ( (OpnCB*)q != opncb &&
290: ((OpnCB*)q)->unitno == unitno &&
291: ((OpnCB*)q)->resid != 0 ) {
292: return TRUE;
293: }
294: }
295: return FALSE;
296: }
297:
298: 299: 300:
301: EXPORT ID _tk_opn_dev( CONST UB *devnm, UINT omode )
302: {
303: UB pdevnm[L_DEVNM + 1];
304: INT unitno;
305: ResCB *rescb;
306: DevCB *devcb;
307: OpnCB *opncb;
308: WaitQ waiq;
309: ER ercd;
310:
311: ercd = ChkSpaceBstrR(devnm, 0);
312: if ( ercd < E_OK ) {
313: goto err_ret1;
314: }
315:
316: unitno = phydevnm(pdevnm, devnm);
317:
318:
319: rescb = GetResCB(DEVICE_SVC, TSK_SELF);
320: if ( rescb == NULL ) {
321: ercd = E_CTX;
322: goto err_ret1;
323: }
324:
325: LockDM();
326:
327:
328: devcb = searchDevCB(pdevnm);
329: if ( devcb == NULL || unitno > devcb->ddev.nsub ) {
330: ercd = E_NOEXS;
331: goto err_ret2;
332: }
333:
334:
335: ercd = chkopenmode(devcb, unitno, omode);
336: if ( ercd < E_OK ) {
337: goto err_ret2;
338: }
339:
340:
341: opncb = newOpnCB(devcb, unitno, omode, rescb);
342: if ( opncb == NULL ) {
343: ercd = E_LIMIT;
344: goto err_ret2;
345: }
346:
347: 348:
349: if ( enterSyncWait(&devcb->syncq, &waiq) ) {
350:
351: UnlockDM();
352: SyncWaitDM();
353: LockDM();
354: }
355:
356:
357: if ( ! ( chkopen(devcb, unitno, opncb) &&
358: (devcb->ddev.drvatr & TDA_OPENREQ) == 0 ) ) {
359:
360: UnlockDM();
361: ercd = call_openfn(devcb, DEVID(devcb, unitno), omode);
362: LockDM();
363: if ( ercd < E_OK ) {
364: goto err_ret3;
365: }
366: }
367: opncb->resid = tk_get_rid(TSK_SELF);
368:
369:
370:
371: leaveSyncWait(&devcb->syncq, &waiq);
372: UnlockDM();
373:
374: return DD(opncb);
375:
376: err_ret3:
377: delOpnCB(opncb);
378: leaveSyncWait(&devcb->syncq, &waiq);
379: err_ret2:
380: UnlockDM();
381: err_ret1:
382: DEBUG_PRINT(("_tk_opn_dev ercd = %d\n", ercd));
383: return ercd;
384: }
385:
386: 387: 388:
389: LOCAL void abort_allrequest( OpnCB *opncb )
390: {
391: DevCB *devcb;
392: ReqCB *reqcb;
393: QUEUE *q;
394:
395:
396: LockDM();
397:
398: devcb = opncb->devcb;
399: opncb->abort_tskid = tk_get_tid();
400: opncb->abort_cnt = 0;
401:
402: LockDAbort();
403: UnlockDM();
404:
405: if ( opncb->nwaireq > 0 ) {
406:
407: reqcb = DEVREQ_REQCB(opncb->waireqlst);
408:
409:
410: call_abortfn(devcb, reqcb->tskid, opncb->waireqlst,
411: opncb->nwaireq);
412: opncb->abort_cnt++;
413: } else {
414:
415: for ( q = opncb->requestq.next;
416: q != &opncb->requestq; q = q->next ) {
417: reqcb = (ReqCB*)q;
418: if ( reqcb->tskid == 0 ) {
419: continue;
420: }
421: reqcb->req.c.abort = TRUE;
422:
423:
424: call_abortfn(devcb, reqcb->tskid, &reqcb->req, 1);
425: opncb->abort_cnt++;
426: }
427: }
428: UnlockDAbort();
429:
430: if ( opncb->abort_cnt > 0 ) {
431:
432: SyncWaitDM();
433: }
434: opncb->abort_tskid = 0;
435:
436:
437: LockDM();
438: while ( !isQueEmpty(&opncb->requestq) ) {
439: reqcb = (ReqCB*)opncb->requestq.next;
440: reqcb->req.c.abort = TRUE;
441:
442:
443: UnlockDM();
444: call_waitfn(devcb, &reqcb->req, 1, TMO_FEVR);
445: LockDM();
446:
447:
448: delReqCB(reqcb);
449: }
450: UnlockDM();
451: }
452:
453: 454: 455:
456: LOCAL ER close_device( OpnCB *opncb, UINT option )
457: {
458: ID devid;
459: DevCB *devcb;
460: INT unitno;
461: WaitQ waiq;
462: ER ercd = E_OK;
463:
464:
465: abort_allrequest(opncb);
466:
467: LockDM();
468:
469: devcb = opncb->devcb;
470: unitno = opncb->unitno;
471: devid = DEVID(devcb, unitno);
472:
473: 474:
475: if ( enterSyncWait(&devcb->syncq, &waiq) ) {
476:
477: UnlockDM();
478: SyncWaitDM();
479: LockDM();
480: }
481:
482:
483: if ( chkopen(devcb, unitno, opncb) ) {
484: if ( (devcb->ddev.drvatr & TDA_OPENREQ) == 0 ) {
485: goto no_drvcall;
486: }
487: option &= ~TD_EJECT;
488: }
489:
490: UnlockDM();
491: ercd = call_closefn(devcb, DEVID(devcb, unitno), option);
492: LockDM();
493:
494: no_drvcall:
495:
496: delOpnCB(opncb);
497:
498:
499: leaveSyncWait(&devcb->syncq, &waiq);
500:
501: UnlockDM();
502:
503: ERCD_PRINT(("close_device ercd = %d\n", ercd));
504:
505: return ercd;
506: }
507:
508: 509: 510:
511: EXPORT ER _tk_cls_dev( ID dd, UINT option )
512: {
513: OpnCB *opncb;
514: ER ercd;
515:
516: LockDM();
517:
518: ercd = check_devdesc(dd, 0, &opncb);
519: if ( ercd < E_OK ) {
520: UnlockDM();
521: goto err_ret;
522: }
523:
524: opncb->resid = -1;
525:
526: UnlockDM();
527:
528:
529: ercd = close_device(opncb, option);
530:
531: err_ret:
532: ERCD_PRINT(("_tk_cls_dev ercd = %d\n", ercd));
533: return ercd;
534: }
535:
536:
537:
538: enum ReqType {
539: AsyncReq,
540: SyncReq
541: };
542:
543: 544: 545:
546: LOCAL ER check_break( void )
547: {
548: T_RTEX rtex;
549: ER ercd;
550:
551: ercd = tk_ref_tex(TSK_SELF, &rtex);
552: if ( ercd < E_OK ) {
553: goto err_ret;
554: }
555:
556: return ( rtex.pendtex != 0 )? E_ABORT: E_OK;
557:
558: err_ret:
559: DEBUG_PRINT(("check_break ercd = %d\n", ercd));
560: return ercd;
561: }
562:
563: 564: 565:
566: LOCAL ID request( ID dd, D start, void *buf, INT size, TMO_U tmout,
567: INT cmd, enum ReqType syncreq )
568: {
569: ATR drvatr;
570: OpnCB *opncb;
571: DevCB *devcb;
572: ReqCB *reqcb;
573: UINT m;
574: ER ercd;
575:
576: LockDM();
577:
578:
579: ercd = check_break();
580: if ( ercd < E_OK ) {
581: goto err_ret1;
582: }
583:
584: m = ( cmd == TDC_READ )? TD_READ: TD_WRITE;
585: ercd = check_devdesc(dd, m, &opncb);
586: if ( ercd < E_OK ) {
587: goto err_ret1;
588: }
589:
590: if ( syncreq == SyncReq ) {
591: 592:
593: if ( opncb->nwaireq > 0 ) { ercd = E_OBJ; goto err_ret1; }
594: opncb->syncreq++;
595: }
596:
597: devcb = opncb->devcb;
598: drvatr = devcb->ddev.drvatr;
599:
600:
601: if ( (drvatr & TDA_DEV_D) == 0 ) {
602: if ( start > 0x7fffffff || start < (-0x7fffffff-1) ) {
603: ercd = E_PAR; goto err_ret2;
604: }
605: }
606:
607:
608: reqcb = newReqCB(opncb);
609: if ( reqcb == NULL ) {
610: ercd = E_LIMIT;
611: goto err_ret2;
612: }
613:
614:
615: MEMSET(&reqcb->req, 0, sizeof(DEVREQ));
616: reqcb->req.c.devid = DEVID(devcb, opncb->unitno);
617: reqcb->req.c.cmd = cmd;
618: if ( (opncb->omode & TD_NOLOCK) != 0 ) {
619: reqcb->req.c.nolock = TRUE;
620: }
621: if ( (drvatr & TDA_DEV_D) == 0 ) {
622: reqcb->req.s.start = start;
623: reqcb->req.s.size = size;
624: reqcb->req.s.buf = buf;
625: } else {
626: reqcb->req.l.start_d = start;
627: reqcb->req.l.size = size;
628: reqcb->req.l.buf = buf;
629: }
630: ercd = tk_get_tsp(TSK_SELF, &reqcb->req.c.tskspc);
631: if ( ercd < E_OK ) {
632: goto err_ret3;
633: }
634:
635:
636: reqcb->tskid = tk_get_tid();
637:
638:
639: UnlockDM();
640: ercd = call_execfn(devcb, &reqcb->req, tmout);
641: LockDM();
642:
643: LockDAbort();
644:
645:
646: reqcb->tskid = 0;
647:
648: 649:
650: if ( opncb->abort_tskid > 0 && --opncb->abort_cnt == 0 ) {
651: SyncSignalDM(opncb->abort_tskid);
652: }
653: UnlockDAbort();
654:
655: if ( ercd < E_OK ) {
656: goto err_ret3;
657: }
658:
659: UnlockDM();
660:
661: return REQID(reqcb);
662:
663: err_ret3:
664: delReqCB(reqcb);
665: err_ret2:
666: if ( syncreq == SyncReq ) {
667: opncb->syncreq--;
668: }
669: err_ret1:
670: UnlockDM();
671: DEBUG_PRINT(("request ercd = %d\n", ercd));
672: return ercd;
673: }
674:
675: 676: 677:
678: LOCAL ID waitcomplete( ID dd, ID reqid, W *asize, ER *ioer,
679: TMO_U tmout, enum ReqType syncreq )
680: {
681: ATR drvatr;
682: OpnCB *opncb;
683: DevCB *devcb;
684: ReqCB *reqcb;
685: DEVREQ *devreq;
686: INT reqno, nreq;
687: ID tskid;
688: BOOL abort;
689: ER ercd;
690:
691: tskid = tk_get_tid();
692:
693: LockDM();
694:
695: ercd = check_devdesc(dd, 0, &opncb);
696: if ( ercd < E_OK ) {
697: goto err_ret1;
698: }
699:
700:
701: abort = FALSE;
702: ercd = check_break();
703: if ( ercd < E_OK ) {
704: if ( syncreq == AsyncReq ) goto err_ret1;
705: abort = TRUE;
706: }
707:
708: devcb = opncb->devcb;
709: drvatr = devcb->ddev.drvatr;
710:
711: if ( reqid == 0 ) {
712:
713: if ( opncb->nwaireq > 0 || opncb->waitone > 0
714: || opncb->syncreq > 0 ) {
715: ercd = E_OBJ;
716: goto err_ret1;
717: }
718: if ( isQueEmpty(&opncb->requestq) ) {
719: ercd = E_NOEXS;
720: goto err_ret1;
721: }
722:
723:
724: reqcb = (ReqCB*)opncb->requestq.next;
725: for ( nreq = 1;; nreq++ ) {
726: reqcb->tskid = tskid;
727: devreq = &reqcb->req;
728: reqcb = (ReqCB*)reqcb->q.next;
729: if ( reqcb == (ReqCB*)&opncb->requestq ) {
730: break;
731: }
732: devreq->c.next = &reqcb->req;
733: }
734: devreq->c.next = NULL;
735: devreq = &((ReqCB*)opncb->requestq.next)->req;
736: opncb->waireqlst = devreq;
737: opncb->nwaireq = nreq;
738: } else {
739:
740: reqcb = check_reqid(reqid, opncb);
741: if ( reqcb == NULL ) {
742: ercd = E_ID;
743: goto err_ret1;
744: }
745: if ( opncb->nwaireq > 0 || reqcb->tskid > 0 ) {
746: ercd = E_OBJ;
747: goto err_ret1;
748: }
749:
750:
751: reqcb->tskid = tskid;
752: devreq = &reqcb->req;
753: devreq->c.next = NULL;
754: if ( abort ) devreq->c.abort = TRUE;
755: nreq = 1;
756: opncb->waitone++;
757: }
758:
759:
760: UnlockDM();
761: reqno = call_waitfn(devcb, devreq, nreq, tmout);
762: LockDM();
763: if ( reqno < E_OK ) {
764: ercd = reqno;
765: } else if ( reqno >= nreq ) {
766: ercd = E_SYS;
767: }
768:
769: LockDAbort();
770:
771:
772: if ( reqid == 0 ) {
773: opncb->nwaireq = 0;
774: } else {
775: opncb->waitone--;
776: }
777:
778: 779:
780: if ( opncb->abort_tskid > 0 && --opncb->abort_cnt == 0 ) {
781: SyncSignalDM(opncb->abort_tskid);
782: }
783:
784:
785: while ( devreq != NULL ) {
786: reqcb = DEVREQ_REQCB(devreq);
787: if ( reqno-- == 0 ) {
788: reqid = REQID(reqcb);
789: if ( (drvatr & TDA_DEV_D) == 0 ) {
790: *asize = devreq->s.asize;
791: *ioer = devreq->s.error;
792: } else {
793: *asize = devreq->l.asize;
794: *ioer = devreq->l.error;
795: }
796: }
797: reqcb->tskid = 0;
798: devreq = devreq->c.next;
799: }
800: UnlockDAbort();
801:
802: if ( ercd < E_OK ) {
803: goto err_ret1;
804: }
805:
806: if ( syncreq == SyncReq ) {
807: opncb->syncreq--;
808: }
809:
810:
811: delReqCB(REQCB(reqid));
812:
813: UnlockDM();
814:
815: return reqid;
816:
817: err_ret1:
818: if ( syncreq == SyncReq ) {
819: opncb->syncreq--;
820: }
821: UnlockDM();
822: DEBUG_PRINT(("waitcomplete ercd = %d\n", ercd));
823: return ercd;
824: }
825:
826: 827: 828:
829: EXPORT ID _tk_rea_dev( ID dd, W start, void *buf, W size, TMO tmout )
830: {
831: return _tk_rea_dev_du(dd, start, buf, size, to_usec_tmo(tmout));
832: }
833: EXPORT ID _tk_rea_dev_du( ID dd, D start, void *buf, W size, TMO_U tmout )
834: {
835: ER ercd;
836:
837: ercd = request(dd, start, buf, size, tmout, TDC_READ, AsyncReq);
838:
839: ERCD_PRINT(("_tk_rea_dev ercd = %d\n", ercd));
840: return ercd;
841: }
842:
843: 844: 845:
846: EXPORT ER _tk_srea_dev( ID dd, W start, void *buf, W size, W *asize )
847: {
848: return _tk_srea_dev_d(dd, start, buf, size, asize);
849: }
850: EXPORT ER _tk_srea_dev_d( ID dd, D start, void *buf, W size, W *asize )
851: {
852: ER ercd, ioercd;
853:
854: ercd = ChkSpaceRW(asize, sizeof(W));
855: if ( ercd < E_OK ) {
856: goto err_ret;
857: }
858:
859: ercd = request(dd, start, buf, size, TMO_FEVR, TDC_READ, SyncReq);
860: if ( ercd < E_OK ) {
861: goto err_ret;
862: }
863:
864: ercd = waitcomplete(dd, ercd, asize, &ioercd, TMO_FEVR, SyncReq);
865: if ( ercd < E_OK ) {
866: goto err_ret;
867: }
868:
869: return ioercd;
870:
871: err_ret:
872: DEBUG_PRINT(("_tk_srea_dev ercd = %d\n", ercd));
873: return ercd;
874: }
875:
876: 877: 878:
879: EXPORT ID _tk_wri_dev( ID dd, W start, CONST void *buf, W size, TMO tmout )
880: {
881: return _tk_wri_dev_du(dd, start, buf, size, to_usec_tmo(tmout));
882: }
883: EXPORT ID _tk_wri_dev_du( ID dd, D start, CONST void *buf, W size, TMO_U tmout )
884: {
885: ER ercd;
886:
887: ercd = request(dd, start, (void*)buf, size, tmout, TDC_WRITE, AsyncReq);
888:
889: ERCD_PRINT(("_tk_wri_dev ercd = %d\n", ercd));
890: return ercd;
891: }
892:
893: 894: 895:
896: EXPORT ER _tk_swri_dev( ID dd, W start, CONST void *buf, W size, W *asize )
897: {
898: return _tk_swri_dev_d(dd, start, buf, size, asize);
899: }
900: EXPORT ER _tk_swri_dev_d( ID dd, D start, CONST void *buf, W size, W *asize )
901: {
902: ER ercd, ioercd;
903:
904: ercd = ChkSpaceRW(asize, sizeof(W));
905: if ( ercd < E_OK ) {
906: goto err_ret;
907: }
908:
909: ercd = request(dd, start, (void*)buf, size, TMO_FEVR,
910: TDC_WRITE, SyncReq);
911: if ( ercd < E_OK ) {
912: goto err_ret;
913: }
914:
915: ercd = waitcomplete(dd, ercd, asize, &ioercd, TMO_FEVR, SyncReq);
916: if ( ercd < E_OK ) {
917: goto err_ret;
918: }
919:
920: return ioercd;
921:
922: err_ret:
923: DEBUG_PRINT(("_tk_swri_dev ercd = %d\n", ercd));
924: return ercd;
925: }
926:
927: 928: 929:
930: EXPORT ID _tk_wai_dev( ID dd, ID reqid, W *asize, ER *ioer, TMO tmout )
931: {
932: return _tk_wai_dev_u(dd, reqid, asize, ioer, to_usec_tmo(tmout));
933: }
934: EXPORT ID _tk_wai_dev_u( ID dd, ID reqid, W *asize, ER *ioer, TMO_U tmout )
935: {
936: ER ercd;
937:
938: ercd = ChkSpaceRW(asize, sizeof(W));
939: if ( ercd < E_OK ) {
940: goto err_ret;
941: }
942:
943: ercd = ChkSpaceRW(ioer, sizeof(ER));
944: if ( ercd < E_OK ) {
945: goto err_ret;
946: }
947:
948: ercd = waitcomplete(dd, reqid, asize, ioer, tmout, AsyncReq);
949: if ( ercd < E_OK ) {
950: goto err_ret;
951: }
952:
953: return ercd;
954:
955: err_ret:
956: DEBUG_PRINT(("_tk_wai_dev_u ercd = %d\n", ercd));
957: return ercd;
958: }
959:
960:
961:
962:
963: LOCAL INT DisSusCnt;
964:
965:
966: #define MAX_DISSUS 0x7fff
967:
968: 969: 970:
971: LOCAL ER sendevt_alldevice( INT evttyp, BOOL disk )
972: {
973: QUEUE *q;
974: DevCB *devcb;
975: BOOL d;
976: ER ercd = E_OK;
977:
978: for ( q = UsedDevCB.next; q != &UsedDevCB; q = q->next ) {
979: devcb = (DevCB*)q;
980:
981: d = ( (devcb->ddev.devatr & TD_DEVTYPE) == TDK_DISK )?
982: TRUE : FALSE;
983: if ( disk != d ) {
984: continue;
985: }
986:
987:
988: ercd = call_eventfn(devcb, evttyp, NULL);
989: }
990:
991: ERCD_PRINT(("sendevt_alldevice ercd = %d\n", ercd));
992: return ercd;
993: }
994:
995: 996: 997:
998: LOCAL ER do_suspend( void )
999: {
1000: ER ercd;
1001:
1002:
1003: LockREG();
1004:
1005:
1006: ercd = tk_evt_ssy(0, TSEVT_SUSPEND_BEGIN, 0, 0);
1007: ERCD_PRINT(("1. do_suspend -> tk_evt_ssy ercd = %d\n", ercd));
1008:
1009:
1010: ercd = sendevt_alldevice(TDV_SUSPEND, FALSE);
1011: ERCD_PRINT(("2. do_suspend -> sendevt_alldevice ercd = %d\n", ercd));
1012:
1013:
1014: ercd = sendevt_alldevice(TDV_SUSPEND, TRUE);
1015: ERCD_PRINT(("3. do_suspend -> sendevt_alldevice ercd = %d\n", ercd));
1016:
1017:
1018: LockDM();
1019:
1020:
1021: ercd = tk_evt_ssy(0, TSEVT_SUSPEND_DONE, 0, 0);
1022: ERCD_PRINT(("4. do_suspend -> tk_evt_ssy ercd = %d\n", ercd));
1023:
1024:
1025: ercd = tk_set_pow(TPW_DOSUSPEND);
1026: ERCD_PRINT(("5. do_suspend -> tk_set_pow ercd = %d\n", ercd));
1027:
1028:
1029:
1030:
1031: ercd = tk_evt_ssy(0, TSEVT_RESUME_BEGIN, 0, 0);
1032: ERCD_PRINT(("6. do_suspend -> tk_evt_ssy ercd = %d\n", ercd));
1033:
1034:
1035: UnlockDM();
1036:
1037:
1038: ercd = sendevt_alldevice(TDV_RESUME, TRUE);
1039: ERCD_PRINT(("7. do_suspend -> sendevt_alldevice ercd = %d\n", ercd));
1040:
1041:
1042: ercd = sendevt_alldevice(TDV_RESUME, FALSE);
1043: ERCD_PRINT(("8. do_suspend -> sendevt_alldevice ercd = %d\n", ercd));
1044:
1045:
1046: UnlockREG();
1047:
1048:
1049: ercd = tk_evt_ssy(0, TSEVT_RESUME_DONE, 0, 0);
1050: ERCD_PRINT(("9. do_suspend -> tk_evt_ssy ercd = %d\n", ercd));
1051:
1052: return ercd;
1053: }
1054:
1055: 1056: 1057:
1058: EXPORT INT _tk_sus_dev( UINT mode )
1059: {
1060: ResCB *rescb;
1061: BOOL suspend = FALSE;
1062: ER ercd;
1063:
1064:
1065: rescb = GetResCB(DEVICE_SVC, TSK_SELF);
1066: if ( rescb == NULL ) {
1067: ercd = E_CTX;
1068: goto err_ret1;
1069: }
1070:
1071: LockDM();
1072:
1073: switch ( mode & 0xf ) {
1074: case TD_SUSPEND:
1075: if ( DisSusCnt > 0 && (mode & TD_FORCE) == 0 ) {
1076: ercd = E_BUSY;
1077: goto err_ret2;
1078: }
1079: suspend = TRUE;
1080: break;
1081:
1082: case TD_DISSUS:
1083: if ( DisSusCnt >= MAX_DISSUS ) {
1084: ercd = E_QOVR;
1085: goto err_ret2;
1086: }
1087: DisSusCnt++;
1088: rescb->dissus++;
1089: break;
1090:
1091: case TD_ENASUS:
1092: if ( rescb->dissus > 0 ) {
1093: rescb->dissus--;
1094: DisSusCnt--;
1095: }
1096: break;
1097:
1098: case TD_CHECK:
1099: break;
1100:
1101: default:
1102: ercd = E_PAR;
1103: goto err_ret2;
1104: }
1105:
1106: UnlockDM();
1107:
1108: if ( suspend ) {
1109:
1110: ercd = do_suspend();
1111: if ( ercd < E_OK ) {
1112: goto err_ret1;
1113: }
1114: }
1115:
1116: return DisSusCnt;
1117:
1118: err_ret2:
1119: UnlockDM();
1120: err_ret1:
1121: DEBUG_PRINT(("_tk_sus_dev ercd = %d\n", ercd));
1122: return ercd;
1123: }
1124:
1125:
1126:
1127: 1128: 1129:
1130: EXPORT void devmgr_break( ID tskid )
1131: {
1132: ResCB *rescb;
1133: OpnCB *opncb;
1134: ReqCB *reqcb;
1135: QUEUE *q, *r;
1136: DEVREQ *devreq = NULL;
1137: INT nreq;
1138:
1139:
1140: rescb = GetResCB(DEVICE_SVC, tskid);
1141: if ( rescb == NULL ) {
1142: return;
1143: }
1144:
1145: LockDM();
1146:
1147:
1148: nreq = 0;
1149: for ( q = rescb->openq.next; q != &rescb->openq; q = q->next ) {
1150: opncb = RESQ_OPNCB(q);
1151:
1152: if ( opncb->nwaireq > 0 ) {
1153:
1154: reqcb = DEVREQ_REQCB(opncb->waireqlst);
1155: if ( reqcb->tskid == tskid ) {
1156: devreq = opncb->waireqlst;
1157: nreq = opncb->nwaireq;
1158: }
1159: } else {
1160:
1161: for ( r = opncb->requestq.next;
1162: r != &opncb->requestq; r = r->next ) {
1163: reqcb = (ReqCB*)r;
1164: if ( reqcb->tskid == tskid ) {
1165: devreq = &reqcb->req;
1166: devreq->c.abort = TRUE;
1167: nreq = 1;
1168: break;
1169: }
1170: }
1171: }
1172: if ( nreq > 0 ) {
1173: LockDAbort();
1174: break;
1175: }
1176: }
1177: UnlockDM();
1178: if ( nreq > 0 ) {
1179:
1180: call_abortfn(opncb->devcb, tskid, devreq, nreq);
1181: UnlockDAbort();
1182: }
1183: }
1184:
1185: 1186: 1187:
1188: EXPORT void devmgr_startup( ID resid, INT info )
1189: {
1190: ResCB *rescb;
1191: ER ercd;
1192:
1193: ercd = tk_get_res(resid, DEVICE_SVC, (void**)&rescb);
1194: if ( ercd < E_OK ) {
1195: goto err_ret;
1196: }
1197:
1198: LockDM();
1199:
1200:
1201: QueInit(&rescb->openq);
1202: rescb->dissus = 0;
1203:
1204: UnlockDM();
1205:
1206: return;
1207:
1208: err_ret:
1209: DEBUG_PRINT(("devmgr_cleanup ercd = %d\n", ercd));
1210: return;
1211: }
1212:
1213: 1214: 1215:
1216: EXPORT void devmgr_cleanup( ID resid, INT info )
1217: {
1218: ResCB *rescb;
1219: OpnCB *opncb;
1220: ER ercd;
1221:
1222: ercd = tk_get_res(resid, DEVICE_SVC, (void**)&rescb);
1223: if ( ercd < E_OK ) {
1224: goto err_ret;
1225: }
1226:
1227:
1228: if ( rescb->openq.next == NULL ) {
1229: return;
1230: }
1231:
1232: LockDM();
1233:
1234:
1235: DisSusCnt -= rescb->dissus;
1236: rescb->dissus = 0;
1237:
1238:
1239: while ( !isQueEmpty(&rescb->openq) ) {
1240: opncb = RESQ_OPNCB(rescb->openq.next);
1241:
1242:
1243: opncb->resid = -1;
1244:
1245:
1246: UnlockDM();
1247: close_device(opncb, 0);
1248: LockDM();
1249: }
1250: UnlockDM();
1251:
1252: return;
1253:
1254: err_ret:
1255: DEBUG_PRINT(("devmgr_cleanup ercd = %d\n", ercd));
1256: return;
1257: }
1258:
1259: 1260: 1261:
1262: EXPORT ER initDevIO( void )
1263: {
1264: INT i;
1265: ER ercd;
1266:
1267: i = _tk_get_cfn(SCTAG_TMAXOPNDEV, &MaxOpnDev, 1);
1268: if ( i < 1 ) {
1269: ercd = E_SYS;
1270: goto err_ret;
1271: }
1272: i = _tk_get_cfn(SCTAG_TMAXREQDEV, &MaxReqDev, 1);
1273: if ( i < 1 ) {
1274: ercd = E_SYS;
1275: goto err_ret;
1276: }
1277:
1278:
1279: OpnCBtbl = Imalloc((UINT)MaxOpnDev * sizeof(OpnCB));
1280: if ( OpnCBtbl == NULL ) {
1281: ercd = E_NOMEM;
1282: goto err_ret;
1283: }
1284:
1285: QueInit(&FreeOpnCB);
1286: for ( i = 0; i < MaxOpnDev; ++i ) {
1287: OpnCBtbl[i].resid = 0;
1288: QueInsert(&OpnCBtbl[i].q, &FreeOpnCB);
1289: }
1290:
1291:
1292: ReqCBtbl = Imalloc((UINT)MaxReqDev * sizeof(ReqCB));
1293: if ( ReqCBtbl == NULL ) {
1294: ercd = E_NOMEM;
1295: goto err_ret;
1296: }
1297:
1298: QueInit(&FreeReqCB);
1299: for ( i = 0; i < MaxReqDev; ++i ) {
1300: ReqCBtbl[i].opncb = NULL;
1301: QueInsert(&ReqCBtbl[i].q, &FreeReqCB);
1302: }
1303:
1304: return E_OK;
1305:
1306: err_ret:
1307: DEBUG_PRINT(("initDevIO ercd = %d\n", ercd));
1308: return ercd;
1309: }
1310:
1311: 1312: 1313:
1314: EXPORT ER finishDevIO( void )
1315: {
1316:
1317: if ( OpnCBtbl != NULL ) {
1318: Ifree(OpnCBtbl);
1319: OpnCBtbl = NULL;
1320: }
1321: if ( ReqCBtbl != NULL ) {
1322: Ifree(ReqCBtbl);
1323: ReqCBtbl = NULL;
1324: }
1325:
1326: return E_OK;
1327: }
1328: