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