|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "io.h" ! 7: #include "ureg.h" ! 8: #include "init.h" ! 9: #include <ctype.h> ! 10: ! 11: ! 12: uchar *sp; /* stack pointer for /boot */ ! 13: ! 14: extern PCArch nsx20, generic, ncr3170; ! 15: ! 16: PCArch *arch; ! 17: PCArch *knownarch[] = ! 18: { ! 19: &nsx20, ! 20: &ncr3170, ! 21: &generic, ! 22: }; ! 23: ! 24: /* where b.com leaves configuration info */ ! 25: #define BOOTARGS ((char*)(KZERO|1024)) ! 26: #define BOOTARGSLEN 1024 ! 27: #define MAXCONF 32 ! 28: ! 29: char bootdisk[NAMELEN]; ! 30: char *confname[MAXCONF]; ! 31: char *confval[MAXCONF]; ! 32: int nconf; ! 33: ! 34: /* memory map */ ! 35: #define MAXMEG 64 ! 36: char mmap[MAXMEG+2]; ! 37: ! 38: void ! 39: main(void) ! 40: { ! 41: ident(); ! 42: i8042a20(); /* enable address lines 20 and up */ ! 43: machinit(); ! 44: active.exiting = 0; ! 45: active.machs = 1; ! 46: confinit(); ! 47: xinit(); ! 48: dmainit(); ! 49: screeninit(); ! 50: printinit(); ! 51: mmuinit(); ! 52: pageinit(); ! 53: trapinit(); ! 54: mathinit(); ! 55: clockinit(); ! 56: printcpufreq(); ! 57: faultinit(); ! 58: kbdinit(); ! 59: procinit0(); ! 60: initseg(); ! 61: streaminit(); ! 62: chandevreset(); ! 63: swapinit(); ! 64: userinit(); ! 65: schedinit(); ! 66: } ! 67: ! 68: /* ! 69: * This tries to capture architecture dependencies since things ! 70: * like power management/reseting/mouse are outside the hardware ! 71: * model. ! 72: */ ! 73: void ! 74: ident(void) ! 75: { ! 76: char *id = (char*)(ROMBIOS + 0xFF40); ! 77: PCArch **p; ! 78: ! 79: for(p = knownarch; *p != &generic; p++) ! 80: if(strncmp((*p)->id, id, strlen((*p)->id)) == 0) ! 81: break; ! 82: arch = *p; ! 83: } ! 84: ! 85: void ! 86: machinit(void) ! 87: { ! 88: int n; ! 89: ! 90: n = m->machno; ! 91: memset(m, 0, sizeof(Mach)); ! 92: m->machno = n; ! 93: m->mmask = 1<<m->machno; ! 94: } ! 95: ! 96: ulong garbage; ! 97: ! 98: void ! 99: init0(void) ! 100: { ! 101: int i; ! 102: char tstr[32]; ! 103: ! 104: u->nerrlab = 0; ! 105: m->proc = u->p; ! 106: u->p->state = Running; ! 107: u->p->mach = m; ! 108: ! 109: spllo(); ! 110: ! 111: /* ! 112: * These are o.k. because rootinit is null. ! 113: * Then early kproc's will have a root and dot. ! 114: */ ! 115: u->slash = (*devtab[0].attach)(0); ! 116: u->dot = clone(u->slash, 0); ! 117: ! 118: kproc("alarm", alarmkproc, 0); ! 119: chandevinit(); ! 120: ! 121: if(!waserror()){ ! 122: strcpy(tstr, arch->id); ! 123: strcat(tstr, " %s"); ! 124: ksetterm(tstr); ! 125: ksetenv("cputype", "386"); ! 126: for(i = 0; i < nconf; i++) ! 127: if(confname[i]) ! 128: ksetenv(confname[i], confval[i]); ! 129: poperror(); ! 130: } ! 131: touser(sp); ! 132: } ! 133: ! 134: void ! 135: userinit(void) ! 136: { ! 137: Proc *p; ! 138: Segment *s; ! 139: User *up; ! 140: KMap *k; ! 141: Page *pg; ! 142: ! 143: p = newproc(); ! 144: p->pgrp = newpgrp(); ! 145: p->egrp = smalloc(sizeof(Egrp)); ! 146: p->egrp->ref = 1; ! 147: p->fgrp = smalloc(sizeof(Fgrp)); ! 148: p->fgrp->ref = 1; ! 149: p->procmode = 0640; ! 150: ! 151: strcpy(p->text, "*init*"); ! 152: strcpy(p->user, eve); ! 153: p->fpstate = FPinit; ! 154: fpoff(); ! 155: ! 156: /* ! 157: * Kernel Stack ! 158: * ! 159: * N.B. The -12 for the stack pointer is important. ! 160: * 4 bytes for gotolabel's return PC ! 161: */ ! 162: p->sched.pc = (ulong)init0; ! 163: p->sched.sp = USERADDR + BY2PG - 4; ! 164: p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF)); ! 165: ! 166: /* ! 167: * User ! 168: */ ! 169: k = kmap(p->upage); ! 170: up = (User*)VA(k); ! 171: up->p = p; ! 172: kunmap(k); ! 173: ! 174: /* ! 175: * User Stack ! 176: */ ! 177: s = newseg(SG_STACK, USTKTOP-BY2PG, 1); ! 178: p->seg[SSEG] = s; ! 179: pg = newpage(1, 0, USTKTOP-BY2PG); ! 180: segpage(s, pg); ! 181: k = kmap(pg); ! 182: bootargs(VA(k)); ! 183: kunmap(k); ! 184: ! 185: /* ! 186: * Text ! 187: */ ! 188: s = newseg(SG_TEXT, UTZERO, 1); ! 189: p->seg[TSEG] = s; ! 190: segpage(s, newpage(1, 0, UTZERO)); ! 191: k = kmap(s->map[0]->pages[0]); ! 192: memmove((ulong*)VA(k), initcode, sizeof initcode); ! 193: kunmap(k); ! 194: ! 195: ready(p); ! 196: } ! 197: ! 198: uchar * ! 199: pusharg(char *p) ! 200: { ! 201: int n; ! 202: ! 203: n = strlen(p)+1; ! 204: sp -= n; ! 205: memmove(sp, p, n); ! 206: return sp; ! 207: } ! 208: ! 209: void ! 210: bootargs(ulong base) ! 211: { ! 212: int i, ac; ! 213: uchar *av[32]; ! 214: uchar **lsp; ! 215: char *cp = BOOTLINE; ! 216: char buf[64]; ! 217: ! 218: sp = (uchar*)base + BY2PG - MAXSYSARG*BY2WD; ! 219: ! 220: ac = 0; ! 221: av[ac++] = pusharg("/386/9pc"); ! 222: cp[64] = 0; ! 223: buf[0] = 0; ! 224: ! 225: /* ! 226: * decode the b.com bootline and convert to ! 227: * a disk device name to pass to the boot ! 228: */ ! 229: if(strncmp(cp, "fd!", 3) == 0){ ! 230: sprint(buf, "local!#f/fd%ddisk", atoi(cp+3)); ! 231: av[ac++] = pusharg(buf); ! 232: } else if(strncmp(cp, "h!", 2) == 0){ ! 233: sprint(buf, "local!#H/hd%dfs", atoi(cp+2)); ! 234: av[ac++] = pusharg(buf); ! 235: } else if(strncmp(cp, "hd!", 3) == 0){ ! 236: sprint(buf, "local!#H/hd%ddisk", atoi(cp+3)); ! 237: av[ac++] = pusharg(buf); ! 238: } else if(strncmp(cp, "s!", 2) == 0){ ! 239: sprint(buf, "local!#w%d/sd%dfs", atoi(cp+2), atoi(cp+2)); ! 240: av[ac++] = pusharg(buf); ! 241: } else if(strncmp(cp, "sd!", 3) == 0){ ! 242: sprint(buf, "local!#w%d/sd%ddisk", atoi(cp+3), atoi(cp+3)); ! 243: av[ac++] = pusharg(buf); ! 244: } else if(getconf("bootdisk") == 0){ ! 245: if(conf.nhard){ ! 246: sprint(buf, "local!#H/hd0disk"); ! 247: av[ac++] = pusharg(buf); ! 248: } else{ ! 249: sprint(buf, "local!#w/sd0disk"); ! 250: av[ac++] = pusharg(buf); ! 251: } ! 252: } ! 253: if(buf[0]){ ! 254: cp = strchr(buf, '!'); ! 255: if(cp){ ! 256: strcpy(bootdisk, cp+1); ! 257: addconf("bootdisk", bootdisk); ! 258: } ! 259: } ! 260: ! 261: /* 4 byte word align stack */ ! 262: sp = (uchar*)((ulong)sp & ~3); ! 263: ! 264: /* build argc, argv on stack */ ! 265: sp -= (ac+1)*sizeof(sp); ! 266: lsp = (uchar**)sp; ! 267: for(i = 0; i < ac; i++) ! 268: *lsp++ = av[i] + ((USTKTOP - BY2PG) - base); ! 269: *lsp = 0; ! 270: sp += (USTKTOP - BY2PG) - base - sizeof(ulong); ! 271: } ! 272: ! 273: Conf conf; ! 274: ! 275: void ! 276: addconf(char *name, char *val) ! 277: { ! 278: if(nconf >= MAXCONF) ! 279: return; ! 280: confname[nconf] = name; ! 281: confval[nconf] = val; ! 282: nconf++; ! 283: } ! 284: ! 285: char* ! 286: getconf(char *name) ! 287: { ! 288: int i; ! 289: ! 290: for(i = 0; i < nconf; i++) ! 291: if(strcmp(confname[i], name) == 0) ! 292: return confval[i]; ! 293: return 0; ! 294: } ! 295: ! 296: /* ! 297: * look for unused address space in 0xC8000 to 1 meg ! 298: */ ! 299: void ! 300: romscan(void) ! 301: { ! 302: uchar *p; ! 303: ! 304: p = (uchar*)(KZERO+0xC8000); ! 305: while(p < (uchar*)(KZERO+0xE0000)){ ! 306: p[0] = 0x55; ! 307: p[1] = 0xAA; ! 308: p[2] = 4; ! 309: if(p[0] != 0x55 || p[1] != 0xAA){ ! 310: putisa(PADDR(p), 2048); ! 311: p += 2048; ! 312: continue; ! 313: } ! 314: p += p[2]*512; ! 315: } ! 316: ! 317: p = (uchar*)(KZERO+0xE0000); ! 318: if(p[0] != 0x55 || p[1] != 0xAA) ! 319: putisa(PADDR(p), 64*1024); ! 320: } ! 321: ! 322: ! 323: void ! 324: confinit(void) ! 325: { ! 326: long x, i, j, n; ! 327: int pcnt; ! 328: ulong ktop; ! 329: char *cp; ! 330: char *line[MAXCONF]; ! 331: ! 332: pcnt = 0; ! 333: ! 334: /* ! 335: * parse configuration args from dos file p9rc ! 336: */ ! 337: cp = BOOTARGS; /* where b.com leaves plan9.ini */ ! 338: cp[BOOTARGSLEN-1] = 0; ! 339: n = getfields(cp, line, MAXCONF, "\n"); ! 340: for(j = 0; j < n; j++){ ! 341: cp = strchr(line[j], '\r'); ! 342: if(cp) ! 343: *cp = 0; ! 344: cp = strchr(line[j], '='); ! 345: if(cp == 0) ! 346: continue; ! 347: *cp++ = 0; ! 348: if(cp - line[j] >= NAMELEN+1) ! 349: *(line[j]+NAMELEN-1) = 0; ! 350: confname[nconf] = line[j]; ! 351: confval[nconf] = cp; ! 352: if(strcmp(confname[nconf], "kernelpercent") == 0) ! 353: pcnt = 100 - atoi(confval[nconf]); ! 354: nconf++; ! 355: } ! 356: /* ! 357: * size memory above 1 meg. Kernel sits at 1 meg. We ! 358: * only recognize MB size chunks. ! 359: */ ! 360: memset(mmap, ' ', sizeof(mmap)); ! 361: x = 0x12345678; ! 362: for(i = 1; i <= MAXMEG; i++){ ! 363: /* ! 364: * write the first & last word in a megabyte of memory ! 365: */ ! 366: *mapaddr(KZERO|(i*MB)) = x; ! 367: *mapaddr(KZERO|((i+1)*MB-BY2WD)) = x; ! 368: ! 369: /* ! 370: * write the first and last word in all previous megs to ! 371: * handle address wrap around ! 372: */ ! 373: for(j = 1; j < i; j++){ ! 374: *mapaddr(KZERO|(j*MB)) = ~x; ! 375: *mapaddr(KZERO|((j+1)*MB-BY2WD)) = ~x; ! 376: } ! 377: ! 378: /* ! 379: * check for correct value ! 380: */ ! 381: if(*mapaddr(KZERO|(i*MB)) == x && *mapaddr(KZERO|((i+1)*MB-BY2WD)) == x){ ! 382: mmap[i] = 'x'; ! 383: /* ! 384: * zero memory to set ECC but skip over the kernel ! 385: */ ! 386: if(i != 1) ! 387: for(j = 0; j < MB/BY2PG; j += BY2PG) ! 388: memset(mapaddr(KZERO|(i*MB+j)), 0, BY2PG); ! 389: } ! 390: x += 0x3141526; ! 391: } ! 392: /* ! 393: * bank0 usually goes from the end of kernel bss to the end of memory ! 394: */ ! 395: ktop = PGROUND((ulong)end); ! 396: ktop = PADDR(ktop); ! 397: conf.base0 = ktop; ! 398: for(i = 1; mmap[i] == 'x'; i++) ! 399: ; ! 400: conf.npage0 = (i*MB - ktop)/BY2PG; ! 401: conf.topofmem = i*MB; ! 402: ! 403: /* ! 404: * bank1 usually goes from the end of BOOTARGS to 640k ! 405: */ ! 406: conf.base1 = (ulong)(BOOTARGS+BOOTARGSLEN); ! 407: conf.base1 = PGROUND(conf.base1); ! 408: conf.base1 = PADDR(conf.base1); ! 409: conf.npage1 = (640*1024-conf.base1)/BY2PG; ! 410: ! 411: /* ! 412: * if there is a hole in memory (due to a shadow BIOS) make the ! 413: * memory after the hole be bank 1. The memory from 0 to 640k ! 414: * is lost. ! 415: */ ! 416: for(; i <= MAXMEG; i++) ! 417: if(mmap[i] == 'x'){ ! 418: conf.base1 = i*MB; ! 419: for(j = i+1; mmap[j] == 'x'; j++) ! 420: ; ! 421: conf.npage1 = (j - i)*MB/BY2PG; ! 422: conf.topofmem = j*MB; ! 423: break; ! 424: } ! 425: ! 426: /* ! 427: * add address space holes holes under 16 meg to available ! 428: * isa space. ! 429: */ ! 430: romscan(); ! 431: if(conf.topofmem < 16*MB) ! 432: putisa(conf.topofmem, 16*MB - conf.topofmem); ! 433: ! 434: conf.npage = conf.npage0 + conf.npage1; ! 435: conf.ldepth = 0; ! 436: if(pcnt < 10) ! 437: pcnt = 70; ! 438: conf.upages = (conf.npage*pcnt)/100; ! 439: ! 440: conf.nproc = 30 + ((conf.npage*BY2PG)/MB)*8; ! 441: conf.monitor = 1; ! 442: conf.nswap = conf.nproc*80; ! 443: conf.nimage = 50; ! 444: switch(x86()){ ! 445: case 3: ! 446: conf.copymode = 1; /* copy on reference */ ! 447: break; ! 448: default: ! 449: conf.copymode = 0; /* copy on write */ ! 450: break; ! 451: } ! 452: conf.nfloppy = 2; ! 453: conf.nhard = 2; ! 454: conf.nmach = 1; ! 455: } ! 456: ! 457: char *mathmsg[] = ! 458: { ! 459: "invalid", ! 460: "denormalized", ! 461: "div-by-zero", ! 462: "overflow", ! 463: "underflow", ! 464: "precision", ! 465: "stack", ! 466: "error", ! 467: }; ! 468: ! 469: /* ! 470: * math coprocessor error ! 471: */ ! 472: void ! 473: matherror(Ureg *ur, void *a) ! 474: { ! 475: ulong status; ! 476: int i; ! 477: char *msg; ! 478: char note[ERRLEN]; ! 479: ! 480: USED(a); ! 481: ! 482: /* ! 483: * a write cycle to port 0xF0 clears the interrupt latch attached ! 484: * to the error# line from the 387 ! 485: */ ! 486: outb(0xF0, 0xFF); ! 487: ! 488: /* ! 489: * save floating point state to check out error ! 490: */ ! 491: fpenv(&u->fpsave); ! 492: status = u->fpsave.status; ! 493: ! 494: msg = 0; ! 495: for(i = 0; i < 8; i++) ! 496: if((1<<i) & status){ ! 497: msg = mathmsg[i]; ! 498: sprint(note, "sys: fp: %s fppc=0x%lux", msg, u->fpsave.pc); ! 499: postnote(u->p, 1, note, NDebug); ! 500: break; ! 501: } ! 502: if(msg == 0){ ! 503: sprint(note, "sys: fp: unknown fppc=0x%lux", u->fpsave.pc); ! 504: postnote(u->p, 1, note, NDebug); ! 505: } ! 506: if(ur->pc & KZERO) ! 507: panic("fp: status %lux fppc=0x%lux pc=0x%lux", status, ! 508: u->fpsave.pc, ur->pc); ! 509: } ! 510: ! 511: /* ! 512: * math coprocessor emulation fault ! 513: */ ! 514: void ! 515: mathemu(Ureg *ur, void *a) ! 516: { ! 517: USED(ur, a); ! 518: ! 519: switch(u->p->fpstate){ ! 520: case FPinit: ! 521: fpinit(); ! 522: u->p->fpstate = FPactive; ! 523: break; ! 524: case FPinactive: ! 525: fprestore(&u->fpsave); ! 526: u->p->fpstate = FPactive; ! 527: break; ! 528: case FPactive: ! 529: panic("math emu", 0); ! 530: break; ! 531: } ! 532: } ! 533: ! 534: /* ! 535: * math coprocessor segment overrun ! 536: */ ! 537: void ! 538: mathover(Ureg *ur, void *a) ! 539: { ! 540: USED(ur, a); ! 541: ! 542: print("sys: fp: math overrun pc 0x%lux pid %d\n", ur->pc, u->p->pid); ! 543: pexit("math overrun", 0); ! 544: } ! 545: ! 546: void ! 547: mathinit(void) ! 548: { ! 549: setvec(Matherr1vec, matherror, 0); ! 550: setvec(Matherr2vec, matherror, 0); ! 551: setvec(Mathemuvec, mathemu, 0); ! 552: setvec(Mathovervec, mathover, 0); ! 553: } ! 554: ! 555: /* ! 556: * set up floating point for a new process ! 557: */ ! 558: void ! 559: procsetup(Proc *p) ! 560: { ! 561: p->fpstate = FPinit; ! 562: fpoff(); ! 563: } ! 564: ! 565: /* ! 566: * Save the mach dependent part of the process state. ! 567: */ ! 568: void ! 569: procsave(Proc *p) ! 570: { ! 571: if(p->fpstate == FPactive){ ! 572: if(p->state == Moribund) ! 573: fpoff(); ! 574: else ! 575: fpsave(&u->fpsave); ! 576: p->fpstate = FPinactive; ! 577: } ! 578: } ! 579: ! 580: /* ! 581: * Restore what procsave() saves ! 582: */ ! 583: void ! 584: procrestore(Proc *p) ! 585: { ! 586: USED(p); ! 587: } ! 588: ! 589: ! 590: /* ! 591: * the following functions all are slightly different from ! 592: * PC to PC. ! 593: */ ! 594: ! 595: /* ! 596: * reset the i387 chip ! 597: */ ! 598: void ! 599: exit(int ispanic) ! 600: { ! 601: u = 0; ! 602: wipekeys(); ! 603: print("exiting\n"); ! 604: if(ispanic){ ! 605: if(cpuserver) ! 606: delay(10000); ! 607: else ! 608: for(;;); ! 609: } ! 610: ! 611: (*arch->reset)(); ! 612: } ! 613: ! 614: /* ! 615: * set cpu speed ! 616: * 0 == low speed ! 617: * 1 == high speed ! 618: */ ! 619: int ! 620: cpuspeed(int speed) ! 621: { ! 622: if(arch->cpuspeed) ! 623: return (*arch->cpuspeed)(speed); ! 624: else ! 625: return 0; ! 626: } ! 627: ! 628: /* ! 629: * f == frequency (Hz) ! 630: * d == duration (ms) ! 631: */ ! 632: void ! 633: buzz(int f, int d) ! 634: { ! 635: if(arch->buzz) ! 636: (*arch->buzz)(f, d); ! 637: } ! 638: ! 639: /* ! 640: * each bit in val stands for a light ! 641: */ ! 642: void ! 643: lights(int val) ! 644: { ! 645: if(arch->lights) ! 646: (*arch->lights)(val); ! 647: } ! 648: ! 649: /* ! 650: * power to serial port ! 651: * onoff == 1 means on ! 652: * onoff == 0 means off ! 653: */ ! 654: int ! 655: serial(int onoff) ! 656: { ! 657: if(arch->serialpower) ! 658: return (*arch->serialpower)(onoff); ! 659: else ! 660: return 0; ! 661: } ! 662: ! 663: /* ! 664: * power to modem ! 665: * onoff == 1 means on ! 666: * onoff == 0 means off ! 667: */ ! 668: int ! 669: modem(int onoff) ! 670: { ! 671: if(arch->modempower) ! 672: return (*arch->modempower)(onoff); ! 673: else ! 674: return 0; ! 675: } ! 676: ! 677: int ! 678: parseether(uchar *to, char *from) ! 679: { ! 680: char nip[4]; ! 681: char *p; ! 682: int i; ! 683: ! 684: p = from; ! 685: while(*p == ' ') ! 686: ++p; ! 687: for(i = 0; i < 6; i++){ ! 688: if(*p == 0) ! 689: return -1; ! 690: nip[0] = *p++; ! 691: if(*p == 0) ! 692: return -1; ! 693: nip[1] = *p++; ! 694: nip[2] = 0; ! 695: to[i] = strtoul(nip, 0, 16); ! 696: if(*p == ':') ! 697: p++; ! 698: } ! 699: return 0; ! 700: } ! 701: ! 702: int ! 703: isaconfig(char *class, int ctlrno, ISAConf *isa) ! 704: { ! 705: char cc[NAMELEN], *p, *q; ! 706: int n; ! 707: ! 708: sprint(cc, "%s%d", class, ctlrno); ! 709: for(n = 0; n < nconf; n++){ ! 710: if(strncmp(confname[n], cc, NAMELEN)) ! 711: continue; ! 712: p = confval[n]; ! 713: while(*p){ ! 714: while(*p == ' ' || *p == '\t') ! 715: p++; ! 716: if(*p == '\0') ! 717: break; ! 718: if(strncmp(p, "type=", 5) == 0){ ! 719: p += 5; ! 720: for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){ ! 721: if(*p == '\0' || *p == ' ' || *p == '\t') ! 722: break; ! 723: *q = *p++; ! 724: } ! 725: *q = '\0'; ! 726: } ! 727: else if(strncmp(p, "port=", 5) == 0) ! 728: isa->port = strtoul(p+5, &p, 0); ! 729: else if(strncmp(p, "irq=", 4) == 0) ! 730: isa->irq = strtoul(p+4, &p, 0); ! 731: else if(strncmp(p, "mem=", 4) == 0) ! 732: isa->mem = strtoul(p+4, &p, 0); ! 733: else if(strncmp(p, "size=", 5) == 0) ! 734: isa->size = strtoul(p+5, &p, 0); ! 735: else if(strncmp(p, "dma=", 4) == 0) ! 736: isa->dma = strtoul(p+4, &p, 0); ! 737: else if(strncmp(p, "ea=", 3) == 0){ ! 738: if(parseether(isa->ea, p+3) == -1) ! 739: memset(isa->ea, 0, 6); ! 740: } ! 741: while(*p && *p != ' ' && *p != '\t') ! 742: p++; ! 743: } ! 744: return 1; ! 745: } ! 746: return 0; ! 747: } ! 748: ! 749: static void ! 750: pcfloppyintr(Ureg *ur, void *a) ! 751: { ! 752: USED(a); ! 753: ! 754: floppyintr(ur); ! 755: } ! 756: ! 757: void ! 758: floppysetup0(FController *fl) ! 759: { ! 760: USED(fl); ! 761: } ! 762: ! 763: void ! 764: floppysetup1(FController *fl) ! 765: { ! 766: uchar equip; ! 767: ! 768: /* ! 769: * read nvram for types of floppies 0 & 1 ! 770: */ ! 771: equip = nvramread(0x10); ! 772: if(conf.nfloppy > 0){ ! 773: fl->d[0].dt = (equip >> 4) & 0xf; ! 774: floppysetdef(&fl->d[0]); ! 775: } ! 776: if(conf.nfloppy > 1){ ! 777: fl->d[1].dt = equip & 0xf; ! 778: floppysetdef(&fl->d[1]); ! 779: } ! 780: ! 781: setvec(Floppyvec, pcfloppyintr, 0); ! 782: } ! 783: ! 784: /* ! 785: * eject disk ( unknown on safari ) ! 786: */ ! 787: void ! 788: floppyeject(FDrive *dp) ! 789: { ! 790: floppyon(dp); ! 791: dp->vers++; ! 792: floppyoff(dp); ! 793: } ! 794: ! 795: int ! 796: floppyexec(char *a, long b, int c) ! 797: { ! 798: USED(a, b, c); ! 799: return b; ! 800: } ! 801: ! 802: int ! 803: cistrcmp(char *a, char *b) ! 804: { ! 805: int ac, bc; ! 806: ! 807: for(;;){ ! 808: ac = *a++; ! 809: bc = *b++; ! 810: ! 811: if(ac >= 'A' && ac <= 'Z') ! 812: ac = 'a' + (ac - 'A'); ! 813: if(bc >= 'A' && bc <= 'Z') ! 814: bc = 'a' + (bc - 'A'); ! 815: ac -= bc; ! 816: if(ac) ! 817: return ac; ! 818: if(bc == 0) ! 819: break; ! 820: } ! 821: return 0; ! 822: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.