1: /* 2: * Copyright (c) 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)sys.c 2.4 (2.11BSD) 1996/3/8 7: */ 8: 9: #include "../h/param.h" 10: #include "../h/dir.h" 11: #include "../machine/seg.h" 12: #include "../machine/iopage.h" 13: #include "../machine/psl.h" 14: #include "../machine/machparam.h" 15: #include "saio.h" 16: 17: #undef KISA0 18: #define KISA0 ((u_short *) 0172340) 19: #define KDSA0 ((u_short *) 0172360) 20: 21: extern struct devsw devsw[]; 22: extern int ssr3copy, bootctlr; 23: extern long atol(); 24: 25: /* 26: * These buffers are only used in mapping inode blocks to disk sectors, 27: * no good reason to make them global. 28: * 29: * The strange initialization is due to the fact that the 0'th case is 30: * not legal since it would be used for quadruple indirect files. The 31: * use of the array 'b' is: 32: * 33: * b[0] - not allocated, saving 1kb of space 34: * b[1] - triple indirect block 35: * b[2] - double indirect block 36: * b[3] - single indirect block 37: * 38: * In the 1kb filesystem double indirect files can be up to ~65 megabytes 39: * (the old 512 byte filesystem double indirect files were up to ~8mb). 40: */ 41: 42: static char tplind[DEV_BSIZE], dblind[DEV_BSIZE], sngind[DEV_BSIZE]; 43: 44: static char *b[4] = { 45: NULL, /* j = 0 */ 46: tplind, /* j = 1 */ 47: dblind, /* j = 2 */ 48: sngind /* j = 3 */ 49: }; 50: 51: static daddr_t blknos[4]; 52: 53: #define NFILES 4 54: struct iob iob[NFILES]; 55: 56: ino_t dlook(); 57: struct direct *readdir(); 58: 59: struct dirstuff { 60: long loc; 61: struct iob *io; 62: }; 63: 64: /* 65: * wfj - mods to trap to explicitly detail why we stopped 66: */ 67: 68: static 69: openi(n, io) 70: register ino_t n; 71: register struct iob *io; 72: { 73: register struct dinode *dp; 74: daddr_t tdp; 75: 76: io->i_offset = 0; 77: tdp = itod(n); 78: io->i_bn = fsbtodb(tdp) + io->i_boff; 79: io->i_cc = DEV_BSIZE; 80: io->i_ma = io->i_buf; 81: devread(io); 82: 83: dp = (struct dinode *)io->i_buf; 84: dp = &dp[itoo(n)]; 85: io->i_ino.i_number = n; 86: io->i_ino.i_mode = dp->di_mode; 87: io->i_ino.i_size = dp->di_size; 88: bcopy(dp->di_addr, io->i_ino.i_addr, NADDR * sizeof (daddr_t)); 89: } 90: 91: static 92: find(path, file) 93: register char *path; 94: struct iob *file; 95: { 96: register char *q; 97: register char c; 98: ino_t n; 99: 100: if (path==NULL || *path=='\0') { 101: printf("null path\n"); 102: return(0); 103: } 104: 105: openi((ino_t) ROOTINO, file); 106: while (*path) { 107: while (*path == '/') 108: path++; 109: q = path; 110: while (*q != '/' && *q != '\0') 111: q++; 112: c = *q; 113: *q = '\0'; 114: if (q == path) path = "." ; /* "/" means "/." */ 115: 116: if ((n=dlook(path, file))!=0) { 117: if (c=='\0') 118: break; 119: openi(n, file); 120: *q = c; 121: path = q; 122: continue; 123: } else { 124: printf("%s not found\n", path); 125: return(0); 126: } 127: /*NOTREACHED*/ 128: } 129: return(n); 130: } 131: 132: static daddr_t 133: sbmap(io, bn) 134: register struct iob *io; 135: daddr_t bn; 136: { 137: register i; 138: register struct inode *ip; 139: int j, sh; 140: daddr_t nb, *bap; 141: 142: ip = &io->i_ino; 143: if (bn < 0) { 144: printf("bn < 0\n"); 145: return((daddr_t)0); 146: } 147: 148: /* 149: * blocks 0..NADDR-4 are direct blocks 150: */ 151: if (bn < NADDR-3) { 152: i = bn; 153: nb = ip->i_addr[i]; 154: return(nb); 155: } 156: 157: /* 158: * addresses NADDR-3, NADDR-2, and NADDR-1 159: * have single, double, triple indirect blocks. 160: * the first step is to determine 161: * how many levels of indirection. 162: */ 163: sh = 0; 164: nb = 1; 165: bn -= NADDR-3; 166: for (j=3; j>0; j--) { 167: sh += NSHIFT; 168: nb <<= NSHIFT; 169: if (bn < nb) 170: break; 171: bn -= nb; 172: } 173: if (j == 0) { 174: printf("bn ovf %D\n", bn); 175: return((daddr_t)0); 176: } 177: /* 178: * At this point: 179: * 180: * j NADDR-j meaning 181: * --- ------- ------- 182: * 0 7 illegal - tossed out in the 'if' above 183: * 1 6 triple indirect block number 184: * 2 5 double indirect block number 185: * 3 4 single indirect block number 186: */ 187: 188: /* 189: * fetch the address from the inode 190: */ 191: nb = ip->i_addr[NADDR-j]; 192: if (nb == 0) 193: goto bnvoid; 194: 195: /* 196: * fetch through the indirect blocks 197: */ 198: for (; j<=3; j++) { 199: if (blknos[j] != nb) { 200: io->i_bn = fsbtodb(nb) + io->i_boff; 201: io->i_ma = b[j]; 202: io->i_cc = DEV_BSIZE; 203: devread(io); 204: blknos[j] = nb; 205: } 206: bap = (daddr_t *)b[j]; 207: sh -= NSHIFT; 208: i = (bn>>sh) & NMASK; 209: nb = bap[i]; 210: if (nb == 0) { 211: bnvoid: 212: printf("bn void %D\n", bn); 213: return((daddr_t)0); 214: } 215: } 216: 217: return(nb); 218: } 219: 220: static ino_t 221: dlook(s, io) 222: char *s; 223: register struct iob *io; 224: { 225: register struct direct *dp; 226: register struct inode *ip; 227: struct dirstuff dirp; 228: int len; 229: 230: if (s==NULL || *s=='\0') 231: return(0); 232: ip = &io->i_ino; 233: if ((ip->i_mode&IFMT) != IFDIR || !ip->i_size) { 234: printf("%s: !directory,mode %o size: %D ip %o\n", s, 235: ip->i_mode, ip->i_size, ip); 236: return(0); 237: } 238: 239: len = strlen(s); 240: dirp.loc = 0; 241: dirp.io = io; 242: for (dp = readdir(&dirp); dp; dp = readdir(&dirp)) { 243: if (dp->d_ino == 0) 244: continue; 245: if (dp->d_namlen == len && !strcmp(s,dp->d_name)) 246: return(dp->d_ino); 247: } 248: return(0); 249: } 250: 251: struct direct * 252: readdir(dirp) 253: register struct dirstuff *dirp; 254: { 255: register struct direct *dp; 256: register struct iob *io; 257: daddr_t lbn, d, off; 258: 259: io = dirp->io; 260: for (;;) { 261: if (dirp->loc >= io->i_ino.i_size) 262: return(NULL); 263: off = blkoff(dirp->loc); 264: if (off == 0) { 265: lbn = lblkno(dirp->loc); 266: d = sbmap(io, lbn); 267: if (d == 0) 268: return(NULL); 269: io->i_bn = fsbtodb(d) + io->i_boff; 270: io->i_ma = io->i_buf; 271: io->i_cc = DEV_BSIZE; 272: devread(io); 273: } 274: dp = (struct direct *)(io->i_buf + off); 275: dirp->loc += dp->d_reclen; 276: if (dp->d_ino == 0) 277: continue; 278: return(dp); 279: } 280: } 281: 282: /* 283: * Modified to call the tape driver's seek routine. This only works when 284: * the record size is DEV_BSIZE (1kb). 285: */ 286: lseek(fdesc, addr, ptr) 287: register int fdesc; 288: off_t addr; 289: int ptr; 290: { 291: off_t new; 292: register struct iob *io; 293: 294: if (ptr != 0) { 295: printf("lseek\n"); 296: return(-1); 297: } 298: fdesc -= 3; 299: if (fdesc < 0 || fdesc >= NFILES || 300: ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) 301: return(-1); 302: new = addr / DEV_BSIZE; 303: 304: if (io->i_flgs & F_TAPE) 305: { 306: #ifdef debug 307: printf("seek: new=%D i_bn=%D\n", new, io->i_bn); 308: #endif 309: /* 310: * Subtract 1 to acccount for the block currently in the buffer - the 311: * tape is currently positioned at the next record. Need to convert the 312: * block number from 512 byte to 1024 byte records (undo the fsbtodb). 313: */ 314: devseek(io, (int)(new - dbtofsb(io->i_bn) - 1)); 315: } 316: io->i_offset = addr; 317: io->i_bn = fsbtodb(new) + io->i_boff; 318: io->i_cc = 0; 319: return(0); 320: } 321: 322: /* if tape mark encountered, set flag (in driver) */ 323: int tapemark; 324: 325: getc(fdesc) 326: int fdesc; 327: { 328: register struct iob *io; 329: register unsigned char *p; 330: register int c; 331: int off; 332: daddr_t tbn; 333: 334: if (fdesc >= 0 && fdesc <= 2) 335: return(getchar()); 336: fdesc -= 3; 337: if (fdesc < 0 || fdesc >= NFILES || ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) 338: return(-1); 339: if (io->i_cc <= 0) { 340: io->i_bn = fsbtodb(io->i_offset/(off_t)DEV_BSIZE); 341: if (io->i_flgs&F_FILE) { 342: tbn = sbmap(io, dbtofsb(io->i_bn)); 343: io->i_bn = fsbtodb(tbn) + io->i_boff; 344: } 345: io->i_ma = io->i_buf; 346: io->i_cc = DEV_BSIZE; 347: #ifdef DEBUG 348: printf("getc: fetch block %D, dev = %d\n", io->i_bn, 349: io->i_ino.i_dev); 350: #endif 351: tapemark = 0; 352: devread(io); 353: off = io->i_offset % (off_t)DEV_BSIZE; 354: if (io->i_flgs&F_FILE) { 355: if (io->i_offset+(DEV_BSIZE-off) >= io->i_ino.i_size) 356: io->i_cc = io->i_ino.i_size - io->i_offset + off; 357: } 358: if (tapemark) 359: return(-1); 360: io->i_cc -= off; 361: if (io->i_cc <= 0) 362: return(-1); 363: io->i_ma = &io->i_buf[off]; 364: } 365: io->i_cc--; 366: io->i_offset++; 367: c = (int)(*(unsigned char *)io->i_ma++); 368: return(c); 369: } 370: getw(fdesc) 371: int fdesc; 372: { 373: register w, i; 374: register unsigned char *cp; 375: int val; 376: 377: for (i = 0, val = 0, cp = (unsigned char *)&val; i < sizeof(val); i++) { 378: w = getc(fdesc); 379: if (w < 0) { 380: if (i == 0) 381: return(-1); 382: else 383: return(val); 384: } 385: *cp++ = w; 386: } 387: return(val); 388: } 389: 390: read(fdesc, buf, count) 391: register int fdesc; 392: char *buf; 393: int count; 394: { 395: register i; 396: register struct iob *file; 397: 398: if (fdesc >= 0 & fdesc <= 2) { 399: i = count; 400: do { 401: *buf = getchar(); 402: } while (--i && *buf++ != '\n'); 403: return(count - i); 404: } 405: fdesc -= 3; 406: if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) 407: return(-1); 408: if ((file->i_flgs&F_READ) == 0) 409: return(-1); 410: if ((file->i_flgs&F_FILE) == 0) { 411: file->i_cc = count; 412: file->i_ma = buf; 413: i = devread(file); 414: if (i > 0) 415: file->i_bn += (i / NBPG); 416: return(i); 417: } 418: else { 419: if (file->i_offset+count > file->i_ino.i_size) 420: count = file->i_ino.i_size - file->i_offset; 421: if ((i = count) <= 0) 422: return(0); 423: do { 424: *buf++ = getc(fdesc+3); 425: } while (--i); 426: return(count); 427: } 428: } 429: 430: write(fdesc, buf, count) 431: register int fdesc; 432: char *buf; 433: int count; 434: { 435: register i; 436: register struct iob *file; 437: 438: if (fdesc >= 0 && fdesc <= 2) { 439: i = count; 440: while (i--) 441: putchar(*buf++); 442: return(count); 443: } 444: fdesc -= 3; 445: if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) 446: return(-1); 447: if ((file->i_flgs&F_WRITE) == 0) 448: return(-1); 449: file->i_cc = count; 450: file->i_ma = buf; 451: i = devwrite(file); 452: file->i_bn += (count / NBPG); 453: return(i); 454: } 455: 456: open(str, how) 457: char *str; 458: int how; 459: { 460: register char *cp; 461: int i, i2, i3; 462: register struct iob *file; 463: register struct devsw *dp; 464: int fdesc; 465: 466: for (fdesc = 0; fdesc < NFILES; fdesc++) 467: if (iob[fdesc].i_flgs == 0) 468: goto gotfile; 469: _stop("No file slots"); 470: gotfile: 471: (file = &iob[fdesc])->i_flgs |= F_ALLOC; 472: 473: for (cp = str; *cp && *cp != '('; cp++) 474: ; 475: if (*cp != '(') { 476: printf("Bad device\n"); 477: file->i_flgs = 0; 478: return(-1); 479: } 480: *cp = '\0'; 481: for (dp = devsw; dp->dv_name; dp++) { 482: if (strcmp(str, dp->dv_name) == 0) 483: goto gotdev; 484: } 485: printf("Unknown device\n"); 486: file->i_flgs = 0; 487: return(-1); 488: gotdev: 489: /* 490: * The parse is a bit lengthier and complex now. The syntax is now: 491: * 492: * xx(ctlr, unit, partition)filename 493: * or 494: * xx(unit, partition)filename 495: * 496: * 497: * The controller number must be less than 4. NOTE: many drivers 498: * limit the number of controllers to 1 or 2. If the controller is not 499: * specified it defaults to 0. 500: * 501: * The unit number must be less than 8. 502: * 503: * The partition number is also used to specify the tapefile to be loaded. 504: * When loading a tapefile the 'filename' must not be specified. The partition 505: * number must be less than 8. This means that the number of standalone 506: * programs is limited to 7. 507: */ 508: 509: *cp++ = '('; 510: file->i_ino.i_dev = dp-devsw; 511: for (i = 0; *cp >= '0' && *cp <= '9'; cp++) { 512: i *= 10; 513: i += (*cp - '0'); 514: } 515: 516: if (*cp++ != ',') { 517: badoff: 518: printf("Bad offset or ctlr, unit, part out of bounds\n"); 519: file->i_flgs = 0; 520: return(-1); 521: } 522: 523: for (i2 = 0; *cp >= '0' && *cp <= '9'; cp++) 524: { 525: i2 *= 10; 526: i2 += (*cp - '0'); 527: } 528: /* 529: * If we encounter a ')' now it means we have the two arg form 'ra(x,y)'. If 530: * a ',' is seen then we have the three arg form 'xp(x,y,z)'. If neither a 531: * ',' or ')' it is an error. 532: */ 533: if (*cp == ')') 534: { 535: file->i_ctlr = bootctlr; 536: file->i_unit = i; 537: file->i_part = i2; 538: cp++; /* skip ) */ 539: } 540: else if (*cp == ',') 541: { 542: for (i3 = 0, cp++; *cp >= '0' && *cp <= '9'; cp++) 543: { 544: i3 *= 10; 545: i3 += (*cp - '0'); 546: } 547: file->i_ctlr = i; 548: file->i_unit = i2; 549: file->i_part = i3; 550: if (*cp++ != ')') 551: goto badoff; 552: } 553: else 554: goto badoff; 555: if (file->i_ctlr > 3 || file->i_unit > 7 || file->i_part > 7) 556: goto badoff; 557: 558: if (devopen(file) < 0) 559: { 560: file->i_flgs = 0; 561: return(-1); 562: } 563: if (*cp == '\0') { 564: file->i_flgs |= how+1; 565: goto comret; 566: } 567: if ((i = find(cp, file)) == 0) { 568: file->i_flgs = 0; 569: return(-1); 570: } 571: if (how != 0) { 572: printf("Can't write files\n"); 573: file->i_flgs = 0; 574: return(-1); 575: } 576: openi(i, file); 577: file->i_flgs |= F_FILE | (how+1); 578: comret: 579: file->i_offset = 0; 580: file->i_cc = 0; 581: file->i_bn = 0; 582: return(fdesc+3); 583: } 584: 585: close(fdesc) 586: register int fdesc; 587: { 588: register struct iob *file; 589: 590: fdesc -= 3; 591: if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) 592: return(-1); 593: if ((file->i_flgs&F_FILE) == 0) 594: devclose(file); 595: file->i_flgs = 0; 596: return(0); 597: } 598: 599: exit() 600: { 601: _stop("Exit called"); 602: } 603: 604: _stop(s) 605: char *s; 606: { 607: printf("%s\n", s); 608: _rtt(); 609: } 610: 611: extern char module[]; 612: 613: trap(r1, r0, nps, pc, ps) 614: int nps, r1, r0, pc, ps; 615: { 616: printf("Trap in %s,", module); 617: switch (nps&7) { 618: case 0: 619: printf("bus error"); 620: break; 621: case 1: 622: printf("illegal instruction"); 623: break; 624: case 2: 625: printf("bpt/trace"); 626: break; 627: case 3: 628: printf("iot"); 629: break; 630: case 4: 631: printf("power fail"); 632: break; 633: case 5: 634: printf("emt"); 635: break; 636: case 6: 637: printf("sys/trap"); 638: break; 639: default: 640: printf("weird"); 641: } 642: printf(" at loc %o\n", pc); 643: printf("registers: r0=%o, r1=%o, ps=%o, nps=%o\n", r0, r1, ps, nps); 644: for (;;) 645: ; 646: } 647: 648: genopen(maxctlr, io) 649: int maxctlr; 650: struct iob *io; 651: { 652: register struct devsw *dp = &devsw[io->i_ino.i_dev]; 653: register char *cp; 654: register int ctlr = io->i_ctlr; 655: int csr; 656: char line[64]; 657: 658: if (ctlr >= maxctlr) 659: return(-1); 660: if (dp->dv_csr[ctlr]) 661: return(0); 662: printf("%s%d csr[0%o]: ", dp->dv_name, ctlr, dp->dv_csr[ctlr]); 663: gets(line); 664: for (csr = 0, cp = line; *cp >= '0' && *cp <= '7'; cp++) 665: csr = csr * 8 + (*cp - '0'); 666: if (csr == 0) 667: return(-1); 668: dp->dv_csr[ctlr] = (caddr_t *)csr; 669: /* 670: * Tapes don't need this. Disk drivers which support labels do not need 671: * this either but disk drivers which do not support labels _do_ need this. 672: * Doing it here is safe for everyone because label capable drivers will 673: * load i_boff from the label _after_ calling this routine. 674: */ 675: io->i_boff = 0; 676: return(0); 677: } 678: 679: delay(i) 680: int i; 681: { 682: 683: while (i) 684: i--; 685: } 686: 687: char * 688: ltoa(l) 689: u_long l; 690: { 691: static char x[12]; 692: register char *cp = x + sizeof (x); 693: 694: do { 695: *--cp = (l % 10) + '0'; 696: l /= 10; 697: } while (l); 698: return(cp); 699: } 700: 701: char * 702: itoa(i) 703: register int i; 704: { 705: static char x[8]; 706: register char *cp = x + sizeof (x); 707: 708: do { 709: *--cp = (i % 10) + '0'; 710: i /= 10; 711: } while (i); 712: return(cp); 713: } 714: 715: /* 716: * Convert a 16 bit (virtual) address into a 18 bit (UNIBUS) address. 717: * The address extension bits (bits 16, 17) are placed into 'bae' while 718: * the lower order bits (bits 0 - 15) are placed in 'lo16'. 719: * 720: * This routine was primarily created to handle split I/D kernel mode 721: * utilities. Boot itself must run non split I/D and runs in user mode. 722: * A side effect of this routine is that Boot no longer must be loaded at 723: * a 64Kb boundary. 724: * 725: * Everything (Boot and standalone utilities) must still run in the low 726: * 248kb of memory which is mapped by the UNIBUS mapping registers. 727: */ 728: 729: iomapadr(buf, bae, lo16) 730: memaddr buf; 731: u_short *bae, *lo16; 732: { 733: u_long uadr; 734: int curmode = *PS & PSL_CURMOD, segno; 735: u_int nb, ts; 736: extern char module[]; 737: 738: if (curmode == 0) 739: { /* Kernel mode - we're in a utility */ 740: /* 741: * For split I/D we need to emulate the kernel's method of looking at 742: * the segment registers and calculating the physical address. Whew, forgot 743: * that ;-) 744: */ 745: nb = ((int)buf >> 6) & 01777; 746: segno = nb >> 7; 747: if (ssr3copy & 4) 748: ts = KDSA0[segno]; /* kernel I/D is on */ 749: else 750: ts = KISA0[segno]; /* kernel I/D is off */ 751: ts += (nb & 0177); 752: uadr = ((u_long)ts << 6) + (buf & 077); 753: } 754: else if (curmode == PSL_CURMOD) 755: { /* User mode - we're in Boot */ 756: uadr = UISA[0]; /* No I/D for Boot! */ 757: uadr <<= 6; /* clicks to bytes */ 758: uadr += buf; 759: } 760: else 761: _stop("Bad PSL mode"); 762: 763: *bae = (uadr >> 16) & 3; /* 18 bit mode */ 764: *lo16 = uadr & 0xffff; 765: }