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