|
|
1.1 root 1: /*
2:
1.1.1.3 root 3: Copyright 1990,1991,1992 Eric R. Smith.
4:
1.1.1.5 root 5: Copyright 1992,1993,1994 Atari Corporation.
1.1.1.3 root 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.1.6 ! root 49: #define SERDEV 6 /* First serial port */
! 50:
1.1 root 51:
52:
53: /* BIOS devices 0..MAX_BHANDLE-1 can be redirected to GEMDOS files */
54:
55: #define MAX_BHANDLE 4
56:
57:
58:
59: /* BIOS redirection maps */
60:
1.1.1.2 root 61: const short binput[MAX_BHANDLE] = { -3, -2, -1, -4 };
1.1 root 62:
1.1.1.2 root 63: const short boutput[MAX_BHANDLE] = { -3, -2, -1, -5 };
1.1 root 64:
65:
66:
67: /* tty structures for the BIOS devices -- see biosfs.c */
68:
1.1.1.6 ! root 69: extern struct tty con_tty, aux_tty, midi_tty, sccb_tty, scca_tty, ttmfp_tty;
! 70:
! 71: extern struct bios_tty bttys[], midi_btty;
! 72:
! 73: extern short btty_max;
1.1 root 74:
75:
76:
77: extern int tosvers; /* from main.c */
78:
1.1.1.4 root 79:
80:
1.1 root 81: char *kbshft; /* set in main.c */
82:
83:
84:
1.1.1.5 root 85: short console_in; /* wait condition for console input */
86:
87:
88:
1.1.1.6 ! root 89: /* save cluster sizes of BIOS drives 0..31 (used in tosfs.c) */
! 90:
! 91: unsigned short clsizb[32];
! 92:
! 93:
! 94:
1.1 root 95: /* some BIOS vectors; note that the routines at these vectors may do nasty
96:
97: * things to registers!
98:
99: */
100:
101:
102:
1.1.1.2 root 103: #define RWABS *((long *)0x476L)
1.1 root 104:
1.1.1.2 root 105: #define MEDIACH *((long *)0x47eL)
1.1 root 106:
1.1.1.2 root 107: #define GETBPB *((long *)0x472L)
1.1 root 108:
109:
110:
1.1.1.3 root 111:
112:
1.1.1.2 root 113: /* these are supposed to be tables holding the addresses of the
1.1 root 114:
1.1.1.2 root 115: * first 8 BconXXX functions, but in fact only the first 5 are
1.1 root 116:
1.1.1.2 root 117: * placed here (and device 5 only has Bconout implemented;
1.1 root 118:
1.1.1.2 root 119: * we don't use that device (raw console) anyway).
1.1 root 120:
1.1.1.2 root 121: */
122:
123:
124:
125: #define xconstat ((long *)0x51eL)
126:
127: #define xconin ((long *)0x53eL)
128:
129: #define xcostat ((long *)0x55eL)
130:
131: #define xconout ((long *)0x57eL)
132:
133:
134:
1.1.1.6 ! root 135: #if 1
! 136:
! 137: /* if the system has Bconmap the ones >= 6 are in a table available
! 138:
! 139: * thru Bconmap(-2)...
! 140:
! 141: */
! 142:
! 143: #define MAPTAB (bconmap2->maptab)
! 144:
! 145:
! 146:
! 147: /* and then do BCOSTAT ourselves, the BIOS SCC ones are often broken */
! 148:
! 149: #define BCOSTAT(dev) \
! 150:
! 151: (((unsigned)dev <= 4) ? ((tosvers >= 0x0102) ? \
! 152:
! 153: (int)callout1(xcostat[dev], dev) : Bcostat(dev)) : \
! 154:
! 155: ((has_bconmap && (unsigned)dev-SERDEV < btty_max) ? \
! 156:
! 157: bcxstat(MAPTAB[dev-SERDEV].iorec+1) : Bcostat(dev)))
! 158:
! 159: #define BCONOUT(dev, c) \
! 160:
! 161: (((unsigned)dev <= 4) ? ((tosvers >= 0x0102) ? \
! 162:
! 163: callout2(xconout[dev], dev, c) : Bconout(dev, c)) : \
! 164:
! 165: ((has_bconmap && (unsigned)dev-SERDEV < btty_max) ? \
! 166:
! 167: callout2(MAPTAB[dev-SERDEV].bconout, dev, c) : Bconout(dev, c)))
! 168:
! 169: #define BCONSTAT(dev) \
! 170:
! 171: (((unsigned)dev <= 4) ? ((tosvers >= 0x0102) ? \
! 172:
! 173: (int)callout1(xconstat[dev], dev) : Bconstat(dev)) : \
! 174:
! 175: ((has_bconmap && (unsigned)dev-SERDEV < btty_max) ? \
! 176:
! 177: (int)callout1(MAPTAB[dev-SERDEV].bconstat, dev) : Bconstat(dev)))
! 178:
! 179: #define BCONIN(dev) \
! 180:
! 181: (((unsigned)dev <= 4) ? ((tosvers >= 0x0102) ? \
! 182:
! 183: callout1(xconin[dev], dev) : Bconin(dev)) : \
! 184:
! 185: ((has_bconmap && (unsigned)dev-SERDEV < btty_max) ? \
! 186:
! 187: callout1(MAPTAB[dev-SERDEV].bconin, dev) : Bconin(dev)))
! 188:
! 189: #else
! 190:
1.1.1.2 root 191: #define BCOSTAT(dev) \
192:
1.1.1.4 root 193: ((tosvers > 0x0102 && (unsigned)dev <= 4) ? \
1.1.1.2 root 194:
195: (int)callout1(xcostat[dev], dev) : Bcostat(dev))
1.1 root 196:
1.1.1.2 root 197: #define BCONOUT(dev, c) \
1.1 root 198:
1.1.1.4 root 199: ((tosvers > 0x0102 && (unsigned)dev <= 4) ? \
1.1 root 200:
1.1.1.2 root 201: callout2(xconout[dev], dev, c) : Bconout(dev, c))
1.1 root 202:
1.1.1.2 root 203: #define BCONSTAT(dev) \
1.1 root 204:
1.1.1.4 root 205: ((tosvers > 0x0102 && (unsigned)dev <= 4) ? \
1.1.1.2 root 206:
207: (int)callout1(xconstat[dev], dev) : Bconstat(dev))
208:
209: #define BCONIN(dev) \
210:
1.1.1.4 root 211: ((tosvers > 0x0102 && (unsigned)dev <= 4) ? \
1.1.1.2 root 212:
213: callout1(xconin[dev], dev) : Bconin(dev))
1.1 root 214:
1.1.1.6 ! root 215: #endif
! 216:
1.1.1.3 root 217:
218:
1.1.1.6 ! root 219: /* variables for monitoring the keyboard */
1.1.1.3 root 220:
1.1.1.6 ! root 221: IOREC_T *keyrec; /* keyboard i/o record pointer */
1.1.1.3 root 222:
1.1.1.6 ! root 223: BCONMAP2_T *bconmap2; /* bconmap struct */
1.1.1.3 root 224:
1.1.1.6 ! root 225: short kintr = 0; /* keyboard interrupt pending (see intr.s) */
1.1.1.3 root 226:
1.1 root 227:
228:
1.1.1.6 ! root 229: /* replacement *costat for BCOSTAT above */
1.1 root 230:
1.1.1.6 ! root 231: INLINE static int bcxstat (IOREC_T *wrec)
1.1 root 232:
1.1.1.6 ! root 233: {
! 234:
! 235: unsigned s = wrec->head - wrec->tail;
! 236:
! 237: if ((int)s <= 0)
! 238:
! 239: s += wrec->buflen;
! 240:
! 241: return s < 3 ? 0 : -1;
! 242:
! 243: }
1.1 root 244:
245:
246:
247: /* Getmpb is not allowed under MiNT */
248:
249:
250:
1.1.1.2 root 251: long ARGS_ON_STACK
1.1 root 252:
253: getmpb(ptr)
254:
255: void *ptr;
256:
257: {
258:
1.1.1.2 root 259: UNUSED(ptr);
260:
261:
262:
263: DEBUG(("failed call to Getmpb"));
1.1 root 264:
265: return -1;
266:
267: }
268:
269:
270:
1.1.1.6 ! root 271: INLINE static int
! 272:
! 273: isonline(b)
! 274:
! 275: struct bios_tty *b;
! 276:
! 277: {
! 278:
! 279: if (b->tty == &aux_tty) {
! 280:
! 281: /* modem1 */
! 282:
! 283: /* CD is !bit 1 on the 68901 GPIP port */
! 284:
! 285: return (1 << 1) & ~*((volatile char *) 0xfffffa01L);
! 286:
! 287: } else if (b->tty == &sccb_tty) {
! 288:
! 289: /* modem2 */
! 290:
! 291: /* CD is bit 3 of read register 0 on SCC port B */
! 292:
! 293: short sr = spl7();
! 294:
! 295: unsigned char r;
! 296:
! 297: volatile char dummy;
! 298:
! 299: dummy = *((volatile char *) 0xfffffa01L);
! 300:
! 301: r = (1 << 3) & *((volatile char *) 0xffff8c85L);
! 302:
! 303: spl(sr);
! 304:
! 305: return r;
! 306:
! 307: } else if (b->tty == &scca_tty) {
! 308:
! 309: /* serial2 */
! 310:
! 311: /* like modem2, only port A */
! 312:
! 313: short sr = spl7();
! 314:
! 315: unsigned char r;
! 316:
! 317: volatile char dummy;
! 318:
! 319: dummy = *((volatile char *) 0xfffffa01L);
! 320:
! 321: r = (1 << 3) & *((volatile char *) 0xffff8c81L);
! 322:
! 323: spl(sr);
! 324:
! 325: return r;
! 326:
! 327: } else {
! 328:
! 329: /* unknown port, assume CD always on. */
! 330:
! 331: return 1;
! 332:
! 333: }
! 334:
! 335: }
! 336:
! 337:
! 338:
! 339: INLINE static int
! 340:
! 341: isbrk(b)
! 342:
! 343: struct bios_tty *b;
! 344:
! 345: {
! 346:
! 347: if (b->tty == &aux_tty) {
! 348:
! 349: /* modem1 */
! 350:
! 351: /* break is bit 3 in the 68901 RSR */
! 352:
! 353: return (1 << 3) & *((volatile char *) 0xfffffa2bL);
! 354:
! 355: } else if (b->tty == &sccb_tty) {
! 356:
! 357: /* modem2 */
! 358:
! 359: /* break is bit 7 of read register 0 on SCC port B */
! 360:
! 361: short sr = spl7();
! 362:
! 363: unsigned char r;
! 364:
! 365: volatile char dummy;
! 366:
! 367: dummy = *((volatile char *) 0xfffffa01L);
! 368:
! 369: r = (1 << 7) & *((volatile char *) 0xffff8c85L);
! 370:
! 371: spl(sr);
! 372:
! 373: return r;
! 374:
! 375: } else if (b->tty == &scca_tty) {
! 376:
! 377: /* serial2 */
! 378:
! 379: /* like modem2, only port A */
! 380:
! 381: short sr = spl7();
! 382:
! 383: unsigned char r;
! 384:
! 385: volatile char dummy;
! 386:
! 387: dummy = *((volatile char *) 0xfffffa01L);
! 388:
! 389: r = (1 << 7) & *((volatile char *) 0xffff8c81L);
! 390:
! 391: spl(sr);
! 392:
! 393: return r;
! 394:
! 395: } else if (b->tty == &ttmfp_tty) {
! 396:
! 397: /* serial1 */
! 398:
! 399: return (1 << 3) & *((volatile char *) 0xfffffaabL);
! 400:
! 401: } else {
! 402:
! 403: /* unknown port, cannot detect breaks... */
! 404:
! 405: return 0;
! 406:
! 407: }
! 408:
! 409: }
! 410:
! 411:
! 412:
! 413: INLINE unsigned
! 414:
! 415: ionwrite(wrec)
! 416:
! 417: IOREC_T *wrec;
! 418:
! 419: {
! 420:
! 421: unsigned s = wrec->head - wrec->tail;
! 422:
! 423: if ((int)s <= 0)
! 424:
! 425: s += wrec->buflen;
! 426:
! 427: if ((int)(s -= 2) < 0)
! 428:
! 429: s = 0;
! 430:
! 431: return s;
! 432:
! 433: }
! 434:
! 435:
! 436:
! 437: INLINE unsigned
! 438:
! 439: ionread(irec)
! 440:
! 441: IOREC_T *irec;
! 442:
! 443: {
! 444:
! 445: unsigned r = irec->tail - irec->head;
! 446:
! 447: if ((int)r < 0)
! 448:
! 449: r += irec->buflen;
! 450:
! 451: return r;
! 452:
! 453: }
! 454:
! 455:
! 456:
! 457: INLINE unsigned
! 458:
! 459: btty_ionread(b)
! 460:
! 461: struct bios_tty *b;
! 462:
! 463: {
! 464:
! 465: long ret = 0;
! 466:
! 467: #if 1
! 468:
! 469: /* try trap #1 first, to read hardware fifos too...
! 470:
! 471: * (except for modem1/serial1 which are always in one-interrupt-per-byte mode)
! 472:
! 473: */
! 474:
! 475: if (b != bttys && b->tty != &ttmfp_tty &&
! 476:
! 477: !rsvf_ioctl (b->tosfd, &ret, FIONREAD))
! 478:
! 479: return ret;
! 480:
! 481: #endif
! 482:
! 483: return ionread (b->irec);
! 484:
! 485: }
! 486:
! 487:
! 488:
! 489: #define _hz_200 (*((long *)0x4baL))
! 490:
! 491:
! 492:
! 493: INLINE static void
! 494:
! 495: checkbtty(b, sig)
! 496:
! 497: struct bios_tty *b;
! 498:
! 499: int sig;
! 500:
! 501: {
! 502:
! 503: long *l;
! 504:
! 505:
! 506:
! 507: if (!b->irec)
! 508:
! 509: return;
! 510:
! 511: if (!b->clocal && !isonline(b)) {
! 512:
! 513: b->vticks = 0;
! 514:
! 515: b->bticks = _hz_200 + 0x80000000L;
! 516:
! 517: if (!(b->tty->state & TS_BLIND)) {
! 518:
! 519: /* just lost carrier... set TS_BLIND, let reads and writes return */
! 520:
! 521: b->tty->state |= TS_BLIND;
! 522:
! 523: iocsbrk (b->bdev, TIOCCBRK, b);
! 524:
! 525: if (sig) {
! 526:
! 527: b->orec->tail = b->orec->head;
! 528:
! 529: DEBUG(("checkbtty: bdev %d disconnect", b->bdev));
! 530:
! 531: if (!(b->tty->sg.sg_flags & T_NOFLSH))
! 532:
! 533: iread (b->bdev, (char *) NULL, 0, 1, 0);
! 534:
! 535: if (b->tty->pgrp)
! 536:
! 537: /* ...and here is the long missed :) SIGHUP */
! 538:
! 539: killgroup(b->tty->pgrp, SIGHUP, 1);
! 540:
! 541: }
! 542:
! 543: wake(IO_Q, (long)b);
! 544:
! 545: wake(IO_Q, (long)&b->tty->state);
! 546:
! 547: }
! 548:
! 549: return;
! 550:
! 551: }
! 552:
! 553: if (b->tty->state & TS_BLIND) {
! 554:
! 555: /* just got carrier (or entered local mode), clear TS_BLIND and
! 556:
! 557: * wake whoever waits for it */
! 558:
! 559: b->tty->state &= ~(TS_BLIND|TS_HOLD);
! 560:
! 561: wake(IO_Q, (long)&b->tty->state);
! 562:
! 563: }
! 564:
! 565: if (sig) {
! 566:
! 567: if (b->brkint && isbrk(b)) {
! 568:
! 569: if (!b->bticks) {
! 570:
! 571: /* the break should last for more than 200 ms or the equivalent of
! 572:
! 573: * 48 10-bit chars at ispeed (then its probably not line noise...)
! 574:
! 575: */
! 576:
! 577: if ((unsigned long)b->ispeed <= 2400)
! 578:
! 579: b->bticks = _hz_200+40L;
! 580:
! 581: else
! 582:
! 583: b->bticks = _hz_200+(480L*200L/(unsigned long)b->ispeed);
! 584:
! 585: if (!b->bticks)
! 586:
! 587: b->bticks = 1;
! 588:
! 589: } else if (_hz_200 - b->bticks > 0) {
! 590:
! 591: /* every break only one interrupt please */
! 592:
! 593: b->bticks += 0x80000000L;
! 594:
! 595: DEBUG(("checkbtty: bdev %d break(int)", b->bdev));
! 596:
! 597: if (!(b->tty->sg.sg_flags & T_NOFLSH))
! 598:
! 599: iread (b->bdev, (char *) NULL, 0, 1, 0);
! 600:
! 601: if (b->tty->pgrp)
! 602:
! 603: killgroup(b->tty->pgrp, SIGINT, 1);
! 604:
! 605: }
! 606:
! 607: } else
! 608:
! 609: b->bticks = 0;
! 610:
! 611: }
! 612:
! 613: if (!b->vticks || _hz_200 - b->vticks > 0) {
! 614:
! 615: long r;
! 616:
! 617:
! 618:
! 619: if ((r = (long)b->tty->vmin - btty_ionread(b)) <= 0) {
! 620:
! 621: b->vticks = 0;
! 622:
! 623: wake(IO_Q, (long)b);
! 624:
! 625: l = b->rsel;
! 626:
! 627: if (*l)
! 628:
! 629: wakeselect(*l);
! 630:
! 631: } else if ((--r, r *= 2000L) > (unsigned long)b->ispeed) {
! 632:
! 633: b->vticks = _hz_200 + (r/(unsigned long)b->ispeed);
! 634:
! 635: if (!b->vticks)
! 636:
! 637: b->vticks = 1;
! 638:
! 639: } else
! 640:
! 641: b->vticks = 0;
! 642:
! 643: }
! 644:
! 645: if (b->tty->state & TS_HOLD)
! 646:
! 647: return;
! 648:
! 649: l = b->wsel;
! 650:
! 651: if (*l) {
! 652:
! 653: short i = b->orec->tail - b->orec->head;
! 654:
! 655: if (i < 0)
! 656:
! 657: i += b->orec->buflen;
! 658:
! 659: if (i < b->orec->hi_water)
! 660:
! 661: wakeselect(*l);
! 662:
! 663: }
! 664:
! 665: }
! 666:
! 667:
! 668:
! 669: void
! 670:
! 671: checkbttys(void)
! 672:
! 673: {
! 674:
! 675: struct bios_tty *b;
! 676:
! 677:
! 678:
! 679: for (b=bttys;b<bttys+btty_max;b++) {
! 680:
! 681: checkbtty(b, 1);
! 682:
! 683: }
! 684:
! 685: b=&midi_btty;
! 686:
! 687: if (!b->vticks || _hz_200 - b->vticks > 0) {
! 688:
! 689: long r, *l;
! 690:
! 691:
! 692:
! 693: if ((r = (long)b->tty->vmin - ionread(b->irec)) <= 0) {
! 694:
! 695: b->vticks = 0;
! 696:
! 697: wake(IO_Q, (long)b);
! 698:
! 699: l = b->rsel;
! 700:
! 701: if (*l)
! 702:
! 703: wakeselect(*l);
! 704:
! 705: } else if ((--r, r *= 2000L) > (unsigned long)31250) {
! 706:
! 707: b->vticks = _hz_200 + (r/(unsigned long)31250);
! 708:
! 709: if (!b->vticks)
! 710:
! 711: b->vticks = 1;
! 712:
! 713: } else
! 714:
! 715: b->vticks = 0;
! 716:
! 717: }
! 718:
! 719: }
! 720:
! 721:
! 722:
! 723: void
! 724:
! 725: checkbttys_vbl(void)
! 726:
! 727: {
! 728:
! 729: struct bios_tty *b;
! 730:
! 731:
! 732:
! 733: for (b=bttys;b<bttys+btty_max;b++) {
! 734:
! 735: if (!b->clocal && b->orec->tail != b->orec->head && !isonline(b))
! 736:
! 737: b->orec->tail = b->orec->head;
! 738:
! 739: }
! 740:
! 741: }
! 742:
! 743:
! 744:
! 745: /* check 1 tty without raising sigs, needed after turning off local mode
! 746:
! 747: * (to avoid getting SIGHUP'd immediately...)
! 748:
! 749: */
! 750:
! 751:
! 752:
! 753: void
! 754:
! 755: checkbtty_nsig(b)
! 756:
! 757: struct bios_tty *b;
! 758:
! 759: {
! 760:
! 761: checkbtty(b, 0);
! 762:
! 763: }
! 764:
1.1 root 765:
766:
767: /*
768:
769: * Note that BIOS handles 0 - MAX_BHANDLE now reference file handles;
770:
771: * to get the physical devices, go through u:\dev\
772:
773: *
774:
775: * A note on translation: all of the bco[n]XXX functions have a "u"
776:
777: * variant that is actually what the user calls. For example,
778:
779: * ubconstat is the function that gets control after the user does
780:
781: * a Bconstat. It figures out what device or file handle is
782:
783: * appropriate. Typically, it will be a biosfs file handle; a
784:
785: * request is sent to biosfs, and biosfs in turn figures out
786:
787: * the "real" device and calls bconstat.
788:
789: */
790:
791:
792:
1.1.1.2 root 793: /*
794:
795: * WARNING: syscall.spp assumes that ubconstat never blocks.
796:
797: */
798:
799: long ARGS_ON_STACK
1.1 root 800:
801: ubconstat(dev)
802:
803: int dev;
804:
805: {
806:
1.1.1.2 root 807: if (dev < MAX_BHANDLE) {
808:
809: FILEPTR *f = curproc->handle[binput[dev]];
1.1 root 810:
1.1.1.2 root 811: return file_instat(f) ? -1 : 0;
812:
813: }
1.1 root 814:
815: else
816:
817: return bconstat(dev);
818:
819: }
820:
821:
822:
823: long
824:
825: bconstat(dev)
826:
827: int dev;
828:
829: {
830:
831: if (dev == CONSDEV) {
832:
833: if (checkkeys()) return 0;
834:
835: return (keyrec->head != keyrec->tail) ? -1 : 0;
836:
837: }
838:
839: if (dev == AUXDEV && has_bconmap)
840:
841: dev = curproc->bconmap;
842:
843:
844:
1.1.1.2 root 845: return BCONSTAT(dev);
1.1 root 846:
847: }
848:
849:
850:
851: /* bconin: input a character */
852:
1.1.1.2 root 853: /*
1.1 root 854:
1.1.1.2 root 855: * WARNING: syscall.spp assumes that ubconin never
1.1 root 856:
1.1.1.2 root 857: * blocks if ubconstat returns non-zero.
858:
859: */
860:
861: long ARGS_ON_STACK
1.1 root 862:
863: ubconin(dev)
864:
865: int dev;
866:
867: {
868:
1.1.1.2 root 869: if (dev < MAX_BHANDLE) {
870:
871: FILEPTR *f = curproc->handle[binput[dev]];
1.1 root 872:
1.1.1.2 root 873: return file_getchar(f, RAW);
874:
875: }
1.1 root 876:
877: else
878:
879: return bconin(dev);
880:
881: }
882:
883:
884:
885: long
886:
887: bconin(dev)
888:
889: int dev;
890:
891: {
892:
893: IOREC_T *k;
894:
895: long r;
896:
897: short h;
898:
899:
900:
901: if (dev == CONSDEV) {
902:
903: k = keyrec;
904:
905: again:
906:
907: while (k->tail == k->head) {
908:
1.1.1.5 root 909: sleep(IO_Q, (long)&console_in);
1.1 root 910:
911: }
912:
913:
914:
915: if (checkkeys()) goto again;
916:
917:
918:
919: h = k->head + 4;
920:
921: if (h >= k->buflen)
922:
923: h = 0;
924:
925: r = *((long *)(k->bufaddr + h));
926:
927: k->head = h;
928:
929: return r;
930:
931: }
932:
933: else {
934:
1.1.1.6 ! root 935: if (dev == AUXDEV) {
! 936:
! 937: if (has_bconmap) {
! 938:
! 939: dev = curproc->bconmap;
! 940:
! 941: h = dev-SERDEV;
! 942:
! 943: } else
1.1 root 944:
1.1.1.6 ! root 945: h = 0;
! 946:
! 947: } else
! 948:
! 949: h = dev-SERDEV;
! 950:
! 951:
! 952:
! 953: if ((unsigned)h < btty_max || dev == 3) {
! 954:
! 955: if (has_bconmap && dev != 3) { /* help the compiler... :) */
! 956:
! 957: long *statc;
! 958:
! 959:
! 960:
! 961: while (!callout1(*(statc=&MAPTAB[dev-SERDEV].bconstat), dev))
! 962:
! 963: sleep(IO_Q, (long)&bttys[h]);
! 964:
! 965: return callout1(statc[1], dev);
! 966:
! 967: }
1.1 root 968:
1.1.1.6 ! root 969: while (!BCONSTAT(dev))
1.1 root 970:
1.1.1.6 ! root 971: sleep(IO_Q, (long)(dev == 3 ? &midi_btty :
1.1 root 972:
1.1.1.6 ! root 973: &bttys[h]));
! 974:
! 975: } else if (dev > 0) {
1.1 root 976:
1.1.1.5 root 977: unsigned long tick;
978:
979:
980:
981: tick = *((unsigned long *)0x4baL);
982:
1.1.1.2 root 983: while (!BCONSTAT(dev)) {
1.1 root 984:
1.1.1.5 root 985: /* make blocking (for longer) reads eat less CPU...
986:
987: * if yield()ed > 2 seconds and still no data continue with nap
988:
989: */
990:
991: if ((*((unsigned long *)0x4baL) - tick) > 400)
992:
993: nap(60);
994:
995: else
996:
1.1 root 997: yield();
998:
999: }
1000:
1.1.1.2 root 1001: }
1002:
1.1 root 1003: }
1004:
1005:
1006:
1.1.1.2 root 1007: r = BCONIN(dev);
1.1 root 1008:
1009:
1010:
1011: return r;
1012:
1013: }
1014:
1015:
1016:
1017: /* bconout: output a character.
1018:
1019: * returns 0 for failure, nonzero for success
1020:
1021: */
1022:
1023:
1024:
1.1.1.2 root 1025: long ARGS_ON_STACK
1.1 root 1026:
1027: ubconout(dev, c)
1028:
1029: int dev, c;
1030:
1031: {
1032:
1033: FILEPTR *f;
1034:
1.1.1.2 root 1035: char outp;
1036:
1.1 root 1037:
1038:
1039: if (dev < MAX_BHANDLE) {
1040:
1041: f = curproc->handle[boutput[dev]];
1042:
1043: if (!f) return 0;
1044:
1045: if (is_terminal(f)) {
1046:
1047: return tty_putchar(f, ((long)c)&0x00ff, RAW);
1048:
1049: }
1050:
1.1.1.2 root 1051: outp = c;
1.1 root 1052:
1.1.1.2 root 1053: return (*f->dev->write)(f, &outp, 1L);
1.1 root 1054:
1055: }
1056:
1057: else if (dev == 5) {
1058:
1059: c &= 0x00ff;
1060:
1061: f = curproc->handle[-1];
1062:
1063: if (!f) return 0;
1064:
1065: if (is_terminal(f)) {
1066:
1067: if (c < ' ') {
1068:
1069: /* MW hack for quoted characters */
1070:
1071: tty_putchar(f, (long)'\033', RAW);
1072:
1073: tty_putchar(f, (long)'Q', RAW);
1074:
1075: }
1076:
1077: return tty_putchar(f, ((long)c)&0x00ff, RAW);
1078:
1079: }
1080:
1081: /* note: we're assuming sizeof(int) == 2 here! */
1082:
1.1.1.2 root 1083: outp = c;
1084:
1085: return (*f->dev->write)(f, &outp, 1L);
1.1 root 1086:
1087: } else
1088:
1089: return bconout(dev, c);
1090:
1091: }
1092:
1093:
1094:
1095: long
1096:
1097: bconout(dev, c)
1098:
1099: int dev,c;
1100:
1101: {
1102:
1103: int statdev;
1104:
1105: long endtime;
1106:
1.1.1.3 root 1107: #define curtime *((unsigned long *)0x4baL)
1.1 root 1108:
1109:
1110:
1111: if (dev == AUXDEV && has_bconmap) {
1112:
1113: dev = curproc->bconmap;
1114:
1115: }
1116:
1117:
1118:
1119: /* compensate for a known BIOS bug; MIDI and IKBD are switched */
1120:
1121: if (dev == 3) { /* MIDI */
1122:
1123: statdev = 4;
1124:
1125: } else if (dev == 4) {
1126:
1127: statdev = 3;
1128:
1.1.1.3 root 1129: } else {
1.1 root 1130:
1131: statdev = dev;
1132:
1.1.1.3 root 1133: }
1134:
1.1 root 1135:
1136:
1.1.1.4 root 1137: /* provide a 10 second time out for the printer */
1.1 root 1138:
1.1.1.2 root 1139: if (!BCOSTAT(statdev)) {
1.1 root 1140:
1.1.1.4 root 1141: if (dev != PRNDEV) {
1142:
1143: do {
1144:
1145: /* BUG: Speedo GDOS isn't re-entrant; so printer output to the
1146:
1147: * serial port could cause problems
1.1 root 1148:
1.1.1.4 root 1149: */
1150:
1151: yield();
1152:
1153: } while (!BCOSTAT(statdev));
1154:
1155: } else {
1156:
1157: endtime = curtime + 10*200L;
1158:
1159: do {
1.1 root 1160:
1.1.1.3 root 1161: #if 0
1162:
1.1.1.4 root 1163: /* Speedo GDOS isn't re-entrant, so we can't give up CPU
1164:
1165: * time here :-(
1166:
1167: */
1168:
1169: yield();
1.1.1.2 root 1170:
1.1.1.3 root 1171: #endif
1.1 root 1172:
1.1.1.4 root 1173: } while (!BCOSTAT(statdev) && curtime < endtime);
1174:
1175: if ( curtime >= endtime) return 0;
1.1.1.3 root 1176:
1.1.1.4 root 1177: }
1.1.1.2 root 1178:
1179: }
1.1 root 1180:
1181:
1182:
1183: /* special case: many text accelerators return a bad value from
1184:
1185: * Bconout, so we ignore the returned value for the console
1186:
1.1.1.4 root 1187: * Sigh. serptch2 and hsmodem1 also screw this up, so for now let's
1188:
1189: * only count on it being correct for the printer.
1190:
1.1 root 1191: */
1192:
1.1.1.4 root 1193: if (dev == PRNDEV) {
1.1 root 1194:
1195: /* NOTE: if your compiler complains about the next line, then Bconout is
1196:
1197: * improperly declared in your osbind.h header file. it should be returning
1198:
1199: * a long value; some libraries incorrectly have Bconout returning void
1200:
1201: * (or cast the returned value to void)
1202:
1203: */
1204:
1.1.1.2 root 1205: return BCONOUT(dev,c);
1.1 root 1206:
1207: } else {
1208:
1.1.1.2 root 1209: (void)BCONOUT(dev, c);
1.1 root 1210:
1211: return 1;
1212:
1213: }
1214:
1215: }
1216:
1217:
1218:
1219: /* rwabs: various disk stuff */
1220:
1221:
1222:
1.1.1.2 root 1223: long ARGS_ON_STACK
1.1 root 1224:
1225: rwabs(rwflag, buffer, number, recno, dev, lrecno)
1226:
1227: int rwflag, number, recno, dev;
1228:
1229: void *buffer;
1230:
1231: long lrecno;
1232:
1233: {
1234:
1235: long r;
1236:
1.1.1.2 root 1237: extern PROC *dlockproc[]; /* in dosdir.c */
1238:
1.1.1.5 root 1239: extern int aliasdrv[]; /* in filesys.c */
1240:
1.1.1.2 root 1241:
1242:
1.1.1.6 ! root 1243: /* jr: inspect bit 3 of rwflag!!! */
! 1244:
! 1245:
! 1246:
! 1247: if (!(rwflag & 8) && dev >= 0 && dev < NUM_DRIVES) {
1.1.1.2 root 1248:
1.1.1.5 root 1249: if (aliasdrv[dev]) {
1250:
1251: dev = aliasdrv[dev] - 1;
1252:
1253: }
1254:
1255: if (dlockproc[dev] && dlockproc[dev] != curproc) {
1.1.1.2 root 1256:
1257: DEBUG(("Rwabs: device %c is locked", dev+'A'));
1258:
1259: return ELOCKED;
1260:
1261: }
1262:
1263: }
1264:
1.1 root 1265:
1266:
1.1.1.6 ! root 1267: #if 0 /* commented out so that loadable file systems work :-( */
1.1.1.5 root 1268:
1269: /* only the superuser can make Rwabs calls directly */
1.1 root 1270:
1271:
1272:
1.1.1.5 root 1273: if (curproc->in_dos || (curproc->euid == 0))
1274:
1275: /* Note that some (most?) Rwabs device drivers don't bother saving
1276:
1277: * registers, whereas our compiler expects politeness. So we go
1278:
1279: * via callout(), which will save registers for us.
1280:
1281: */
1282:
1283: r = callout(RWABS, rwflag, buffer, number, recno, dev, lrecno);
1284:
1285: else {
1286:
1287: DEBUG(("Rwabs by non privileged process!"));
1288:
1289: r = EACCDN;
1290:
1291: }
1292:
1293: #else
1.1 root 1294:
1295: r = callout(RWABS, rwflag, buffer, number, recno, dev, lrecno);
1296:
1.1.1.5 root 1297: #endif
1298:
1.1 root 1299: return r;
1300:
1301: }
1302:
1303:
1304:
1305: /* setexc: set exception vector */
1306:
1307:
1308:
1.1.1.2 root 1309: long ARGS_ON_STACK
1.1 root 1310:
1311: setexc(number, vector)
1312:
1313: int number;
1314:
1315: long vector;
1316:
1317: {
1318:
1319: long *place;
1320:
1321: long old;
1322:
1323: extern long save_dos, save_bios, save_xbios; /* in main.c */
1324:
1.1.1.3 root 1325: extern int no_mem_prot; /* in main.c */
1.1 root 1326:
1327:
1328:
1329: place = (long *)(((long)number) << 2);
1330:
1331: if (number == 0x21) /* trap_1 */
1332:
1333: old = save_dos;
1334:
1335: else if (number == 0x2d) /* trap_13 */
1336:
1337: old = save_bios;
1338:
1339: else if (number == 0x2e) /* trap_14 */
1340:
1341: old = save_xbios;
1342:
1343: else if (number == 0x101)
1344:
1345: old = (long)curproc->criticerr; /* critical error vector */
1346:
1347: else if (number == 0x102)
1348:
1349: old = curproc->ctxt[SYSCALL].term_vec; /* GEMDOS term vector */
1350:
1351: else
1352:
1353: old = *place;
1354:
1355:
1356:
1357: if (vector > 0) {
1358:
1.1.1.3 root 1359: /* validate vector; this will cause a bus error if mem
1360:
1361: * protection is on and the current process doesn't have
1362:
1363: * access to the memory
1364:
1365: */
1366:
1367: if (*((long *)vector) == 0xDEADBEEFL)
1368:
1369: return old;
1370:
1371:
1372:
1.1 root 1373: if (number == 0x21)
1374:
1375: save_dos = vector;
1376:
1377: else if (number == 0x2d)
1378:
1379: save_bios = vector;
1380:
1381: else if (number == 0x2e)
1382:
1383: save_xbios = vector;
1384:
1385: else if (number == 0x102)
1386:
1387: curproc->ctxt[SYSCALL].term_vec = vector;
1388:
1389: else if (number == 0x101) {
1390:
1391: long mintcerr;
1392:
1393:
1394:
1395: /*
1396:
1397: * problem: lots of TSR's look for the Setexc(0x101,...)
1398:
1399: * that the AES does at startup time; so we have
1400:
1401: * to pass it along.
1402:
1403: */
1404:
1405: mintcerr = (long) Setexc(0x101, (void *)vector);
1406:
1.1.1.2 root 1407: curproc->criticerr = (long ARGS_ON_STACK (*) P_((long))) *place;
1.1 root 1408:
1409: *place = mintcerr;
1410:
1411: }
1412:
1413: else {
1414:
1.1.1.3 root 1415: if (!no_mem_prot) {
1416:
1417: /*
1418:
1419: * if memory protection is on, the vector should be
1420:
1421: * pointing at supervisor or global memory
1422:
1423: */
1424:
1425: MEMREGION *r;
1426:
1427:
1428:
1429: r = addr2region(vector);
1430:
1431: if (r && get_prot_mode(r) == PROT_P) {
1432:
1433: DEBUG(("Changing protection to Supervisor because of Setexc"));
1434:
1435: mark_region(r, PROT_S);
1436:
1437: }
1438:
1439: }
1440:
1.1 root 1441: /* We would do just *place = vector except that
1442:
1443: * someone else might be intercepting Setexc looking
1444:
1445: * for something in particular...
1446:
1447: */
1448:
1449: old = (long) Setexc(number, (void *)vector);
1450:
1451: }
1452:
1453: }
1454:
1.1.1.3 root 1455:
1456:
1457: TRACE(("Setexc %d, %lx -> %lx", number, vector, old));
1458:
1.1 root 1459: return old;
1460:
1461: }
1462:
1463:
1464:
1465: /* tickcal: return milliseconds per system clock tick */
1466:
1467:
1468:
1.1.1.2 root 1469: long ARGS_ON_STACK
1.1 root 1470:
1471: tickcal()
1472:
1473: {
1474:
1475: return (long) (*( (unsigned *) 0x0442L ));
1476:
1477: }
1478:
1479:
1480:
1481: /* getbpb: get BIOS parameter block */
1482:
1483:
1484:
1.1.1.2 root 1485: long ARGS_ON_STACK
1.1 root 1486:
1487: getbpb(dev)
1488:
1489: int dev;
1490:
1491: {
1492:
1493: long r;
1494:
1495:
1496:
1497: /* we can't trust the Getbpb routine to accurately save all registers,
1498:
1499: * so we do it ourselves
1500:
1501: */
1502:
1.1.1.4 root 1503: r = callout1(GETBPB, dev);
1.1 root 1504:
1505: /*
1506:
1507: * There is a bug in the TOS disk handling routines (well several actually).
1508:
1509: * If the directory size of Getbpb() is returned as zero then the drive 'dies'
1510:
1511: * and wont read any new disks even with the 'ESC' enforced disk change . This
1512:
1513: * is present even in TOS 1.6 (not sure about 1.62 though). This small routine
1514:
1515: * changes the dir size to '1' if it is zero . It may make some non-TOS disks
1516:
1517: * look a bit weird but that's better than killing the drive .
1518:
1519: */
1520:
1521: if (r) {
1522:
1523: if ( ((short *)r)[3] == 0) /* 0 directory size? */
1524:
1525: ((short *)r)[3] = 1;
1526:
1.1.1.6 ! root 1527:
! 1528:
! 1529: /* jr: save cluster size in area */
! 1530:
! 1531: if (dev >= 0 && dev < 32)
! 1532:
! 1533: clsizb[dev] = ((unsigned short *)r)[2];
! 1534:
1.1 root 1535: }
1536:
1537: return r;
1538:
1539: }
1540:
1541:
1542:
1543: /* bcostat: return output device status */
1544:
1545:
1546:
1.1.1.2 root 1547: /* WARNING: syscall.spp assumes that ubcostat never
1548:
1549: * blocks
1550:
1551: */
1552:
1553: long ARGS_ON_STACK
1.1 root 1554:
1555: ubcostat(dev)
1556:
1557: int dev;
1558:
1559: {
1560:
1.1.1.2 root 1561: FILEPTR *f;
1562:
1563:
1564:
1.1 root 1565: /* the BIOS switches MIDI (3) and IKBD (4) (a bug, but it can't be corrected) */
1566:
1567: if (dev == 4) { /* really the MIDI port */
1568:
1.1.1.2 root 1569: f = curproc->handle[boutput[3]];
1570:
1571: return file_outstat(f) ? -1 : 0;
1.1 root 1572:
1573: }
1574:
1575: if (dev == 3)
1576:
1.1.1.2 root 1577: return BCOSTAT(dev);
1.1 root 1578:
1579:
1580:
1.1.1.2 root 1581: if (dev < MAX_BHANDLE) {
1.1 root 1582:
1.1.1.2 root 1583: f = curproc->handle[boutput[dev]];
1.1 root 1584:
1.1.1.2 root 1585: return file_outstat(f) ? -1 : 0;
1586:
1587: } else
1.1 root 1588:
1589: return bcostat(dev);
1590:
1591: }
1592:
1593:
1594:
1595: long
1596:
1597: bcostat(dev)
1598:
1599: int dev;
1600:
1601: {
1602:
1603:
1604:
1605: if (dev == CONSDEV) {
1606:
1607: return -1;
1608:
1609: }
1610:
1611: else if (dev == AUXDEV && has_bconmap) {
1612:
1613: dev = curproc->bconmap;
1614:
1615: }
1616:
1617: /* compensate here for the BIOS bug, so that the MIDI and IKBD files work
1618:
1619: * correctly
1620:
1621: */
1622:
1623: else if (dev == 3) dev = 4;
1624:
1625: else if (dev == 4) dev = 3;
1626:
1627:
1628:
1.1.1.2 root 1629: return BCOSTAT(dev);
1.1 root 1630:
1631: }
1632:
1633:
1634:
1635: /* mediach: check for media change */
1636:
1637:
1638:
1.1.1.2 root 1639: long ARGS_ON_STACK
1.1 root 1640:
1641: mediach(dev)
1642:
1643: int dev;
1644:
1645: {
1646:
1647: long r;
1648:
1649:
1650:
1.1.1.3 root 1651: r = callout1(MEDIACH, dev);
1.1 root 1652:
1653: return r;
1654:
1655: }
1656:
1657:
1658:
1659: /* drvmap: return drives connected to system */
1660:
1661:
1662:
1.1.1.2 root 1663: long ARGS_ON_STACK
1.1 root 1664:
1665: drvmap()
1666:
1667: {
1668:
1669: return *( (long *)0x4c2L );
1670:
1671: }
1672:
1673:
1674:
1675: /* kbshift: return (and possibly change) keyboard shift key status */
1676:
1.1.1.2 root 1677: /* WARNING: syscall.spp assumes that kbshift never blocks, and never
1.1 root 1678:
1.1.1.2 root 1679: * calls any underlying TOS functions
1.1 root 1680:
1.1.1.2 root 1681: */
1682:
1683: long ARGS_ON_STACK
1.1 root 1684:
1685: kbshift(mode)
1686:
1687: int mode;
1688:
1689: {
1690:
1691: int oldshft;
1692:
1693:
1694:
1695: oldshft = *((unsigned char *)kbshft);
1696:
1697: if (mode >= 0)
1698:
1699: *kbshft = mode;
1700:
1701: return oldshft;
1702:
1703: }
1704:
1705:
1706:
1707:
1708:
1709: /* special Bconout buffering code:
1710:
1711: * Because system call overhead is so high, programs that do output
1712:
1713: * with Bconout suffer in performance. To compensate for this,
1714:
1715: * Bconout is special-cased in syscall.s, and if possible characters
1716:
1717: * are placed in the 256 byte bconbuf buffer. This buffer is flushed
1718:
1719: * when any system call other than Bconout happens, or when a context
1720:
1721: * switch occurs.
1722:
1723: */
1724:
1725:
1726:
1727: short bconbsiz; /* number of characters in buffer */
1728:
1729: unsigned char bconbuf[256]; /* buffer contents */
1730:
1731: short bconbdev; /* BIOS device for which the buffer is valid */
1732:
1733: /* (-1 means no buffering is active) */
1734:
1735:
1736:
1737: /*
1738:
1739: * flush pending BIOS output. Return 0 if some bytes were not successfully
1740:
1741: * written, non-zero otherwise (just like bconout)
1742:
1743: */
1744:
1745:
1746:
1.1.1.2 root 1747: long ARGS_ON_STACK
1.1 root 1748:
1749: bflush() /* flush bios output */
1750:
1751: {
1752:
1753: long ret, bsiz;
1754:
1755: unsigned char *s;
1756:
1757: FILEPTR *f;
1758:
1759: short dev;
1760:
1761: short statdev;
1762:
1.1.1.2 root 1763: long lbconbuf[256];
1764:
1.1 root 1765:
1766:
1767: if ((dev = bconbdev) < 0) return 0;
1768:
1769:
1770:
1771: /*
1772:
1773: * Here we lock the BIOS buffering mechanism by setting bconbdev to -1
1774:
1775: * This is necessary because if two or more programs try to do
1776:
1777: * buffered BIOS output at the same time, they can get seriously
1778:
1779: * mixed up. We unlock by setting bconbdev to 0.
1780:
1781: *
1782:
1783: * NOTE: some code (e.g. in sleep()) checks for bconbsiz != 0 in
1784:
1785: * order to see if we need to do a bflush; if one is already in
1786:
1787: * progress, it's pointless to do this, so we save a bit of
1788:
1789: * time by setting bconbsiz to 0 here.
1790:
1791: */
1792:
1793: bconbdev = -1;
1794:
1795: bsiz = bconbsiz;
1796:
1.1.1.2 root 1797: if (bsiz == 0) return 0;
1798:
1.1 root 1799: bconbsiz = 0;
1800:
1801:
1802:
1803: /* BIOS handles 0..MAX_BHANDLE-1 are aliases for special GEMDOS files */
1804:
1805: if (dev < MAX_BHANDLE || dev == 5) {
1806:
1807: if (dev == 5)
1808:
1809: f = curproc->handle[-1];
1810:
1811: else
1812:
1813: f = curproc->handle[boutput[dev]];
1814:
1815:
1816:
1817: if (!f) {
1818:
1819: bconbdev = 0;
1820:
1821: return 0;
1822:
1823: }
1824:
1825: if (is_terminal(f)) {
1826:
1.1.1.6 ! root 1827: int oldflags = f->flags;
! 1828:
! 1829:
! 1830:
1.1 root 1831: s = bconbuf;
1832:
1.1.1.6 ! root 1833: /* turn off NDELAY for this write... */
! 1834:
! 1835: f->flags &= ~O_NDELAY;
! 1836:
1.1 root 1837: if (dev == 5) {
1838:
1839: while (bsiz-- > 0) {
1840:
1841: if (*s < ' ') {
1842:
1843: /* use ESC-Q to quote control character */
1844:
1845: (void)tty_putchar(f, (long)'\033',
1846:
1847: RAW);
1848:
1849: (void)tty_putchar(f, (long)'Q',
1850:
1851: RAW);
1852:
1853: }
1854:
1855: (void) tty_putchar(f, (long)*s++, RAW);
1856:
1857: }
1858:
1859: } else {
1860:
1.1.1.6 ! root 1861: long *where, nbytes;
! 1862:
1.1.1.2 root 1863: #if 1
1864:
1.1.1.6 ! root 1865: extern FILESYS bios_filesys;
! 1866:
! 1867:
! 1868:
! 1869: /* see if we can do fast RAW byte IO thru the device driver... */
! 1870:
! 1871: if ((f->fc.fs != &bios_filesys ||
! 1872:
! 1873: (bsiz > 1 &&
! 1874:
! 1875: ((struct bios_file *)f->fc.index)->drvsize >
! 1876:
! 1877: offsetof (DEVDRV, writeb))) && f->dev->writeb) {
! 1878:
! 1879: struct tty *tty = (struct tty *)f->devinfo;
! 1880:
! 1881:
! 1882:
! 1883: tty_checkttou (f, tty);
1.1.1.2 root 1884:
1.1.1.6 ! root 1885: tty->state &= ~TS_COOKED;
1.1.1.2 root 1886:
1.1.1.6 ! root 1887: if ((ret = (*f->dev->writeb)(f, (char *)s, bsiz)) != EUNDEV) {
! 1888:
! 1889: f->flags = oldflags;
! 1890:
! 1891: bconbdev = 0;
! 1892:
! 1893: return ret;
! 1894:
! 1895: }
! 1896:
! 1897: }
! 1898:
! 1899: #endif
1.1.1.2 root 1900:
1901: /* the tty_putchar should set up terminal modes correctly */
1902:
1903: (void) tty_putchar(f, (long)*s++, RAW);
1904:
1905: where = lbconbuf;
1906:
1907: nbytes = 0;
1908:
1909: while (--bsiz > 0) {
1910:
1911: *where++ = *s++; nbytes+=4;
1912:
1913: }
1914:
1915: if (nbytes)
1916:
1917: (*f->dev->write)(f, (char *)lbconbuf, nbytes);
1918:
1.1 root 1919: }
1920:
1921: ret = -1;
1922:
1.1.1.6 ! root 1923: f->flags = oldflags;
! 1924:
1.1 root 1925: } else {
1926:
1927: ret = (*f->dev->write)(f, (char *)bconbuf, bsiz);
1928:
1929: }
1930:
1931: bconbdev = 0;
1932:
1933: return ret;
1934:
1935: }
1936:
1937:
1938:
1939: /* Otherwise, we have a real BIOS device */
1940:
1941:
1942:
1943: if (dev == AUXDEV && has_bconmap) {
1944:
1945: dev = curproc->bconmap;
1946:
1947: statdev = dev;
1948:
1949: }
1950:
1.1.1.6 ! root 1951: if ((ret = iwrite (dev, bconbuf, bsiz, 0, 0)) != EUNDEV) {
1.1 root 1952:
1.1.1.6 ! root 1953: bconbdev = 0;
! 1954:
! 1955: return ret;
! 1956:
! 1957: } else if (dev == 3) { /* MIDI */
! 1958:
! 1959: /* compensate for a known BIOS bug; MIDI and IKBD are switched */
1.1 root 1960:
1961: statdev = 4;
1962:
1963: } else if (dev == 4) {
1964:
1965: statdev = 3;
1966:
1967: } else
1968:
1969: statdev = dev;
1970:
1971:
1972:
1973: s = bconbuf;
1974:
1975: while (bsiz-- > 0) {
1976:
1.1.1.2 root 1977: while (!BCOSTAT(statdev)) yield();
1.1 root 1978:
1.1.1.2 root 1979: (void)BCONOUT(dev,*s);
1.1 root 1980:
1981: s++;
1982:
1983: }
1984:
1985: bconbdev = 0;
1986:
1987: return 1L;
1988:
1989: }
1990:
1991:
1992:
1993: /* initialize bios table */
1994:
1995:
1996:
1997: #define BIOS_MAX 0x20
1998:
1999:
2000:
2001: Func bios_tab[BIOS_MAX] = {
2002:
2003: getmpb,
2004:
2005: ubconstat,
2006:
2007: ubconin,
2008:
2009: ubconout,
2010:
1.1.1.2 root 2011:
2012:
1.1 root 2013: rwabs,
2014:
2015: setexc,
2016:
2017: tickcal,
2018:
2019: getbpb,
2020:
1.1.1.2 root 2021:
2022:
1.1 root 2023: ubcostat,
2024:
2025: mediach,
2026:
2027: drvmap,
2028:
2029: kbshift,
2030:
1.1.1.2 root 2031:
2032:
1.1 root 2033: 0, 0, 0, 0,
2034:
2035: 0, 0, 0, 0, 0, 0, 0, 0,
2036:
2037: 0, 0, 0, 0, 0, 0, 0, 0
2038:
2039: };
2040:
2041:
2042:
2043: short bios_max = BIOS_MAX;
2044:
2045:
2046:
2047: /*
2048:
2049: * BIOS initialization routine: gets keyboard buffer pointers, for the
2050:
2051: * interrupt routine below
2052:
2053: */
2054:
2055:
2056:
2057: void
2058:
2059: init_bios()
2060:
2061: {
2062:
2063: keyrec = (IOREC_T *)Iorec(1);
2064:
2065: }
2066:
2067:
2068:
2069: /*
2070:
1.1.1.2 root 2071: * do_bconin: try to do a bconin function quickly, without
2072:
2073: * blocking. If we can't do it without blocking, we return
2074:
2075: * 0x0123dead and the calling trap #13 code falls through
2076:
2077: * to the normal bconin stuff. We can't block here because
2078:
2079: * the trap #13 code hasn't yet saved registers or other
2080:
2081: * context bits, so sleep() wouldn't work properly.
2082:
2083: */
2084:
2085:
2086:
2087: #define WOULDBLOCK 0x0123deadL
2088:
2089:
2090:
2091: /* WARNING: syscall.spp assumes that do_bconin never blocks */
2092:
2093:
2094:
2095: long ARGS_ON_STACK
2096:
2097: do_bconin(dev)
2098:
2099: int dev;
2100:
2101: {
2102:
2103: FILEPTR *f;
2104:
1.1.1.6 ! root 2105: long r, nread;
1.1.1.2 root 2106:
2107: unsigned char c;
2108:
2109:
2110:
2111: if (dev < MAX_BHANDLE) {
2112:
2113: f = curproc->handle[binput[dev]];
2114:
2115: if (!f) return 0;
2116:
1.1.1.6 ! root 2117: nread = 0;
1.1.1.2 root 2118:
1.1.1.6 ! root 2119: (void)(*f->dev->ioctl)(f, FIONREAD, &nread);
1.1.1.2 root 2120:
1.1.1.6 ! root 2121: if (!nread) return WOULDBLOCK; /* data not ready */
1.1.1.2 root 2122:
2123: if (is_terminal(f))
2124:
2125: r = tty_getchar(f, RAW);
2126:
2127: else {
2128:
2129: r = (*f->dev->read)(f, (char *)&c, 1L);
2130:
2131: r = (r == 1) ? c : MiNTEOF;
2132:
2133: }
2134:
2135: } else {
2136:
2137: if (!bconstat(dev))
2138:
2139: r = WOULDBLOCK;
2140:
2141: else
2142:
2143: r = bconin(dev);
2144:
2145: }
2146:
2147: return r;
2148:
2149: }
2150:
2151:
2152:
2153: /*
2154:
1.1 root 2155: * routine for checking keyboard (called by sleep() on any context
2156:
2157: * switch where a keyboard event occured). returns 1 if a special
2158:
2159: * control character was eaten, 0 if not
2160:
2161: */
2162:
2163:
2164:
2165: int
2166:
2167: checkkeys()
2168:
2169: {
2170:
2171: char scan, ch;
2172:
2173: short shift;
2174:
2175: int sig, ret;
2176:
2177: struct tty *tty = &con_tty;
2178:
2179: extern char mshift; /* for mouse -- see biosfs.c */
2180:
2181: static short oldktail = 0;
2182:
2183:
2184:
2185: ret = 0;
2186:
2187: mshift = kbshift(-1);
2188:
2189: while (oldktail != keyrec->tail) {
2190:
2191:
2192:
2193: /* BUG: we really should check the shift status _at the time the key was
2194:
2195: * pressed_, not now!
2196:
2197: */
2198:
2199: sig = 0;
2200:
2201: shift = mshift;
2202:
2203: oldktail += 4;
2204:
2205: if (oldktail >= keyrec->buflen)
2206:
2207: oldktail = 0;
2208:
2209:
2210:
2211: scan = (keyrec->bufaddr + oldktail)[1];
2212:
2213: /* function key?? */
2214:
2215: if ( (scan >= 0x3b && scan <= 0x44) ||
2216:
2217: (scan >= 0x54 && scan <= 0x5d) ||
2218:
2219: scan == DEL || scan == UNDO) {
2220:
2221: if ( (shift & CTRLALT) == CTRLALT ) {
2222:
2223: oldktail = keyrec->head = keyrec->tail;
2224:
2225: do_func_key(scan);
2226:
1.1.1.2 root 2227: /* do_func_key may have read some keys */
2228:
2229: oldktail = keyrec->head;
2230:
2231: mshift = kbshift (-1);
2232:
1.1 root 2233: ret = 1;
2234:
2235: continue;
2236:
2237: }
2238:
2239: }
2240:
2241:
2242:
2243: /* check for special control keys, etc. */
2244:
2245: /* BUG: this doesn't exactly match TOS' behavior, particularly for
2246:
2247: * ^S/^Q
2248:
2249: */
2250:
2251: if ((tty->state & TS_COOKED) || (shift & CTRLALT) == CTRLALT) {
2252:
2253: ch = (keyrec->bufaddr + keyrec->tail)[3];
2254:
2255: if (ch == UNDEF)
2256:
2257: ; /* do nothing */
2258:
2259: else if (ch == tty->tc.t_intrc)
2260:
2261: sig = SIGINT;
2262:
2263: else if (ch == tty->tc.t_quitc)
2264:
2265: sig = SIGQUIT;
2266:
2267: else if (ch == tty->ltc.t_suspc)
2268:
2269: sig = SIGTSTP;
2270:
2271: else if (ch == tty->tc.t_stopc) {
2272:
2273: tty->state |= TS_HOLD;
2274:
2275: ret = 1;
2276:
2277: keyrec->head = oldktail;
2278:
2279: continue;
2280:
2281: }
2282:
2283: else if (ch == tty->tc.t_startc) {
2284:
2285: tty->state &= ~TS_HOLD;
2286:
2287: ret = 1;
2288:
2289: keyrec->head = oldktail;
2290:
2291: continue;
2292:
2293: }
2294:
2295: if (sig) {
2296:
2297: tty->state &= ~TS_HOLD;
2298:
2299: if (!(tty->sg.sg_flags & T_NOFLSH))
2300:
2301: oldktail = keyrec->head = keyrec->tail;
2302:
1.1.1.6 ! root 2303: killgroup(tty->pgrp, sig, 1);
1.1 root 2304:
2305: ret = 1;
2306:
2307: }
2308:
2309: else if (tty->state & TS_HOLD) {
2310:
2311: keyrec->head = oldktail;
2312:
2313: ret = 1;
2314:
2315: }
2316:
2317: }
2318:
2319:
2320:
2321: }
2322:
2323:
2324:
1.1.1.5 root 2325: if (keyrec->head != keyrec->tail) {
1.1 root 2326:
1.1.1.5 root 2327: /* wake up any processes waiting in bconin() */
1.1 root 2328:
1.1.1.5 root 2329: wake(IO_Q, (long)&console_in);
2330:
2331: /* wake anyone that did a select() on the keyboard */
2332:
2333: if (tty->rsel)
2334:
2335: wakeselect(tty->rsel);
2336:
2337: }
1.1 root 2338:
2339:
2340:
2341: return ret;
2342:
2343: }
2344:
2345:
2346:
1.1.1.3 root 2347:
2348:
2349: /*
2350:
2351: * special vector stuff: we try to save as many vectors as possible,
2352:
2353: * just in case we need to restore them later
2354:
2355: *
2356:
2357: * BUG: this really should be integrated with the init_intr routine
2358:
2359: * in main.c
2360:
2361: */
2362:
2363:
2364:
2365: #define A(x) ((long *)(long)(x))
2366:
2367: #define L(x) (long)(x)
2368:
2369:
2370:
2371: struct vectab {
2372:
2373: long *addr;
2374:
2375: long def_value;
2376:
2377: } VEC[] = {
2378:
2379: {A(0x28), 0}, /* Line A */
2380:
2381: {A(0x2c), 0}, /* Line F */
2382:
2383: {A(0x60), 0}, /* spurious interrupt */
2384:
2385: {A(0x64), 0}, /* level 1 interrupt */
2386:
2387: {A(0x68), 0}, /* level 2 interrupt */
2388:
2389: {A(0x6c), 0}, /* level 3 interrupt */
2390:
2391: {A(0x70), 0}, /* level 4 interrupt */
2392:
2393: {A(0x74), 0}, /* level 5 interrupt */
2394:
2395: {A(0x78), 0}, /* level 6 interrupt */
2396:
2397: {A(0x7c), 0}, /* level 7 interrupt */
2398:
2399: {A(0x100), 0}, /* various MFP interrupts */
2400:
2401: {A(0x104), 0},
2402:
2403: {A(0x108), 0},
2404:
2405: {A(0x10c), 0},
2406:
2407: {A(0x110), 0},
2408:
2409: {A(0x114), 0},
2410:
2411: {A(0x118), 0},
2412:
2413: {A(0x11c), 0},
2414:
2415: {A(0x120), 0},
2416:
2417: {A(0x124), 0},
2418:
2419: {A(0x128), 0},
2420:
2421: {A(0x12c), 0},
2422:
2423: {A(0x130), 0},
2424:
2425: {A(0x134), 0},
2426:
2427: {A(0x138), 0},
2428:
2429: {A(0x13c), 0},
2430:
2431: {A(0x400), 0}, /* etv_timer */
2432:
2433: {A(0x4f6), 0}, /* shell_p */
2434:
2435:
2436:
2437: {A(0), 0} /* special tag indicating end of list */
2438:
2439: };
2440:
2441:
2442:
2443: void
2444:
2445: init_vectors()
2446:
2447: {
2448:
2449: struct vectab *v;
2450:
2451:
2452:
2453: for (v = VEC; v->addr; v++) {
2454:
2455: v->def_value = *(v->addr);
2456:
2457: }
2458:
2459: }
2460:
2461:
2462:
2463: #if 0 /* bad code */
2464:
2465:
2466:
2467: /* unhook a vector; if possible, do this with XBRA, but
2468:
2469: * if that isn't possible force the vector to have the
2470:
2471: * same value it had when MiNT started
2472:
2473: */
2474:
2475:
2476:
2477: static void
2478:
2479: unhook(v, where)
2480:
2481: struct vectab *v;
2482:
2483: long where;
2484:
2485: {
2486:
2487: xbra_vec *xbra;
2488:
2489: long newval;
2490:
2491: int cookie;
2492:
2493:
2494:
2495: /* to check for XBRA, we need access to the memory where the
2496:
2497: * vector is
2498:
2499: */
2500:
2501: cookie = prot_temp(where - 12, 16L, -1);
2502:
2503:
2504:
2505: if (cookie == 0)
2506:
2507: newval = v->def_value;
2508:
2509: else {
2510:
2511: xbra = (xbra_vec *)(where - 12);
2512:
2513: if (xbra->xbra_magic == XBRA_MAGIC) {
2514:
2515: newval = (long)xbra->next;
2516:
2517: } else {
2518:
2519: newval = v->def_value;
2520:
2521: }
2522:
2523: }
2524:
2525: *(v->addr) = newval;
2526:
2527:
2528:
2529: (void)prot_temp(where - 12, 16L, cookie);
2530:
2531: }
2532:
2533: #endif
2534:
2535:
2536:
2537: /*
2538:
2539: * unlink_vectors(start, end): any of the "normal" system vectors
2540:
2541: * pointing into a freed memory region must be reset to their
2542:
2543: * default values, or else we'll get a memory protection violation
2544:
2545: * next time the vector gets called
2546:
2547: */
2548:
2549:
2550:
2551: void
2552:
2553: unlink_vectors(start, end)
2554:
2555: long start, end;
2556:
2557: {
2558:
2559: #if 0 /* this code is hosed somewhere */
2560:
2561:
2562:
2563: struct vectab *v;
2564:
2565: long where, *p;
2566:
2567: int i;
2568:
2569:
2570:
2571: /* first, unhook any VBL handlers */
2572:
2573: i = *((short *)0x454L); /* i = nvbls */
2574:
2575: p = *((long **)0x456L); /* p = _vblqueue */
2576:
2577: while (i-- > 0) {
2578:
2579: where = *p;
2580:
2581: if (where >= start && where < end)
2582:
2583: *p = 0;
2584:
2585: p++;
2586:
2587: }
2588:
2589:
2590:
2591: /* next, unhook various random vectors */
2592:
2593: for (v = VEC; v->addr; v++) {
2594:
2595: where = *(v->addr);
2596:
2597: if (where >= start && where < end) {
2598:
2599: unhook(v, where);
2600:
2601: }
2602:
2603: }
2604:
1.1.1.4 root 2605: #else
2606:
2607: UNUSED(start); UNUSED(end);
2608:
1.1.1.3 root 2609: #endif
2610:
2611: }
2612:
2613:
1.1 root 2614:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.