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/svc/ifdevmgr.h>
25:
26:
27: EXPORT FastMLock DevMgrLock;
28:
29: EXPORT ID DevMgrSync;
30:
31: LOCAL T_IDEV DefaultIDev;
32:
33:
34: #define OBJNAME_DMMBF "DEvt"
35: #define OBJNAME_DMSEM "DMSy"
36: #define OBJNAME_DMLOCK "DMLk"
37:
38: 39: 40:
41: LOCAL ER initIDev( void )
42: {
43: T_CMBF cmbf;
44: INT val[2];
45: ER ercd;
46:
47:
48: ercd = _tk_get_cfn(SCTAG_TDEVTMBFSZ, val, 2);
49:
50: if ( ercd >= 2 && val[0] >= 0 ) {
51:
52: SetOBJNAME(cmbf.exinf, OBJNAME_DMMBF);
53: cmbf.mbfatr = TA_TFIFO;
54: cmbf.bufsz = val[0];
55: cmbf.maxmsz = val[1];
56: ercd = tk_cre_mbf(&cmbf);
57: if ( ercd < E_OK ) {
58: DefaultIDev.evtmbfid = 0;
59: goto err_ret;
60: }
61: DefaultIDev.evtmbfid = ercd;
62: } else {
63:
64: DefaultIDev.evtmbfid = 0;
65: }
66:
67: return E_OK;
68:
69: err_ret:
70: DEBUG_PRINT(("initIDev ercd = %d\n", ercd));
71: return ercd;
72: }
73:
74: 75: 76:
77: LOCAL ER delIDev( void )
78: {
79: ER ercd = E_OK;
80:
81:
82: if ( DefaultIDev.evtmbfid > 0 ) {
83: ercd = tk_del_mbf(DefaultIDev.evtmbfid);
84: DefaultIDev.evtmbfid = 0;
85: }
86:
87: ERCD_PRINT(("delIDev ercd = %d\n", ercd));
88: return ercd;
89: }
90:
91:
92: 93: 94:
95:
96: EXPORT DevCB *DevCBtbl;
97: EXPORT QUEUE UsedDevCB;
98: LOCAL QUEUE FreeDevCB;
99: LOCAL INT MaxRegDev;
100:
101: #define MAX_UNIT 255
102:
103: 104: 105:
106: Inline ER check_devid( ID devid )
107: {
108: devid >>= 8;
109: if ( devid < 1 || devid > MaxRegDev ) {
110: return E_ID;
111: }
112: return E_OK;
113: }
114:
115: 116: 117:
118: LOCAL ER initDevCB( void )
119: {
120: DevCB *devcb;
121: INT num;
122: ER ercd;
123:
124:
125: ercd = _tk_get_cfn(SCTAG_TMAXREGDEV, &MaxRegDev, 1);
126: if ( ercd < 1 ) {
127: ercd = E_SYS;
128: goto err_ret;
129: }
130: num = MaxRegDev;
131:
132:
133: DevCBtbl = Imalloc((UINT)num * sizeof(DevCB));
134: if ( DevCBtbl == NULL ) {
135: ercd = E_NOMEM;
136: goto err_ret;
137: }
138:
139: QueInit(&UsedDevCB);
140: QueInit(&FreeDevCB);
141:
142: devcb = DevCBtbl;
143: while ( num-- > 0 ) {
144: QueInsert(&devcb->q, &FreeDevCB);
145: devcb->devnm[0] = '\0';
146: devcb++;
147: }
148:
149: return E_OK;
150:
151: err_ret:
152: DEBUG_PRINT(("initDevCB ercd = %d\n", ercd));
153: return ercd;
154: }
155:
156: 157: 158:
159: EXPORT DevCB* searchDevCB( CONST UB *devnm )
160: {
161: QUEUE *q;
162: DevCB *devcb;
163:
164: for ( q = UsedDevCB.next; q != &UsedDevCB; q = q->next ) {
165: devcb = (DevCB*)q;
166: if ( devcb->devnm[0] == devnm[0] &&
167: STRCMP((char*)devcb->devnm, (char*)devnm) == 0 ) {
168: return devcb;
169: }
170: }
171:
172: return NULL;
173: }
174:
175: 176: 177:
178: LOCAL DevCB* newDevCB( CONST UB *devnm )
179: {
180: DevCB *devcb;
181:
182: devcb = (DevCB*)QueRemoveNext(&FreeDevCB);
183: if ( devcb == NULL ) {
184: return NULL;
185: }
186:
187: STRNCPY((char*)devcb->devnm, (char*)devnm, L_DEVNM + 1);
188: QueInit(&devcb->openq);
189: QueInit(&devcb->syncq);
190:
191: QueInsert(&devcb->q, &UsedDevCB);
192:
193: return devcb;
194: }
195:
196: 197: 198:
199: LOCAL void delDevCB( DevCB *devcb )
200: {
201: QueRemove(&devcb->q);
202: QueInsert(&devcb->q, &FreeDevCB);
203: devcb->devnm[0] = '\0';
204: }
205:
206: 207: 208:
209: LOCAL ID _tk_def_dev( CONST UB *devnm, CONST T_DDEV *ddev,
210: T_IDEV *idev, void *caller_gp )
211: {
212: DevCB *devcb;
213: INT len, evttyp;
214: ER ercd;
215:
216: LockREG();
217:
218: len = ChkSpaceBstrR(devnm, 0);
219: if ( len < E_OK ) {
220: ercd = len;
221: goto err_ret1;
222: }
223: if ( len <= 0 || len > L_DEVNM ) {
224: ercd = E_PAR;
225: goto err_ret1;
226: }
227:
228: if ( ddev != NULL ) {
229: ercd = ChkSpaceR(ddev, sizeof(T_DDEV));
230: if ( ercd < E_OK ) {
231: goto err_ret1;
232: }
233: if ( ddev->nsub < 0 || ddev->nsub > MAX_UNIT ) {
234: ercd = E_PAR;
235: goto err_ret1;
236: }
237:
238: 239:
240: if ( ddev->nsub > 0 ) {
241: ++len;
242: }
243: if ( ddev->nsub > 10 ) {
244: ++len;
245: }
246: if ( ddev->nsub > 100 ) {
247: ++len;
248: }
249: if ( len > L_DEVNM ) {
250: ercd = E_PAR;
251: goto err_ret1;
252: }
253: }
254:
255: if ( idev != NULL ) {
256: ercd = ChkSpaceRW(idev, sizeof(T_IDEV));
257: if ( ercd < E_OK ) {
258: goto err_ret1;
259: }
260: }
261:
262: LockDM();
263:
264:
265: devcb = searchDevCB(devnm);
266: if ( devcb == NULL ) {
267: if ( ddev == NULL ) {
268: ercd = E_NOEXS;
269: goto err_ret2;
270: }
271:
272: 273:
274: devcb = newDevCB(devnm);
275: if ( devcb == NULL ) {
276: ercd = E_LIMIT;
277: goto err_ret2;
278: }
279: }
280:
281: if ( ddev != NULL ) {
282:
283: devcb->ddev = *ddev;
284: #if TA_GP
285: if ( (ddev->drvatr & TA_GP) == 0 ) {
286:
287: devcb->ddev.gp = caller_gp;
288: }
289: #endif
290:
291: if ( idev != NULL ) {
292:
293: *idev = DefaultIDev;
294: }
295: evttyp = TSEVT_DEVICE_REGIST;
296: } else {
297: if ( !isQueEmpty(&devcb->openq) ) {
298:
299: ercd = E_BUSY;
300: goto err_ret2;
301: }
302:
303:
304: delDevCB(devcb);
305: evttyp = TSEVT_DEVICE_DELETE;
306: }
307:
308: UnlockDM();
309: UnlockREG();
310:
311:
312: tk_evt_ssy(0, evttyp, 0, DID(devcb));
313:
314: return DID(devcb);
315:
316: err_ret2:
317: UnlockDM();
318: err_ret1:
319: UnlockREG();
320: DEBUG_PRINT(("_tk_def_dev ercd = %d\n", ercd));
321: return ercd;
322: }
323:
324: 325: 326:
327: LOCAL ER _tk_ref_idv( T_IDEV *idev )
328: {
329: ER ercd;
330:
331: ercd = ChkSpaceRW(idev, sizeof(T_IDEV));
332: if ( ercd < E_OK ) {
333: goto err_ret;
334: }
335:
336: LockDM();
337: *idev = DefaultIDev;
338: UnlockDM();
339:
340: return E_OK;
341:
342: err_ret:
343: DEBUG_PRINT(("_tk_ref_idv ercd = %d\n", ercd));
344: return ercd;
345: }
346:
347:
348:
349: 350: 351: 352: 353:
354: LOCAL void logdevnm( UB *ldevnm, UB *pdevnm, INT unitno )
355: {
356: UB unostr[12], *cp;
357:
358: STRCPY((char*)ldevnm, (char*)pdevnm);
359: if ( unitno > 0 ) {
360: cp = &unostr[11];
361: *cp = '\0';
362: while (*ldevnm != '\0') {
363: ++ldevnm;
364: }
365: --unitno;
366: do {
367: *(--cp) = (UB)('0' + (unitno % 10));
368: unitno /= 10;
369: } while (unitno);
370: STRCAT((char*)ldevnm, (char*)cp);
371: }
372: }
373:
374: 375: 376: 377: 378: 379:
380: EXPORT INT phydevnm( UB *pdevnm, CONST UB *ldevnm )
381: {
382: UB c;
383: INT unitno;
384:
385: while ( (c = *ldevnm) != '\0' ) {
386: if ( c >= '0' && c <= '9' ) {
387: break;
388: }
389: *pdevnm++ = c;
390: ldevnm++;
391: }
392: *pdevnm = '\0';
393:
394: unitno = 0;
395: if (c != '\0') {
396: while ( (c = *ldevnm) != '\0' ) {
397: unitno = unitno * 10 + (c - '0');
398: ldevnm++;
399: }
400: ++unitno;
401: }
402:
403: return unitno;
404: }
405:
406: 407: 408:
409: LOCAL ID _tk_get_dev( ID devid, UB *devnm )
410: {
411: DevCB *devcb;
412: ER ercd;
413:
414: ercd = ChkSpaceRW(devnm, (L_DEVNM + 1) * sizeof(UB));
415: if ( ercd < E_OK ) {
416: goto err_ret1;
417: }
418: ercd = check_devid(devid);
419: if ( ercd < E_OK ) {
420: goto err_ret1;
421: }
422:
423: LockDM();
424:
425: devcb = DEVCB(devid);
426: if ( (devcb->devnm[0] == '\0')||(UNITNO(devid) > devcb->ddev.nsub) ) {
427: ercd = E_NOEXS;
428: goto err_ret2;
429: }
430:
431: logdevnm(devnm, devcb->devnm, UNITNO(devid));
432:
433: UnlockDM();
434:
435: return DID(devcb);
436:
437: err_ret2:
438: UnlockDM();
439: err_ret1:
440: DEBUG_PRINT(("_tk_get_dev ercd = %d\n", ercd));
441: return ercd;
442: }
443:
444: 445: 446:
447: LOCAL ID _tk_ref_dev( CONST UB *devnm, T_RDEV *rdev )
448: {
449: UB pdevnm[L_DEVNM + 1];
450: DevCB *devcb;
451: INT unitno;
452: ER ercd;
453:
454: ercd = ChkSpaceBstrR(devnm, 0);
455: if ( ercd < E_OK ) {
456: goto err_ret1;
457: }
458: if ( rdev != NULL ) {
459: ercd = ChkSpaceRW(rdev, sizeof(T_RDEV));
460: if ( ercd < E_OK ) {
461: goto err_ret1;
462: }
463: }
464:
465: unitno = phydevnm(pdevnm, devnm);
466:
467: LockDM();
468:
469: devcb = searchDevCB(pdevnm);
470: if ( devcb == NULL || unitno > devcb->ddev.nsub ) {
471: ercd = E_NOEXS;
472: goto err_ret2;
473: }
474:
475: if ( rdev != NULL ) {
476: rdev->devatr = devcb->ddev.devatr;
477: rdev->blksz = devcb->ddev.blksz;
478: rdev->nsub = devcb->ddev.nsub;
479: rdev->subno = unitno;
480: }
481:
482: UnlockDM();
483:
484: return DEVID(devcb, unitno);
485:
486: err_ret2:
487: UnlockDM();
488: err_ret1:
489: DEBUG_PRINT(("_tk_ref_dev ercd = %d\n", ercd));
490: return ercd;
491: }
492:
493: 494: 495:
496: LOCAL ID _tk_oref_dev( ID dd, T_RDEV *rdev )
497: {
498: OpnCB *opncb;
499: DevCB *devcb;
500: INT unitno;
501: ER ercd;
502:
503: if ( rdev != NULL ) {
504: ercd = ChkSpaceRW(rdev, sizeof(T_RDEV));
505: if ( ercd < E_OK ) {
506: goto err_ret1;
507: }
508: }
509:
510: LockDM();
511:
512: ercd = check_devdesc(dd, 0, &opncb);
513: if ( ercd < E_OK ) {
514: goto err_ret2;
515: }
516:
517: devcb = opncb->devcb;
518: unitno = opncb->unitno;
519:
520: if ( rdev != NULL ) {
521: rdev->devatr = devcb->ddev.devatr;
522: rdev->blksz = devcb->ddev.blksz;
523: rdev->nsub = devcb->ddev.nsub;
524: rdev->subno = unitno;
525: }
526:
527: UnlockDM();
528:
529: return DEVID(devcb, unitno);
530:
531: err_ret2:
532: UnlockDM();
533: err_ret1:
534: DEBUG_PRINT(("_tk_oref_dev ercd = %d\n", ercd));
535: return ercd;
536: }
537:
538: 539: 540:
541: LOCAL INT _tk_lst_dev( T_LDEV *ldev, INT start, INT ndev )
542: {
543: DevCB *devcb;
544: QUEUE *q;
545: INT n, end;
546: ER ercd;
547:
548: if ( start < 0 || ndev < 0 ) {
549: ercd = E_PAR;
550: goto err_ret;
551: }
552: ercd = ChkSpaceRW(ldev, ndev * (INT)sizeof(T_LDEV));
553: if ( ercd < E_OK ) {
554: goto err_ret;
555: }
556:
557: LockDM();
558:
559: end = start + ndev;
560: n = 0;
561: for ( q = UsedDevCB.next; q != &UsedDevCB; q = q->next ) {
562: if ( n >= start && n < end ) {
563: devcb = (DevCB*)q;
564: ldev->devatr = devcb->ddev.devatr;
565: ldev->blksz = devcb->ddev.blksz;
566: ldev->nsub = devcb->ddev.nsub;
567: STRNCPY((char*)ldev->devnm,
568: (char*)devcb->devnm, L_DEVNM);
569: ldev++;
570: }
571: n++;
572: }
573:
574: UnlockDM();
575:
576: if ( start >= n ) {
577: ercd = E_NOEXS;
578: goto err_ret;
579: }
580:
581: return n - start;
582:
583: err_ret:
584: DEBUG_PRINT(("_tk_lst_dev ercd = %d\n", ercd));
585: return ercd;
586: }
587:
588:
589:
590: 591: 592:
593: LOCAL INT _tk_evt_dev( ID devid, INT evttyp, void *evtinf )
594: {
595: DevCB *devcb;
596: ER ercd;
597:
598: ercd = check_devid(devid);
599: if ( ercd < E_OK ) {
600: goto err_ret1;
601: }
602: if ( evttyp < 0 ) {
603: ercd = E_PAR;
604: goto err_ret1;
605: }
606:
607: LockDM();
608:
609: devcb = DEVCB(devid);
610: if ( (devcb->devnm[0] == '\0')||(UNITNO(devid) > devcb->ddev.nsub) ) {
611: ercd = E_NOEXS;
612: goto err_ret2;
613: }
614:
615: UnlockDM();
616:
617:
618: ercd = call_eventfn(devcb, evttyp, evtinf);
619:
620: return ercd;
621:
622: err_ret2:
623: UnlockDM();
624: err_ret1:
625: DEBUG_PRINT(("_tk_evt_dev ercd = %d\n", ercd));
626: return ercd;
627: }
628:
629:
630:
631: 632: 633:
634: LOCAL INT devmgr_svcentry( void *pk_para, FN fncd, void *caller_gp )
635: {
636: ER ercd;
637:
638:
639: ercd = ChkCallPLevel();
640: if ( ercd < E_OK ) {
641: goto err_ret;
642: }
643:
644: switch ( fncd ) {
645: case DEVICE_TK_OPN_DEV_FN:
646: { DEVICE_TK_OPN_DEV_PARA *p = pk_para;
647: return _tk_opn_dev(p->devnm, p->omode); }
648: case DEVICE_TK_CLS_DEV_FN:
649: { DEVICE_TK_CLS_DEV_PARA *p = pk_para;
650: return _tk_cls_dev(p->dd, p->option); }
651: case DEVICE_TK_REA_DEV_FN:
652: { DEVICE_TK_REA_DEV_PARA *p = pk_para;
653: return _tk_rea_dev(p->dd, p->start, p->buf, p->size,
654: p->tmout); }
655: case DEVICE_TK_SREA_DEV_FN:
656: { DEVICE_TK_SREA_DEV_PARA *p = pk_para;
657: return _tk_srea_dev(p->dd, p->start, p->buf, p->size,
658: p->asize); }
659: case DEVICE_TK_WRI_DEV_FN:
660: { DEVICE_TK_WRI_DEV_PARA *p = pk_para;
661: return _tk_wri_dev(p->dd, p->start, p->buf, p->size,
662: p->tmout); }
663: case DEVICE_TK_SWRI_DEV_FN:
664: { DEVICE_TK_SWRI_DEV_PARA *p = pk_para;
665: return _tk_swri_dev(p->dd, p->start, p->buf, p->size,
666: p->asize); }
667: case DEVICE_TK_WAI_DEV_FN:
668: { DEVICE_TK_WAI_DEV_PARA *p = pk_para;
669: return _tk_wai_dev(p->dd, p->reqid, p->asize, p->ioer,
670: p->tmout); }
671: case DEVICE_TK_SUS_DEV_FN:
672: { DEVICE_TK_SUS_DEV_PARA *p = pk_para;
673: return _tk_sus_dev(p->mode); }
674: case DEVICE_TK_GET_DEV_FN:
675: { DEVICE_TK_GET_DEV_PARA *p = pk_para;
676: return _tk_get_dev(p->devid, p->devnm); }
677: case DEVICE_TK_REF_DEV_FN:
678: { DEVICE_TK_REF_DEV_PARA *p = pk_para;
679: return _tk_ref_dev(p->devnm, p->rdev); }
680: case DEVICE_TK_OREF_DEV_FN:
681: { DEVICE_TK_OREF_DEV_PARA *p = pk_para;
682: return _tk_oref_dev(p->dd, p->rdev); }
683: case DEVICE_TK_LST_DEV_FN:
684: { DEVICE_TK_LST_DEV_PARA *p = pk_para;
685: return _tk_lst_dev(p->ldev, p->start, p->ndev); }
686: case DEVICE_TK_EVT_DEV_FN:
687: { DEVICE_TK_EVT_DEV_PARA *p = pk_para;
688: return _tk_evt_dev(p->devid, p->evttyp, p->evtinf); }
689: case DEVICE_TK_DEF_DEV_FN:
690: { DEVICE_TK_DEF_DEV_PARA *p = pk_para;
691: return _tk_def_dev(p->devnm, p->ddev, p->idev, caller_gp); }
692: case DEVICE_TK_REF_IDV_FN:
693: { DEVICE_TK_REF_IDV_PARA *p = pk_para;
694: return _tk_ref_idv(p->idev); }
695:
696:
697: case DEVICE_TK_REA_DEV_DU_FN:
698: { DEVICE_TK_REA_DEV_DU_PARA *p = pk_para;
699: return _tk_rea_dev_du(p->dd, p->start_d, p->buf, p->size,
700: p->tmout_u); }
701: case DEVICE_TK_SREA_DEV_D_FN:
702: { DEVICE_TK_SREA_DEV_D_PARA *p = pk_para;
703: return _tk_srea_dev_d(p->dd, p->start_d, p->buf, p->size,
704: p->asize); }
705: case DEVICE_TK_WRI_DEV_DU_FN:
706: { DEVICE_TK_WRI_DEV_DU_PARA *p = pk_para;
707: return _tk_wri_dev_du(p->dd, p->start_d, p->buf, p->size,
708: p->tmout_u); }
709: case DEVICE_TK_SWRI_DEV_D_FN:
710: { DEVICE_TK_SWRI_DEV_D_PARA *p = pk_para;
711: return _tk_swri_dev_d(p->dd, p->start_d, p->buf, p->size,
712: p->asize); }
713: case DEVICE_TK_WAI_DEV_U_FN:
714: { DEVICE_TK_WAI_DEV_U_PARA *p = pk_para;
715: return _tk_wai_dev_u(p->dd, p->reqid, p->asize, p->ioer,
716: p->tmout_u); }
717:
718: default:
719: ercd = E_RSFN;
720: }
721: err_ret:
722: DEBUG_PRINT(("devmgr_svcentry ercd = %d\n", ercd));
723: return ercd;
724: }
725:
726: 727: 728:
729: EXPORT ER initialize_devmgr( void )
730: {
731: T_DSSY dssy;
732: T_CSEM csem;
733: ER ercd;
734:
735:
736: ercd = CreateMLock(&DevMgrLock, (UB*)OBJNAME_DMLOCK);
737: if ( ercd < E_OK ) {
738: goto err_ret;
739: }
740:
741:
742: SetOBJNAME(csem.exinf, OBJNAME_DMSEM);
743: csem.sematr = TA_TFIFO | TA_FIRST;
744: csem.isemcnt = 0;
745: csem.maxsem = 1;
746: ercd = tk_cre_sem(&csem);
747: if ( ercd < E_OK ) {
748: goto err_ret;
749: }
750: DevMgrSync = ercd;
751:
752:
753: ercd = initDevCB();
754: if ( ercd < E_OK ) {
755: goto err_ret;
756: }
757:
758:
759: ercd = initDevIO();
760: if ( ercd < E_OK ) {
761: goto err_ret;
762: }
763:
764:
765: ercd = initIDev();
766: if ( ercd < E_OK ) {
767: goto err_ret;
768: }
769:
770:
771: dssy.ssyatr = TA_NULL;
772: dssy.ssypri = DEVICE_PRI;
773: dssy.svchdr = (FP)&devmgr_svcentry;
774: dssy.breakfn = (FP)&devmgr_break;
775: dssy.startupfn = (FP)&devmgr_startup;
776: dssy.cleanupfn = (FP)&devmgr_cleanup;
777: dssy.eventfn = NULL;
778: dssy.resblksz = sizeof(ResCB);
779: ercd = tk_def_ssy(DEVICE_SVC, &dssy);
780: if ( ercd < E_OK ) {
781: goto err_ret;
782: }
783:
784: return E_OK;
785:
786: err_ret:
787: DEBUG_PRINT(("initialize_devmgr ercd = %d\n", ercd));
788: finish_devmgr();
789: return ercd;
790: }
791:
792: 793: 794:
795: EXPORT ER finish_devmgr( void )
796: {
797: ER ercd;
798:
799:
800: ercd = tk_def_ssy(DEVICE_SVC, NULL);
801: ERCD_PRINT(("1. finish_devmgr -> tk_def_ssy ercd = %d\n", ercd));
802:
803:
804: ercd = delIDev();
805: ERCD_PRINT(("2. finish_devmgr -> delIDev ercd = %d\n", ercd));
806:
807:
808: ercd = finishDevIO();
809: ERCD_PRINT(("3. finish_devmgr -> finishDevIO ercd = %d\n", ercd));
810:
811:
812: if ( DevCBtbl != NULL ) {
813: Ifree(DevCBtbl);
814: DevCBtbl = NULL;
815: }
816:
817:
818: if ( DevMgrSync > 0 ) {
819: tk_del_sem(DevMgrSync);
820: DevMgrSync = 0;
821: }
822:
823:
824: DeleteMLock(&DevMgrLock);
825:
826: return ercd;
827: }