|
|
1.1 root 1: /*
2:
3: Copyright 1990,1991,1992 Eric R. Smith. All rights reserved.
4:
5: */
6:
7:
8:
9: /*
10:
11: * BIOS replacement routines
12:
13: */
14:
15:
16:
17: #include "mint.h"
18:
19:
20:
21: #define UNDEF 0 /* should match definition in tty.c */
22:
23:
24:
25: /* some key definitions */
26:
27: #define CTRLALT 0xc
28:
29: #define DEL 0x53 /* scan code of delete key */
30:
31: #define UNDO 0x61 /* scan code of undo key */
32:
33:
34:
35: /* BIOS device definitions */
36:
37: #define CONSDEV 2
38:
39: #define AUXDEV 1
40:
41:
42:
43: /* BIOS devices 0..MAX_BHANDLE-1 can be redirected to GEMDOS files */
44:
45: #define MAX_BHANDLE 4
46:
47:
48:
49: /* BIOS redirection maps */
50:
1.1.1.2 ! root 51: const short binput[MAX_BHANDLE] = { -3, -2, -1, -4 };
1.1 root 52:
1.1.1.2 ! root 53: const short boutput[MAX_BHANDLE] = { -3, -2, -1, -5 };
1.1 root 54:
55:
56:
57: /* tty structures for the BIOS devices -- see biosfs.c */
58:
59: extern struct tty con_tty, aux_tty, midi_tty;
60:
61:
62:
63: extern int tosvers; /* from main.c */
64:
65: char *kbshft; /* set in main.c */
66:
67:
68:
69: /* some BIOS vectors; note that the routines at these vectors may do nasty
70:
71: * things to registers!
72:
73: */
74:
75:
76:
1.1.1.2 ! root 77: #define RWABS *((long *)0x476L)
1.1 root 78:
1.1.1.2 ! root 79: #define MEDIACH *((long *)0x47eL)
1.1 root 80:
1.1.1.2 ! root 81: #define GETBPB *((long *)0x472L)
1.1 root 82:
83:
84:
1.1.1.2 ! root 85: /* these are supposed to be tables holding the addresses of the
1.1 root 86:
1.1.1.2 ! root 87: * first 8 BconXXX functions, but in fact only the first 5 are
1.1 root 88:
1.1.1.2 ! root 89: * placed here (and device 5 only has Bconout implemented;
1.1 root 90:
1.1.1.2 ! root 91: * we don't use that device (raw console) anyway).
1.1 root 92:
1.1.1.2 ! root 93: */
! 94:
! 95:
! 96:
! 97: #define xconstat ((long *)0x51eL)
! 98:
! 99: #define xconin ((long *)0x53eL)
! 100:
! 101: #define xcostat ((long *)0x55eL)
! 102:
! 103: #define xconout ((long *)0x57eL)
! 104:
! 105:
! 106:
! 107: #define BCOSTAT(dev) \
! 108:
! 109: ((tosvers >= 0x0102 && (unsigned)dev <= 4) ? \
! 110:
! 111: (int)callout1(xcostat[dev], dev) : Bcostat(dev))
1.1 root 112:
1.1.1.2 ! root 113: #define BCONOUT(dev, c) \
1.1 root 114:
1.1.1.2 ! root 115: ((tosvers >= 0x0102 && (unsigned)dev <= 4) ? \
1.1 root 116:
1.1.1.2 ! root 117: callout2(xconout[dev], dev, c) : Bconout(dev, c))
1.1 root 118:
1.1.1.2 ! root 119: #define BCONSTAT(dev) \
1.1 root 120:
1.1.1.2 ! root 121: ((tosvers >= 0x0102 && (unsigned)dev <= 4) ? \
! 122:
! 123: (int)callout1(xconstat[dev], dev) : Bconstat(dev))
! 124:
! 125: #define BCONIN(dev) \
! 126:
! 127: ((tosvers >= 0x0102 && (unsigned)dev <= 4) ? \
! 128:
! 129: callout1(xconin[dev], dev) : Bconin(dev))
1.1 root 130:
131:
132:
133: /* variables for monitoring the keyboard */
134:
135: IOREC_T *keyrec; /* keyboard i/o record pointer */
136:
137: short kintr = 0; /* keyboard interrupt pending (see intr.s) */
138:
139:
140:
141: /* Getmpb is not allowed under MiNT */
142:
143:
144:
1.1.1.2 ! root 145: long ARGS_ON_STACK
1.1 root 146:
147: getmpb(ptr)
148:
149: void *ptr;
150:
151: {
152:
1.1.1.2 ! root 153: UNUSED(ptr);
! 154:
! 155:
! 156:
! 157: DEBUG(("failed call to Getmpb"));
1.1 root 158:
159: return -1;
160:
161: }
162:
163:
164:
165:
166:
167: /*
168:
169: * Note that BIOS handles 0 - MAX_BHANDLE now reference file handles;
170:
171: * to get the physical devices, go through u:\dev\
172:
173: *
174:
175: * A note on translation: all of the bco[n]XXX functions have a "u"
176:
177: * variant that is actually what the user calls. For example,
178:
179: * ubconstat is the function that gets control after the user does
180:
181: * a Bconstat. It figures out what device or file handle is
182:
183: * appropriate. Typically, it will be a biosfs file handle; a
184:
185: * request is sent to biosfs, and biosfs in turn figures out
186:
187: * the "real" device and calls bconstat.
188:
189: */
190:
191:
192:
1.1.1.2 ! root 193: /*
! 194:
! 195: * WARNING: syscall.spp assumes that ubconstat never blocks.
! 196:
! 197: */
! 198:
! 199: long ARGS_ON_STACK
1.1 root 200:
201: ubconstat(dev)
202:
203: int dev;
204:
205: {
206:
1.1.1.2 ! root 207: if (dev < MAX_BHANDLE) {
! 208:
! 209: FILEPTR *f = curproc->handle[binput[dev]];
1.1 root 210:
1.1.1.2 ! root 211: return file_instat(f) ? -1 : 0;
! 212:
! 213: }
1.1 root 214:
215: else
216:
217: return bconstat(dev);
218:
219: }
220:
221:
222:
223: long
224:
225: bconstat(dev)
226:
227: int dev;
228:
229: {
230:
231: if (dev == CONSDEV) {
232:
233: if (checkkeys()) return 0;
234:
235: return (keyrec->head != keyrec->tail) ? -1 : 0;
236:
237: }
238:
239: if (dev == AUXDEV && has_bconmap)
240:
241: dev = curproc->bconmap;
242:
243:
244:
1.1.1.2 ! root 245: return BCONSTAT(dev);
1.1 root 246:
247: }
248:
249:
250:
251: /* bconin: input a character */
252:
1.1.1.2 ! root 253: /*
1.1 root 254:
1.1.1.2 ! root 255: * WARNING: syscall.spp assumes that ubconin never
1.1 root 256:
1.1.1.2 ! root 257: * blocks if ubconstat returns non-zero.
! 258:
! 259: */
! 260:
! 261: long ARGS_ON_STACK
1.1 root 262:
263: ubconin(dev)
264:
265: int dev;
266:
267: {
268:
1.1.1.2 ! root 269: if (dev < MAX_BHANDLE) {
! 270:
! 271: FILEPTR *f = curproc->handle[binput[dev]];
1.1 root 272:
1.1.1.2 ! root 273: return file_getchar(f, RAW);
! 274:
! 275: }
1.1 root 276:
277: else
278:
279: return bconin(dev);
280:
281: }
282:
283:
284:
285: long
286:
287: bconin(dev)
288:
289: int dev;
290:
291: {
292:
293: IOREC_T *k;
294:
295: long r;
296:
297: short h;
298:
299:
300:
301: if (dev == CONSDEV) {
302:
303: k = keyrec;
304:
305: again:
306:
307: while (k->tail == k->head) {
308:
309: yield();
310:
311: }
312:
313:
314:
315: if (checkkeys()) goto again;
316:
317:
318:
319: h = k->head + 4;
320:
321: if (h >= k->buflen)
322:
323: h = 0;
324:
325: r = *((long *)(k->bufaddr + h));
326:
327: k->head = h;
328:
329: return r;
330:
331: }
332:
333: else {
334:
335: if (dev == AUXDEV && has_bconmap)
336:
337: dev = curproc->bconmap;
338:
339:
340:
1.1.1.2 ! root 341: if (dev > 0) {
1.1 root 342:
1.1.1.2 ! root 343: while (!BCONSTAT(dev)) {
1.1 root 344:
345: yield();
346:
347: }
348:
1.1.1.2 ! root 349: }
! 350:
1.1 root 351: }
352:
353:
354:
1.1.1.2 ! root 355: r = BCONIN(dev);
1.1 root 356:
357:
358:
359: return r;
360:
361: }
362:
363:
364:
365: /* bconout: output a character.
366:
367: * returns 0 for failure, nonzero for success
368:
369: */
370:
371:
372:
1.1.1.2 ! root 373: long ARGS_ON_STACK
1.1 root 374:
375: ubconout(dev, c)
376:
377: int dev, c;
378:
379: {
380:
381: FILEPTR *f;
382:
1.1.1.2 ! root 383: char outp;
! 384:
1.1 root 385:
386:
387: if (dev < MAX_BHANDLE) {
388:
389: f = curproc->handle[boutput[dev]];
390:
391: if (!f) return 0;
392:
393: if (is_terminal(f)) {
394:
395: return tty_putchar(f, ((long)c)&0x00ff, RAW);
396:
397: }
398:
1.1.1.2 ! root 399: outp = c;
1.1 root 400:
1.1.1.2 ! root 401: return (*f->dev->write)(f, &outp, 1L);
1.1 root 402:
403: }
404:
405: else if (dev == 5) {
406:
407: c &= 0x00ff;
408:
409: f = curproc->handle[-1];
410:
411: if (!f) return 0;
412:
413: if (is_terminal(f)) {
414:
415: if (c < ' ') {
416:
417: /* MW hack for quoted characters */
418:
419: tty_putchar(f, (long)'\033', RAW);
420:
421: tty_putchar(f, (long)'Q', RAW);
422:
423: }
424:
425: return tty_putchar(f, ((long)c)&0x00ff, RAW);
426:
427: }
428:
429: /* note: we're assuming sizeof(int) == 2 here! */
430:
1.1.1.2 ! root 431: outp = c;
! 432:
! 433: return (*f->dev->write)(f, &outp, 1L);
1.1 root 434:
435: } else
436:
437: return bconout(dev, c);
438:
439: }
440:
441:
442:
443: long
444:
445: bconout(dev, c)
446:
447: int dev,c;
448:
449: {
450:
451: int statdev;
452:
453: long endtime;
454:
455: extern long searchtime; /* in dosdir.c; updated once per second */
456:
457:
458:
459: if (dev == AUXDEV && has_bconmap) {
460:
461: dev = curproc->bconmap;
462:
463: }
464:
465:
466:
467: /* compensate for a known BIOS bug; MIDI and IKBD are switched */
468:
469: if (dev == 3) { /* MIDI */
470:
471: statdev = 4;
472:
473: } else if (dev == 4) {
474:
475: statdev = 3;
476:
477: } else
478:
479: statdev = dev;
480:
481:
482:
483: /* provide a 10 second time out */
484:
1.1.1.2 ! root 485: if (!BCOSTAT(statdev)) {
1.1 root 486:
1.1.1.2 ! root 487: endtime = searchtime + 10;
1.1 root 488:
1.1.1.2 ! root 489: do {
1.1 root 490:
1.1.1.2 ! root 491: yield();
! 492:
! 493: } while (!BCOSTAT(statdev) && searchtime < endtime);
1.1 root 494:
1.1.1.2 ! root 495: if ( searchtime >= endtime) return 0;
! 496:
! 497: }
1.1 root 498:
499:
500:
501: /* special case: many text accelerators return a bad value from
502:
503: * Bconout, so we ignore the returned value for the console
504:
505: */
506:
507: if (dev != CONSDEV) {
508:
509: /* NOTE: if your compiler complains about the next line, then Bconout is
510:
511: * improperly declared in your osbind.h header file. it should be returning
512:
513: * a long value; some libraries incorrectly have Bconout returning void
514:
515: * (or cast the returned value to void)
516:
517: */
518:
1.1.1.2 ! root 519: return BCONOUT(dev,c);
1.1 root 520:
521: } else {
522:
1.1.1.2 ! root 523: (void)BCONOUT(dev, c);
1.1 root 524:
525: return 1;
526:
527: }
528:
529: }
530:
531:
532:
533: /* rwabs: various disk stuff */
534:
535:
536:
1.1.1.2 ! root 537: /* BUG: Rwabs should respect Dlock */
! 538:
! 539:
! 540:
! 541: long ARGS_ON_STACK
1.1 root 542:
543: rwabs(rwflag, buffer, number, recno, dev, lrecno)
544:
545: int rwflag, number, recno, dev;
546:
547: void *buffer;
548:
549: long lrecno;
550:
551: {
552:
553: long r;
554:
1.1.1.2 ! root 555: extern PROC *dlockproc[]; /* in dosdir.c */
! 556:
! 557:
! 558:
! 559: if (dev >= 0 && dev < NUM_DRIVES && dlockproc[dev]) {
! 560:
! 561: if (dlockproc[dev] != curproc) {
! 562:
! 563: DEBUG(("Rwabs: device %c is locked", dev+'A'));
! 564:
! 565: return ELOCKED;
! 566:
! 567: }
! 568:
! 569: }
! 570:
1.1 root 571:
572:
573: /* Note that some (most?) Rwabs device drivers don't bother saving
574:
575: * registers, whereas our compiler expects politeness. So we go
576:
577: * via callout(), which will save registers for us.
578:
579: */
580:
581: r = callout(RWABS, rwflag, buffer, number, recno, dev, lrecno);
582:
583: return r;
584:
585: }
586:
587:
588:
589: /* setexc: set exception vector */
590:
591:
592:
1.1.1.2 ! root 593: long ARGS_ON_STACK
1.1 root 594:
595: setexc(number, vector)
596:
597: int number;
598:
599: long vector;
600:
601: {
602:
603: long *place;
604:
605: long old;
606:
607: extern long save_dos, save_bios, save_xbios; /* in main.c */
608:
609:
610:
1.1.1.2 ! root 611: TRACE(("Setexc %d, %lx", number, vector));
1.1 root 612:
613: place = (long *)(((long)number) << 2);
614:
615: if (number == 0x21) /* trap_1 */
616:
617: old = save_dos;
618:
619: else if (number == 0x2d) /* trap_13 */
620:
621: old = save_bios;
622:
623: else if (number == 0x2e) /* trap_14 */
624:
625: old = save_xbios;
626:
627: else if (number == 0x101)
628:
629: old = (long)curproc->criticerr; /* critical error vector */
630:
631: else if (number == 0x102)
632:
633: old = curproc->ctxt[SYSCALL].term_vec; /* GEMDOS term vector */
634:
635: else
636:
637: old = *place;
638:
639:
640:
641: if (vector > 0) {
642:
643: if (number == 0x21)
644:
645: save_dos = vector;
646:
647: else if (number == 0x2d)
648:
649: save_bios = vector;
650:
651: else if (number == 0x2e)
652:
653: save_xbios = vector;
654:
655: else if (number == 0x102)
656:
657: curproc->ctxt[SYSCALL].term_vec = vector;
658:
659: else if (number == 0x101) {
660:
661: long mintcerr;
662:
663:
664:
665: /*
666:
667: * problem: lots of TSR's look for the Setexc(0x101,...)
668:
669: * that the AES does at startup time; so we have
670:
671: * to pass it along.
672:
673: */
674:
675: mintcerr = (long) Setexc(0x101, (void *)vector);
676:
1.1.1.2 ! root 677: curproc->criticerr = (long ARGS_ON_STACK (*) P_((long))) *place;
1.1 root 678:
679: *place = mintcerr;
680:
681: }
682:
683: else {
684:
685: /* We would do just *place = vector except that
686:
687: * someone else might be intercepting Setexc looking
688:
689: * for something in particular...
690:
691: */
692:
693: old = (long) Setexc(number, (void *)vector);
694:
695: }
696:
697: }
698:
699: return old;
700:
701: }
702:
703:
704:
705: /* tickcal: return milliseconds per system clock tick */
706:
707:
708:
1.1.1.2 ! root 709: long ARGS_ON_STACK
1.1 root 710:
711: tickcal()
712:
713: {
714:
715: return (long) (*( (unsigned *) 0x0442L ));
716:
717: }
718:
719:
720:
721: /* getbpb: get BIOS parameter block */
722:
723:
724:
1.1.1.2 ! root 725: long ARGS_ON_STACK
1.1 root 726:
727: getbpb(dev)
728:
729: int dev;
730:
731: {
732:
733: long r;
734:
735:
736:
737: /* we can't trust the Getbpb routine to accurately save all registers,
738:
739: * so we do it ourselves
740:
741: */
742:
743: r = callout(GETBPB, dev);
744:
745: /*
746:
747: * There is a bug in the TOS disk handling routines (well several actually).
748:
749: * If the directory size of Getbpb() is returned as zero then the drive 'dies'
750:
751: * and wont read any new disks even with the 'ESC' enforced disk change . This
752:
753: * is present even in TOS 1.6 (not sure about 1.62 though). This small routine
754:
755: * changes the dir size to '1' if it is zero . It may make some non-TOS disks
756:
757: * look a bit weird but that's better than killing the drive .
758:
759: */
760:
761: if (r) {
762:
763: if ( ((short *)r)[3] == 0) /* 0 directory size? */
764:
765: ((short *)r)[3] = 1;
766:
767: }
768:
769: return r;
770:
771: }
772:
773:
774:
775: /* bcostat: return output device status */
776:
777:
778:
1.1.1.2 ! root 779: /* WARNING: syscall.spp assumes that ubcostat never
! 780:
! 781: * blocks
! 782:
! 783: */
! 784:
! 785: long ARGS_ON_STACK
1.1 root 786:
787: ubcostat(dev)
788:
789: int dev;
790:
791: {
792:
1.1.1.2 ! root 793: FILEPTR *f;
! 794:
! 795:
! 796:
1.1 root 797: /* the BIOS switches MIDI (3) and IKBD (4) (a bug, but it can't be corrected) */
798:
799: if (dev == 4) { /* really the MIDI port */
800:
1.1.1.2 ! root 801: f = curproc->handle[boutput[3]];
! 802:
! 803: return file_outstat(f) ? -1 : 0;
1.1 root 804:
805: }
806:
807: if (dev == 3)
808:
1.1.1.2 ! root 809: return BCOSTAT(dev);
1.1 root 810:
811:
812:
1.1.1.2 ! root 813: if (dev < MAX_BHANDLE) {
1.1 root 814:
1.1.1.2 ! root 815: f = curproc->handle[boutput[dev]];
1.1 root 816:
1.1.1.2 ! root 817: return file_outstat(f) ? -1 : 0;
! 818:
! 819: } else
1.1 root 820:
821: return bcostat(dev);
822:
823: }
824:
825:
826:
827: long
828:
829: bcostat(dev)
830:
831: int dev;
832:
833: {
834:
835:
836:
837: if (dev == CONSDEV) {
838:
839: return -1;
840:
841: }
842:
843: else if (dev == AUXDEV && has_bconmap) {
844:
845: dev = curproc->bconmap;
846:
847: }
848:
849: /* compensate here for the BIOS bug, so that the MIDI and IKBD files work
850:
851: * correctly
852:
853: */
854:
855: else if (dev == 3) dev = 4;
856:
857: else if (dev == 4) dev = 3;
858:
859:
860:
1.1.1.2 ! root 861: return BCOSTAT(dev);
1.1 root 862:
863: }
864:
865:
866:
867: /* mediach: check for media change */
868:
869:
870:
1.1.1.2 ! root 871: long ARGS_ON_STACK
1.1 root 872:
873: mediach(dev)
874:
875: int dev;
876:
877: {
878:
879: long r;
880:
881:
882:
883: r = callout(MEDIACH, dev);
884:
885: return r;
886:
887: }
888:
889:
890:
891: /* drvmap: return drives connected to system */
892:
893:
894:
1.1.1.2 ! root 895: long ARGS_ON_STACK
1.1 root 896:
897: drvmap()
898:
899: {
900:
901: return *( (long *)0x4c2L );
902:
903: }
904:
905:
906:
907: /* kbshift: return (and possibly change) keyboard shift key status */
908:
1.1.1.2 ! root 909: /* WARNING: syscall.spp assumes that kbshift never blocks, and never
1.1 root 910:
1.1.1.2 ! root 911: * calls any underlying TOS functions
1.1 root 912:
1.1.1.2 ! root 913: */
! 914:
! 915: long ARGS_ON_STACK
1.1 root 916:
917: kbshift(mode)
918:
919: int mode;
920:
921: {
922:
923: int oldshft;
924:
925:
926:
927: oldshft = *((unsigned char *)kbshft);
928:
929: if (mode >= 0)
930:
931: *kbshft = mode;
932:
933: return oldshft;
934:
935: }
936:
937:
938:
939:
940:
941: /* special Bconout buffering code:
942:
943: * Because system call overhead is so high, programs that do output
944:
945: * with Bconout suffer in performance. To compensate for this,
946:
947: * Bconout is special-cased in syscall.s, and if possible characters
948:
949: * are placed in the 256 byte bconbuf buffer. This buffer is flushed
950:
951: * when any system call other than Bconout happens, or when a context
952:
953: * switch occurs.
954:
955: */
956:
957:
958:
959: short bconbsiz; /* number of characters in buffer */
960:
961: unsigned char bconbuf[256]; /* buffer contents */
962:
963: short bconbdev; /* BIOS device for which the buffer is valid */
964:
965: /* (-1 means no buffering is active) */
966:
967:
968:
969: /*
970:
971: * flush pending BIOS output. Return 0 if some bytes were not successfully
972:
973: * written, non-zero otherwise (just like bconout)
974:
975: */
976:
977:
978:
1.1.1.2 ! root 979: long ARGS_ON_STACK
1.1 root 980:
981: bflush() /* flush bios output */
982:
983: {
984:
985: long ret, bsiz;
986:
987: unsigned char *s;
988:
989: FILEPTR *f;
990:
991: short dev;
992:
993: short statdev;
994:
1.1.1.2 ! root 995: long lbconbuf[256];
! 996:
1.1 root 997:
998:
999: if ((dev = bconbdev) < 0) return 0;
1000:
1001:
1002:
1003: /*
1004:
1005: * Here we lock the BIOS buffering mechanism by setting bconbdev to -1
1006:
1007: * This is necessary because if two or more programs try to do
1008:
1009: * buffered BIOS output at the same time, they can get seriously
1010:
1011: * mixed up. We unlock by setting bconbdev to 0.
1012:
1013: *
1014:
1015: * NOTE: some code (e.g. in sleep()) checks for bconbsiz != 0 in
1016:
1017: * order to see if we need to do a bflush; if one is already in
1018:
1019: * progress, it's pointless to do this, so we save a bit of
1020:
1021: * time by setting bconbsiz to 0 here.
1022:
1023: */
1024:
1025: bconbdev = -1;
1026:
1027: bsiz = bconbsiz;
1028:
1.1.1.2 ! root 1029: if (bsiz == 0) return 0;
! 1030:
1.1 root 1031: bconbsiz = 0;
1032:
1033:
1034:
1035: /* BIOS handles 0..MAX_BHANDLE-1 are aliases for special GEMDOS files */
1036:
1037: if (dev < MAX_BHANDLE || dev == 5) {
1038:
1039: if (dev == 5)
1040:
1041: f = curproc->handle[-1];
1042:
1043: else
1044:
1045: f = curproc->handle[boutput[dev]];
1046:
1047:
1048:
1049: if (!f) {
1050:
1051: bconbdev = 0;
1052:
1053: return 0;
1054:
1055: }
1056:
1057: if (is_terminal(f)) {
1058:
1059: s = bconbuf;
1060:
1061: if (dev == 5) {
1062:
1063: while (bsiz-- > 0) {
1064:
1065: if (*s < ' ') {
1066:
1067: /* use ESC-Q to quote control character */
1068:
1069: (void)tty_putchar(f, (long)'\033',
1070:
1071: RAW);
1072:
1073: (void)tty_putchar(f, (long)'Q',
1074:
1075: RAW);
1076:
1077: }
1078:
1079: (void) tty_putchar(f, (long)*s++, RAW);
1080:
1081: }
1082:
1083: } else {
1084:
1.1.1.2 ! root 1085: #if 1
! 1086:
! 1087: long *where, nbytes;
! 1088:
! 1089:
! 1090:
! 1091: /* the tty_putchar should set up terminal modes correctly */
! 1092:
! 1093: (void) tty_putchar(f, (long)*s++, RAW);
! 1094:
! 1095: where = lbconbuf;
! 1096:
! 1097: nbytes = 0;
! 1098:
! 1099: while (--bsiz > 0) {
! 1100:
! 1101: *where++ = *s++; nbytes+=4;
! 1102:
! 1103: }
! 1104:
! 1105: if (nbytes)
! 1106:
! 1107: (*f->dev->write)(f, (char *)lbconbuf, nbytes);
! 1108:
! 1109: #else
! 1110:
1.1 root 1111: while (bsiz-- > 0) {
1112:
1113: (void) tty_putchar(f, (long)*s++, RAW);
1114:
1115: }
1116:
1.1.1.2 ! root 1117: #endif
! 1118:
1.1 root 1119: }
1120:
1121: ret = -1;
1122:
1123: } else {
1124:
1125: ret = (*f->dev->write)(f, (char *)bconbuf, bsiz);
1126:
1127: }
1128:
1129: bconbdev = 0;
1130:
1131: return ret;
1132:
1133: }
1134:
1135:
1136:
1137: /* Otherwise, we have a real BIOS device */
1138:
1139:
1140:
1141: if (dev == AUXDEV && has_bconmap) {
1142:
1143: dev = curproc->bconmap;
1144:
1145: statdev = dev;
1146:
1147: }
1148:
1149: /* compensate for a known BIOS bug; MIDI and IKBD are switched */
1150:
1151: else if (dev == 3) { /* MIDI */
1152:
1153: statdev = 4;
1154:
1155: } else if (dev == 4) {
1156:
1157: statdev = 3;
1158:
1159: } else
1160:
1161: statdev = dev;
1162:
1163:
1164:
1165: s = bconbuf;
1166:
1167: while (bsiz-- > 0) {
1168:
1.1.1.2 ! root 1169: while (!BCOSTAT(statdev)) yield();
1.1 root 1170:
1.1.1.2 ! root 1171: (void)BCONOUT(dev,*s);
1.1 root 1172:
1173: s++;
1174:
1175: }
1176:
1177: bconbdev = 0;
1178:
1179: return 1L;
1180:
1181: }
1182:
1183:
1184:
1185: /* initialize bios table */
1186:
1187:
1188:
1189: #define BIOS_MAX 0x20
1190:
1191:
1192:
1193: Func bios_tab[BIOS_MAX] = {
1194:
1195: getmpb,
1196:
1197: ubconstat,
1198:
1199: ubconin,
1200:
1201: ubconout,
1202:
1.1.1.2 ! root 1203:
! 1204:
1.1 root 1205: rwabs,
1206:
1207: setexc,
1208:
1209: tickcal,
1210:
1211: getbpb,
1212:
1.1.1.2 ! root 1213:
! 1214:
1.1 root 1215: ubcostat,
1216:
1217: mediach,
1218:
1219: drvmap,
1220:
1221: kbshift,
1222:
1.1.1.2 ! root 1223:
! 1224:
1.1 root 1225: 0, 0, 0, 0,
1226:
1227: 0, 0, 0, 0, 0, 0, 0, 0,
1228:
1229: 0, 0, 0, 0, 0, 0, 0, 0
1230:
1231: };
1232:
1233:
1234:
1235: short bios_max = BIOS_MAX;
1236:
1237:
1238:
1239: /*
1240:
1241: * BIOS initialization routine: gets keyboard buffer pointers, for the
1242:
1243: * interrupt routine below
1244:
1245: */
1246:
1247:
1248:
1249: void
1250:
1251: init_bios()
1252:
1253: {
1254:
1255: keyrec = (IOREC_T *)Iorec(1);
1256:
1257: }
1258:
1259:
1260:
1261: /*
1262:
1.1.1.2 ! root 1263: * do_bconin: try to do a bconin function quickly, without
! 1264:
! 1265: * blocking. If we can't do it without blocking, we return
! 1266:
! 1267: * 0x0123dead and the calling trap #13 code falls through
! 1268:
! 1269: * to the normal bconin stuff. We can't block here because
! 1270:
! 1271: * the trap #13 code hasn't yet saved registers or other
! 1272:
! 1273: * context bits, so sleep() wouldn't work properly.
! 1274:
! 1275: */
! 1276:
! 1277:
! 1278:
! 1279: #define WOULDBLOCK 0x0123deadL
! 1280:
! 1281:
! 1282:
! 1283: /* WARNING: syscall.spp assumes that do_bconin never blocks */
! 1284:
! 1285:
! 1286:
! 1287: long ARGS_ON_STACK
! 1288:
! 1289: do_bconin(dev)
! 1290:
! 1291: int dev;
! 1292:
! 1293: {
! 1294:
! 1295: FILEPTR *f;
! 1296:
! 1297: long r;
! 1298:
! 1299: unsigned char c;
! 1300:
! 1301:
! 1302:
! 1303: if (dev < MAX_BHANDLE) {
! 1304:
! 1305: f = curproc->handle[binput[dev]];
! 1306:
! 1307: if (!f) return 0;
! 1308:
! 1309: r = 0;
! 1310:
! 1311: (void)(*f->dev->ioctl)(f, FIONREAD, &r);
! 1312:
! 1313: if (!r) return WOULDBLOCK; /* data not ready */
! 1314:
! 1315: if (is_terminal(f))
! 1316:
! 1317: r = tty_getchar(f, RAW);
! 1318:
! 1319: else {
! 1320:
! 1321: r = (*f->dev->read)(f, (char *)&c, 1L);
! 1322:
! 1323: r = (r == 1) ? c : MiNTEOF;
! 1324:
! 1325: }
! 1326:
! 1327: } else {
! 1328:
! 1329: if (!bconstat(dev))
! 1330:
! 1331: r = WOULDBLOCK;
! 1332:
! 1333: else
! 1334:
! 1335: r = bconin(dev);
! 1336:
! 1337: }
! 1338:
! 1339: return r;
! 1340:
! 1341: }
! 1342:
! 1343:
! 1344:
! 1345: /*
! 1346:
1.1 root 1347: * routine for checking keyboard (called by sleep() on any context
1348:
1349: * switch where a keyboard event occured). returns 1 if a special
1350:
1351: * control character was eaten, 0 if not
1352:
1353: */
1354:
1355:
1356:
1357: int
1358:
1359: checkkeys()
1360:
1361: {
1362:
1363: char scan, ch;
1364:
1365: short shift;
1366:
1367: int sig, ret;
1368:
1369: struct tty *tty = &con_tty;
1370:
1371: extern char mshift; /* for mouse -- see biosfs.c */
1372:
1373: static short oldktail = 0;
1374:
1375:
1376:
1377: ret = 0;
1378:
1379: mshift = kbshift(-1);
1380:
1381: while (oldktail != keyrec->tail) {
1382:
1383:
1384:
1385: /* BUG: we really should check the shift status _at the time the key was
1386:
1387: * pressed_, not now!
1388:
1389: */
1390:
1391: sig = 0;
1392:
1393: shift = mshift;
1394:
1395: oldktail += 4;
1396:
1397: if (oldktail >= keyrec->buflen)
1398:
1399: oldktail = 0;
1400:
1401:
1402:
1403: scan = (keyrec->bufaddr + oldktail)[1];
1404:
1405: /* function key?? */
1406:
1407: if ( (scan >= 0x3b && scan <= 0x44) ||
1408:
1409: (scan >= 0x54 && scan <= 0x5d) ||
1410:
1411: scan == DEL || scan == UNDO) {
1412:
1413: if ( (shift & CTRLALT) == CTRLALT ) {
1414:
1415: oldktail = keyrec->head = keyrec->tail;
1416:
1417: do_func_key(scan);
1418:
1.1.1.2 ! root 1419: /* do_func_key may have read some keys */
! 1420:
! 1421: oldktail = keyrec->head;
! 1422:
! 1423: mshift = kbshift (-1);
! 1424:
1.1 root 1425: ret = 1;
1426:
1427: continue;
1428:
1429: }
1430:
1431: }
1432:
1433:
1434:
1435: /* check for special control keys, etc. */
1436:
1437: /* BUG: this doesn't exactly match TOS' behavior, particularly for
1438:
1439: * ^S/^Q
1440:
1441: */
1442:
1443: if ((tty->state & TS_COOKED) || (shift & CTRLALT) == CTRLALT) {
1444:
1445: ch = (keyrec->bufaddr + keyrec->tail)[3];
1446:
1447: if (ch == UNDEF)
1448:
1449: ; /* do nothing */
1450:
1451: else if (ch == tty->tc.t_intrc)
1452:
1453: sig = SIGINT;
1454:
1455: else if (ch == tty->tc.t_quitc)
1456:
1457: sig = SIGQUIT;
1458:
1459: else if (ch == tty->ltc.t_suspc)
1460:
1461: sig = SIGTSTP;
1462:
1463: else if (ch == tty->tc.t_stopc) {
1464:
1465: tty->state |= TS_HOLD;
1466:
1467: ret = 1;
1468:
1469: keyrec->head = oldktail;
1470:
1471: continue;
1472:
1473: }
1474:
1475: else if (ch == tty->tc.t_startc) {
1476:
1477: tty->state &= ~TS_HOLD;
1478:
1479: ret = 1;
1480:
1481: keyrec->head = oldktail;
1482:
1483: continue;
1484:
1485: }
1486:
1487: if (sig) {
1488:
1489: tty->state &= ~TS_HOLD;
1490:
1491: if (!(tty->sg.sg_flags & T_NOFLSH))
1492:
1493: oldktail = keyrec->head = keyrec->tail;
1494:
1495: killgroup(tty->pgrp, sig);
1496:
1497: ret = 1;
1498:
1499: }
1500:
1501: else if (tty->state & TS_HOLD) {
1502:
1503: keyrec->head = oldktail;
1504:
1505: ret = 1;
1506:
1507: }
1508:
1509: }
1510:
1511:
1512:
1513: }
1514:
1515:
1516:
1517: /* has someone done select() on the keyboard?? */
1518:
1519: if (tty->rsel && keyrec->head != keyrec->tail)
1520:
1521: wakeselect(tty->rsel);
1522:
1523:
1524:
1525: return ret;
1526:
1527: }
1528:
1529:
1530:
1531: /* do_func_key moved to debug.c */
1532:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.