├── README.md ├── buf.h ├── conf.h ├── conf ├── data.s ├── m40.s ├── m45.s ├── mkconf.c └── sysfix.c ├── dmr ├── bio.c ├── cat.c ├── dc.c ├── dh.c ├── dhdm.c ├── dhfdm.c ├── dn.c ├── dp.c ├── hp.c ├── hs.c ├── ht.c ├── kl.c ├── lp.c ├── mem.c ├── partab.c ├── pc.c ├── rf.c ├── rk.c ├── rp.c ├── sys.c ├── tc.c ├── tm.c ├── tty.c ├── vs.c └── vt.c ├── file.h ├── filsys.h ├── ino.h ├── inode.h ├── ken ├── alloc.c ├── clock.c ├── fio.c ├── iget.c ├── main.c ├── malloc.c ├── nami.c ├── pipe.c ├── prf.c ├── rdwri.c ├── sig.c ├── slp.c ├── subr.c ├── sys1.c ├── sys2.c ├── sys3.c ├── sys4.c ├── sysent.c ├── text.c └── trap.c ├── param.h ├── proc.h ├── reg.h ├── seg.h ├── systm.h ├── tags ├── text.h ├── tty.h └── user.h /README.md: -------------------------------------------------------------------------------- 1 | # UNX V6 2 | machine: PDP11 3 | -------------------------------------------------------------------------------- /buf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Each buffer in the pool is usually doubly linked into 2 lists: 3 | * the device with which it is currently associated (always) 4 | * and also on a list of blocks available for allocation 5 | * for other use (usually). 6 | * The latter list is kept in last-used order, and the two 7 | * lists are doubly linked to make it easy to remove 8 | * a buffer from one list when it was found by 9 | * looking through the other. 10 | * A buffer is on the available list, and is liable 11 | * to be reassigned to another disk block, if and only 12 | * if it is not marked BUSY. When a buffer is busy, the 13 | * available-list pointers can be used for other purposes. 14 | * Most drivers use the forward ptr as a link in their I/O 15 | * active queue. 16 | * A buffer header contains all the information required 17 | * to perform I/O. 18 | * Most of the routines which manipulate these things 19 | * are in bio.c. 20 | */ 21 | struct buf 22 | { 23 | int b_flags; /* see defines below */ 24 | struct buf *b_forw; /* headed by devtab of b_dev */ 25 | struct buf *b_back; /* " */ 26 | struct buf *av_forw; /* position on free list, */ 27 | struct buf *av_back; /* if not BUSY*/ 28 | int b_dev; /* major+minor device name */ 29 | int b_wcount; /* transfer count (usu. words) */ 30 | char *b_addr; /* low order core address */ 31 | char *b_xmem; /* high order core address */ 32 | char *b_blkno; /* block # on device */ 33 | char b_error; /* returned after I/O */ 34 | char *b_resid; /* words not transferred after error */ 35 | } buf[NBUF]; 36 | 37 | /* 38 | * Each block device has a devtab, which contains private state stuff 39 | * and 2 list heads: the b_forw/b_back list, which is doubly linked 40 | * and has all the buffers currently associated with that major 41 | * device; and the d_actf/d_actl list, which is private to the 42 | * device but in fact is always used for the head and tail 43 | * of the I/O queue for the device. 44 | * Various routines in bio.c look at b_forw/b_back 45 | * (notice they are the same as in the buf structure) 46 | * but the rest is private to each device driver. 47 | */ 48 | struct devtab 49 | { 50 | char d_active; /* busy flag */ 51 | char d_errcnt; /* error count (for recovery) */ 52 | struct buf *b_forw; /* first buffer for this dev */ 53 | struct buf *b_back; /* last buffer for this dev */ 54 | struct buf *d_actf; /* head of I/O queue */ 55 | struct buf *d_actl; /* tail of I/O queue */ 56 | }; 57 | 58 | /* 59 | * This is the head of the queue of available 60 | * buffers-- all unused except for the 2 list heads. 61 | */ 62 | struct buf bfreelist; 63 | 64 | /* 65 | * These flags are kept in b_flags. 66 | */ 67 | #define B_WRITE 0 /* non-read pseudo-flag */ 68 | #define B_READ 01 /* read when I/O occurs */ 69 | #define B_DONE 02 /* transaction finished */ 70 | #define B_ERROR 04 /* transaction aborted */ 71 | #define B_BUSY 010 /* not on av_forw/back list */ 72 | #define B_PHYS 020 /* Physical IO potentially using UNIBUS map */ 73 | #define B_MAP 040 /* This block has the UNIBUS map allocated */ 74 | #define B_WANTED 0100 /* issue wakeup when BUSY goes off */ 75 | #define B_RELOC 0200 /* no longer used */ 76 | #define B_ASYNC 0400 /* don't wait for I/O completion */ 77 | #define B_DELWRI 01000 /* don't write till block leaves available list */ 78 | -------------------------------------------------------------------------------- /conf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Used to dissect integer device code 3 | * into major (driver designation) and 4 | * minor (driver parameter) parts. 5 | */ 6 | struct 7 | { 8 | char d_minor; 9 | char d_major; 10 | }; 11 | 12 | /* 13 | * Declaration of block device 14 | * switch. Each entry (row) is 15 | * the only link between the 16 | * main unix code and the driver. 17 | * The initialization of the 18 | * device switches is in the 19 | * file conf.c. 20 | */ 21 | struct bdevsw 22 | { 23 | int (*d_open)(); 24 | int (*d_close)(); 25 | int (*d_strategy)(); 26 | int *d_tab; 27 | } bdevsw[]; 28 | 29 | /* 30 | * Nblkdev is the number of entries 31 | * (rows) in the block switch. It is 32 | * set in binit/bio.c by making 33 | * a pass over the switch. 34 | * Used in bounds checking on major 35 | * device numbers. 36 | */ 37 | int nblkdev; 38 | 39 | /* 40 | * Character device switch. 41 | */ 42 | struct cdevsw 43 | { 44 | int (*d_open)(); 45 | int (*d_close)(); 46 | int (*d_read)(); 47 | int (*d_write)(); 48 | int (*d_sgtty)(); 49 | } cdevsw[]; 50 | 51 | /* 52 | * Number of character switch entries. 53 | * Set by cinit/tty.c 54 | */ 55 | int nchrdev; 56 | -------------------------------------------------------------------------------- /conf/data.s: -------------------------------------------------------------------------------- 1 | / l45.o needs to be in data space 2 | / to get l45.o; as data.s l.s 3 | .data 4 | -------------------------------------------------------------------------------- /conf/mkconf.c: -------------------------------------------------------------------------------- 1 | #define CHAR 01 2 | #define BLOCK 02 3 | #define INTR 04 4 | #define EVEN 010 5 | #define KL 020 6 | #define ROOT 040 7 | char *btab[] 8 | { 9 | "rk", 10 | "rp", 11 | "rf", 12 | "tm", 13 | "tc", 14 | "hs", 15 | "hp", 16 | "ht", 17 | 0 18 | }; 19 | char *ctab[] 20 | { 21 | "console", 22 | "pc", 23 | "lp", 24 | "dc", 25 | "dh", 26 | "dp", 27 | "dj", 28 | "dn", 29 | "mem", 30 | "rk", 31 | "rf", 32 | "rp", 33 | "tm", 34 | "hs", 35 | "hp", 36 | "ht", 37 | 0 38 | }; 39 | struct tab 40 | { 41 | char *name; 42 | int count; 43 | int address; 44 | int key; 45 | char *codea; 46 | char *codeb; 47 | char *codec; 48 | char *coded; 49 | char *codee; 50 | } table[] 51 | { 52 | "console", 53 | -1, 60, CHAR+INTR+KL, 54 | "\tklin; br4\n\tklou; br4\n", 55 | ".globl\t_klrint\nklin:\tjsr\tr0,call; _klrint\n", 56 | ".globl\t_klxint\nklou:\tjsr\tr0,call; _klxint\n", 57 | "", 58 | "\t&klopen, &klclose, &klread, &klwrite, &klsgtty,", 59 | 60 | "mem", 61 | -1, 300, CHAR, 62 | "", 63 | "", 64 | "", 65 | "", 66 | "\t&nulldev, &nulldev, &mmread, &mmwrite, &nodev,", 67 | 68 | "pc", 69 | 0, 70, CHAR+INTR, 70 | "\tpcin; br4\n\tpcou; br4\n", 71 | ".globl\t_pcrint\npcin:\tjsr\tr0,call; _pcrint\n", 72 | ".globl\t_pcpint\npcou:\tjsr\tr0,call; _pcpint\n", 73 | "", 74 | "\t&pcopen, &pcclose, &pcread, &pcwrite, &nodev,", 75 | 76 | "clock", 77 | -2, 100, INTR, 78 | "\tkwlp; br6\n", 79 | ".globl\t_clock\n", 80 | "kwlp:\tjsr\tr0,call; _clock\n", 81 | "", 82 | "", 83 | 84 | "parity", 85 | -1, 114, INTR, 86 | "\ttrap; br7+7.\t\t/ 11/70 parity\n", 87 | "", 88 | "", 89 | "", 90 | "", 91 | 92 | /* 93 | * 110 unused 94 | * 114 memory parity 95 | * 120 XY plotter 96 | * 124 DR11-B 97 | * 130 AD01 98 | * 134 AFC11 99 | * 140 AA11 100 | * 144 AA11 101 | * 150-174 unused 102 | */ 103 | 104 | "lp", 105 | 0, 200, CHAR+INTR, 106 | "\tlpou; br4\n", 107 | "", 108 | ".globl\t_lpint\nlpou:\tjsr\tr0,call; _lpint\n", 109 | "", 110 | "\t&lpopen, &lpclose, &nodev, &lpwrite, &nodev,", 111 | 112 | "rf", 113 | 0, 204, BLOCK+CHAR+INTR, 114 | "\trfio; br5\n", 115 | ".globl\t_rfintr\n", 116 | "rfio:\tjsr\tr0,call; _rfintr\n", 117 | "\t&nulldev,\t&nulldev,\t&rfstrategy, \t&rftab,", 118 | "\t&nulldev, &nulldev, &rfread, &rfwrite, &nodev,", 119 | 120 | "hs", 121 | 0, 204, BLOCK+CHAR+INTR, 122 | "\thsio; br5\n", 123 | ".globl\t_hsintr\n", 124 | "hsio:\tjsr\tr0,call; _hsintr\n", 125 | "\t&nulldev,\t&nulldev,\t&hsstrategy, \t&hstab,", 126 | "\t&nulldev, &nulldev, &hsread, &hswrite, &nodev,", 127 | 128 | /* 129 | * 210 RC 130 | */ 131 | 132 | "tc", 133 | 0, 214, BLOCK+INTR, 134 | "\ttcio; br6\n", 135 | ".globl\t_tcintr\n", 136 | "tcio:\tjsr\tr0,call; _tcintr\n", 137 | "\t&nulldev,\t&tcclose,\t&tcstrategy, \t&tctab,", 138 | "", 139 | 140 | "rk", 141 | 0, 220, BLOCK+CHAR+INTR, 142 | "\trkio; br5\n", 143 | ".globl\t_rkintr\n", 144 | "rkio:\tjsr\tr0,call; _rkintr\n", 145 | "\t&nulldev,\t&nulldev,\t&rkstrategy, \t&rktab,", 146 | "\t&nulldev, &nulldev, &rkread, &rkwrite, &nodev,", 147 | 148 | "tm", 149 | 0, 224, BLOCK+CHAR+INTR, 150 | "\ttmio; br5\n", 151 | ".globl\t_tmintr\n", 152 | "tmio:\tjsr\tr0,call; _tmintr\n", 153 | "\t&tmopen,\t&tmclose,\t&tmstrategy, \t&tmtab,", 154 | "\t&tmopen, &tmclose, &tmread, &tmwrite, &nodev,", 155 | 156 | "ht", 157 | 0, 224, BLOCK+CHAR+INTR, 158 | "\thtio; br5\n", 159 | ".globl\t_htintr\n", 160 | "htio:\tjsr\tr0,call; _htintr\n", 161 | "\t&htopen,\t&htclose,\t&htstrategy, \t&httab,", 162 | "\t&htopen, &htclose, &htread, &htwrite, &nodev,", 163 | 164 | "cr", 165 | 0, 230, CHAR+INTR, 166 | "\tcrin; br6\n", 167 | "", 168 | ".globl\t_crint\ncrin:\tjsr\tr0,call; _crint\n", 169 | "", 170 | "\t&cropen, &crclose, &crread, &nodev, &nodev,", 171 | 172 | /* 173 | * 234 UDC11 174 | */ 175 | 176 | "rp", 177 | 0, 254, BLOCK+CHAR+INTR, 178 | "\trpio; br5\n", 179 | ".globl\t_rpintr\n", 180 | "rpio:\tjsr\tr0,call; _rpintr\n", 181 | "\t&nulldev,\t&nulldev,\t&rpstrategy, \t&rptab,", 182 | "\t&nulldev, &nulldev, &rpread, &rpwrite, &nodev,", 183 | 184 | "hp", 185 | 0, 254, BLOCK+CHAR+INTR, 186 | "\thpio; br5\n", 187 | ".globl\t_hpintr\n", 188 | "hpio:\tjsr\tr0,call; _hpintr\n", 189 | "\t&hpopen,\t&nulldev,\t&hpstrategy, \t&hptab,", 190 | "\t&hpopen, &nulldev, &hpread, &hpwrite, &nodev,", 191 | 192 | /* 193 | * 260 TA11 194 | * 264-274 unused 195 | */ 196 | 197 | "dc", 198 | 0, 308, CHAR+INTR, 199 | "\tdcin; br5+%d.\n\tdcou; br5+%d.\n", 200 | ".globl\t_dcrint\ndcin:\tjsr\tr0,call; _dcrint\n", 201 | ".globl\t_dcxint\ndcou:\tjsr\tr0,call; _dcxint\n", 202 | "", 203 | "\t&dcopen, &dcclose, &dcread, &dcwrite, &dcsgtty,", 204 | 205 | "kl", 206 | 0, 308, INTR+KL, 207 | "\tklin; br4+%d.\n\tklou; br4+%d.\n", 208 | "", 209 | "", 210 | "", 211 | "", 212 | 213 | "dp", 214 | 0, 308, CHAR+INTR, 215 | "\tdpin; br6+%d.\n\tdpou; br6+%d.\n", 216 | ".globl\t_dprint\ndpin:\tjsr\tr0,call; _dprint\n", 217 | ".globl\t_dpxint\ndpou:\tjsr\tr0,call; _dpxint\n", 218 | "", 219 | "\t&dpopen, &dpclose, &dpread, &dpwrite, &nodev,", 220 | 221 | /* 222 | * DM11-A 223 | */ 224 | 225 | "dn", 226 | 0, 304, CHAR+INTR, 227 | "\tdnou; br5+%d.\n", 228 | "", 229 | ".globl\t_dnint\ndnou:\tjsr\tr0,call; _dnint\n", 230 | "", 231 | "\t&dnopen, &dnclose, &nodev, &dnwrite, &nodev,", 232 | 233 | "dhdm", 234 | 0, 304, INTR, 235 | "\tdmin; br4+%d.\n", 236 | "", 237 | ".globl\t_dmint\ndmin:\tjsr\tr0,call; _dmint\n", 238 | "", 239 | "", 240 | 241 | /* 242 | * DR11-A+ 243 | * DR11-C+ 244 | * PA611+ 245 | * PA611+ 246 | * DT11+ 247 | * DX11+ 248 | */ 249 | 250 | "dl", 251 | 0, 308, INTR+KL, 252 | "\tklin; br4+%d.\n\tklou; br4+%d.\n", 253 | "", 254 | "", 255 | "", 256 | "", 257 | 258 | /* 259 | * DJ11 260 | */ 261 | 262 | "dh", 263 | 0, 308, CHAR+INTR+EVEN, 264 | "\tdhin; br5+%d.\n\tdhou; br5+%d.\n", 265 | ".globl\t_dhrint\ndhin:\tjsr\tr0,call; _dhrint\n", 266 | ".globl\t_dhxint\ndhou:\tjsr\tr0,call; _dhxint\n", 267 | "", 268 | "\t&dhopen, &dhclose, &dhread, &dhwrite, &dhsgtty,", 269 | 270 | /* 271 | * GT40 272 | * LPS+ 273 | * VT20 274 | */ 275 | 276 | 0 277 | }; 278 | 279 | char *stra[] 280 | { 281 | "/ low core", 282 | "", 283 | "br4 = 200", 284 | "br5 = 240", 285 | "br6 = 300", 286 | "br7 = 340", 287 | "", 288 | ". = 0^.", 289 | "\tbr\t1f", 290 | "\t4", 291 | "", 292 | "/ trap vectors", 293 | "\ttrap; br7+0.\t\t/ bus error", 294 | "\ttrap; br7+1.\t\t/ illegal instruction", 295 | "\ttrap; br7+2.\t\t/ bpt-trace trap", 296 | "\ttrap; br7+3.\t\t/ iot trap", 297 | "\ttrap; br7+4.\t\t/ power fail", 298 | "\ttrap; br7+5.\t\t/ emulator trap", 299 | "\ttrap; br7+6.\t\t/ system entry", 300 | "", 301 | ". = 40^.", 302 | ".globl\tstart, dump", 303 | "1:\tjmp\tstart", 304 | "\tjmp\tdump", 305 | "", 306 | 0, 307 | }; 308 | 309 | char *strb[] 310 | { 311 | "", 312 | ". = 240^.", 313 | "\ttrap; br7+7.\t\t/ programmed interrupt", 314 | "\ttrap; br7+8.\t\t/ floating point", 315 | "\ttrap; br7+9.\t\t/ segmentation violation", 316 | 0 317 | }; 318 | 319 | char *strc[] 320 | { 321 | "", 322 | "/ floating vectors", 323 | ". = 300^.", 324 | 0, 325 | }; 326 | 327 | char *strd[] 328 | { 329 | "", 330 | "//////////////////////////////////////////////////////", 331 | "/\t\tinterface code to C", 332 | "//////////////////////////////////////////////////////", 333 | "", 334 | ".globl\tcall, trap", 335 | 0 336 | }; 337 | 338 | char *stre[] 339 | { 340 | "/*", 341 | " */", 342 | "", 343 | "int\t(*bdevsw[])()", 344 | "{", 345 | 0, 346 | }; 347 | 348 | char *strf[] 349 | { 350 | "\t0", 351 | "};", 352 | "", 353 | "int\t(*cdevsw[])()", 354 | "{", 355 | 0, 356 | }; 357 | 358 | char *strg[] 359 | { 360 | "\t0", 361 | "};", 362 | "", 363 | "int\trootdev\t{(%d<<8)|0};", 364 | "int\tswapdev\t{(%d<<8)|0};", 365 | "int\tswplo\t4000;\t/* cannot be zero */", 366 | "int\tnswap\t872;", 367 | 0, 368 | }; 369 | 370 | int fout; 371 | int root -1; 372 | 373 | main() 374 | { 375 | register struct tab *p; 376 | register *q; 377 | int i, n, ev, nkl; 378 | int flagf, flagb; 379 | 380 | while(input()); 381 | 382 | /* 383 | * pass1 -- create interrupt vectors 384 | */ 385 | nkl = 0; 386 | flagf = flagb = 1; 387 | fout = creat("l.s", 0666); 388 | puke(stra); 389 | for(p=table; p->name; p++) 390 | if(p->count != 0 && p->key & INTR) { 391 | if(p->address>240 && flagb) { 392 | flagb = 0; 393 | puke(strb); 394 | } 395 | if(p->address >= 300) { 396 | if(flagf) { 397 | ev = 0; 398 | flagf = 0; 399 | puke(strc); 400 | } 401 | if(p->key & EVEN && ev & 07) { 402 | printf("\t.=.+4\n"); 403 | ev =+ 4; 404 | } 405 | ev =+ p->address - 300; 406 | } else 407 | printf("\n. = %d^.\n", p->address); 408 | n = p->count; 409 | if(n < 0) 410 | n = -n; 411 | for(i=0; ikey & KL) { 413 | printf(p->codea, nkl, nkl); 414 | nkl++; 415 | } else 416 | printf(p->codea, i, i); 417 | } 418 | if(flagb) 419 | puke(strb); 420 | puke(strd); 421 | for(p=table; p->name; p++) 422 | if(p->count != 0 && p->key & INTR) 423 | printf("\n%s%s", p->codeb, p->codec); 424 | flush(); 425 | close(fout); 426 | 427 | /* 428 | * pass 2 -- create configuration table 429 | */ 430 | 431 | fout = creat("c.c", 0666); 432 | puke(stre); 433 | for(i=0; q=btab[i]; i++) { 434 | for(p=table; p->name; p++) 435 | if(equal(q, p->name) && 436 | (p->key&BLOCK) && p->count) { 437 | printf("%s\t/* %s */\n", p->coded, q); 438 | if(p->key & ROOT) 439 | root = i; 440 | goto newb; 441 | } 442 | printf("\t&nodev,\t\t&nodev,\t\t&nodev,\t\t0,\t/* %s */\n", q); 443 | newb:; 444 | } 445 | puke(strf); 446 | for(i=0; q=ctab[i]; i++) { 447 | for(p=table; p->name; p++) 448 | if(equal(q, p->name) && 449 | (p->key&CHAR) && p->count) { 450 | printf("%s\t/* %s */\n", p->codee, q); 451 | goto newc; 452 | } 453 | printf("\t&nodev, &nodev, &nodev, &nodev, &nodev,\t/* %s */\n", q); 454 | newc:; 455 | } 456 | puke(strg, root); 457 | flush(); 458 | close(fout); 459 | if(root < 0) 460 | write(2, "no block device given\n", 22); 461 | } 462 | 463 | puke(s, a) 464 | char **s; 465 | { 466 | char *c; 467 | 468 | while(c = *s++) { 469 | printf(c, a); 470 | printf("\n"); 471 | } 472 | } 473 | 474 | input() 475 | { 476 | char line[100]; 477 | register char *p; 478 | register struct tab *q; 479 | register n; 480 | 481 | p = line; 482 | while((n=getchar()) != '\n') { 483 | if(n == 0) 484 | return(0); 485 | if(n == ' ' || n == '\t') 486 | continue; 487 | *p++ = n; 488 | } 489 | *p++ = 0; 490 | n = 0; 491 | p = line; 492 | while(*p>='0' && *p<='9') { 493 | n =* 10; 494 | n =+ *p++ - '0'; 495 | } 496 | if(n == 0) 497 | n = 1; 498 | if(*p == 0) 499 | return(1); 500 | for(q=table; q->name; q++) 501 | if(equal(q->name, p)) { 502 | if(root < 0 && (q->key&BLOCK)) { 503 | root = 0; 504 | q->key =| ROOT; 505 | } 506 | if(q->count < 0) { 507 | printf("%s: no more, no less\n", p); 508 | return(1); 509 | } 510 | q->count =+ n; 511 | if(q->address < 300 && q->count > 1) { 512 | q->count = 1; 513 | printf("%s: only one\n", p); 514 | } 515 | return(1); 516 | } 517 | if(equal(p, "done")) 518 | return(0); 519 | printf("%s: cannot find\n", p); 520 | return(1); 521 | } 522 | 523 | equal(a, b) 524 | char *a, *b; 525 | { 526 | 527 | while(*a++ == *b) 528 | if(*b++ == 0) 529 | return(1); 530 | return(0); 531 | } 532 | 533 | getchar() 534 | { 535 | int c; 536 | 537 | c = 0; 538 | read(0, &c, 1); 539 | return(c); 540 | } 541 | -------------------------------------------------------------------------------- /conf/sysfix.c: -------------------------------------------------------------------------------- 1 | /* 2 | * fix system image for I/D space 3 | * Move data down to 0; move text to 4K. 4 | * Also put the data at the start of the 5 | * file and the text after it. 6 | */ 7 | 8 | int tbuf[259]; 9 | int rbuf[259]; 10 | int obuf[259]; 11 | int txtsiz; 12 | int datsiz; 13 | int bsssiz; 14 | int symsiz; 15 | 16 | int txtrel 8192; 17 | int datrel; 18 | 19 | 20 | main(argc, argv) 21 | char **argv; 22 | { 23 | register word, rel, s; 24 | 25 | if (argc<3) { 26 | printf("Arg count\n"); 27 | exit(1); 28 | } 29 | if ((tbuf[0] = open(argv[1], 0)) < 0) { 30 | printf("Input file\n"); 31 | exit(1); 32 | } 33 | rbuf[0] = open(argv[1], 0); 34 | if ((fcreat(argv[2], obuf)) < 0) { 35 | printf("Output file\n"); 36 | exit(1); 37 | } 38 | if (getw(tbuf) != 0407) { 39 | printf("Bad input format\n"); 40 | exit(1); 41 | } 42 | putw(0407, obuf); 43 | txtsiz = getw(tbuf); 44 | datsiz = getw(tbuf); 45 | bsssiz = getw(tbuf); 46 | symsiz = getw(tbuf); 47 | getw(tbuf); 48 | getw(tbuf); 49 | if (getw(tbuf) != 0) { 50 | printf("No relocation bits\n"); 51 | exit(1); 52 | } 53 | putw(txtsiz, obuf); 54 | putw(datsiz, obuf); 55 | putw(bsssiz, obuf); 56 | putw(symsiz, obuf); 57 | putw(0, obuf); 58 | putw(0, obuf); 59 | putw(1, obuf); 60 | datrel = -txtsiz; 61 | /* 62 | * Copy out data first 63 | */ 64 | tbuf[1] = 0; 65 | seek(tbuf[0], 020+txtsiz, 0); 66 | seek(rbuf[0], 020+txtsiz, 0); 67 | seek(rbuf[0], txtsiz, 1); 68 | seek(rbuf[0], datsiz, 1); 69 | s = datsiz >> 1; 70 | while (s--) { 71 | word = getw(tbuf); 72 | rel = getw(rbuf); 73 | if (rel&01) 74 | word =- datrel; 75 | word =+ getrel(rel); 76 | putw(word, obuf); 77 | } 78 | /* 79 | * Now to the text. 80 | */ 81 | rbuf[1] = 0; 82 | tbuf[1] = 0; 83 | seek(rbuf[0], 020+txtsiz, 0); 84 | seek(rbuf[0], datsiz, 1); 85 | seek(tbuf[0], 020, 0); 86 | s = txtsiz >> 1; 87 | while(s--) { 88 | rel = getw(rbuf); 89 | word = getw(tbuf); 90 | if (rel&01) 91 | word =- txtrel; 92 | word =+ getrel(rel); 93 | putw(word, obuf); 94 | } 95 | /* 96 | * The symbol table. 97 | */ 98 | tbuf[1] = 0; 99 | seek(tbuf[0], 020+txtsiz, 0); 100 | seek(tbuf[0], txtsiz, 1); 101 | seek(tbuf[0], datsiz, 1); 102 | seek(tbuf[0], datsiz, 1); 103 | s = symsiz; 104 | while ((s =- 12) >= 0) { 105 | putw(getw(tbuf), obuf); 106 | putw(getw(tbuf), obuf); 107 | putw(getw(tbuf), obuf); 108 | putw(getw(tbuf), obuf); 109 | rel = getw(tbuf); 110 | putw(rel, obuf); 111 | word = getw(tbuf); 112 | switch(rel&07) { 113 | case 2: 114 | word =+ txtrel; 115 | break; 116 | 117 | case 3: 118 | case 4: 119 | word =+ datrel; 120 | } 121 | putw(word, obuf); 122 | } 123 | fflush(obuf); 124 | close(obuf[0]); 125 | exit(0); 126 | } 127 | 128 | getrel(r) 129 | { 130 | switch (r&016) { 131 | 132 | case 02: /* ref to text */ 133 | return(txtrel); 134 | 135 | case 04: /* ref to data */ 136 | case 06: /* ref to bss */ 137 | return(datrel); 138 | 139 | case 0: 140 | return(0); 141 | 142 | default: 143 | printf("Bad relocation %o\n", r); 144 | return(0); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /dmr/cat.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * GP DR11C driver used for C/A/T 7 | */ 8 | 9 | #include "../param.h" 10 | #include "../user.h" 11 | #include "../tty.h" 12 | 13 | #define CATADDR 0167750 14 | #define PCAT 9 15 | #define CATHIWAT 60 16 | #define CATLOWAT 15 17 | 18 | struct { 19 | int catlock; 20 | struct clist oq; 21 | } cat; 22 | 23 | struct { 24 | int catcsr; 25 | int catbuf; 26 | }; 27 | 28 | ctopen(dev) 29 | { 30 | if (cat.catlock==0) { 31 | cat.catlock++; 32 | CATADDR->catcsr =| IENABLE; 33 | } else 34 | u.u_error = ENXIO; 35 | } 36 | 37 | ctclose() 38 | { 39 | cat.catlock = 0; 40 | } 41 | 42 | ctwrite(dev) 43 | { 44 | register c; 45 | extern lbolt; 46 | 47 | while ((c=cpass()) >= 0) { 48 | spl5(); 49 | while (cat.oq.c_cc > CATHIWAT) 50 | sleep(&cat.oq, PCAT); 51 | while (putc(c, &cat.oq) < 0) 52 | sleep(&lbolt, PCAT); 53 | catintr(); 54 | spl0(); 55 | } 56 | } 57 | 58 | catintr() 59 | { 60 | register int c; 61 | 62 | if (CATADDR->catcsr&DONE && (c=getc(&cat.oq))>=0) { 63 | CATADDR->catbuf = c; 64 | if (cat.oq.c_cc==0 || cat.oq.c_cc==CATLOWAT) 65 | wakeup(&cat.oq); 66 | } else { 67 | if (cat.catlock==0) 68 | CATADDR->catcsr = 0; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /dmr/dc.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * DC-11 driver 7 | */ 8 | #include "../param.h" 9 | #include "../conf.h" 10 | #include "../user.h" 11 | #include "../tty.h" 12 | #include "../proc.h" 13 | 14 | /* 15 | * Base address of DC-11's. Minor device i is at 16 | * DCADDR + 10*i. 17 | */ 18 | #define DCADDR 0174000 19 | 20 | /* 21 | * Number of DC's for which table space is allocated. 22 | */ 23 | #define NDC11 14 24 | 25 | /* 26 | * Control bits in device registers 27 | */ 28 | #define CDLEAD 01 29 | #define CARRIER 04 30 | #define SPEED1 010 31 | #define STOP1 0400 32 | #define RQSEND 01 33 | #define PARITY 040 34 | #define ERROR 0100000 35 | #define CTRANS 040000 36 | #define RINGIND 020000 37 | 38 | 39 | struct tty dc11[NDC11]; 40 | 41 | struct dcregs { 42 | int dcrcsr; 43 | int dcrbuf; 44 | int dctcsr; 45 | int dctbuf; 46 | }; 47 | 48 | /* 49 | * Input-side speed and control bit table. 50 | * Each DC11 has 4 speeds which correspond to the 4 non-zero entries. 51 | * The table index is the same as the speed-selector 52 | * number for the DH11. 53 | * Attempts to set the speed to a zero entry are ignored. 54 | */ 55 | int dcrstab[] { 56 | 0, /* 0 baud */ 57 | 0, /* 50 baud */ 58 | 0, /* 75 baud */ 59 | 0, /* 110 baud */ 60 | 01101, /* 134.5 baud: 7b/ch, speed 0 */ 61 | 0111, /* 150 baud: 8b/ch, speed 1 */ 62 | 0, /* 200 baud */ 63 | 0121, /* 300 baud: 8b/ch, speed 2 */ 64 | 0, /* 600 baud */ 65 | 0131, /* 1200 baud */ 66 | 0, /* 1800 baud */ 67 | 0, /* 2400 baud */ 68 | 0, /* 4800 baud */ 69 | 0, /* 9600 baud */ 70 | 0, /* X0 */ 71 | 0, /* X1 */ 72 | }; 73 | 74 | /* 75 | * Transmitter speed table 76 | */ 77 | int dctstab[] { 78 | 0, /* 0 baud */ 79 | 0, /* 50 baud */ 80 | 0, /* 75 baud */ 81 | 0, /* 110 baud */ 82 | 0501, /* 134.5 baud: stop 1 */ 83 | 0511, /* 150 baud */ 84 | 0, /* 200 baud */ 85 | 0521, /* 300 baud */ 86 | 0, /* 600 baud */ 87 | 0531, /* 1200 baud */ 88 | 0, /* 1800 baud */ 89 | 0, /* 2400 baud */ 90 | 0, /* 4800 baud */ 91 | 0, /* 9600 baud */ 92 | 0, /* X0 */ 93 | 0, /* X1 */ 94 | }; 95 | 96 | /* 97 | * Open a DC11, waiting until carrier is established. 98 | * Default initial conditions are set up on the first open. 99 | * t_state's CARR_ON bit is a pure copy of the hardware 100 | * CARRIER bit, and is only used to regularize 101 | * carrier tests in general tty routines. 102 | */ 103 | dcopen(dev, flag) 104 | { 105 | register struct tty *rtp; 106 | register *addr; 107 | 108 | if (dev.d_minor >= NDC11) { 109 | u.u_error = ENXIO; 110 | return; 111 | } 112 | rtp = &dc11[dev.d_minor]; 113 | rtp->t_addr = addr = DCADDR + dev.d_minor*8; 114 | rtp->t_state =| WOPEN; 115 | addr->dcrcsr =| IENABLE|CDLEAD; 116 | if ((rtp->t_state&ISOPEN) == 0) { 117 | rtp->t_erase = CERASE; 118 | rtp->t_kill = CKILL; 119 | addr->dcrcsr = IENABLE|CDLEAD|SPEED1; 120 | addr->dctcsr = IENABLE|SPEED1|STOP1|RQSEND; 121 | rtp->t_state = ISOPEN | WOPEN; 122 | rtp->t_flags = ODDP|EVENP|ECHO; 123 | } 124 | if (addr->dcrcsr & CARRIER) 125 | rtp->t_state =| CARR_ON; 126 | while ((rtp->t_state & CARR_ON) == 0) 127 | sleep(&rtp->t_rawq, TTIPRI); 128 | rtp->t_state =& ~WOPEN; 129 | if (u.u_procp->p_ttyp == 0) { 130 | u.u_procp->p_ttyp = rtp; 131 | rtp->t_dev = dev; 132 | } 133 | } 134 | 135 | /* 136 | * Close a dc11 137 | */ 138 | dcclose(dev) 139 | { 140 | register struct tty *tp; 141 | 142 | (tp = &dc11[dev.d_minor])->t_state = 0; 143 | if (tp->t_flags&HUPCL) 144 | tp->t_addr->dcrcsr =& ~CDLEAD; 145 | wflushtty(tp); 146 | } 147 | 148 | /* 149 | * Read a DC11 150 | */ 151 | dcread(dev) 152 | { 153 | ttread(&dc11[dev.d_minor]); 154 | } 155 | 156 | /* 157 | * Write a DC11 158 | */ 159 | dcwrite(dev) 160 | { 161 | ttwrite(&dc11[dev.d_minor]); 162 | } 163 | 164 | /* 165 | * DC11 transmitter interrupt. 166 | */ 167 | dcxint(dev) 168 | { 169 | register struct tty *tp; 170 | 171 | ttstart(tp = &dc11[dev.d_minor]); 172 | if (tp->t_outq.c_cc == 0 || tp->t_outq.c_cc == TTLOWAT) 173 | wakeup(&tp->t_outq); 174 | } 175 | 176 | /* 177 | * DC11 receiver interrupt. 178 | */ 179 | dcrint(dev) 180 | { 181 | register struct tty *tp; 182 | register int c, csr; 183 | 184 | tp = &dc11[dev.d_minor]; 185 | c = tp->t_addr->dcrbuf; 186 | /* 187 | * If carrier is off, and an open is not in progress, 188 | * knock down the CD lead to hang up the local dataset 189 | * and signal a hangup. 190 | */ 191 | if (((csr = tp->t_addr->dcrcsr) & CARRIER) == 0) { 192 | if ((tp->t_state&WOPEN) == 0) { 193 | tp->t_addr->dcrcsr =& ~CDLEAD; 194 | if (tp->t_state & CARR_ON) 195 | signal(tp, SIGHUP); 196 | flushtty(tp); 197 | } 198 | tp->t_state =& ~CARR_ON; 199 | return; 200 | } 201 | if (csr&ERROR || (tp->t_state&ISOPEN)==0) { 202 | if (tp->t_state&WOPEN && csr&CARRIER) 203 | tp->t_state =| CARR_ON; 204 | wakeup(tp); 205 | return; 206 | } 207 | csr =& PARITY; 208 | if (csr&&(tp->t_flags&ODDP) || !csr&&(tp->t_flags&EVENP)) 209 | ttyinput(c, tp); 210 | } 211 | 212 | /* 213 | * DC11 stty/gtty. 214 | * Perform general functions and set speeds. 215 | */ 216 | dcsgtty(dev, av) 217 | int *av; 218 | { 219 | register struct tty *tp; 220 | register r; 221 | 222 | tp = &dc11[dev.d_minor]; 223 | if (ttystty(tp, av)) 224 | return; 225 | if (r = dcrstab[tp->t_speeds.lobyte&017]) 226 | tp->t_addr->dcrcsr = r; 227 | else 228 | tp->t_addr->dcrcsr =& ~CDLEAD; 229 | if (r = dctstab[tp->t_speeds.hibyte&017]) 230 | tp->t_addr->dctcsr = r; 231 | } 232 | -------------------------------------------------------------------------------- /dmr/dh.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * DH-11 driver 7 | * This driver calls on the DHDM driver. 8 | * If the DH has no DM11-BB, then the latter will 9 | * be fake. To insure loading of the correct DM code, 10 | * lib2 should have dhdm.o, dh.o and dhfdm.o in that order. 11 | */ 12 | 13 | #include "../param.h" 14 | #include "../conf.h" 15 | #include "../user.h" 16 | #include "../tty.h" 17 | #include "../proc.h" 18 | 19 | #define DHADDR 0160020 20 | #define NDH11 16 /* number of lines */ 21 | #define DHNCH 8 /* max number of DMA chars */ 22 | 23 | struct tty dh11[NDH11]; 24 | /* 25 | * Place from which to do DMA on output 26 | */ 27 | char dh_clist[NDH11][DHNCH]; 28 | 29 | /* 30 | * Used to communicate the number of lines to the DM 31 | */ 32 | int ndh11 NDH11; 33 | 34 | /* 35 | * Hardware control bits 36 | */ 37 | #define BITS6 01 38 | #define BITS7 02 39 | #define BITS8 03 40 | #define TWOSB 04 41 | #define PENABLE 020 42 | /* DEC manuals incorrectly say this bit causes generation of even parity. */ 43 | #define OPAR 040 44 | #define HDUPLX 040000 45 | 46 | #define IENABLE 030100 47 | #define PERROR 010000 48 | #define FRERROR 020000 49 | #define XINT 0100000 50 | #define SSPEED 7 /* standard speed: 300 baud */ 51 | 52 | /* 53 | * Software copy of last dhbar 54 | */ 55 | int dhsar; 56 | 57 | struct dhregs { 58 | int dhcsr; 59 | int dhnxch; 60 | int dhlpr; 61 | int dhcar; 62 | int dhbcr; 63 | int dhbar; 64 | int dhbreak; 65 | int dhsilo; 66 | }; 67 | 68 | /* 69 | * Open a DH11 line. 70 | */ 71 | dhopen(dev, flag) 72 | { 73 | register struct tty *tp; 74 | extern dhstart(); 75 | 76 | if (dev.d_minor >= NDH11) { 77 | u.u_error = ENXIO; 78 | return; 79 | } 80 | tp = &dh11[dev.d_minor]; 81 | tp->t_addr = dhstart; 82 | tp->t_dev = dev; 83 | DHADDR->dhcsr =| IENABLE; 84 | tp->t_state =| WOPEN|SSTART; 85 | if ((tp->t_state&ISOPEN) == 0) { 86 | tp->t_erase = CERASE; 87 | tp->t_kill = CKILL; 88 | tp->t_speeds = SSPEED | (SSPEED<<8); 89 | tp->t_flags = ODDP|EVENP|ECHO; 90 | dhparam(tp); 91 | } 92 | dmopen(dev); 93 | tp->t_state =& ~WOPEN; 94 | tp->t_state =| ISOPEN; 95 | if (u.u_procp->p_ttyp == 0) 96 | u.u_procp->p_ttyp = tp; 97 | } 98 | 99 | /* 100 | * Close a DH11 line. 101 | */ 102 | dhclose(dev) 103 | { 104 | register struct tty *tp; 105 | 106 | tp = &dh11[dev.d_minor]; 107 | dmclose(dev); 108 | tp->t_state =& (CARR_ON|SSTART); 109 | wflushtty(tp); 110 | } 111 | 112 | /* 113 | * Read from a DH11 line. 114 | */ 115 | dhread(dev) 116 | { 117 | ttread(&dh11[dev.d_minor]); 118 | } 119 | 120 | /* 121 | * write on a DH11 line 122 | */ 123 | dhwrite(dev) 124 | { 125 | ttwrite(&dh11[dev.d_minor]); 126 | } 127 | 128 | /* 129 | * DH11 receiver interrupt. 130 | */ 131 | dhrint() 132 | { 133 | register struct tty *tp; 134 | register int c; 135 | 136 | while ((c = DHADDR->dhnxch) < 0) { /* char. present */ 137 | tp = &dh11[(c>>8)&017]; 138 | if (tp >= &dh11[NDH11]) 139 | continue; 140 | if((tp->t_state&ISOPEN)==0 || (c&PERROR)) { 141 | wakeup(tp); 142 | continue; 143 | } 144 | if (c&FRERROR) /* break */ 145 | if (tp->t_flags&RAW) 146 | c = 0; /* null (for getty) */ 147 | else 148 | c = 0177; /* DEL (intr) */ 149 | ttyinput(c, tp); 150 | } 151 | } 152 | 153 | /* 154 | * stty/gtty for DH11 155 | */ 156 | dhsgtty(dev, av) 157 | int *av; 158 | { 159 | register struct tty *tp; 160 | register r; 161 | 162 | tp = &dh11[dev.d_minor]; 163 | if (ttystty(tp, av)) 164 | return; 165 | dhparam(tp); 166 | } 167 | 168 | /* 169 | * Set parameters from open or stty into the DH hardware 170 | * registers. 171 | */ 172 | dhparam(atp) 173 | struct tty *atp; 174 | { 175 | register struct tty *tp; 176 | register int lpr; 177 | 178 | tp = atp; 179 | spl5(); 180 | DHADDR->dhcsr.lobyte = tp->t_dev.d_minor | IENABLE; 181 | /* 182 | * Hang up line? 183 | */ 184 | if (tp->t_speeds.lobyte==0) { 185 | tp->t_flags =| HUPCL; 186 | dmclose(tp->t_dev); 187 | return; 188 | } 189 | lpr = (tp->t_speeds.hibyte<<10) | (tp->t_speeds.lobyte<<6); 190 | if (tp->t_speeds.lobyte == 4) /* 134.5 baud */ 191 | lpr =| BITS6|PENABLE|HDUPLX; else 192 | if (tp->t_flags&EVENP) 193 | if (tp->t_flags&ODDP) 194 | lpr =| BITS8; else 195 | lpr =| BITS7|PENABLE; else 196 | lpr =| BITS7|OPAR|PENABLE; 197 | if (tp->t_speeds.lobyte == 3) /* 110 baud */ 198 | lpr =| TWOSB; 199 | DHADDR->dhlpr = lpr; 200 | spl0(); 201 | } 202 | 203 | /* 204 | * DH11 transmitter interrupt. 205 | * Restart each line which used to be active but has 206 | * terminated transmission since the last interrupt. 207 | */ 208 | dhxint() 209 | { 210 | register struct tty *tp; 211 | register ttybit, bar; 212 | 213 | bar = dhsar & ~DHADDR->dhbar; 214 | DHADDR->dhcsr =& ~XINT; 215 | ttybit = 1; 216 | for (tp = dh11; bar; tp++) { 217 | if(bar&ttybit) { 218 | dhsar =& ~ttybit; 219 | bar =& ~ttybit; 220 | tp->t_state =& ~BUSY; 221 | dhstart(tp); 222 | } 223 | ttybit =<< 1; 224 | } 225 | } 226 | 227 | /* 228 | * Start (restart) transmission on the given DH11 line. 229 | */ 230 | dhstart(atp) 231 | struct tty *atp; 232 | { 233 | extern ttrstrt(); 234 | register c, nch; 235 | register struct tty *tp; 236 | int sps; 237 | char *cp; 238 | 239 | sps = PS->integ; 240 | spl5(); 241 | tp = atp; 242 | /* 243 | * If it's currently active, or delaying, 244 | * no need to do anything. 245 | */ 246 | if (tp->t_state&(TIMEOUT|BUSY)) 247 | goto out; 248 | /* 249 | * t_char is a delay indicator which may have been 250 | * left over from the last start. 251 | * Arrange for the delay. 252 | */ 253 | if (c = tp->t_char) { 254 | tp->t_char = 0; 255 | timeout(ttrstrt, tp, (c&0177)+6); 256 | tp->t_state =| TIMEOUT; 257 | goto out; 258 | } 259 | cp = dh_clist[tp->t_dev.d_minor]; 260 | nch = 0; 261 | /* 262 | * Copy DHNCH characters, or up to a delay indicator, 263 | * to the DMA area. 264 | */ 265 | while (nch > -DHNCH && (c = getc(&tp->t_outq))>=0) { 266 | if (c >= 0200) { 267 | tp->t_char = c; 268 | break; 269 | } 270 | *cp++ = c; 271 | nch--; 272 | } 273 | /* 274 | * If the writer was sleeping on output overflow, 275 | * wake him when low tide is reached. 276 | */ 277 | if (tp->t_outq.c_cc<=TTLOWAT && tp->t_state&ASLEEP) { 278 | tp->t_state =& ~ASLEEP; 279 | wakeup(&tp->t_outq); 280 | } 281 | /* 282 | * If any characters were set up, start transmission; 283 | * otherwise, check for possible delay. 284 | */ 285 | if (nch) { 286 | DHADDR->dhcsr.lobyte = tp->t_dev.d_minor | IENABLE; 287 | DHADDR->dhcar = cp+nch; 288 | DHADDR->dhbcr = nch; 289 | c = 1<t_dev.d_minor; 290 | DHADDR->dhbar =| c; 291 | dhsar =| c; 292 | tp->t_state =| BUSY; 293 | } else if (c = tp->t_char) { 294 | tp->t_char = 0; 295 | timeout(ttrstrt, tp, (c&0177)+6); 296 | tp->t_state =| TIMEOUT; 297 | } 298 | out: 299 | PS->integ = sps; 300 | } 301 | -------------------------------------------------------------------------------- /dmr/dhdm.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * DM-BB driver 7 | */ 8 | #include "../param.h" 9 | #include "../tty.h" 10 | #include "../conf.h" 11 | 12 | #define DMADDR 0170500 13 | 14 | struct tty dh11[]; 15 | int ndh11; /* Set by dh.c to number of lines */ 16 | 17 | #define DONE 0200 18 | #define SCENABL 040 19 | #define CLSCAN 01000 20 | #define TURNON 07 /* RQ send, CD lead, line enable */ 21 | #define TURNOFF 1 /* line enable only */ 22 | #define CARRIER 0100 23 | 24 | struct dmregs { 25 | int dmcsr; 26 | int dmlstat; 27 | }; 28 | 29 | /* 30 | * Turn on the line associated with the (DH) device dev. 31 | */ 32 | dmopen(dev) 33 | { 34 | register struct tty *tp; 35 | 36 | tp = &dh11[dev.d_minor]; 37 | DMADDR->dmcsr = dev.d_minor; 38 | DMADDR->dmlstat = TURNON; 39 | if (DMADDR->dmlstat&CARRIER) 40 | tp->t_state =| CARR_ON; 41 | DMADDR->dmcsr = IENABLE|SCENABL; 42 | spl5(); 43 | while ((tp->t_state&CARR_ON)==0) 44 | sleep(&tp->t_rawq, TTIPRI); 45 | spl0(); 46 | } 47 | 48 | /* 49 | * If a DH line has the HUPCL mode, 50 | * turn off carrier when it is closed. 51 | */ 52 | dmclose(dev) 53 | { 54 | register struct tty *tp; 55 | 56 | tp = &dh11[dev.d_minor]; 57 | if (tp->t_flags&HUPCL) { 58 | DMADDR->dmcsr = dev.d_minor; 59 | DMADDR->dmlstat = TURNOFF; 60 | DMADDR->dmcsr = IENABLE|SCENABL; 61 | } 62 | } 63 | 64 | /* 65 | * DM11 interrupt. 66 | * Mainly, deal with carrier transitions. 67 | */ 68 | dmint() 69 | { 70 | register struct tty *tp; 71 | 72 | if (DMADDR->dmcsr&DONE) { 73 | tp = &dh11[DMADDR->dmcsr&017]; 74 | if (tp < &dh11[ndh11]) { 75 | wakeup(tp); 76 | if ((DMADDR->dmlstat&CARRIER)==0) { 77 | if ((tp->t_state&WOPEN)==0) { 78 | signal(tp, SIGHUP); 79 | DMADDR->dmlstat = 0; 80 | flushtty(tp); 81 | } 82 | tp->t_state =& ~CARR_ON; 83 | } else 84 | tp->t_state =| CARR_ON; 85 | } 86 | DMADDR->dmcsr = IENABLE|SCENABL; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /dmr/dhfdm.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * DM-BB fake driver 7 | */ 8 | #include "../tty.h" 9 | #include "../conf.h" 10 | 11 | struct tty dh11[]; 12 | 13 | dmopen(dev) 14 | { 15 | register struct tty *tp; 16 | 17 | tp = &dh11[dev.d_minor]; 18 | tp->t_state =| CARR_ON; 19 | } 20 | 21 | dmclose(dev) 22 | { 23 | } 24 | -------------------------------------------------------------------------------- /dmr/dn.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * DN-11 ACU interface 7 | */ 8 | 9 | #include "../param.h" 10 | #include "../conf.h" 11 | #include "../user.h" 12 | 13 | struct dn { 14 | struct { 15 | char dn_stat; 16 | char dn_reg; 17 | } dn11[3]; 18 | } 19 | 20 | #define DNADDR 0175200 21 | 22 | #define PWI 00200 23 | #define ACR 00100 24 | #define DLO 0020 25 | #define DONE 0200 26 | #define IENABLE 0100 27 | #define DSS 040 28 | #define PND 020 29 | #define MENABLE 04 30 | #define DPR 02 31 | #define CRQ 01 32 | 33 | #define DNPRI 5 34 | 35 | dnopen(dev, flag) 36 | { 37 | register struct dn *dp; 38 | register int rdev; 39 | 40 | rdev = dev.d_minor; 41 | dp = &DNADDR->dn11[rdev]; 42 | if (dp->dn_reg&(PWI|DLO)) 43 | u.u_error = ENXIO; 44 | else { 45 | DNADDR->dn11[0].dn_stat =| MENABLE; 46 | dp->dn_stat = IENABLE|MENABLE|CRQ; 47 | } 48 | } 49 | 50 | dnclose(dev) 51 | { 52 | DNADDR->dn11[dev.d_minor].dn_stat =& MENABLE; 53 | } 54 | 55 | dnwrite(dev) 56 | { 57 | register struct dn *dp; 58 | register c; 59 | extern lbolt; 60 | 61 | dp = &DNADDR->dn11[dev.d_minor]; 62 | for(;;) { 63 | while ((dp->dn_stat&DONE)==0) 64 | sleep(DNADDR, DNPRI); 65 | dp->dn_stat =& ~DONE; 66 | contin: 67 | if (dp->dn_reg&(PWI|ACR)) { 68 | u.u_error = EIO; 69 | return; 70 | } 71 | if (dp->dn_stat&DSS) 72 | return; 73 | c = 0; 74 | if (u.u_count==0 || (dp->dn_stat&PND)==0 || (c=cpass())<0) 75 | continue; 76 | if (c=='-') { 77 | sleep(&lbolt, DNPRI); 78 | sleep(&lbolt, DNPRI); 79 | goto contin; 80 | } 81 | dp->dn_reg = c-'0'; 82 | dp->dn_stat =| DPR; 83 | } 84 | } 85 | 86 | dnint(dev) 87 | { 88 | wakeup(DNADDR); 89 | } 90 | -------------------------------------------------------------------------------- /dmr/dp.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * DP-11 Synchronous interface driver 7 | * This driver is rather insensitive to the remote 8 | * device it talks to, which is to say most of the protocol 9 | * must be supplied by the calling program. 10 | * Exceptions: parity is even; 7 data bits per character; 11 | * max. of 512 characters per record; 10 second timeout 12 | * on waiting to receive; half-duplex transmission. 13 | */ 14 | 15 | #include "../param.h" 16 | #include "../conf.h" 17 | #include "../user.h" 18 | #include "../buf.h" 19 | 20 | /* control info */ 21 | struct { 22 | char *dp_buf; 23 | char *dp_bufp; 24 | int dp_nxmit; 25 | char dp_state; 26 | char dp_timer; 27 | int dp_proc; 28 | } dp11; 29 | 30 | /* device registers */ 31 | struct { 32 | int dprcsr; 33 | char dprbuf; 34 | char dpsyn0; 35 | int dptcsr; 36 | char dptbuf; 37 | char dpsyn1; 38 | }; 39 | 40 | /* bits */ 41 | #define ODDPAR 010000 42 | #define IENABLE 0100 43 | #define HDUPLX 02 44 | 45 | #define CTRANS 0100000 46 | #define RORUN 040000 47 | #define RING 020000 48 | #define DSRDY 010000 49 | #define CARRIER 04000 50 | #define DONE 0200 51 | #define IENABLE 0100 52 | #define SIENABL 040 53 | 54 | #define WRITE 1 55 | #define READ 0 56 | 57 | #define DTRDY 01 58 | #define RCVACT 04000 59 | 60 | #define DPADDR 0174770 61 | #define DPPRI 5 62 | #define SYN 026 /* (receive) sync character */ 63 | 64 | /* 65 | * The open fails unless the device is not open or 66 | * the opening process is the one that has it open already. 67 | */ 68 | dpopen(dev, flag) 69 | { 70 | int dptimeout(); 71 | 72 | if (dp11.dp_proc!=0 && dp11.dp_proc!=u.u_procp) { 73 | u.u_error = ENXIO; 74 | return; 75 | } 76 | dp11.dp_proc = u.u_procp; 77 | dp11.dp_state = READ; 78 | if (dp11.dp_buf==0) { 79 | dp11.dp_buf = getblk(NODEV); 80 | dp11.dp_bufp = dp11.dp_buf->b_addr; 81 | dp11.dp_timer = HZ; 82 | timeout(dptimeout, 0, HZ); 83 | } 84 | DPADDR->dpsyn0 = SYN; 85 | DPADDR->dprcsr = HDUPLX|IENABLE; 86 | DPADDR->dptcsr = IENABLE|SIENABL|DTRDY; 87 | } 88 | 89 | dpclose() 90 | { 91 | DPADDR->dprcsr = 0; 92 | DPADDR->dptcsr = 0; 93 | dp11.dp_timer = 0; 94 | dp11.dp_proc = 0; 95 | if (dp11.dp_buf != 0) { 96 | brelse(dp11.dp_buf); 97 | dp11.dp_buf = 0; 98 | } 99 | } 100 | 101 | /* 102 | * Read waits until: 103 | * there is loss of "data set ready", or 104 | * a timeout occurs, or 105 | * a full record has been received. 106 | * The former two result in an error. 107 | */ 108 | dpread() 109 | { 110 | register char *bp, **epp; 111 | 112 | bp = dp11.dp_buf->b_addr; 113 | epp = &dp11.dp_bufp; 114 | for(;;) { 115 | if(dpwait()) 116 | return; 117 | if (*epp > bp) 118 | break; 119 | spl6(); 120 | if (dp11.dp_timer <= 1) { 121 | spl0(); 122 | return; 123 | } 124 | sleep(&dp11, DPPRI); 125 | spl0(); 126 | } 127 | iomove(dp11.dp_buf, 0, min(u.u_count, *epp-bp), B_READ); 128 | } 129 | 130 | /* 131 | * write checks to make sure that the data set is not reading, 132 | * and that it is ready. Then the record is copied 133 | * and transmission started. 134 | */ 135 | dpwrite() 136 | { 137 | register char *bp; 138 | 139 | if (u.u_count==0 || dpwait()) 140 | return; 141 | dp11.dp_state = WRITE; 142 | bp = dp11.dp_buf->b_addr; 143 | dp11.dp_bufp = bp; 144 | if (u.u_count>512) 145 | u.u_count = 512; 146 | dp11.dp_nxmit = u.u_count; 147 | iomove(dp11.dp_buf, 0, u.u_count, B_WRITE); 148 | dpstart(); 149 | } 150 | 151 | /* 152 | * If "data set ready" is down return an error; otherwise 153 | * wait until the dataset is in read state with no carrier, 154 | * which means a record has just been received. 155 | */ 156 | dpwait() 157 | { 158 | for(;;) { 159 | if ((DPADDR->dptcsr&DSRDY)==0 || dp11.dp_buf==0) { 160 | u.u_error = EIO; 161 | return(1); 162 | } 163 | spl6(); 164 | if (dp11.dp_state==READ && (DPADDR->dptcsr&CARRIER)==0) { 165 | spl0(); 166 | return(0); 167 | } 168 | sleep(&dp11, DPPRI); 169 | spl0(); 170 | } 171 | } 172 | 173 | /* 174 | * Start off the next character to be transmitted; 175 | * when the record is done, drop back into read state. 176 | */ 177 | dpstart() 178 | { 179 | register int c; 180 | extern char partab[]; 181 | 182 | dp11.dp_timer = 10; 183 | if (--dp11.dp_nxmit >= 0) { 184 | c = (*dp11.dp_bufp++) & 0177; 185 | DPADDR->dptbuf = c | ~partab[c]&0200; 186 | } else { 187 | dp11.dp_bufp = dp11.dp_buf->b_addr; 188 | dp11.dp_state = READ; 189 | } 190 | } 191 | 192 | /* 193 | * Count down the DP timer (once per second) 194 | * If it runs out, it presumably means the other station 195 | * won't speak. 196 | */ 197 | dptimeout() 198 | { 199 | if (dp11.dp_timer==0) 200 | return; 201 | if (--dp11.dp_timer==0) { 202 | dpturnaround(); 203 | dp11.dp_timer = 1; 204 | } 205 | timeout(dptimeout, 0, HZ); 206 | } 207 | 208 | /* 209 | * Receiver interrupt: if reading, stash character 210 | * unless there is an overrun. 211 | */ 212 | dprint() 213 | { 214 | register int c; 215 | 216 | c = DPADDR->dprbuf & 0177; 217 | if (dp11.dp_state==READ) { 218 | if ((DPADDR->dprcsr&ODDPAR) == 0) 219 | c =| 0200; 220 | if (dp11.dp_bufp < dp11.dp_buf->b_addr+512) 221 | *dp11.dp_bufp++ = c; 222 | } 223 | } 224 | 225 | /* 226 | * Transmitter interrupt: 227 | * Knock down hardware bits. 228 | * If carrier has dropped, the record is done, so turn the line around; 229 | * otherwise start another character. 230 | */ 231 | dpxint() 232 | { 233 | register int dpstat; 234 | 235 | dpstat = DPADDR->dptcsr; 236 | DPADDR->dptcsr =& ~(CTRANS|RORUN|RING|DONE); 237 | if (dpstat & (CTRANS|RORUN)) 238 | dpturnaround(); 239 | else if (dpstat&DONE && dp11.dp_state==WRITE) 240 | dpstart(); 241 | } 242 | 243 | /* 244 | * Change the state from writing to reading at the end of a record. 245 | */ 246 | dpturnaround() 247 | { 248 | DPADDR->dprcsr =& ~RCVACT; 249 | if (dp11.dp_state==WRITE) { 250 | dp11.dp_timer = 10; 251 | dp11.dp_state = READ; 252 | dp11.dp_bufp = dp11.dp_buf->b_addr; 253 | } 254 | wakeup(&dp11); 255 | } 256 | -------------------------------------------------------------------------------- /dmr/hp.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * RP04 disk driver 7 | * 8 | * This driver has been tested on a working RP04 for a few hours. 9 | * It does not attempt ECC error correction and is probably 10 | * deficient in general in the case of errors and when packs 11 | * are dismounted. 12 | */ 13 | 14 | #include "../param.h" 15 | #include "../buf.h" 16 | #include "../conf.h" 17 | #include "../user.h" 18 | 19 | struct { 20 | int hpcs1; /* Control and Status register 1 */ 21 | int hpwc; /* Word count register */ 22 | int hpba; /* UNIBUS address register */ 23 | int hpda; /* Desired address register */ 24 | int hpcs2; /* Control and Status register 2*/ 25 | int hpds; /* Drive Status */ 26 | int hper1; /* Error register 1 */ 27 | int hpas; /* Attention Summary */ 28 | int hpla; /* Look ahead */ 29 | int hpdb; /* Data buffer */ 30 | int hpmr; /* Maintenance register */ 31 | int hpdt; /* Drive type */ 32 | int hpsn; /* Serial number */ 33 | int hpof; /* Offset register */ 34 | int hpca; /* Desired Cylinder address register*/ 35 | int hpcc; /* Current Cylinder */ 36 | int hper2; /* Error register 2 */ 37 | int hper3; /* Error register 3 */ 38 | int hppos; /* Burst error bit position */ 39 | int hppat; /* Burst error bit pattern */ 40 | int hpbae; /* 11/70 bus extension */ 41 | }; 42 | 43 | #define HPADDR 0176700 44 | #define NHP 8 45 | 46 | struct { 47 | char *nblocks; 48 | int cyloff; 49 | } hp_sizes[] { 50 | 9614, 0, /* cyl 0 thru 23 */ 51 | /* cyl 24 thru 43 available */ 52 | -1, 44, /* cyl 44 thru 200 */ 53 | -1, 201, /* cyl 201 thru 357 */ 54 | 20900, 358, /* cyl 358 thru 407 */ 55 | /* cyl 408 thru 410 blank */ 56 | 40600, 0, 57 | 40600, 100, 58 | 40600, 200, 59 | 40600, 300, 60 | }; 61 | 62 | 63 | struct devtab hptab; 64 | struct buf hpbuf; 65 | 66 | char hp_openf; 67 | 68 | /* Drive Commands */ 69 | #define GO 01 70 | #define PRESET 020 71 | #define RECAL 06 72 | #define RCLR 010 73 | #define OFFSET 014 74 | 75 | #define READY 0200 /* hpds - drive ready */ 76 | #define PIP 020000 /* hpds - Positioning Operation in Progress */ 77 | #define ERR 040000 /* hpcs1 - composite error */ 78 | 79 | #define DU 040000 /* hper1 - Drive Unsafe */ 80 | #define DTE 010000 /* hper1 - Drive Timing Error */ 81 | #define OPI 020000 /* hper1 - Operation Incomplete */ 82 | /* Error Correction Code errors */ 83 | #define DCK 0100000 /* hper1 - Data Check error */ 84 | #define ECH 0100 /* hper1 - ECC hard error */ 85 | 86 | #define CLR 040 /* hpcs2 - Controller Clear */ 87 | 88 | #define FMT22 010000 /* hpof - 16 bit /word format */ 89 | /* 90 | * Use av_back to save track+sector, 91 | * b_resid for cylinder. 92 | */ 93 | 94 | #define trksec av_back 95 | #define cylin b_resid 96 | 97 | hpopen() 98 | { 99 | 100 | if(!hp_openf){ 101 | hp_openf++; 102 | HPADDR->hpcs2 = CLR; 103 | HPADDR->hpcs1 = RCLR|GO; 104 | HPADDR->hpcs1 = PRESET|GO; 105 | HPADDR->hpof = FMT22; 106 | } 107 | } 108 | 109 | hpstrategy(abp) 110 | struct buf *abp; 111 | { 112 | register struct buf *bp; 113 | register char *p1, *p2; 114 | 115 | bp = abp; 116 | p1 = &hp_sizes[bp->b_dev.d_minor&07]; 117 | if (bp->b_dev.d_minor >= (NHP<<3) || 118 | bp->b_blkno >= p1->nblocks) { 119 | bp->b_flags =| B_ERROR; 120 | iodone(bp); 121 | return; 122 | } 123 | bp->av_forw = 0; 124 | bp->cylin = p1->cyloff; 125 | p1 = bp->b_blkno; 126 | p2 = lrem(p1, 22); 127 | p1 = ldiv(p1, 22); 128 | bp->trksec = (p1%19)<<8 | p2; 129 | bp->cylin =+ p1/19; 130 | spl5(); 131 | if ((p1 = hptab.d_actf)==0) 132 | hptab.d_actf = bp; 133 | else { 134 | for (; p2 = p1->av_forw; p1 = p2) { 135 | if (p1->cylin <= bp->cylin 136 | && bp->cylin < p2->cylin 137 | || p1->cylin >= bp->cylin 138 | && bp->cylin > p2->cylin) 139 | break; 140 | } 141 | bp->av_forw = p2; 142 | p1->av_forw = bp; 143 | } 144 | if (hptab.d_active==0) 145 | hpstart(); 146 | spl0(); 147 | } 148 | 149 | hpstart() 150 | { 151 | register struct buf *bp; 152 | 153 | if ((bp = hptab.d_actf) == 0) 154 | return; 155 | hptab.d_active++; 156 | HPADDR->hpcs2 = bp->b_dev.d_minor >> 3; 157 | HPADDR->hpca = bp->cylin; 158 | rhstart(bp, &HPADDR->hpda, bp->trksec, &HPADDR->hpbae); 159 | } 160 | 161 | hpintr() 162 | { 163 | register struct buf *bp; 164 | register int ctr; 165 | 166 | if (hptab.d_active == 0) 167 | return; 168 | bp = hptab.d_actf; 169 | hptab.d_active = 0; 170 | if (HPADDR->hpcs1 & ERR) { /* error bit */ 171 | deverror(bp, HPADDR->hpcs2, 0); 172 | if(HPADDR->hper1 & (DU|DTE|OPI)) { 173 | HPADDR->hpcs2 = CLR; 174 | HPADDR->hpcs1 = RECAL|GO; 175 | ctr = 0; 176 | while ((HPADDR->hpds&PIP) && --ctr); 177 | } 178 | HPADDR->hpcs1 = RCLR|GO; 179 | if (++hptab.d_errcnt <= 10) { 180 | hpstart(); 181 | return; 182 | } 183 | bp->b_flags =| B_ERROR; 184 | } 185 | hptab.d_errcnt = 0; 186 | hptab.d_actf = bp->av_forw; 187 | bp->b_resid = HPADDR->hpwc; 188 | iodone(bp); 189 | hpstart(); 190 | } 191 | 192 | hpread(dev) 193 | { 194 | 195 | if(hpphys(dev)) 196 | physio(hpstrategy, &hpbuf, dev, B_READ); 197 | } 198 | 199 | hpwrite(dev) 200 | { 201 | 202 | if(hpphys(dev)) 203 | physio(hpstrategy, &hpbuf, dev, B_WRITE); 204 | } 205 | 206 | hpphys(dev) 207 | { 208 | register c; 209 | 210 | c = lshift(u.u_offset, -9); 211 | c =+ ldiv(u.u_count+511, 512); 212 | if(c > hp_sizes[dev.d_minor & 07].nblocks) { 213 | u.u_error = ENXIO; 214 | return(0); 215 | } 216 | return(1); 217 | } 218 | 219 | -------------------------------------------------------------------------------- /dmr/hs.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * RS03/04 disk driver 7 | */ 8 | 9 | #include "../param.h" 10 | #include "../buf.h" 11 | #include "../conf.h" 12 | #include "../user.h" 13 | 14 | 15 | struct { 16 | int hscs1; /* Control and Status register 1 */ 17 | int hswc; /* Word count register */ 18 | int hsba; /* UNIBUS address register */ 19 | int hsda; /* Desired address register */ 20 | int hscs2; /* Control and Status register 2 */ 21 | int hsds; /* Drive Status */ 22 | int hser; /* Error register */ 23 | int hsas; /* not used */ 24 | int hsla; /* not used */ 25 | int hsdb; /* not used */ 26 | int hsmr; /* not used */ 27 | int hsdt; /* not used */ 28 | int hsbae; /* 11/70 bus extension */ 29 | }; 30 | 31 | struct devtab hstab; 32 | struct buf rhsbuf; 33 | 34 | #define HSADDR 0172040 35 | 36 | #define ERR 040000 /* hscs1 - composite error */ 37 | 38 | #define GO 01 39 | #define RCLR 010 40 | #define DRY 0200 /* hsds - Drive Ready */ 41 | 42 | hsstrategy(abp) 43 | struct buf *abp; 44 | { 45 | register struct buf *bp; 46 | register mblks; 47 | 48 | bp = abp; 49 | mblks = 1024; /* RJS03 */ 50 | if(bp->b_dev.d_minor >= 8) 51 | mblks = 2048; /* RJS04 */ 52 | if(bp->b_blkno >= mblks) { 53 | bp->b_flags =| B_ERROR; 54 | iodone(bp); 55 | return; 56 | } 57 | bp->av_forw = 0; 58 | spl5(); 59 | if (hstab.d_actf==0) 60 | hstab.d_actf = bp; else 61 | hstab.d_actl->av_forw = bp; 62 | hstab.d_actl = bp; 63 | if (hstab.d_active==0) 64 | hsstart(); 65 | spl0(); 66 | } 67 | 68 | hsstart() 69 | { 70 | register struct buf *bp; 71 | register addr; 72 | 73 | if ((bp = hstab.d_actf) == 0) 74 | return; 75 | hstab.d_active++; 76 | addr = bp->b_blkno; 77 | if(bp->b_dev.d_minor < 8) 78 | addr =<< 1; /* RJS03 */ 79 | HSADDR->hscs2 = bp->b_dev.d_minor & 07; 80 | rhstart(bp, &HSADDR->hsda, addr<<1, &HSADDR->hsbae); 81 | } 82 | 83 | hsintr() 84 | { 85 | register struct buf *bp; 86 | 87 | if (hstab.d_active == 0) 88 | return; 89 | bp = hstab.d_actf; 90 | hstab.d_active = 0; 91 | if(HSADDR->hscs1 & ERR){ /* error bit */ 92 | deverror(bp, HSADDR->hscs2, 0); 93 | HSADDR->hscs1 = RCLR|GO; 94 | if (++hstab.d_errcnt <= 10) { 95 | hsstart(); 96 | return; 97 | } 98 | bp->b_flags =| B_ERROR; 99 | } 100 | hstab.d_errcnt = 0; 101 | hstab.d_actf = bp->av_forw; 102 | iodone(bp); 103 | hsstart(); 104 | } 105 | 106 | hsread(dev) 107 | { 108 | 109 | physio(hsstrategy, &rhsbuf, dev, B_READ); 110 | } 111 | 112 | hswrite(dev) 113 | { 114 | 115 | physio(hsstrategy, &rhsbuf, dev, B_WRITE); 116 | } 117 | -------------------------------------------------------------------------------- /dmr/ht.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * TJU16 tape driver 7 | */ 8 | 9 | #include "../param.h" 10 | #include "../buf.h" 11 | #include "../conf.h" 12 | #include "../user.h" 13 | 14 | struct { 15 | int htcs1; 16 | int htwc; 17 | int htba; 18 | int htfc; 19 | int htcs2; 20 | int htds; 21 | int hter; 22 | int htas; 23 | int htck; 24 | int htdb; 25 | int htmr; 26 | int htdt; 27 | int htsn; 28 | int httc; 29 | int htbae; /* 11/70 bus extension */ 30 | }; 31 | 32 | struct devtab httab; 33 | struct buf rhtbuf; 34 | 35 | #define NUNIT 8 36 | 37 | char h_openf[NUNIT]; 38 | char *h_blkno[NUNIT]; 39 | char *h_nxrec[NUNIT]; 40 | 41 | #define HTADDR 0172440 42 | 43 | #define GO 01 44 | #define NOP 0 45 | #define WEOF 026 46 | #define SFORW 030 47 | #define SREV 032 48 | #define ERASE 024 49 | #define REW 06 50 | #define CLR 010 51 | #define P800 01300 /* 800 + pdp11 mode */ 52 | #define P1600 02300 /* 1600 + pdp11 mode */ 53 | #define IENABLE 0100 54 | #define CRDY 0200 55 | #define EOF 04 56 | #define DRY 0200 57 | #define MOL 010000 58 | #define PIP 020000 59 | #define ERR 040000 60 | 61 | #define SSEEK 1 62 | #define SIO 2 63 | 64 | htopen(dev, flag) 65 | { 66 | register unit; 67 | 68 | unit = dev.d_minor&077; 69 | if (unit >= NUNIT || h_openf[unit]) 70 | u.u_error = ENXIO; 71 | else { 72 | h_openf[unit]++; 73 | h_blkno[unit] = 0; 74 | h_nxrec[unit] = 65535; 75 | hcommand(dev, NOP); 76 | } 77 | } 78 | 79 | htclose(dev, flag) 80 | { 81 | register int unit; 82 | 83 | unit = dev.d_minor&077; 84 | h_openf[unit] = 0; 85 | if (flag) { 86 | hcommand(dev, WEOF); 87 | hcommand(dev, WEOF); 88 | } 89 | hcommand(dev, REW); 90 | } 91 | 92 | hcommand(dev, com) 93 | { 94 | register unit; 95 | extern lbolt; 96 | 97 | unit = dev.d_minor; 98 | while (httab.d_active || (HTADDR->htcs1 & CRDY)==0) 99 | sleep(&lbolt, 1); 100 | HTADDR->htcs2 = (unit>>3)&07; 101 | while((HTADDR->htds&DRY) == 0) 102 | sleep(&lbolt, 1); 103 | if(unit >= 64) 104 | HTADDR->httc = P800 | (unit&07); else 105 | HTADDR->httc = P1600 | (unit&07); 106 | while((HTADDR->htds&(MOL|PIP)) != MOL) 107 | sleep(&lbolt, 1); 108 | HTADDR->htcs1 = com | GO; 109 | } 110 | 111 | htstrategy(abp) 112 | struct buf *abp; 113 | { 114 | register struct buf *bp; 115 | register char **p; 116 | 117 | bp = abp; 118 | p = &h_nxrec[bp->b_dev.d_minor&077]; 119 | if (*p <= bp->b_blkno) { 120 | if (*p < bp->b_blkno) { 121 | bp->b_flags =| B_ERROR; 122 | iodone(bp); 123 | return; 124 | } 125 | if (bp->b_flags&B_READ) { 126 | clrbuf(bp); 127 | iodone(bp); 128 | return; 129 | } 130 | } 131 | if ((bp->b_flags&B_READ)==0) 132 | *p = bp->b_blkno + 1; 133 | bp->av_forw = 0; 134 | spl5(); 135 | if (httab.d_actf==0) 136 | httab.d_actf = bp; 137 | else 138 | httab.d_actl->av_forw = bp; 139 | httab.d_actl = bp; 140 | if (httab.d_active==0) 141 | htstart(); 142 | spl0(); 143 | } 144 | 145 | htstart() 146 | { 147 | register struct buf *bp; 148 | register int unit; 149 | register char *blkno; 150 | 151 | loop: 152 | if ((bp = httab.d_actf) == 0) 153 | return; 154 | unit = bp->b_dev.d_minor; 155 | HTADDR->htcs2 = (unit>>3)&07; 156 | if(unit >= 64) 157 | HTADDR->httc = P800 | (unit&07); else 158 | HTADDR->httc = P1600 | (unit&07); 159 | unit =& 077; 160 | blkno = h_blkno[unit]; 161 | if (h_openf[unit] < 0 || (HTADDR->htcs1 & CRDY)==0) { 162 | bp->b_flags =| B_ERROR; 163 | httab.d_actf = bp->av_forw; 164 | iodone(bp); 165 | goto loop; 166 | } 167 | if (blkno != bp->b_blkno) { 168 | httab.d_active = SSEEK; 169 | if (blkno < bp->b_blkno) { 170 | HTADDR->htfc = blkno - bp->b_blkno; 171 | HTADDR->htcs1 = SFORW|IENABLE|GO; 172 | } else { 173 | if (bp->b_blkno == 0) 174 | HTADDR->htcs1 = REW|IENABLE|GO; 175 | else { 176 | HTADDR->htfc = bp->b_blkno - blkno; 177 | HTADDR->htcs1 = SREV|IENABLE|GO; 178 | } 179 | } 180 | return; 181 | } 182 | httab.d_active = SIO; 183 | rhstart(bp, &HTADDR->htfc, bp->b_wcount<<1, &HTADDR->htbae); 184 | } 185 | 186 | htintr() 187 | { 188 | register struct buf *bp; 189 | register int unit; 190 | 191 | if ((bp = httab.d_actf)==0) 192 | return; 193 | unit = bp->b_dev.d_minor&077; 194 | if (HTADDR->htcs1 & ERR) { 195 | /* 196 | deverror(bp, HTADDR->hter, 0); 197 | */ 198 | if(HTADDR->htds&EOF) { 199 | if(bp != &rhtbuf && h_openf[unit]) 200 | h_openf[unit] = -1; 201 | } 202 | HTADDR->htcs1 = ERR|CLR|GO; 203 | if ((HTADDR->htds&DRY)!=0 && httab.d_active==SIO) { 204 | if (++httab.d_errcnt < 10) { 205 | h_blkno[unit]++; 206 | httab.d_active = 0; 207 | htstart(); 208 | return; 209 | } 210 | } 211 | bp->b_flags =| B_ERROR; 212 | httab.d_active = SIO; 213 | } 214 | if (httab.d_active == SIO) { 215 | httab.d_errcnt = 0; 216 | h_blkno[unit]++; 217 | httab.d_actf = bp->av_forw; 218 | httab.d_active = 0; 219 | iodone(bp); 220 | bp->b_resid = HTADDR->htfc; 221 | } else 222 | h_blkno[unit] = bp->b_blkno; 223 | htstart(); 224 | } 225 | 226 | htread(dev) 227 | { 228 | htphys(dev); 229 | physio(htstrategy, &rhtbuf, dev, B_READ); 230 | u.u_count = -rhtbuf.b_resid; 231 | } 232 | 233 | htwrite(dev) 234 | { 235 | htphys(dev); 236 | physio(htstrategy, &rhtbuf, dev, B_WRITE); 237 | u.u_count = 0; 238 | } 239 | 240 | htphys(dev) 241 | { 242 | register unit, a; 243 | 244 | unit = dev.d_minor; 245 | a = lshift(u.u_offset, -9); 246 | h_blkno[unit] = a; 247 | h_nxrec[unit] = ++a; 248 | } 249 | -------------------------------------------------------------------------------- /dmr/kl.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * KL/DL-11 driver 7 | */ 8 | #include "../param.h" 9 | #include "../conf.h" 10 | #include "../user.h" 11 | #include "../tty.h" 12 | #include "../proc.h" 13 | 14 | /* base address */ 15 | #define KLADDR 0177560 /* console */ 16 | #define KLBASE 0176500 /* kl and dl11-a */ 17 | #define DLBASE 0175610 /* dl-e */ 18 | #define NKL11 1 19 | #define NDL11 0 20 | #define DSRDY 02 21 | #define RDRENB 01 22 | 23 | struct tty kl11[NKL11+NDL11]; 24 | 25 | struct klregs { 26 | int klrcsr; 27 | int klrbuf; 28 | int kltcsr; 29 | int kltbuf; 30 | } 31 | 32 | klopen(dev, flag) 33 | { 34 | register char *addr; 35 | register struct tty *tp; 36 | 37 | if(dev.d_minor >= NKL11+NDL11) { 38 | u.u_error = ENXIO; 39 | return; 40 | } 41 | tp = &kl11[dev.d_minor]; 42 | if (u.u_procp->p_ttyp == 0) { 43 | u.u_procp->p_ttyp = tp; 44 | tp->t_dev = dev; 45 | } 46 | /* 47 | * set up minor 0 to address KLADDR 48 | * set up minor 1 thru NKL11-1 to address from KLBASE 49 | * set up minor NKL11 on to address from DLBASE 50 | */ 51 | addr = KLADDR + 8*dev.d_minor; 52 | if(dev.d_minor) 53 | addr =+ KLBASE-KLADDR-8; 54 | if(dev.d_minor >= NKL11) 55 | addr =+ DLBASE-KLBASE-8*NKL11+8; 56 | tp->t_addr = addr; 57 | if ((tp->t_state&ISOPEN) == 0) { 58 | tp->t_state = ISOPEN|CARR_ON; 59 | tp->t_flags = XTABS|LCASE|ECHO|CRMOD; 60 | tp->t_erase = CERASE; 61 | tp->t_kill = CKILL; 62 | } 63 | addr->klrcsr =| IENABLE|DSRDY|RDRENB; 64 | addr->kltcsr =| IENABLE; 65 | } 66 | 67 | klclose(dev) 68 | { 69 | register struct tty *tp; 70 | 71 | tp = &kl11[dev.d_minor]; 72 | wflushtty(tp); 73 | tp->t_state = 0; 74 | } 75 | 76 | klread(dev) 77 | { 78 | ttread(&kl11[dev.d_minor]); 79 | } 80 | 81 | klwrite(dev) 82 | { 83 | ttwrite(&kl11[dev.d_minor]); 84 | } 85 | 86 | klxint(dev) 87 | { 88 | register struct tty *tp; 89 | 90 | tp = &kl11[dev.d_minor]; 91 | ttstart(tp); 92 | if (tp->t_outq.c_cc == 0 || tp->t_outq.c_cc == TTLOWAT) 93 | wakeup(&tp->t_outq); 94 | } 95 | 96 | klrint(dev) 97 | { 98 | register int c, *addr; 99 | register struct tty *tp; 100 | 101 | tp = &kl11[dev.d_minor]; 102 | addr = tp->t_addr; 103 | c = addr->klrbuf; 104 | addr->klrcsr =| RDRENB; 105 | if ((c&0177)==0) 106 | addr->kltbuf = c; /* hardware botch */ 107 | ttyinput(c, tp); 108 | } 109 | 110 | klsgtty(dev, v) 111 | int *v; 112 | { 113 | register struct tty *tp; 114 | 115 | tp = &kl11[dev.d_minor]; 116 | ttystty(tp, v); 117 | } 118 | -------------------------------------------------------------------------------- /dmr/lp.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * LP-11 Line printer driver 7 | */ 8 | 9 | #include "../param.h" 10 | #include "../conf.h" 11 | #include "../user.h" 12 | 13 | #define LPADDR 0177514 14 | 15 | #define IENABLE 0100 16 | #define DONE 0200 17 | 18 | #define LPPRI 10 19 | #define LPLWAT 50 20 | #define LPHWAT 100 21 | #define EJLINE 60 22 | #define MAXCOL 80 23 | 24 | struct { 25 | int lpsr; 26 | int lpbuf; 27 | }; 28 | 29 | struct { 30 | int cc; 31 | int cf; 32 | int cl; 33 | int flag; 34 | int mcc; 35 | int ccc; 36 | int mlc; 37 | } lp11; 38 | 39 | #define CAP 01 /* Set to 0 for 96-char printer, else to 01 */ 40 | #define EJECT 02 41 | #define OPEN 04 42 | #define IND 010 /* Set to 0 for no indent, else to 010 */ 43 | 44 | #define FORM 014 45 | 46 | lpopen(dev, flag) 47 | { 48 | 49 | if(lp11.flag & OPEN || LPADDR->lpsr < 0) { 50 | u.u_error = EIO; 51 | return; 52 | } 53 | lp11.flag =| (IND|EJECT|OPEN); 54 | LPADDR->lpsr =| IENABLE; 55 | lpcanon(FORM); 56 | } 57 | 58 | lpclose(dev, flag) 59 | { 60 | lpcanon(FORM); 61 | lp11.flag = 0; 62 | } 63 | 64 | lpwrite() 65 | { 66 | register int c; 67 | 68 | while ((c=cpass())>=0) 69 | lpcanon(c); 70 | } 71 | 72 | lpcanon(c) 73 | { 74 | register c1, c2; 75 | 76 | c1 = c; 77 | if(lp11.flag&CAP) { 78 | if(c1>='a' && c1<='z') 79 | c1 =+ 'A'-'a'; else 80 | switch(c1) { 81 | 82 | case '{': 83 | c2 = '('; 84 | goto esc; 85 | 86 | case '}': 87 | c2 = ')'; 88 | goto esc; 89 | 90 | case '`': 91 | c2 = '\''; 92 | goto esc; 93 | 94 | case '|': 95 | c2 = '!'; 96 | goto esc; 97 | 98 | case '~': 99 | c2 = '^'; 100 | 101 | esc: 102 | lpcanon(c2); 103 | lp11.ccc--; 104 | c1 = '-'; 105 | } 106 | } 107 | 108 | switch(c1) { 109 | 110 | case '\t': 111 | lp11.ccc = (lp11.ccc+8) & ~7; 112 | return; 113 | 114 | case FORM: 115 | case '\n': 116 | if((lp11.flag&EJECT) == 0 || 117 | lp11.mcc!=0 || lp11.mlc!=0) { 118 | lp11.mcc = 0; 119 | lp11.mlc++; 120 | if(lp11.mlc >= EJLINE && lp11.flag&EJECT) 121 | c1 = FORM; 122 | lpoutput(c1); 123 | if(c1 == FORM) 124 | lp11.mlc = 0; 125 | } 126 | 127 | case '\r': 128 | lp11.ccc = 0; 129 | if(lp11.flag&IND) 130 | lp11.ccc = 8; 131 | return; 132 | 133 | case 010: 134 | if(lp11.ccc > 0) 135 | lp11.ccc--; 136 | return; 137 | 138 | case ' ': 139 | lp11.ccc++; 140 | return; 141 | 142 | default: 143 | if(lp11.ccc < lp11.mcc) { 144 | lpoutput('\r'); 145 | lp11.mcc = 0; 146 | } 147 | if(lp11.ccc < MAXCOL) { 148 | while(lp11.ccc > lp11.mcc) { 149 | lpoutput(' '); 150 | lp11.mcc++; 151 | } 152 | lpoutput(c1); 153 | lp11.mcc++; 154 | } 155 | lp11.ccc++; 156 | } 157 | } 158 | 159 | lpstart() 160 | { 161 | register int c; 162 | 163 | while (LPADDR->lpsr&DONE && (c = getc(&lp11)) >= 0) 164 | LPADDR->lpbuf = c; 165 | } 166 | 167 | lpint() 168 | { 169 | register int c; 170 | 171 | lpstart(); 172 | if (lp11.cc == LPLWAT || lp11.cc == 0) 173 | wakeup(&lp11); 174 | } 175 | 176 | lpoutput(c) 177 | { 178 | if (lp11.cc >= LPHWAT) 179 | sleep(&lp11, LPPRI); 180 | putc(c, &lp11); 181 | spl4(); 182 | lpstart(); 183 | spl0(); 184 | } 185 | -------------------------------------------------------------------------------- /dmr/mem.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * Memory special file 7 | * minor device 0 is physical memory 8 | * minor device 1 is kernel memory 9 | * minor device 2 is EOF/RATHOLE 10 | */ 11 | 12 | #include "../param.h" 13 | #include "../user.h" 14 | #include "../conf.h" 15 | #include "../seg.h" 16 | 17 | mmread(dev) 18 | { 19 | register c, bn, on; 20 | int a, d; 21 | 22 | if(dev.d_minor == 2) 23 | return; 24 | do { 25 | bn = lshift(u.u_offset, -6); 26 | on = u.u_offset[1] & 077; 27 | a = UISA->r[0]; 28 | d = UISD->r[0]; 29 | spl7(); 30 | UISA->r[0] = bn; 31 | UISD->r[0] = 077406; 32 | if(dev.d_minor == 1) 33 | UISA->r[0] = (ka6-6)->r[(bn>>7)&07] + (bn & 0177); 34 | c = fuibyte(on); 35 | UISA->r[0] = a; 36 | UISD->r[0] = d; 37 | spl0(); 38 | } while(u.u_error==0 && passc(c)>=0); 39 | } 40 | 41 | mmwrite(dev) 42 | { 43 | register c, bn, on; 44 | int a, d; 45 | 46 | if(dev.d_minor == 2) { 47 | c = u.u_count; 48 | u.u_count = 0; 49 | u.u_base =+ c; 50 | dpadd(u.u_offset, c); 51 | return; 52 | } 53 | for(;;) { 54 | bn = lshift(u.u_offset, -6); 55 | on = u.u_offset[1] & 077; 56 | if ((c=cpass())<0 || u.u_error!=0) 57 | break; 58 | a = UISA->r[0]; 59 | d = UISD->r[0]; 60 | spl7(); 61 | UISA->r[0] = bn; 62 | UISD->r[0] = 077406; 63 | if(dev.d_minor == 1) 64 | UISA->r[0] = (ka6-6)->r[(bn>>7)&07] + (bn & 0177); 65 | suibyte(on, c); 66 | UISA->r[0] = a; 67 | UISD->r[0] = d; 68 | spl0(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /dmr/partab.c: -------------------------------------------------------------------------------- 1 | /* 2 | */ 3 | 4 | char partab[] { 5 | 0001,0201,0201,0001,0201,0001,0001,0201, 6 | 0202,0004,0003,0205,0005,0206,0201,0001, 7 | 0201,0001,0001,0201,0001,0201,0201,0001, 8 | 0001,0201,0201,0001,0201,0001,0001,0201, 9 | 0200,0000,0000,0200,0000,0200,0200,0000, 10 | 0000,0200,0200,0000,0200,0000,0000,0200, 11 | 0000,0200,0200,0000,0200,0000,0000,0200, 12 | 0200,0000,0000,0200,0000,0200,0200,0000, 13 | 0200,0000,0000,0200,0000,0200,0200,0000, 14 | 0000,0200,0200,0000,0200,0000,0000,0200, 15 | 0000,0200,0200,0000,0200,0000,0000,0200, 16 | 0200,0000,0000,0200,0000,0200,0200,0000, 17 | 0000,0200,0200,0000,0200,0000,0000,0200, 18 | 0200,0000,0000,0200,0000,0200,0200,0000, 19 | 0200,0000,0000,0200,0000,0200,0200,0000, 20 | 0000,0200,0200,0000,0200,0000,0000,0201 21 | }; 22 | -------------------------------------------------------------------------------- /dmr/pc.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * PC-11 Paper tape reader/punch driver 7 | */ 8 | 9 | #include "../param.h" 10 | #include "../conf.h" 11 | #include "../user.h" 12 | 13 | #define PCADDR 0177550 14 | 15 | #define CLOSED 0 16 | #define WAITING 1 17 | #define READING 2 18 | #define EOF 3 19 | 20 | #define RDRENB 01 21 | #define IENABLE 0100 22 | #define DONE 0200 23 | #define BUSY 04000 24 | #define ERROR 0100000 25 | 26 | #define PCIPRI 30 27 | #define PCOPRI 40 28 | #define PCOLWAT 50 29 | #define PCOHWAT 100 30 | #define PCIHWAT 250 31 | 32 | struct { 33 | int pcrcsr; 34 | int pcrbuf; 35 | int pcpcsr; 36 | int pcpbuf; 37 | }; 38 | 39 | struct clist { 40 | int cc; 41 | int cf; 42 | int cl; 43 | }; 44 | 45 | struct pc11 { 46 | int pcstate; 47 | struct clist pcin; 48 | struct clist pcout; 49 | } pc11; 50 | 51 | pcopen(dev, flag) 52 | { 53 | extern lbolt; 54 | 55 | if (flag==0) { 56 | if (pc11.pcstate!=CLOSED) { 57 | u.u_error = ENXIO; 58 | return; 59 | } 60 | pc11.pcstate = WAITING; 61 | while(pc11.pcstate==WAITING) { 62 | PCADDR->pcrcsr = IENABLE|RDRENB; 63 | sleep(&lbolt, PCIPRI); 64 | } 65 | } else { 66 | PCADDR->pcpcsr =| IENABLE; 67 | pcleader(); 68 | } 69 | } 70 | 71 | pcclose(dev, flag) 72 | { 73 | if (flag==0) { 74 | spl4(); 75 | while (getc(&pc11.pcin) >= 0); 76 | PCADDR->pcrcsr = 0; 77 | pc11.pcstate = CLOSED; 78 | spl0(); 79 | } else 80 | pcleader(); 81 | } 82 | 83 | pcread() 84 | { 85 | register int c; 86 | 87 | spl4(); 88 | do { 89 | while ((c = getc(&pc11.pcin)) < 0) { 90 | if (pc11.pcstate==EOF) 91 | goto out; 92 | if ((PCADDR->pcrcsr&(ERROR|BUSY|DONE))==0) 93 | PCADDR->pcrcsr =| IENABLE|RDRENB; 94 | sleep(&pc11.pcin, PCIPRI); 95 | } 96 | } while (passc(c)>=0); 97 | out: 98 | spl0(); 99 | } 100 | 101 | pcwrite() 102 | { 103 | register int c; 104 | 105 | while ((c=cpass())>=0) 106 | pcoutput(c); 107 | } 108 | 109 | pcstart() 110 | { 111 | register int c; 112 | 113 | if (PCADDR->pcpcsr&DONE && (c = getc(&pc11.pcout)) >= 0) 114 | PCADDR->pcpbuf = c; 115 | } 116 | 117 | pcrint() 118 | { 119 | if (pc11.pcstate==WAITING) { 120 | if (PCADDR->pcrcsr&ERROR) 121 | return; 122 | pc11.pcstate = READING; 123 | } 124 | if (pc11.pcstate==READING) { 125 | if (PCADDR->pcrcsr&ERROR) 126 | pc11.pcstate = EOF; 127 | else { 128 | putc(PCADDR->pcrbuf, &pc11.pcin); 129 | if (pc11.pcin.cc < PCIHWAT) 130 | PCADDR->pcrcsr =| IENABLE|RDRENB; 131 | } 132 | wakeup(&pc11.pcin); 133 | } 134 | } 135 | 136 | pcpint() 137 | { 138 | 139 | pcstart(); 140 | if (pc11.pcout.cc <= PCOLWAT) 141 | wakeup(&pc11.pcout); 142 | } 143 | 144 | pcoutput(c) 145 | { 146 | if (PCADDR->pcpcsr&ERROR) { 147 | u.u_error = EIO; 148 | return; 149 | } 150 | if (pc11.pcout.cc >= PCOHWAT) 151 | sleep(&pc11.pcout, PCOPRI); 152 | putc(c, &pc11.pcout); 153 | spl4(); 154 | pcstart(); 155 | spl0(); 156 | } 157 | 158 | pcleader() 159 | { 160 | register int i; 161 | 162 | i = 100; 163 | do 164 | pcoutput(0); 165 | while (--i); 166 | } 167 | -------------------------------------------------------------------------------- /dmr/rf.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * RF disk driver 7 | */ 8 | 9 | #include "../param.h" 10 | #include "../buf.h" 11 | #include "../conf.h" 12 | #include "../user.h" 13 | 14 | struct { 15 | int rfcs; 16 | int rfwc; 17 | int rfba; 18 | int rfda; 19 | int rfdae; 20 | }; 21 | 22 | struct devtab rftab; 23 | struct buf rrfbuf; 24 | 25 | #define NRFBLK 1024 26 | #define RFADDR 0177460 27 | 28 | #define GO 01 29 | #define RCOM 02 30 | #define WCOM 04 31 | #define CTLCLR 0400 32 | #define IENABLE 0100 33 | 34 | rfstrategy(abp) 35 | struct buf *abp; 36 | { 37 | register struct buf *bp; 38 | 39 | bp = abp; 40 | if(bp->b_flags&B_PHYS) 41 | mapalloc(bp); 42 | if (bp->b_blkno >= NRFBLK*(bp->b_dev.d_minor+1)) { 43 | bp->b_flags =| B_ERROR; 44 | iodone(bp); 45 | return; 46 | } 47 | bp->av_forw = 0; 48 | spl5(); 49 | if (rftab.d_actf==0) 50 | rftab.d_actf = bp; 51 | else 52 | rftab.d_actl->av_forw = bp; 53 | rftab.d_actl = bp; 54 | if (rftab.d_active==0) 55 | rfstart(); 56 | spl0(); 57 | } 58 | 59 | rfstart() 60 | { 61 | register struct buf *bp; 62 | 63 | if ((bp = rftab.d_actf) == 0) 64 | return; 65 | rftab.d_active++; 66 | RFADDR->rfdae = bp->b_blkno.hibyte; 67 | devstart(bp, &RFADDR->rfda, bp->b_blkno<<8, 0); 68 | } 69 | 70 | rfintr() 71 | { 72 | register struct buf *bp; 73 | 74 | if (rftab.d_active == 0) 75 | return; 76 | bp = rftab.d_actf; 77 | rftab.d_active = 0; 78 | if (RFADDR->rfcs < 0) { /* error bit */ 79 | deverror(bp, RFADDR->rfcs, RFADDR->rfdae); 80 | RFADDR->rfcs = CTLCLR; 81 | if (++rftab.d_errcnt <= 10) { 82 | rfstart(); 83 | return; 84 | } 85 | bp->b_flags =| B_ERROR; 86 | } 87 | rftab.d_errcnt = 0; 88 | rftab.d_actf = bp->av_forw; 89 | iodone(bp); 90 | rfstart(); 91 | } 92 | 93 | rfread(dev) 94 | { 95 | 96 | physio(rfstrategy, &rrfbuf, dev, B_READ); 97 | } 98 | 99 | rfwrite(dev) 100 | { 101 | 102 | physio(rfstrategy, &rrfbuf, dev, B_WRITE); 103 | } 104 | -------------------------------------------------------------------------------- /dmr/rk.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * RK disk driver 7 | */ 8 | 9 | #include "../param.h" 10 | #include "../buf.h" 11 | #include "../conf.h" 12 | #include "../user.h" 13 | 14 | #define RKADDR 0177400 15 | #define NRK 4 16 | #define NRKBLK 4872 17 | 18 | #define RESET 0 19 | #define GO 01 20 | #define DRESET 014 21 | #define IENABLE 0100 22 | #define DRY 0200 23 | #define ARDY 0100 24 | #define WLO 020000 25 | #define CTLRDY 0200 26 | 27 | struct { 28 | int rkds; 29 | int rker; 30 | int rkcs; 31 | int rkwc; 32 | int rkba; 33 | int rkda; 34 | }; 35 | 36 | struct devtab rktab; 37 | struct buf rrkbuf; 38 | 39 | rkstrategy(abp) 40 | struct buf *abp; 41 | { 42 | register struct buf *bp; 43 | register *qc, *ql; 44 | int d; 45 | 46 | bp = abp; 47 | if(bp->b_flags&B_PHYS) 48 | mapalloc(bp); 49 | d = bp->b_dev.d_minor-7; 50 | if(d <= 0) 51 | d = 1; 52 | if (bp->b_blkno >= NRKBLK*d) { 53 | bp->b_flags =| B_ERROR; 54 | iodone(bp); 55 | return; 56 | } 57 | bp->av_forw = 0; 58 | spl5(); 59 | if (rktab.d_actf==0) 60 | rktab.d_actf = bp; 61 | else 62 | rktab.d_actl->av_forw = bp; 63 | rktab.d_actl = bp; 64 | if (rktab.d_active==0) 65 | rkstart(); 66 | spl0(); 67 | } 68 | 69 | rkaddr(bp) 70 | struct buf *bp; 71 | { 72 | register struct buf *p; 73 | register int b; 74 | int d, m; 75 | 76 | p = bp; 77 | b = p->b_blkno; 78 | m = p->b_dev.d_minor - 7; 79 | if(m <= 0) 80 | d = p->b_dev.d_minor; 81 | else { 82 | d = lrem(b, m); 83 | b = ldiv(b, m); 84 | } 85 | return(d<<13 | (b/12)<<4 | b%12); 86 | } 87 | 88 | rkstart() 89 | { 90 | register struct buf *bp; 91 | 92 | if ((bp = rktab.d_actf) == 0) 93 | return; 94 | rktab.d_active++; 95 | devstart(bp, &RKADDR->rkda, rkaddr(bp), 0); 96 | } 97 | 98 | rkintr() 99 | { 100 | register struct buf *bp; 101 | 102 | if (rktab.d_active == 0) 103 | return; 104 | bp = rktab.d_actf; 105 | rktab.d_active = 0; 106 | if (RKADDR->rkcs < 0) { /* error bit */ 107 | deverror(bp, RKADDR->rker, RKADDR->rkds); 108 | RKADDR->rkcs = RESET|GO; 109 | while((RKADDR->rkcs&CTLRDY) == 0) ; 110 | if (++rktab.d_errcnt <= 10) { 111 | rkstart(); 112 | return; 113 | } 114 | bp->b_flags =| B_ERROR; 115 | } 116 | rktab.d_errcnt = 0; 117 | rktab.d_actf = bp->av_forw; 118 | iodone(bp); 119 | rkstart(); 120 | } 121 | 122 | rkread(dev) 123 | { 124 | 125 | physio(rkstrategy, &rrkbuf, dev, B_READ); 126 | } 127 | 128 | rkwrite(dev) 129 | { 130 | 131 | physio(rkstrategy, &rrkbuf, dev, B_WRITE); 132 | } 133 | -------------------------------------------------------------------------------- /dmr/rp.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * RP disk driver 7 | */ 8 | 9 | #include "../param.h" 10 | #include "../buf.h" 11 | #include "../conf.h" 12 | #include "../user.h" 13 | 14 | struct { 15 | int rpds; 16 | int rper; 17 | int rpcs; 18 | int rpwc; 19 | int rpba; 20 | int rpca; 21 | int rpda; 22 | }; 23 | 24 | #define RPADDR 0176710 25 | #define NRP 8 26 | 27 | struct { 28 | char *nblocks; 29 | int cyloff; 30 | } rp_sizes[] { 31 | 40600, 0, /* cyl 0 thru 202 */ 32 | 40600, 203, /* cyl 203 thru 405 */ 33 | 9200, 0, /* cyl 0 thru 45 */ 34 | 9200, 360, /* cyl 360 thru 405 */ 35 | -1, 0, /* cyl 0 thru 327 */ 36 | -1, 78, /* cyl 78 thru 405 */ 37 | 15600, 0, /* cyl 0 thru 77 */ 38 | 15600, 328, /* cyl 328 thru 405 */ 39 | }; 40 | 41 | struct devtab rptab; 42 | struct buf rrpbuf; 43 | 44 | #define GO 01 45 | #define RESET 0 46 | #define HSEEK 014 47 | 48 | #define IENABLE 0100 49 | #define READY 0200 50 | 51 | #define SUFU 01000 52 | #define SUSU 02000 53 | #define SUSI 04000 54 | #define HNF 010000 55 | 56 | /* 57 | * Use av_back to save track+sector, 58 | * b_resid for cylinder. 59 | */ 60 | 61 | #define trksec av_back 62 | #define cylin b_resid 63 | 64 | rpstrategy(abp) 65 | struct buf *abp; 66 | { 67 | register struct buf *bp; 68 | register char *p1, *p2; 69 | 70 | bp = abp; 71 | if(bp->b_flags&B_PHYS) 72 | mapalloc(bp); 73 | p1 = &rp_sizes[bp->b_dev.d_minor&07]; 74 | if (bp->b_dev.d_minor >= (NRP<<3) || 75 | bp->b_blkno >= p1->nblocks) { 76 | bp->b_flags =| B_ERROR; 77 | iodone(bp); 78 | return; 79 | } 80 | bp->av_forw = 0; 81 | bp->cylin = p1->cyloff; 82 | p1 = bp->b_blkno; 83 | p2 = lrem(p1, 10); 84 | p1 = ldiv(p1, 10); 85 | bp->trksec = (p1%20)<<8 | p2; 86 | bp->cylin =+ p1/20; 87 | spl5(); 88 | if ((p1 = rptab.d_actf)==0) 89 | rptab.d_actf = bp; 90 | else { 91 | for (; p2 = p1->av_forw; p1 = p2) { 92 | if (p1->cylin <= bp->cylin 93 | && bp->cylin < p2->cylin 94 | || p1->cylin >= bp->cylin 95 | && bp->cylin > p2->cylin) 96 | break; 97 | } 98 | bp->av_forw = p2; 99 | p1->av_forw = bp; 100 | } 101 | if (rptab.d_active==0) 102 | rpstart(); 103 | spl0(); 104 | } 105 | 106 | rpstart() 107 | { 108 | register struct buf *bp; 109 | 110 | if ((bp = rptab.d_actf) == 0) 111 | return; 112 | rptab.d_active++; 113 | RPADDR->rpda = bp->trksec; 114 | devstart(bp, &RPADDR->rpca, bp->cylin, bp->b_dev.d_minor>>3); 115 | } 116 | 117 | rpintr() 118 | { 119 | register struct buf *bp; 120 | register int ctr; 121 | 122 | if (rptab.d_active == 0) 123 | return; 124 | bp = rptab.d_actf; 125 | rptab.d_active = 0; 126 | if (RPADDR->rpcs < 0) { /* error bit */ 127 | deverror(bp, RPADDR->rper, RPADDR->rpds); 128 | if(RPADDR->rpds & (SUFU|SUSI|HNF)) { 129 | RPADDR->rpcs.lobyte = HSEEK|GO; 130 | ctr = 0; 131 | while ((RPADDR->rpds&SUSU) && --ctr); 132 | } 133 | RPADDR->rpcs = RESET|GO; 134 | ctr = 0; 135 | while ((RPADDR->rpcs&READY) == 0 && --ctr); 136 | if (++rptab.d_errcnt <= 10) { 137 | rpstart(); 138 | return; 139 | } 140 | bp->b_flags =| B_ERROR; 141 | } 142 | rptab.d_errcnt = 0; 143 | rptab.d_actf = bp->av_forw; 144 | bp->b_resid = RPADDR->rpwc; 145 | iodone(bp); 146 | rpstart(); 147 | } 148 | 149 | rpread(dev) 150 | { 151 | 152 | if(rpphys(dev)) 153 | physio(rpstrategy, &rrpbuf, dev, B_READ); 154 | } 155 | 156 | rpwrite(dev) 157 | { 158 | 159 | if(rpphys(dev)) 160 | physio(rpstrategy, &rrpbuf, dev, B_WRITE); 161 | } 162 | 163 | rpphys(dev) 164 | { 165 | register c; 166 | 167 | c = lshift(u.u_offset, -9); 168 | c =+ ldiv(u.u_count+511, 512); 169 | if(c > rp_sizes[dev.d_minor & 07].nblocks) { 170 | u.u_error = ENXIO; 171 | return(0); 172 | } 173 | return(1); 174 | } 175 | -------------------------------------------------------------------------------- /dmr/sys.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * indirect driver for controlling tty. 7 | */ 8 | #include "../param.h" 9 | #include "../conf.h" 10 | #include "../user.h" 11 | #include "../tty.h" 12 | #include "../proc.h" 13 | 14 | syopen(dev, flag) 15 | { 16 | register *tp; 17 | 18 | if(tp = syttyp()) 19 | (*cdevsw[tp->t_dev.d_major].d_open)(tp->t_dev, flag); 20 | } 21 | 22 | syread(dev) 23 | { 24 | register *tp; 25 | 26 | if(tp = syttyp()) 27 | (*cdevsw[tp->t_dev.d_major].d_read)(tp->t_dev); 28 | } 29 | 30 | sywrite(dev) 31 | { 32 | register *tp; 33 | 34 | if(tp = syttyp()) 35 | (*cdevsw[tp->t_dev.d_major].d_write)(tp->t_dev); 36 | } 37 | 38 | sysgtty(dev, flag) 39 | { 40 | register *tp; 41 | 42 | if(tp = syttyp()) 43 | (*cdevsw[tp->t_dev.d_major].d_sgtty)(tp->t_dev, flag); 44 | } 45 | 46 | syttyp() 47 | { 48 | register tp; 49 | 50 | tp = u.u_procp->p_ttyp; 51 | if(tp == NULL) 52 | u.u_error = ENXIO; 53 | return(tp); 54 | } 55 | -------------------------------------------------------------------------------- /dmr/tc.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * TC-11 DECtape driver 7 | */ 8 | 9 | #include "../param.h" 10 | #include "../conf.h" 11 | #include "../buf.h" 12 | #include "../user.h" 13 | 14 | struct { 15 | int tccsr; 16 | int tccm; 17 | int tcwc; 18 | int tcba; 19 | int tcdt; 20 | }; 21 | 22 | struct devtab tctab; 23 | char tcper[8]; 24 | 25 | #define TCADDR 0177340 26 | #define NTCBLK 578 27 | 28 | #define TAPERR 0100000 29 | #define TREV 04000 30 | #define READY 0200 31 | #define IENABLE 0100 32 | #define UPS 0200 33 | #define ENDZ 0100000 34 | #define BLKM 02000 35 | #define ILGOP 010000 36 | #define SELERR 04000 37 | 38 | #define SAT 0 39 | #define RNUM 02 40 | #define RDATA 04 41 | #define SST 010 42 | #define WDATA 014 43 | #define GO 01 44 | 45 | #define SFORW 1 46 | #define SREV 2 47 | #define SIO 3 48 | 49 | tcclose(dev) 50 | { 51 | bflush(dev); 52 | tcper[dev&07] = 0; 53 | } 54 | 55 | tcstrategy(abp) 56 | struct buf *abp; 57 | { 58 | register struct buf *bp; 59 | 60 | bp = abp; 61 | if(bp->b_flags&B_PHYS) 62 | mapalloc(bp); 63 | if(bp->b_blkno >= NTCBLK || tcper[bp->b_dev&07]) { 64 | bp->b_flags =| B_ERROR; 65 | iodone(bp); 66 | return; 67 | } 68 | bp->av_forw = 0; 69 | spl6(); 70 | if (tctab.d_actf==0) 71 | tctab.d_actf = bp; 72 | else 73 | tctab.d_actl->av_forw = bp; 74 | tctab.d_actl = bp; 75 | if (tctab.d_active==0) 76 | tcstart(); 77 | spl0(); 78 | } 79 | 80 | tcstart() 81 | { 82 | register struct buf *bp; 83 | register int *tccmp, com; 84 | 85 | loop: 86 | tccmp = &TCADDR->tccm; 87 | if ((bp = tctab.d_actf) == 0) 88 | return; 89 | if(tcper[bp->b_dev&07]) { 90 | if((tctab.d_actf = bp->av_forw) == 0) 91 | (*tccmp).lobyte = SAT|GO; 92 | bp->b_flags =| B_ERROR; 93 | iodone(bp); 94 | goto loop; 95 | } 96 | if (((*tccmp).hibyte&07) != bp->b_dev.d_minor) 97 | (*tccmp).lobyte = SAT|GO; 98 | tctab.d_errcnt = 20; 99 | tctab.d_active = SFORW; 100 | com = (bp->b_dev.d_minor<<8) | IENABLE|RNUM|GO; 101 | if ((TCADDR->tccsr & UPS) == 0) { 102 | com =| TREV; 103 | tctab.d_active = SREV; 104 | } 105 | *tccmp = com; 106 | } 107 | 108 | tcintr() 109 | { 110 | register struct buf *bp; 111 | register int *tccmp; 112 | register int *tcdtp; 113 | 114 | tccmp = &TCADDR->tccm; 115 | tcdtp = &TCADDR->tccsr; 116 | bp = tctab.d_actf; 117 | if (*tccmp&TAPERR) { 118 | if((*tcdtp&(ENDZ|BLKM)) == 0) 119 | deverror(bp, *tcdtp, 0); 120 | if(*tcdtp & (ILGOP|SELERR)) { 121 | tcper[bp->b_dev&07]++; 122 | tctab.d_errcnt = 0; 123 | } 124 | *tccmp =& ~TAPERR; 125 | if (--tctab.d_errcnt <= 0) { 126 | bp->b_flags =| B_ERROR; 127 | goto done; 128 | } 129 | if (*tccmp&TREV) { 130 | setforw: 131 | tctab.d_active = SFORW; 132 | *tccmp =& ~TREV; 133 | } else { 134 | setback: 135 | tctab.d_active = SREV; 136 | *tccmp =| TREV; 137 | } 138 | (*tccmp).lobyte = IENABLE|RNUM|GO; 139 | return; 140 | } 141 | tcdtp = &TCADDR->tcdt; 142 | switch (tctab.d_active) { 143 | 144 | case SIO: 145 | done: 146 | tctab.d_active = 0; 147 | if (tctab.d_actf = bp->av_forw) 148 | tcstart(); 149 | else 150 | TCADDR->tccm.lobyte = SAT|GO; 151 | iodone(bp); 152 | return; 153 | 154 | case SFORW: 155 | if (*tcdtp > bp->b_blkno) 156 | goto setback; 157 | if (*tcdtp < bp->b_blkno) 158 | goto setforw; 159 | *--tcdtp = bp->b_addr; /* core address */ 160 | *--tcdtp = bp->b_wcount; 161 | tccmp->lobyte = ((bp->b_xmem & 03) << 4) | IENABLE|GO 162 | | (bp->b_flags&B_READ?RDATA:WDATA); 163 | tctab.d_active = SIO; 164 | return; 165 | 166 | case SREV: 167 | if (*tcdtp+3 > bp->b_blkno) 168 | goto setback; 169 | goto setforw; 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /dmr/tm.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * TM tape driver 7 | */ 8 | 9 | #include "../param.h" 10 | #include "../buf.h" 11 | #include "../conf.h" 12 | #include "../user.h" 13 | 14 | struct { 15 | int tmer; 16 | int tmcs; 17 | int tmbc; 18 | int tmba; 19 | int tmdb; 20 | int tmrd; 21 | }; 22 | 23 | struct devtab tmtab; 24 | struct buf rtmbuf; 25 | 26 | char t_openf[8]; 27 | char *t_blkno[8]; 28 | char *t_nxrec[8]; 29 | 30 | #define TMADDR 0172520 31 | 32 | #define GO 01 33 | #define RCOM 02 34 | #define WCOM 04 35 | #define WEOF 06 36 | #define SFORW 010 37 | #define SREV 012 38 | #define WIRG 014 39 | #define REW 016 40 | #define DENS 060000 /* 9-channel */ 41 | #define IENABLE 0100 42 | #define CRDY 0200 43 | #define GAPSD 010000 44 | #define TUR 1 45 | #define HARD 0102200 /* ILC, EOT, NXM */ 46 | #define EOF 0040000 47 | 48 | #define SSEEK 1 49 | #define SIO 2 50 | 51 | tmopen(dev, flag) 52 | { 53 | register dminor; 54 | 55 | dminor = dev.d_minor; 56 | if (t_openf[dminor]) 57 | u.u_error = ENXIO; 58 | else { 59 | t_openf[dminor]++; 60 | t_blkno[dminor] = 0; 61 | t_nxrec[dminor] = 65535; 62 | } 63 | } 64 | 65 | tmclose(dev, flag) 66 | { 67 | register int dminor; 68 | 69 | dminor = dev.d_minor; 70 | t_openf[dminor] = 0; 71 | if (flag) 72 | tcommand(dminor, WEOF); 73 | tcommand(dminor, REW); 74 | } 75 | 76 | tcommand(unit, com) 77 | { 78 | extern lbolt; 79 | 80 | while (tmtab.d_active || (TMADDR->tmcs & CRDY)==0) 81 | sleep(&lbolt, 1); 82 | TMADDR->tmcs = DENS|com|GO | (unit<<8); 83 | } 84 | 85 | tmstrategy(abp) 86 | struct buf *abp; 87 | { 88 | register struct buf *bp; 89 | register char **p; 90 | 91 | bp = abp; 92 | p = &t_nxrec[bp->b_dev.d_minor]; 93 | if (*p <= bp->b_blkno) { 94 | if (*p < bp->b_blkno) { 95 | bp->b_flags =| B_ERROR; 96 | iodone(bp); 97 | return; 98 | } 99 | if (bp->b_flags&B_READ) { 100 | clrbuf(bp); 101 | iodone(bp); 102 | return; 103 | } 104 | } 105 | if ((bp->b_flags&B_READ)==0) 106 | *p = bp->b_blkno + 1; 107 | bp->av_forw = 0; 108 | spl5(); 109 | if (tmtab.d_actf==0) 110 | tmtab.d_actf = bp; 111 | else 112 | tmtab.d_actl->av_forw = bp; 113 | tmtab.d_actl = bp; 114 | if (tmtab.d_active==0) 115 | tmstart(); 116 | spl0(); 117 | } 118 | 119 | tmstart() 120 | { 121 | register struct buf *bp; 122 | register int com; 123 | int unit; 124 | register char *blkno; 125 | 126 | loop: 127 | if ((bp = tmtab.d_actf) == 0) 128 | return; 129 | unit = bp->b_dev.d_minor; 130 | blkno = t_blkno[unit]; 131 | if (t_openf[unit] < 0 || (TMADDR->tmcs & CRDY)==0) { 132 | bp->b_flags =| B_ERROR; 133 | tmtab.d_actf = bp->av_forw; 134 | iodone(bp); 135 | goto loop; 136 | } 137 | com = (unit<<8) | ((bp->b_xmem & 03) << 4) | IENABLE|DENS; 138 | if (blkno != bp->b_blkno) { 139 | tmtab.d_active = SSEEK; 140 | if (blkno < bp->b_blkno) { 141 | com =| SFORW|GO; 142 | TMADDR->tmbc = blkno - bp->b_blkno; 143 | } else { 144 | if (bp->b_blkno == 0) 145 | com =| REW|GO; 146 | else { 147 | com =| SREV|GO; 148 | TMADDR->tmbc = bp->b_blkno - blkno; 149 | } 150 | } 151 | TMADDR->tmcs = com; 152 | return; 153 | } 154 | tmtab.d_active = SIO; 155 | TMADDR->tmbc = bp->b_wcount << 1; 156 | TMADDR->tmba = bp->b_addr; /* core address */ 157 | TMADDR->tmcs = com | ((bp->b_flags&B_READ)? RCOM|GO: 158 | ((tmtab.d_errcnt)? WIRG|GO: WCOM|GO)); 159 | } 160 | 161 | tmintr() 162 | { 163 | register struct buf *bp; 164 | register int unit; 165 | 166 | if ((bp = tmtab.d_actf)==0) 167 | return; 168 | unit = bp->b_dev.d_minor; 169 | if (TMADDR->tmcs < 0) { /* error bit */ 170 | /* 171 | deverror(bp, TMADDR->tmer); 172 | */ 173 | while(TMADDR->tmrd & GAPSD) ; /* wait for gap shutdown */ 174 | if ((TMADDR->tmer&(HARD|EOF))==0 && tmtab.d_active==SIO) { 175 | if (++tmtab.d_errcnt < 10) { 176 | t_blkno[unit]++; 177 | tmtab.d_active = 0; 178 | tmstart(); 179 | return; 180 | } 181 | } else 182 | if(bp != &rtmbuf && (TMADDR->tmer&EOF)==0) 183 | t_openf[unit] = -1; 184 | bp->b_flags =| B_ERROR; 185 | tmtab.d_active = SIO; 186 | } 187 | if (tmtab.d_active == SIO) { 188 | tmtab.d_errcnt = 0; 189 | t_blkno[unit]++; 190 | tmtab.d_actf = bp->av_forw; 191 | tmtab.d_active = 0; 192 | iodone(bp); 193 | bp->b_resid = TMADDR->tmbc; 194 | } else 195 | t_blkno[unit] = bp->b_blkno; 196 | tmstart(); 197 | } 198 | 199 | tmread(dev) 200 | { 201 | tmphys(dev); 202 | physio(tmstrategy, &rtmbuf, dev, B_READ); 203 | u.u_count = -rtmbuf.b_resid; 204 | } 205 | 206 | tmwrite(dev) 207 | { 208 | tmphys(dev); 209 | physio(tmstrategy, &rtmbuf, dev, B_WRITE); 210 | u.u_count = 0; 211 | } 212 | 213 | tmphys(dev) 214 | { 215 | register unit, a; 216 | 217 | unit = dev.d_minor; 218 | a = lshift(u.u_offset, -9); 219 | t_blkno[unit] = a; 220 | t_nxrec[unit] = ++a; 221 | } 222 | -------------------------------------------------------------------------------- /dmr/tty.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * general TTY subroutines 7 | */ 8 | #include "../param.h" 9 | #include "../systm.h" 10 | #include "../user.h" 11 | #include "../tty.h" 12 | #include "../proc.h" 13 | #include "../inode.h" 14 | #include "../file.h" 15 | #include "../reg.h" 16 | #include "../conf.h" 17 | 18 | /* 19 | * Input mapping table-- if an entry is non-zero, when the 20 | * corresponding character is typed preceded by "\" the escape 21 | * sequence is replaced by the table value. Mostly used for 22 | * upper-case only terminals. 23 | */ 24 | char maptab[] 25 | { 26 | 000,000,000,000,004,000,000,000, 27 | 000,000,000,000,000,000,000,000, 28 | 000,000,000,000,000,000,000,000, 29 | 000,000,000,000,000,000,000,000, 30 | 000,'|',000,'#',000,000,000,'`', 31 | '{','}',000,000,000,000,000,000, 32 | 000,000,000,000,000,000,000,000, 33 | 000,000,000,000,000,000,000,000, 34 | '@',000,000,000,000,000,000,000, 35 | 000,000,000,000,000,000,000,000, 36 | 000,000,000,000,000,000,000,000, 37 | 000,000,000,000,000,000,'~',000, 38 | 000,'A','B','C','D','E','F','G', 39 | 'H','I','J','K','L','M','N','O', 40 | 'P','Q','R','S','T','U','V','W', 41 | 'X','Y','Z',000,000,000,000,000, 42 | }; 43 | 44 | /* 45 | * The actual structure of a clist block manipulated by 46 | * getc and putc (mch.s) 47 | */ 48 | struct cblock { 49 | struct cblock *c_next; 50 | char info[6]; 51 | }; 52 | 53 | /* The character lists-- space for 6*NCLIST characters */ 54 | struct cblock cfree[NCLIST]; 55 | /* List head for unused character blocks. */ 56 | struct cblock *cfreelist; 57 | 58 | /* 59 | * structure of device registers for KL, DL, and DC 60 | * interfaces-- more particularly, those for which the 61 | * SSTART bit is off and can be treated by general routines 62 | * (that is, not DH). 63 | */ 64 | struct { 65 | int ttrcsr; 66 | int ttrbuf; 67 | int tttcsr; 68 | int tttbuf; 69 | }; 70 | 71 | /* 72 | * The routine implementing the gtty system call. 73 | * Just call lower level routine and pass back values. 74 | */ 75 | gtty() 76 | { 77 | int v[3]; 78 | register *up, *vp; 79 | 80 | vp = v; 81 | sgtty(vp); 82 | if (u.u_error) 83 | return; 84 | up = u.u_arg[0]; 85 | suword(up, *vp++); 86 | suword(++up, *vp++); 87 | suword(++up, *vp++); 88 | } 89 | 90 | /* 91 | * The routine implementing the stty system call. 92 | * Read in values and call lower level. 93 | */ 94 | stty() 95 | { 96 | register int *up; 97 | 98 | up = u.u_arg[0]; 99 | u.u_arg[0] = fuword(up); 100 | u.u_arg[1] = fuword(++up); 101 | u.u_arg[2] = fuword(++up); 102 | sgtty(0); 103 | } 104 | 105 | /* 106 | * Stuff common to stty and gtty. 107 | * Check legality and switch out to individual 108 | * device routine. 109 | * v is 0 for stty; the parameters are taken from u.u_arg[]. 110 | * c is non-zero for gtty and is the place in which the device 111 | * routines place their information. 112 | */ 113 | sgtty(v) 114 | int *v; 115 | { 116 | register struct file *fp; 117 | register struct inode *ip; 118 | 119 | if ((fp = getf(u.u_ar0[R0])) == NULL) 120 | return; 121 | ip = fp->f_inode; 122 | if ((ip->i_mode&IFMT) != IFCHR) { 123 | u.u_error = ENOTTY; 124 | return; 125 | } 126 | (*cdevsw[ip->i_addr[0].d_major].d_sgtty)(ip->i_addr[0], v); 127 | } 128 | 129 | /* 130 | * Wait for output to drain, then flush input waiting. 131 | */ 132 | wflushtty(atp) 133 | struct tty *atp; 134 | { 135 | register struct tty *tp; 136 | 137 | tp = atp; 138 | spl5(); 139 | while (tp->t_outq.c_cc) { 140 | tp->t_state =| ASLEEP; 141 | sleep(&tp->t_outq, TTOPRI); 142 | } 143 | flushtty(tp); 144 | spl0(); 145 | } 146 | 147 | /* 148 | * Initialize clist by freeing all character blocks, then count 149 | * number of character devices. (Once-only routine) 150 | */ 151 | cinit() 152 | { 153 | register int ccp; 154 | register struct cblock *cp; 155 | register struct cdevsw *cdp; 156 | 157 | ccp = cfree; 158 | for (cp=(ccp+07)&~07; cp <= &cfree[NCLIST-1]; cp++) { 159 | cp->c_next = cfreelist; 160 | cfreelist = cp; 161 | } 162 | ccp = 0; 163 | for(cdp = cdevsw; cdp->d_open; cdp++) 164 | ccp++; 165 | nchrdev = ccp; 166 | } 167 | 168 | /* 169 | * flush all TTY queues 170 | */ 171 | flushtty(atp) 172 | struct tty *atp; 173 | { 174 | register struct tty *tp; 175 | register int sps; 176 | 177 | tp = atp; 178 | while (getc(&tp->t_canq) >= 0); 179 | while (getc(&tp->t_outq) >= 0); 180 | wakeup(&tp->t_rawq); 181 | wakeup(&tp->t_outq); 182 | sps = PS->integ; 183 | spl5(); 184 | while (getc(&tp->t_rawq) >= 0); 185 | tp->t_delct = 0; 186 | PS->integ = sps; 187 | } 188 | 189 | /* 190 | * transfer raw input list to canonical list, 191 | * doing erase-kill processing and handling escapes. 192 | * It waits until a full line has been typed in cooked mode, 193 | * or until any character has been typed in raw mode. 194 | */ 195 | canon(atp) 196 | struct tty *atp; 197 | { 198 | register char *bp; 199 | char *bp1; 200 | register struct tty *tp; 201 | register int c; 202 | 203 | tp = atp; 204 | spl5(); 205 | while (tp->t_delct==0) { 206 | if ((tp->t_state&CARR_ON)==0) 207 | return(0); 208 | sleep(&tp->t_rawq, TTIPRI); 209 | } 210 | spl0(); 211 | loop: 212 | bp = &canonb[2]; 213 | while ((c=getc(&tp->t_rawq)) >= 0) { 214 | if (c==0377) { 215 | tp->t_delct--; 216 | break; 217 | } 218 | if ((tp->t_flags&RAW)==0) { 219 | if (bp[-1]!='\\') { 220 | if (c==tp->t_erase) { 221 | if (bp > &canonb[2]) 222 | bp--; 223 | continue; 224 | } 225 | if (c==tp->t_kill) 226 | goto loop; 227 | if (c==CEOT) 228 | continue; 229 | } else 230 | if (maptab[c] && (maptab[c]==c || (tp->t_flags&LCASE))) { 231 | if (bp[-2] != '\\') 232 | c = maptab[c]; 233 | bp--; 234 | } 235 | } 236 | *bp++ = c; 237 | if (bp>=canonb+CANBSIZ) 238 | break; 239 | } 240 | bp1 = bp; 241 | bp = &canonb[2]; 242 | c = &tp->t_canq; 243 | while (bpt_flags; 264 | if ((c =& 0177) == '\r' && t_flags&CRMOD) 265 | c = '\n'; 266 | if ((t_flags&RAW)==0 && (c==CQUIT || c==CINTR)) { 267 | signal(tp, c==CINTR? SIGINT:SIGQIT); 268 | flushtty(tp); 269 | return; 270 | } 271 | if (tp->t_rawq.c_cc>=TTYHOG) { 272 | flushtty(tp); 273 | return; 274 | } 275 | if (t_flags&LCASE && c>='A' && c<='Z') 276 | c =+ 'a'-'A'; 277 | putc(c, &tp->t_rawq); 278 | if (t_flags&RAW || c=='\n' || c==004) { 279 | wakeup(&tp->t_rawq); 280 | if (putc(0377, &tp->t_rawq)==0) 281 | tp->t_delct++; 282 | } 283 | if (t_flags&ECHO) { 284 | ttyoutput(c, tp); 285 | ttstart(tp); 286 | } 287 | } 288 | 289 | /* 290 | * put character on TTY output queue, adding delays, 291 | * expanding tabs, and handling the CR/NL bit. 292 | * It is called both from the top half for output, and from 293 | * interrupt level for echoing. 294 | * The arguments are the character and the tty structure. 295 | */ 296 | ttyoutput(ac, tp) 297 | struct tty *tp; 298 | { 299 | register int c; 300 | register struct tty *rtp; 301 | register char *colp; 302 | int ctype; 303 | 304 | rtp = tp; 305 | c = ac&0177; 306 | /* 307 | * Ignore EOT in normal mode to avoid hanging up 308 | * certain terminals. 309 | */ 310 | if (c==004 && (rtp->t_flags&RAW)==0) 311 | return; 312 | /* 313 | * Turn tabs to spaces as required 314 | */ 315 | if (c=='\t' && rtp->t_flags&XTABS) { 316 | do 317 | ttyoutput(' ', rtp); 318 | while (rtp->t_col&07); 319 | return; 320 | } 321 | /* 322 | * for upper-case-only terminals, 323 | * generate escapes. 324 | */ 325 | if (rtp->t_flags&LCASE) { 326 | colp = "({)}!|^~'`"; 327 | while(*colp++) 328 | if(c == *colp++) { 329 | ttyoutput('\\', rtp); 330 | c = colp[-2]; 331 | break; 332 | } 333 | if ('a'<=c && c<='z') 334 | c =+ 'A' - 'a'; 335 | } 336 | /* 337 | * turn to if desired. 338 | */ 339 | if (c=='\n' && rtp->t_flags&CRMOD) 340 | ttyoutput('\r', rtp); 341 | if (putc(c, &rtp->t_outq)) 342 | return; 343 | /* 344 | * Calculate delays. 345 | * The numbers here represent clock ticks 346 | * and are not necessarily optimal for all terminals. 347 | * The delays are indicated by characters above 0200, 348 | * thus (unfortunately) restricting the transmission 349 | * path to 7 bits. 350 | */ 351 | colp = &rtp->t_col; 352 | ctype = partab[c]; 353 | c = 0; 354 | switch (ctype&077) { 355 | 356 | /* ordinary */ 357 | case 0: 358 | (*colp)++; 359 | 360 | /* non-printing */ 361 | case 1: 362 | break; 363 | 364 | /* backspace */ 365 | case 2: 366 | if (*colp) 367 | (*colp)--; 368 | break; 369 | 370 | /* newline */ 371 | case 3: 372 | ctype = (rtp->t_flags >> 8) & 03; 373 | if(ctype == 1) { /* tty 37 */ 374 | if (*colp) 375 | c = max((*colp>>4) + 3, 6); 376 | } else 377 | if(ctype == 2) { /* vt05 */ 378 | c = 6; 379 | } 380 | *colp = 0; 381 | break; 382 | 383 | /* tab */ 384 | case 4: 385 | ctype = (rtp->t_flags >> 10) & 03; 386 | if(ctype == 1) { /* tty 37 */ 387 | c = 1 - (*colp | ~07); 388 | if(c < 5) 389 | c = 0; 390 | } 391 | *colp =| 07; 392 | (*colp)++; 393 | break; 394 | 395 | /* vertical motion */ 396 | case 5: 397 | if(rtp->t_flags & VTDELAY) /* tty 37 */ 398 | c = 0177; 399 | break; 400 | 401 | /* carriage return */ 402 | case 6: 403 | ctype = (rtp->t_flags >> 12) & 03; 404 | if(ctype == 1) { /* tn 300 */ 405 | c = 5; 406 | } else 407 | if(ctype == 2) { /* ti 700 */ 408 | c = 10; 409 | } 410 | *colp = 0; 411 | } 412 | if(c) 413 | putc(c|0200, &rtp->t_outq); 414 | } 415 | 416 | /* 417 | * Restart typewriter output following a delay 418 | * timeout. 419 | * The name of the routine is passed to the timeout 420 | * subroutine and it is called during a clock interrupt. 421 | */ 422 | ttrstrt(atp) 423 | { 424 | register struct tty *tp; 425 | 426 | tp = atp; 427 | tp->t_state =& ~TIMEOUT; 428 | ttstart(tp); 429 | } 430 | 431 | /* 432 | * Start output on the typewriter. It is used from the top half 433 | * after some characters have been put on the output queue, 434 | * from the interrupt routine to transmit the next 435 | * character, and after a timeout has finished. 436 | * If the SSTART bit is off for the tty the work is done here, 437 | * using the protocol of the single-line interfaces (KL, DL, DC); 438 | * otherwise the address word of the tty structure is 439 | * taken to be the name of the device-dependent startup routine. 440 | */ 441 | ttstart(atp) 442 | struct tty *atp; 443 | { 444 | register int *addr, c; 445 | register struct tty *tp; 446 | struct { int (*func)(); }; 447 | 448 | tp = atp; 449 | addr = tp->t_addr; 450 | if (tp->t_state&SSTART) { 451 | (*addr.func)(tp); 452 | return; 453 | } 454 | if ((addr->tttcsr&DONE)==0 || tp->t_state&TIMEOUT) 455 | return; 456 | if ((c=getc(&tp->t_outq)) >= 0) { 457 | if (c<=0177) 458 | addr->tttbuf = c | (partab[c]&0200); 459 | else { 460 | timeout(ttrstrt, tp, c&0177); 461 | tp->t_state =| TIMEOUT; 462 | } 463 | } 464 | } 465 | 466 | /* 467 | * Called from device's read routine after it has 468 | * calculated the tty-structure given as argument. 469 | * The pc is backed up for the duration of this call. 470 | * In case of a caught interrupt, an RTI will re-execute. 471 | */ 472 | ttread(atp) 473 | struct tty *atp; 474 | { 475 | register struct tty *tp; 476 | 477 | tp = atp; 478 | if ((tp->t_state&CARR_ON)==0) 479 | return; 480 | if (tp->t_canq.c_cc || canon(tp)) 481 | while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0); 482 | } 483 | 484 | /* 485 | * Called from the device's write routine after it has 486 | * calculated the tty-structure given as argument. 487 | */ 488 | ttwrite(atp) 489 | struct tty *atp; 490 | { 491 | register struct tty *tp; 492 | register int c; 493 | 494 | tp = atp; 495 | if ((tp->t_state&CARR_ON)==0) 496 | return; 497 | while ((c=cpass())>=0) { 498 | spl5(); 499 | while (tp->t_outq.c_cc > TTHIWAT) { 500 | ttstart(tp); 501 | tp->t_state =| ASLEEP; 502 | sleep(&tp->t_outq, TTOPRI); 503 | } 504 | spl0(); 505 | ttyoutput(c, tp); 506 | } 507 | ttstart(tp); 508 | } 509 | 510 | /* 511 | * Common code for gtty and stty functions on typewriters. 512 | * If v is non-zero then gtty is being done and information is 513 | * passed back therein; 514 | * if it is zero stty is being done and the input information is in the 515 | * u_arg array. 516 | */ 517 | ttystty(atp, av) 518 | int *atp, *av; 519 | { 520 | register *tp, *v; 521 | 522 | tp = atp; 523 | if(v = av) { 524 | *v++ = tp->t_speeds; 525 | v->lobyte = tp->t_erase; 526 | v->hibyte = tp->t_kill; 527 | v[1] = tp->t_flags; 528 | return(1); 529 | } 530 | wflushtty(tp); 531 | v = u.u_arg; 532 | tp->t_speeds = *v++; 533 | tp->t_erase = v->lobyte; 534 | tp->t_kill = v->hibyte; 535 | tp->t_flags = v[1]; 536 | return(0); 537 | } 538 | -------------------------------------------------------------------------------- /dmr/vs.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * Screw Works interface via DC-11 7 | */ 8 | 9 | #include "../tty.h" 10 | 11 | #define VSADDR 0174150 12 | #define CDLEAD 01 13 | #define B1200 030 14 | #define STOP1 0400 15 | #define CLSEND 02 16 | #define RQSEND 01 17 | 18 | #define MAGIC_MAP 0377 19 | 20 | struct { 21 | int vsrcsr; 22 | int vsrbuf; 23 | int vsxcsr; 24 | int vsxbuf; 25 | }; 26 | 27 | struct { 28 | struct clist iq; 29 | struct clist oq; 30 | } vs; 31 | 32 | vsopen(dev) 33 | { 34 | VSADDR->vsrcsr = IENABLE|B1200|CDLEAD; 35 | VSADDR->vsxcsr = STOP1|IENABLE|B1200; 36 | vschar(0); 37 | } 38 | 39 | vsclose(dev) 40 | { 41 | vschar(0); 42 | VSADDR->vsrcsr =& ~IENABLE; 43 | while (getc(&vs.iq) >= 0); 44 | } 45 | 46 | vswrite(dev) 47 | { 48 | register int count, c; 49 | 50 | count = 0; 51 | while ((c=cpass()) >= 0) { 52 | if (--count <= 0) { 53 | count = 60; 54 | vschar(0); 55 | } 56 | vschar(c); 57 | } 58 | vschar(0); 59 | } 60 | 61 | vschar(c) 62 | { 63 | 64 | c =^ MAGIC_MAP; 65 | spl5(); 66 | while (vs.oq.c_cc > 60) { 67 | vsxintr(); 68 | sleep(&vs.oq, TTIPRI); 69 | } 70 | putc(c, &vs.oq); 71 | vsxintr(); 72 | spl0(); 73 | } 74 | 75 | vsxintr() 76 | { 77 | static lchar; 78 | register c; 79 | register int *xcsr; 80 | 81 | xcsr = &VSADDR->vsxcsr; 82 | if (*xcsr&DONE) { 83 | if (lchar==MAGIC_MAP) { 84 | *xcsr =& ~RQSEND; 85 | lchar = 0; 86 | if (vs.oq.c_cc==0) 87 | goto wake; 88 | } 89 | if ((*xcsr&CLSEND) == 0) { 90 | *xcsr =& ~RQSEND; 91 | *xcsr =| RQSEND; 92 | if ((*xcsr&CLSEND) == 0) 93 | goto wake; 94 | } 95 | if ((c = getc(&vs.oq)) >= 0) 96 | VSADDR->vsxbuf = lchar = c; 97 | if (vs.oq.c_cc <= 15) 98 | wake: 99 | wakeup(&vs.oq); 100 | } 101 | } 102 | 103 | vsread(dev) 104 | { 105 | register int c; 106 | 107 | spl5(); 108 | while ((c = getc(&vs.iq)) < 0) 109 | sleep(&vs.iq, TTIPRI); 110 | spl0(); 111 | passc("?0*#?546?213?879?"[c&017]); 112 | } 113 | 114 | vsrintr() 115 | { 116 | register int c; 117 | 118 | c = VSADDR->vsrbuf; 119 | if (vs.iq.c_cc<=10) 120 | putc(c, &vs.iq); 121 | wakeup(&vs.iq); 122 | } 123 | -------------------------------------------------------------------------------- /dmr/vt.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * VT01 driver via DR11C to 11/20 7 | */ 8 | 9 | #include "../param.h" 10 | #include "../user.h" 11 | 12 | int vtflag; 13 | 14 | struct vtreg { 15 | int csr; 16 | int buf; 17 | }; 18 | 19 | #define VTADDR 0167770 20 | #define RQINT 01 21 | #define BIENABL 040 22 | #define SEOF 0100000 23 | #define VTPRI 8 24 | 25 | vtopen(dev, flag) 26 | { 27 | if (!flag) 28 | u.u_error = ENXIO; 29 | else 30 | VTADDR->csr = BIENABL; 31 | } 32 | 33 | vtclose() 34 | { 35 | VTADDR->buf = SEOF; 36 | VTADDR->csr =| RQINT; 37 | } 38 | 39 | vtwrite() 40 | { 41 | register int c; 42 | int register count; 43 | 44 | while ((c=cpass()) >= 0) { 45 | retry: 46 | for (count=0; count<10; count++) 47 | if ((VTADDR->csr&RQINT)==0) { 48 | VTADDR->buf = c&0377; 49 | VTADDR->csr =| RQINT; 50 | goto contin; 51 | } 52 | spl5(); 53 | if (VTADDR->csr&RQINT) { 54 | vtflag++; 55 | sleep(VTADDR, VTPRI); 56 | } 57 | spl0(); 58 | goto retry; 59 | contin:; 60 | } 61 | } 62 | 63 | vtintr() 64 | { 65 | VTADDR->csr =& ~RQINT; 66 | if (vtflag) { 67 | vtflag = 0; 68 | wakeup(VTADDR); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /file.h: -------------------------------------------------------------------------------- 1 | /* 2 | * One file structure is allocated 3 | * for each open/creat/pipe call. 4 | * Main use is to hold the read/write 5 | * pointer associated with each open 6 | * file. 7 | */ 8 | struct file 9 | { 10 | char f_flag; 11 | char f_count; /* reference count */ 12 | int f_inode; /* pointer to inode structure */ 13 | char *f_offset[2]; /* read/write character pointer */ 14 | } file[NFILE]; 15 | 16 | /* flags */ 17 | #define FREAD 01 18 | #define FWRITE 02 19 | #define FPIPE 04 20 | -------------------------------------------------------------------------------- /filsys.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Definition of the unix super block. 3 | * The root super block is allocated and 4 | * read in iinit/alloc.c. Subsequently 5 | * a super block is allocated and read 6 | * with each mount (smount/sys3.c) and 7 | * released with unmount (sumount/sys3.c). 8 | * A disk block is ripped off for storage. 9 | * See alloc.c for general alloc/free 10 | * routines for free list and I list. 11 | */ 12 | struct filsys 13 | { 14 | int s_isize; /* size in blocks of I list */ 15 | int s_fsize; /* size in blocks of entire volume */ 16 | int s_nfree; /* number of in core free blocks (0-100) */ 17 | int s_free[100]; /* in core free blocks */ 18 | int s_ninode; /* number of in core I nodes (0-100) */ 19 | int s_inode[100]; /* in core free I nodes */ 20 | char s_flock; /* lock during free list manipulation */ 21 | char s_ilock; /* lock during I list manipulation */ 22 | char s_fmod; /* super block modified flag */ 23 | char s_ronly; /* mounted read-only flag */ 24 | int s_time[2]; /* current date of last update */ 25 | int pad[50]; 26 | }; 27 | -------------------------------------------------------------------------------- /ino.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Inode structure as it appears on 3 | * the disk. Not used by the system, 4 | * but by things like check, df, dump. 5 | */ 6 | struct inode 7 | { 8 | int i_mode; 9 | char i_nlink; 10 | char i_uid; 11 | char i_gid; 12 | char i_size0; 13 | char *i_size1; 14 | int i_addr[8]; 15 | int i_atime[2]; 16 | int i_mtime[2]; 17 | }; 18 | 19 | /* modes */ 20 | #define IALLOC 0100000 21 | #define IFMT 060000 22 | #define IFDIR 040000 23 | #define IFCHR 020000 24 | #define IFBLK 060000 25 | #define ILARG 010000 26 | #define ISUID 04000 27 | #define ISGID 02000 28 | #define ISVTX 01000 29 | #define IREAD 0400 30 | #define IWRITE 0200 31 | #define IEXEC 0100 32 | -------------------------------------------------------------------------------- /inode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The I node is the focus of all 3 | * file activity in unix. There is a unique 4 | * inode allocated for each active file, 5 | * each current directory, each mounted-on 6 | * file, text file, and the root. An inode is 'named' 7 | * by its dev/inumber pair. (iget/iget.c) 8 | * Data, from mode on, is read in 9 | * from permanent inode on volume. 10 | */ 11 | struct inode 12 | { 13 | char i_flag; 14 | char i_count; /* reference count */ 15 | int i_dev; /* device where inode resides */ 16 | int i_number; /* i number, 1-to-1 with device address */ 17 | int i_mode; 18 | char i_nlink; /* directory entries */ 19 | char i_uid; /* owner */ 20 | char i_gid; /* group of owner */ 21 | char i_size0; /* most significant of size */ 22 | char *i_size1; /* least sig */ 23 | int i_addr[8]; /* device addresses constituting file */ 24 | int i_lastr; /* last logical block read (for read-ahead) */ 25 | } inode[NINODE]; 26 | 27 | /* flags */ 28 | #define ILOCK 01 /* inode is locked */ 29 | #define IUPD 02 /* inode has been modified */ 30 | #define IACC 04 /* inode access time to be updated */ 31 | #define IMOUNT 010 /* inode is mounted on */ 32 | #define IWANT 020 /* some process waiting on lock */ 33 | #define ITEXT 040 /* inode is pure text prototype */ 34 | 35 | /* modes */ 36 | #define IALLOC 0100000 /* file is used */ 37 | #define IFMT 060000 /* type of file */ 38 | #define IFDIR 040000 /* directory */ 39 | #define IFCHR 020000 /* character special */ 40 | #define IFBLK 060000 /* block special, 0 is regular */ 41 | #define ILARG 010000 /* large addressing algorithm */ 42 | #define ISUID 04000 /* set user id on execution */ 43 | #define ISGID 02000 /* set group id on execution */ 44 | #define ISVTX 01000 /* save swapped text even after use */ 45 | #define IREAD 0400 /* read, write, execute permissions */ 46 | #define IWRITE 0200 47 | #define IEXEC 0100 48 | -------------------------------------------------------------------------------- /ken/alloc.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | #include "../param.h" 6 | #include "../systm.h" 7 | #include "../filsys.h" 8 | #include "../conf.h" 9 | #include "../buf.h" 10 | #include "../inode.h" 11 | #include "../user.h" 12 | 13 | /* 14 | * iinit is called once (from main) 15 | * very early in initialization. 16 | * It reads the root's super block 17 | * and initializes the current date 18 | * from the last modified date. 19 | * 20 | * panic: iinit -- cannot read the super 21 | * block. Usually because of an IO error. 22 | */ 23 | iinit() 24 | { 25 | register *cp, *bp; 26 | 27 | (*bdevsw[rootdev.d_major].d_open)(rootdev, 1); 28 | bp = bread(rootdev, 1); 29 | cp = getblk(NODEV); 30 | if(u.u_error) 31 | panic("iinit"); 32 | bcopy(bp->b_addr, cp->b_addr, 256); 33 | brelse(bp); 34 | mount[0].m_bufp = cp; 35 | mount[0].m_dev = rootdev; 36 | cp = cp->b_addr; 37 | cp->s_flock = 0; 38 | cp->s_ilock = 0; 39 | cp->s_ronly = 0; 40 | time[0] = cp->s_time[0]; 41 | time[1] = cp->s_time[1]; 42 | } 43 | 44 | /* 45 | * alloc will obtain the next available 46 | * free disk block from the free list of 47 | * the specified device. 48 | * The super block has up to 100 remembered 49 | * free blocks; the last of these is read to 50 | * obtain 100 more . . . 51 | * 52 | * no space on dev x/y -- when 53 | * the free list is exhausted. 54 | */ 55 | alloc(dev) 56 | { 57 | int bno; 58 | register *bp, *ip, *fp; 59 | 60 | fp = getfs(dev); 61 | while(fp->s_flock) 62 | sleep(&fp->s_flock, PINOD); 63 | do { 64 | if(fp->s_nfree <= 0) 65 | goto nospace; 66 | bno = fp->s_free[--fp->s_nfree]; 67 | if(bno == 0) 68 | goto nospace; 69 | } while (badblock(fp, bno, dev)); 70 | if(fp->s_nfree <= 0) { 71 | fp->s_flock++; 72 | bp = bread(dev, bno); 73 | ip = bp->b_addr; 74 | fp->s_nfree = *ip++; 75 | bcopy(ip, fp->s_free, 100); 76 | brelse(bp); 77 | fp->s_flock = 0; 78 | wakeup(&fp->s_flock); 79 | } 80 | bp = getblk(dev, bno); 81 | clrbuf(bp); 82 | fp->s_fmod = 1; 83 | return(bp); 84 | 85 | nospace: 86 | fp->s_nfree = 0; 87 | prdev("no space", dev); 88 | u.u_error = ENOSPC; 89 | return(NULL); 90 | } 91 | 92 | /* 93 | * place the specified disk block 94 | * back on the free list of the 95 | * specified device. 96 | */ 97 | free(dev, bno) 98 | { 99 | register *fp, *bp, *ip; 100 | 101 | fp = getfs(dev); 102 | fp->s_fmod = 1; 103 | while(fp->s_flock) 104 | sleep(&fp->s_flock, PINOD); 105 | if (badblock(fp, bno, dev)) 106 | return; 107 | if(fp->s_nfree <= 0) { 108 | fp->s_nfree = 1; 109 | fp->s_free[0] = 0; 110 | } 111 | if(fp->s_nfree >= 100) { 112 | fp->s_flock++; 113 | bp = getblk(dev, bno); 114 | ip = bp->b_addr; 115 | *ip++ = fp->s_nfree; 116 | bcopy(fp->s_free, ip, 100); 117 | fp->s_nfree = 0; 118 | bwrite(bp); 119 | fp->s_flock = 0; 120 | wakeup(&fp->s_flock); 121 | } 122 | fp->s_free[fp->s_nfree++] = bno; 123 | fp->s_fmod = 1; 124 | } 125 | 126 | /* 127 | * Check that a block number is in the 128 | * range between the I list and the size 129 | * of the device. 130 | * This is used mainly to check that a 131 | * garbage file system has not been mounted. 132 | * 133 | * bad block on dev x/y -- not in range 134 | */ 135 | badblock(afp, abn, dev) 136 | { 137 | register struct filsys *fp; 138 | register char *bn; 139 | 140 | fp = afp; 141 | bn = abn; 142 | if (bn < fp->s_isize+2 || bn >= fp->s_fsize) { 143 | prdev("bad block", dev); 144 | return(1); 145 | } 146 | return(0); 147 | } 148 | 149 | /* 150 | * Allocate an unused I node 151 | * on the specified device. 152 | * Used with file creation. 153 | * The algorithm keeps up to 154 | * 100 spare I nodes in the 155 | * super block. When this runs out, 156 | * a linear search through the 157 | * I list is instituted to pick 158 | * up 100 more. 159 | */ 160 | ialloc(dev) 161 | { 162 | register *fp, *bp, *ip; 163 | int i, j, k, ino; 164 | 165 | fp = getfs(dev); 166 | while(fp->s_ilock) 167 | sleep(&fp->s_ilock, PINOD); 168 | loop: 169 | if(fp->s_ninode > 0) { 170 | ino = fp->s_inode[--fp->s_ninode]; 171 | ip = iget(dev, ino); 172 | if (ip==NULL) 173 | return(NULL); 174 | if(ip->i_mode == 0) { 175 | for(bp = &ip->i_mode; bp < &ip->i_addr[8];) 176 | *bp++ = 0; 177 | fp->s_fmod = 1; 178 | return(ip); 179 | } 180 | /* 181 | * Inode was allocated after all. 182 | * Look some more. 183 | */ 184 | iput(ip); 185 | goto loop; 186 | } 187 | fp->s_ilock++; 188 | ino = 0; 189 | for(i=0; is_isize; i++) { 190 | bp = bread(dev, i+2); 191 | ip = bp->b_addr; 192 | for(j=0; j<256; j=+16) { 193 | ino++; 194 | if(ip[j] != 0) 195 | continue; 196 | for(k=0; ks_inode[fp->s_ninode++] = ino; 200 | if(fp->s_ninode >= 100) 201 | break; 202 | cont:; 203 | } 204 | brelse(bp); 205 | if(fp->s_ninode >= 100) 206 | break; 207 | } 208 | fp->s_ilock = 0; 209 | wakeup(&fp->s_ilock); 210 | if (fp->s_ninode > 0) 211 | goto loop; 212 | prdev("Out of inodes", dev); 213 | u.u_error = ENOSPC; 214 | return(NULL); 215 | } 216 | 217 | /* 218 | * Free the specified I node 219 | * on the specified device. 220 | * The algorithm stores up 221 | * to 100 I nodes in the super 222 | * block and throws away any more. 223 | */ 224 | ifree(dev, ino) 225 | { 226 | register *fp; 227 | 228 | fp = getfs(dev); 229 | if(fp->s_ilock) 230 | return; 231 | if(fp->s_ninode >= 100) 232 | return; 233 | fp->s_inode[fp->s_ninode++] = ino; 234 | fp->s_fmod = 1; 235 | } 236 | 237 | /* 238 | * getfs maps a device number into 239 | * a pointer to the incore super 240 | * block. 241 | * The algorithm is a linear 242 | * search through the mount table. 243 | * A consistency check of the 244 | * in core free-block and i-node 245 | * counts. 246 | * 247 | * bad count on dev x/y -- the count 248 | * check failed. At this point, all 249 | * the counts are zeroed which will 250 | * almost certainly lead to "no space" 251 | * diagnostic 252 | * panic: no fs -- the device is not mounted. 253 | * this "cannot happen" 254 | */ 255 | getfs(dev) 256 | { 257 | register struct mount *p; 258 | register char *n1, *n2; 259 | 260 | for(p = &mount[0]; p < &mount[NMOUNT]; p++) 261 | if(p->m_bufp != NULL && p->m_dev == dev) { 262 | p = p->m_bufp->b_addr; 263 | n1 = p->s_nfree; 264 | n2 = p->s_ninode; 265 | if(n1 > 100 || n2 > 100) { 266 | prdev("bad count", dev); 267 | p->s_nfree = 0; 268 | p->s_ninode = 0; 269 | } 270 | return(p); 271 | } 272 | panic("no fs"); 273 | } 274 | 275 | /* 276 | * update is the internal name of 277 | * 'sync'. It goes through the disk 278 | * queues to initiate sandbagged IO; 279 | * goes through the I nodes to write 280 | * modified nodes; and it goes through 281 | * the mount table to initiate modified 282 | * super blocks. 283 | */ 284 | update() 285 | { 286 | register struct inode *ip; 287 | register struct mount *mp; 288 | register *bp; 289 | 290 | if(updlock) 291 | return; 292 | updlock++; 293 | for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 294 | if(mp->m_bufp != NULL) { 295 | ip = mp->m_bufp->b_addr; 296 | if(ip->s_fmod==0 || ip->s_ilock!=0 || 297 | ip->s_flock!=0 || ip->s_ronly!=0) 298 | continue; 299 | bp = getblk(mp->m_dev, 1); 300 | ip->s_fmod = 0; 301 | ip->s_time[0] = time[0]; 302 | ip->s_time[1] = time[1]; 303 | bcopy(ip, bp->b_addr, 256); 304 | bwrite(bp); 305 | } 306 | for(ip = &inode[0]; ip < &inode[NINODE]; ip++) 307 | if((ip->i_flag&ILOCK) == 0) { 308 | ip->i_flag =| ILOCK; 309 | iupdat(ip, time); 310 | prele(ip); 311 | } 312 | updlock = 0; 313 | bflush(NODEV); 314 | } 315 | -------------------------------------------------------------------------------- /ken/clock.c: -------------------------------------------------------------------------------- 1 | # 2 | #include "../param.h" 3 | #include "../systm.h" 4 | #include "../user.h" 5 | #include "../proc.h" 6 | 7 | #define UMODE 0170000 8 | #define SCHMAG 10 9 | 10 | /* 11 | * clock is called straight from 12 | * the real time clock interrupt. 13 | * 14 | * Functions: 15 | * reprime clock 16 | * copy *switches to display 17 | * implement callouts 18 | * maintain user/system times 19 | * maintain date 20 | * profile 21 | * tout wakeup (sys sleep) 22 | * lightning bolt wakeup (every 4 sec) 23 | * alarm clock signals 24 | * jab the scheduler 25 | */ 26 | clock(dev, sp, r1, nps, r0, pc, ps) 27 | { 28 | register struct callo *p1, *p2; 29 | register struct proc *pp; 30 | 31 | /* 32 | * restart clock 33 | */ 34 | 35 | *lks = 0115; 36 | 37 | /* 38 | * display register 39 | */ 40 | 41 | display(); 42 | 43 | /* 44 | * callouts 45 | * if none, just return 46 | * else update first non-zero time 47 | */ 48 | 49 | if(callout[0].c_func == 0) 50 | goto out; 51 | p2 = &callout[0]; 52 | while(p2->c_time<=0 && p2->c_func!=0) 53 | p2++; 54 | p2->c_time--; 55 | 56 | /* 57 | * if ps is high, just return 58 | */ 59 | 60 | if((ps&0340) != 0) 61 | goto out; 62 | 63 | /* 64 | * callout 65 | */ 66 | 67 | spl5(); 68 | if(callout[0].c_time <= 0) { 69 | p1 = &callout[0]; 70 | while(p1->c_func != 0 && p1->c_time <= 0) { 71 | (*p1->c_func)(p1->c_arg); 72 | p1++; 73 | } 74 | p2 = &callout[0]; 75 | while(p2->c_func = p1->c_func) { 76 | p2->c_time = p1->c_time; 77 | p2->c_arg = p1->c_arg; 78 | p1++; 79 | p2++; 80 | } 81 | } 82 | 83 | /* 84 | * lightning bolt time-out 85 | * and time of day 86 | */ 87 | 88 | out: 89 | if((ps&UMODE) == UMODE) { 90 | u.u_utime++; 91 | if(u.u_prof[3]) 92 | incupc(pc, u.u_prof); 93 | } else 94 | u.u_stime++; 95 | pp = u.u_procp; 96 | if(++pp->p_cpu == 0) 97 | pp->p_cpu--; 98 | if(++lbolt >= HZ) { 99 | if((ps&0340) != 0) 100 | return; 101 | lbolt =- HZ; 102 | if(++time[1] == 0) 103 | ++time[0]; 104 | spl1(); 105 | if(time[1]==tout[1] && time[0]==tout[0]) 106 | wakeup(tout); 107 | if((time[1]&03) == 0) { 108 | runrun++; 109 | wakeup(&lbolt); 110 | } 111 | for(pp = &proc[0]; pp < &proc[NPROC]; pp++) 112 | if (pp->p_stat) { 113 | if(pp->p_time != 127) 114 | pp->p_time++; 115 | if((pp->p_cpu & 0377) > SCHMAG) 116 | pp->p_cpu =- SCHMAG; else 117 | pp->p_cpu = 0; 118 | if(pp->p_pri > PUSER) 119 | setpri(pp); 120 | } 121 | if(runin!=0) { 122 | runin = 0; 123 | wakeup(&runin); 124 | } 125 | if((ps&UMODE) == UMODE) { 126 | u.u_ar0 = &r0; 127 | if(issig()) 128 | psig(); 129 | setpri(u.u_procp); 130 | } 131 | } 132 | } 133 | 134 | /* 135 | * timeout is called to arrange that 136 | * fun(arg) is called in tim/HZ seconds. 137 | * An entry is sorted into the callout 138 | * structure. The time in each structure 139 | * entry is the number of HZ's more 140 | * than the previous entry. 141 | * In this way, decrementing the 142 | * first entry has the effect of 143 | * updating all entries. 144 | */ 145 | timeout(fun, arg, tim) 146 | { 147 | register struct callo *p1, *p2; 148 | register t; 149 | int s; 150 | 151 | t = tim; 152 | s = PS->integ; 153 | p1 = &callout[0]; 154 | spl7(); 155 | while(p1->c_func != 0 && p1->c_time <= t) { 156 | t =- p1->c_time; 157 | p1++; 158 | } 159 | p1->c_time =- t; 160 | p2 = p1; 161 | while(p2->c_func != 0) 162 | p2++; 163 | while(p2 >= p1) { 164 | (p2+1)->c_time = p2->c_time; 165 | (p2+1)->c_func = p2->c_func; 166 | (p2+1)->c_arg = p2->c_arg; 167 | p2--; 168 | } 169 | p1->c_time = t; 170 | p1->c_func = fun; 171 | p1->c_arg = arg; 172 | PS->integ = s; 173 | } 174 | -------------------------------------------------------------------------------- /ken/fio.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | #include "../param.h" 6 | #include "../user.h" 7 | #include "../filsys.h" 8 | #include "../file.h" 9 | #include "../conf.h" 10 | #include "../inode.h" 11 | #include "../reg.h" 12 | 13 | /* 14 | * Convert a user supplied 15 | * file descriptor into a pointer 16 | * to a file structure. 17 | * Only task is to check range 18 | * of the descriptor. 19 | */ 20 | getf(f) 21 | { 22 | register *fp, rf; 23 | 24 | rf = f; 25 | if(rf<0 || rf>=NOFILE) 26 | goto bad; 27 | fp = u.u_ofile[rf]; 28 | if(fp != NULL) 29 | return(fp); 30 | bad: 31 | u.u_error = EBADF; 32 | return(NULL); 33 | } 34 | 35 | /* 36 | * Internal form of close. 37 | * Decrement reference count on 38 | * file structure and call closei 39 | * on last closef. 40 | * Also make sure the pipe protocol 41 | * does not constipate. 42 | */ 43 | closef(fp) 44 | int *fp; 45 | { 46 | register *rfp, *ip; 47 | 48 | rfp = fp; 49 | if(rfp->f_flag&FPIPE) { 50 | ip = rfp->f_inode; 51 | ip->i_mode =& ~(IREAD|IWRITE); 52 | wakeup(ip+1); 53 | wakeup(ip+2); 54 | } 55 | if(rfp->f_count <= 1) 56 | closei(rfp->f_inode, rfp->f_flag&FWRITE); 57 | rfp->f_count--; 58 | } 59 | 60 | /* 61 | * Decrement reference count on an 62 | * inode due to the removal of a 63 | * referencing file structure. 64 | * On the last closei, switchout 65 | * to the close entry point of special 66 | * device handler. 67 | * Note that the handler gets called 68 | * on every open and only on the last 69 | * close. 70 | */ 71 | closei(ip, rw) 72 | int *ip; 73 | { 74 | register *rip; 75 | register dev, maj; 76 | 77 | rip = ip; 78 | dev = rip->i_addr[0]; 79 | maj = rip->i_addr[0].d_major; 80 | if(rip->i_count <= 1) 81 | switch(rip->i_mode&IFMT) { 82 | 83 | case IFCHR: 84 | (*cdevsw[maj].d_close)(dev, rw); 85 | break; 86 | 87 | case IFBLK: 88 | (*bdevsw[maj].d_close)(dev, rw); 89 | } 90 | iput(rip); 91 | } 92 | 93 | /* 94 | * openi called to allow handler 95 | * of special files to initialize and 96 | * validate before actual IO. 97 | * Called on all sorts of opens 98 | * and also on mount. 99 | */ 100 | openi(ip, rw) 101 | int *ip; 102 | { 103 | register *rip; 104 | register dev, maj; 105 | 106 | rip = ip; 107 | dev = rip->i_addr[0]; 108 | maj = rip->i_addr[0].d_major; 109 | switch(rip->i_mode&IFMT) { 110 | 111 | case IFCHR: 112 | if(maj >= nchrdev) 113 | goto bad; 114 | (*cdevsw[maj].d_open)(dev, rw); 115 | break; 116 | 117 | case IFBLK: 118 | if(maj >= nblkdev) 119 | goto bad; 120 | (*bdevsw[maj].d_open)(dev, rw); 121 | } 122 | return; 123 | 124 | bad: 125 | u.u_error = ENXIO; 126 | } 127 | 128 | /* 129 | * Check mode permission on inode pointer. 130 | * Mode is READ, WRITE or EXEC. 131 | * In the case of WRITE, the 132 | * read-only status of the file 133 | * system is checked. 134 | * Also in WRITE, prototype text 135 | * segments cannot be written. 136 | * The mode is shifted to select 137 | * the owner/group/other fields. 138 | * The super user is granted all 139 | * permissions except for EXEC where 140 | * at least one of the EXEC bits must 141 | * be on. 142 | */ 143 | access(aip, mode) 144 | int *aip; 145 | { 146 | register *ip, m; 147 | 148 | ip = aip; 149 | m = mode; 150 | if(m == IWRITE) { 151 | if(getfs(ip->i_dev)->s_ronly != 0) { 152 | u.u_error = EROFS; 153 | return(1); 154 | } 155 | if(ip->i_flag & ITEXT) { 156 | u.u_error = ETXTBSY; 157 | return(1); 158 | } 159 | } 160 | if(u.u_uid == 0) { 161 | if(m == IEXEC && (ip->i_mode & 162 | (IEXEC | (IEXEC>>3) | (IEXEC>>6))) == 0) 163 | goto bad; 164 | return(0); 165 | } 166 | if(u.u_uid != ip->i_uid) { 167 | m =>> 3; 168 | if(u.u_gid != ip->i_gid) 169 | m =>> 3; 170 | } 171 | if((ip->i_mode&m) != 0) 172 | return(0); 173 | 174 | bad: 175 | u.u_error = EACCES; 176 | return(1); 177 | } 178 | 179 | /* 180 | * Look up a pathname and test if 181 | * the resultant inode is owned by the 182 | * current user. 183 | * If not, try for super-user. 184 | * If permission is granted, 185 | * return inode pointer. 186 | */ 187 | owner() 188 | { 189 | register struct inode *ip; 190 | extern uchar(); 191 | 192 | if ((ip = namei(uchar, 0)) == NULL) 193 | return(NULL); 194 | if(u.u_uid == ip->i_uid) 195 | return(ip); 196 | if (suser()) 197 | return(ip); 198 | iput(ip); 199 | return(NULL); 200 | } 201 | 202 | /* 203 | * Test if the current user is the 204 | * super user. 205 | */ 206 | suser() 207 | { 208 | 209 | if(u.u_uid == 0) 210 | return(1); 211 | u.u_error = EPERM; 212 | return(0); 213 | } 214 | 215 | /* 216 | * Allocate a user file descriptor. 217 | */ 218 | ufalloc() 219 | { 220 | register i; 221 | 222 | for (i=0; if_count==0) { 249 | u.u_ofile[i] = fp; 250 | fp->f_count++; 251 | fp->f_offset[0] = 0; 252 | fp->f_offset[1] = 0; 253 | return(fp); 254 | } 255 | printf("no file\n"); 256 | u.u_error = ENFILE; 257 | return(NULL); 258 | } 259 | -------------------------------------------------------------------------------- /ken/iget.c: -------------------------------------------------------------------------------- 1 | # 2 | #include "../param.h" 3 | #include "../systm.h" 4 | #include "../user.h" 5 | #include "../inode.h" 6 | #include "../filsys.h" 7 | #include "../conf.h" 8 | #include "../buf.h" 9 | 10 | /* 11 | * Look up an inode by device,inumber. 12 | * If it is in core (in the inode structure), 13 | * honor the locking protocol. 14 | * If it is not in core, read it in from the 15 | * specified device. 16 | * If the inode is mounted on, perform 17 | * the indicated indirection. 18 | * In all cases, a pointer to a locked 19 | * inode structure is returned. 20 | * 21 | * printf warning: no inodes -- if the inode 22 | * structure is full 23 | * panic: no imt -- if the mounted file 24 | * system is not in the mount table. 25 | * "cannot happen" 26 | */ 27 | iget(dev, ino) 28 | { 29 | register struct inode *p; 30 | register *ip2; 31 | int *ip1; 32 | register struct mount *ip; 33 | 34 | loop: 35 | ip = NULL; 36 | for(p = &inode[0]; p < &inode[NINODE]; p++) { 37 | if(dev==p->i_dev && ino==p->i_number) { 38 | if((p->i_flag&ILOCK) != 0) { 39 | p->i_flag =| IWANT; 40 | sleep(p, PINOD); 41 | goto loop; 42 | } 43 | if((p->i_flag&IMOUNT) != 0) { 44 | for(ip = &mount[0]; ip < &mount[NMOUNT]; ip++) 45 | if(ip->m_inodp == p) { 46 | dev = ip->m_dev; 47 | ino = ROOTINO; 48 | goto loop; 49 | } 50 | panic("no imt"); 51 | } 52 | p->i_count++; 53 | p->i_flag =| ILOCK; 54 | return(p); 55 | } 56 | if(ip==NULL && p->i_count==0) 57 | ip = p; 58 | } 59 | if((p=ip) == NULL) { 60 | printf("Inode table overflow\n"); 61 | u.u_error = ENFILE; 62 | return(NULL); 63 | } 64 | p->i_dev = dev; 65 | p->i_number = ino; 66 | p->i_flag = ILOCK; 67 | p->i_count++; 68 | p->i_lastr = -1; 69 | ip = bread(dev, ldiv(ino+31,16)); 70 | /* 71 | * Check I/O errors 72 | */ 73 | if (ip->b_flags&B_ERROR) { 74 | brelse(ip); 75 | iput(p); 76 | return(NULL); 77 | } 78 | ip1 = ip->b_addr + 32*lrem(ino+31, 16); 79 | ip2 = &p->i_mode; 80 | while(ip2 < &p->i_addr[8]) 81 | *ip2++ = *ip1++; 82 | brelse(ip); 83 | return(p); 84 | } 85 | 86 | /* 87 | * Decrement reference count of 88 | * an inode structure. 89 | * On the last reference, 90 | * write the inode out and if necessary, 91 | * truncate and deallocate the file. 92 | */ 93 | iput(p) 94 | struct inode *p; 95 | { 96 | register *rp; 97 | 98 | rp = p; 99 | if(rp->i_count == 1) { 100 | rp->i_flag =| ILOCK; 101 | if(rp->i_nlink <= 0) { 102 | itrunc(rp); 103 | rp->i_mode = 0; 104 | ifree(rp->i_dev, rp->i_number); 105 | } 106 | iupdat(rp, time); 107 | prele(rp); 108 | rp->i_flag = 0; 109 | rp->i_number = 0; 110 | } 111 | rp->i_count--; 112 | prele(rp); 113 | } 114 | 115 | /* 116 | * Check accessed and update flags on 117 | * an inode structure. 118 | * If either is on, update the inode 119 | * with the corresponding dates 120 | * set to the argument tm. 121 | */ 122 | iupdat(p, tm) 123 | int *p; 124 | int *tm; 125 | { 126 | register *ip1, *ip2, *rp; 127 | int *bp, i; 128 | 129 | rp = p; 130 | if((rp->i_flag&(IUPD|IACC)) != 0) { 131 | if(getfs(rp->i_dev)->s_ronly) 132 | return; 133 | i = rp->i_number+31; 134 | bp = bread(rp->i_dev, ldiv(i,16)); 135 | ip1 = bp->b_addr + 32*lrem(i, 16); 136 | ip2 = &rp->i_mode; 137 | while(ip2 < &rp->i_addr[8]) 138 | *ip1++ = *ip2++; 139 | if(rp->i_flag&IACC) { 140 | *ip1++ = time[0]; 141 | *ip1++ = time[1]; 142 | } else 143 | ip1 =+ 2; 144 | if(rp->i_flag&IUPD) { 145 | *ip1++ = *tm++; 146 | *ip1++ = *tm; 147 | } 148 | bwrite(bp); 149 | } 150 | } 151 | 152 | /* 153 | * Free all the disk blocks associated 154 | * with the specified inode structure. 155 | * The blocks of the file are removed 156 | * in reverse order. This FILO 157 | * algorithm will tend to maintain 158 | * a contiguous free list much longer 159 | * than FIFO. 160 | */ 161 | itrunc(ip) 162 | int *ip; 163 | { 164 | register *rp, *bp, *cp; 165 | int *dp, *ep; 166 | 167 | rp = ip; 168 | if((rp->i_mode&(IFCHR&IFBLK)) != 0) 169 | return; 170 | for(ip = &rp->i_addr[7]; ip >= &rp->i_addr[0]; ip--) 171 | if(*ip) { 172 | if((rp->i_mode&ILARG) != 0) { 173 | bp = bread(rp->i_dev, *ip); 174 | for(cp = bp->b_addr+512; cp >= bp->b_addr; cp--) 175 | if(*cp) { 176 | if(ip == &rp->i_addr[7]) { 177 | dp = bread(rp->i_dev, *cp); 178 | for(ep = dp->b_addr+512; ep >= dp->b_addr; ep--) 179 | if(*ep) 180 | free(rp->i_dev, *ep); 181 | brelse(dp); 182 | } 183 | free(rp->i_dev, *cp); 184 | } 185 | brelse(bp); 186 | } 187 | free(rp->i_dev, *ip); 188 | *ip = 0; 189 | } 190 | rp->i_mode =& ~ILARG; 191 | rp->i_size0 = 0; 192 | rp->i_size1 = 0; 193 | rp->i_flag =| IUPD; 194 | } 195 | 196 | /* 197 | * Make a new file. 198 | */ 199 | maknode(mode) 200 | { 201 | register *ip; 202 | 203 | ip = ialloc(u.u_pdir->i_dev); 204 | if (ip==NULL) 205 | return(NULL); 206 | ip->i_flag =| IACC|IUPD; 207 | ip->i_mode = mode|IALLOC; 208 | ip->i_nlink = 1; 209 | ip->i_uid = u.u_uid; 210 | ip->i_gid = u.u_gid; 211 | wdir(ip); 212 | return(ip); 213 | } 214 | 215 | /* 216 | * Write a directory entry with 217 | * parameters left as side effects 218 | * to a call to namei. 219 | */ 220 | wdir(ip) 221 | int *ip; 222 | { 223 | register char *cp1, *cp2; 224 | 225 | u.u_dent.u_ino = ip->i_number; 226 | cp1 = &u.u_dent.u_name[0]; 227 | for(cp2 = &u.u_dbuf[0]; cp2 < &u.u_dbuf[DIRSIZ];) 228 | *cp1++ = *cp2++; 229 | u.u_count = DIRSIZ+2; 230 | u.u_segflg = 1; 231 | u.u_base = &u.u_dent; 232 | writei(u.u_pdir); 233 | iput(u.u_pdir); 234 | } 235 | -------------------------------------------------------------------------------- /ken/main.c: -------------------------------------------------------------------------------- 1 | # 2 | #include "../param.h" 3 | #include "../user.h" 4 | #include "../systm.h" 5 | #include "../proc.h" 6 | #include "../text.h" 7 | #include "../inode.h" 8 | #include "../seg.h" 9 | 10 | #define CLOCK1 0177546 11 | #define CLOCK2 0172540 12 | /* 13 | * Icode is the octal bootstrap 14 | * program executed in user mode 15 | * to bring up the system. 16 | */ 17 | int icode[] 18 | { 19 | 0104413, /* sys exec; init; initp */ 20 | 0000014, 21 | 0000010, 22 | 0000777, /* br . */ 23 | 0000014, /* initp: init; 0 */ 24 | 0000000, 25 | 0062457, /* init: */ 26 | 0061564, 27 | 0064457, 28 | 0064556, 29 | 0000164, 30 | }; 31 | 32 | /* 33 | * Initialization code. 34 | * Called from m40.s or m45.s as 35 | * soon as a stack and segmentation 36 | * have been established. 37 | * Functions: 38 | * clear and free user core 39 | * find which clock is configured 40 | * hand craft 0th process 41 | * call all initialization routines 42 | * fork - process 0 to schedule 43 | * - process 1 execute bootstrap 44 | * 45 | * panic: no clock -- neither clock responds 46 | * loop at loc 6 in user mode -- /etc/init 47 | * cannot be executed. 48 | */ 49 | main() 50 | { 51 | extern schar; 52 | register i, *p; 53 | 54 | /* 55 | * zero and free all of core 56 | */ 57 | 58 | updlock = 0; 59 | i = *ka6 + USIZE; 60 | UISD->r[0] = 077406; 61 | for(;;) { 62 | UISA->r[0] = i; 63 | if(fuibyte(0) < 0) 64 | break; 65 | clearseg(i); 66 | maxmem++; 67 | mfree(coremap, 1, i); 68 | i++; 69 | } 70 | if(cputype == 70) 71 | for(i=0; i<62; i=+2) { 72 | UBMAP->r[i] = i<<12; 73 | UBMAP->r[i+1] = 0; 74 | } 75 | printf("mem = %l\n", maxmem*5/16); 76 | maxmem = min(maxmem, MAXMEM); 77 | mfree(swapmap, nswap, swplo); 78 | 79 | /* 80 | * determine clock 81 | */ 82 | 83 | UISA->r[7] = ka6[1]; /* io segment */ 84 | UISD->r[7] = 077406; 85 | lks = CLOCK1; 86 | if(fuiword(lks) == -1) { 87 | lks = CLOCK2; 88 | if(fuiword(lks) == -1) 89 | panic("no clock"); 90 | } 91 | 92 | /* 93 | * set up system process 94 | */ 95 | 96 | proc[0].p_addr = *ka6; 97 | proc[0].p_size = USIZE; 98 | proc[0].p_stat = SRUN; 99 | proc[0].p_flag =| SLOAD|SSYS; 100 | u.u_procp = &proc[0]; 101 | 102 | /* 103 | * set up 'known' i-nodes 104 | */ 105 | 106 | *lks = 0115; 107 | cinit(); 108 | binit(); 109 | iinit(); 110 | rootdir = iget(rootdev, ROOTINO); 111 | rootdir->i_flag =& ~ILOCK; 112 | u.u_cdir = iget(rootdev, ROOTINO); 113 | u.u_cdir->i_flag =& ~ILOCK; 114 | 115 | /* 116 | * make init process 117 | * enter scheduling loop 118 | * with system process 119 | */ 120 | 121 | if(newproc()) { 122 | expand(USIZE+1); 123 | estabur(0, 1, 0, 0); 124 | copyout(icode, 0, sizeof icode); 125 | /* 126 | * Return goes to loc. 0 of user init 127 | * code just copied out. 128 | */ 129 | return; 130 | } 131 | sched(); 132 | } 133 | 134 | /* 135 | * Load the user hardware segmentation 136 | * registers from the software prototype. 137 | * The software registers must have 138 | * been setup prior by estabur. 139 | */ 140 | sureg() 141 | { 142 | register *up, *rp, a; 143 | 144 | a = u.u_procp->p_addr; 145 | up = &u.u_uisa[16]; 146 | rp = &UISA->r[16]; 147 | if(cputype == 40) { 148 | up =- 8; 149 | rp =- 8; 150 | } 151 | while(rp > &UISA->r[0]) 152 | *--rp = *--up + a; 153 | if((up=u.u_procp->p_textp) != NULL) 154 | a =- up->x_caddr; 155 | up = &u.u_uisd[16]; 156 | rp = &UISD->r[16]; 157 | if(cputype == 40) { 158 | up =- 8; 159 | rp =- 8; 160 | } 161 | while(rp > &UISD->r[0]) { 162 | *--rp = *--up; 163 | if((*rp & WO) == 0) 164 | rp[(UISA-UISD)/2] =- a; 165 | } 166 | } 167 | 168 | /* 169 | * Set up software prototype segmentation 170 | * registers to implement the 3 pseudo 171 | * text,data,stack segment sizes passed 172 | * as arguments. 173 | * The argument sep specifies if the 174 | * text and data+stack segments are to 175 | * be separated. 176 | */ 177 | estabur(nt, nd, ns, sep) 178 | { 179 | register a, *ap, *dp; 180 | 181 | if(sep) { 182 | if(cputype == 40) 183 | goto err; 184 | if(nseg(nt) > 8 || nseg(nd)+nseg(ns) > 8) 185 | goto err; 186 | } else 187 | if(nseg(nt)+nseg(nd)+nseg(ns) > 8) 188 | goto err; 189 | if(nt+nd+ns+USIZE > maxmem) 190 | goto err; 191 | a = 0; 192 | ap = &u.u_uisa[0]; 193 | dp = &u.u_uisd[0]; 194 | while(nt >= 128) { 195 | *dp++ = (127<<8) | RO; 196 | *ap++ = a; 197 | a =+ 128; 198 | nt =- 128; 199 | } 200 | if(nt) { 201 | *dp++ = ((nt-1)<<8) | RO; 202 | *ap++ = a; 203 | } 204 | if(sep) 205 | while(ap < &u.u_uisa[8]) { 206 | *ap++ = 0; 207 | *dp++ = 0; 208 | } 209 | a = USIZE; 210 | while(nd >= 128) { 211 | *dp++ = (127<<8) | RW; 212 | *ap++ = a; 213 | a =+ 128; 214 | nd =- 128; 215 | } 216 | if(nd) { 217 | *dp++ = ((nd-1)<<8) | RW; 218 | *ap++ = a; 219 | a =+ nd; 220 | } 221 | while(ap < &u.u_uisa[8]) { 222 | *dp++ = 0; 223 | *ap++ = 0; 224 | } 225 | if(sep) 226 | while(ap < &u.u_uisa[16]) { 227 | *dp++ = 0; 228 | *ap++ = 0; 229 | } 230 | a =+ ns; 231 | while(ns >= 128) { 232 | a =- 128; 233 | ns =- 128; 234 | *--dp = (127<<8) | RW; 235 | *--ap = a; 236 | } 237 | if(ns) { 238 | *--dp = ((128-ns)<<8) | RW | ED; 239 | *--ap = a-128; 240 | } 241 | if(!sep) { 242 | ap = &u.u_uisa[0]; 243 | dp = &u.u_uisa[8]; 244 | while(ap < &u.u_uisa[8]) 245 | *dp++ = *ap++; 246 | ap = &u.u_uisd[0]; 247 | dp = &u.u_uisd[8]; 248 | while(ap < &u.u_uisd[8]) 249 | *dp++ = *ap++; 250 | } 251 | sureg(); 252 | return(0); 253 | 254 | err: 255 | u.u_error = ENOMEM; 256 | return(-1); 257 | } 258 | 259 | /* 260 | * Return the arg/128 rounded up. 261 | */ 262 | nseg(n) 263 | { 264 | 265 | return((n+127)>>7); 266 | } 267 | -------------------------------------------------------------------------------- /ken/malloc.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * Structure of the coremap and swapmap 7 | * arrays. Consists of non-zero count 8 | * and base address of that many 9 | * contiguous units. 10 | * (The coremap unit is 64 bytes, 11 | * the swapmap unit is 512 bytes) 12 | * The addresses are increasing and 13 | * the list is terminated with the 14 | * first zero count. 15 | */ 16 | struct map 17 | { 18 | char *m_size; 19 | char *m_addr; 20 | }; 21 | 22 | /* 23 | * Allocate size units from the given 24 | * map. Return the base of the allocated 25 | * space. 26 | * Algorithm is first fit. 27 | */ 28 | malloc(mp, size) 29 | struct map *mp; 30 | { 31 | register int a; 32 | register struct map *bp; 33 | 34 | for (bp = mp; bp->m_size; bp++) { 35 | if (bp->m_size >= size) { 36 | a = bp->m_addr; 37 | bp->m_addr =+ size; 38 | if ((bp->m_size =- size) == 0) 39 | do { 40 | bp++; 41 | (bp-1)->m_addr = bp->m_addr; 42 | } while ((bp-1)->m_size = bp->m_size); 43 | return(a); 44 | } 45 | } 46 | return(0); 47 | } 48 | 49 | /* 50 | * Free the previously allocated space aa 51 | * of size units into the specified map. 52 | * Sort aa into map and combine on 53 | * one or both ends if possible. 54 | */ 55 | mfree(mp, size, aa) 56 | struct map *mp; 57 | { 58 | register struct map *bp; 59 | register int t; 60 | register int a; 61 | 62 | a = aa; 63 | for (bp = mp; bp->m_addr<=a && bp->m_size!=0; bp++); 64 | if (bp>mp && (bp-1)->m_addr+(bp-1)->m_size == a) { 65 | (bp-1)->m_size =+ size; 66 | if (a+size == bp->m_addr) { 67 | (bp-1)->m_size =+ bp->m_size; 68 | while (bp->m_size) { 69 | bp++; 70 | (bp-1)->m_addr = bp->m_addr; 71 | (bp-1)->m_size = bp->m_size; 72 | } 73 | } 74 | } else { 75 | if (a+size == bp->m_addr && bp->m_size) { 76 | bp->m_addr =- size; 77 | bp->m_size =+ size; 78 | } else if (size) do { 79 | t = bp->m_addr; 80 | bp->m_addr = a; 81 | a = t; 82 | t = bp->m_size; 83 | bp->m_size = size; 84 | bp++; 85 | } while (size = t); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /ken/nami.c: -------------------------------------------------------------------------------- 1 | # 2 | #include "../param.h" 3 | #include "../inode.h" 4 | #include "../user.h" 5 | #include "../systm.h" 6 | #include "../buf.h" 7 | 8 | /* 9 | * Convert a pathname into a pointer to 10 | * an inode. Note that the inode is locked. 11 | * 12 | * func = function called to get next char of name 13 | * &uchar if name is in user space 14 | * &schar if name is in system space 15 | * flag = 0 if name is sought 16 | * 1 if name is to be created 17 | * 2 if name is to be deleted 18 | */ 19 | namei(func, flag) 20 | int (*func)(); 21 | { 22 | register struct inode *dp; 23 | register c; 24 | register char *cp; 25 | int eo, *bp; 26 | 27 | /* 28 | * If name starts with '/' start from 29 | * root; otherwise start from current dir. 30 | */ 31 | 32 | dp = u.u_cdir; 33 | if((c=(*func)()) == '/') 34 | dp = rootdir; 35 | iget(dp->i_dev, dp->i_number); 36 | while(c == '/') 37 | c = (*func)(); 38 | if(c == '\0' && flag != 0) { 39 | u.u_error = ENOENT; 40 | goto out; 41 | } 42 | 43 | cloop: 44 | /* 45 | * Here dp contains pointer 46 | * to last component matched. 47 | */ 48 | 49 | if(u.u_error) 50 | goto out; 51 | if(c == '\0') 52 | return(dp); 53 | 54 | /* 55 | * If there is another component, 56 | * dp must be a directory and 57 | * must have x permission. 58 | */ 59 | 60 | if((dp->i_mode&IFMT) != IFDIR) { 61 | u.u_error = ENOTDIR; 62 | goto out; 63 | } 64 | if(access(dp, IEXEC)) 65 | goto out; 66 | 67 | /* 68 | * Gather up name into 69 | * users' dir buffer. 70 | */ 71 | 72 | cp = &u.u_dbuf[0]; 73 | while(c!='/' && c!='\0' && u.u_error==0) { 74 | if(cp < &u.u_dbuf[DIRSIZ]) 75 | *cp++ = c; 76 | c = (*func)(); 77 | } 78 | while(cp < &u.u_dbuf[DIRSIZ]) 79 | *cp++ = '\0'; 80 | while(c == '/') 81 | c = (*func)(); 82 | if(u.u_error) 83 | goto out; 84 | 85 | /* 86 | * Set up to search a directory. 87 | */ 88 | 89 | u.u_offset[1] = 0; 90 | u.u_offset[0] = 0; 91 | u.u_segflg = 1; 92 | eo = 0; 93 | u.u_count = ldiv(dp->i_size1, DIRSIZ+2); 94 | bp = NULL; 95 | 96 | eloop: 97 | 98 | /* 99 | * If at the end of the directory, 100 | * the search failed. Report what 101 | * is appropriate as per flag. 102 | */ 103 | 104 | if(u.u_count == 0) { 105 | if(bp != NULL) 106 | brelse(bp); 107 | if(flag==1 && c=='\0') { 108 | if(access(dp, IWRITE)) 109 | goto out; 110 | u.u_pdir = dp; 111 | if(eo) 112 | u.u_offset[1] = eo-DIRSIZ-2; else 113 | dp->i_flag =| IUPD; 114 | return(NULL); 115 | } 116 | u.u_error = ENOENT; 117 | goto out; 118 | } 119 | 120 | /* 121 | * If offset is on a block boundary, 122 | * read the next directory block. 123 | * Release previous if it exists. 124 | */ 125 | 126 | if((u.u_offset[1]&0777) == 0) { 127 | if(bp != NULL) 128 | brelse(bp); 129 | bp = bread(dp->i_dev, 130 | bmap(dp, ldiv(u.u_offset[1], 512))); 131 | } 132 | 133 | /* 134 | * Note first empty directory slot 135 | * in eo for possible creat. 136 | * String compare the directory entry 137 | * and the current component. 138 | * If they do not match, go back to eloop. 139 | */ 140 | 141 | bcopy(bp->b_addr+(u.u_offset[1]&0777), &u.u_dent, (DIRSIZ+2)/2); 142 | u.u_offset[1] =+ DIRSIZ+2; 143 | u.u_count--; 144 | if(u.u_dent.u_ino == 0) { 145 | if(eo == 0) 146 | eo = u.u_offset[1]; 147 | goto eloop; 148 | } 149 | for(cp = &u.u_dbuf[0]; cp < &u.u_dbuf[DIRSIZ]; cp++) 150 | if(*cp != cp[u.u_dent.u_name - u.u_dbuf]) 151 | goto eloop; 152 | 153 | /* 154 | * Here a component matched in a directory. 155 | * If there is more pathname, go back to 156 | * cloop, otherwise return. 157 | */ 158 | 159 | if(bp != NULL) 160 | brelse(bp); 161 | if(flag==2 && c=='\0') { 162 | if(access(dp, IWRITE)) 163 | goto out; 164 | return(dp); 165 | } 166 | bp = dp->i_dev; 167 | iput(dp); 168 | dp = iget(bp, u.u_dent.u_ino); 169 | if(dp == NULL) 170 | return(NULL); 171 | goto cloop; 172 | 173 | out: 174 | iput(dp); 175 | return(NULL); 176 | } 177 | 178 | /* 179 | * Return the next character from the 180 | * kernel string pointed at by dirp. 181 | */ 182 | schar() 183 | { 184 | 185 | return(*u.u_dirp++ & 0377); 186 | } 187 | 188 | /* 189 | * Return the next character from the 190 | * user string pointed at by dirp. 191 | */ 192 | uchar() 193 | { 194 | register c; 195 | 196 | c = fubyte(u.u_dirp++); 197 | if(c == -1) 198 | u.u_error = EFAULT; 199 | return(c); 200 | } 201 | -------------------------------------------------------------------------------- /ken/pipe.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | #include "../param.h" 6 | #include "../systm.h" 7 | #include "../user.h" 8 | #include "../inode.h" 9 | #include "../file.h" 10 | #include "../reg.h" 11 | 12 | /* 13 | * Max allowable buffering per pipe. 14 | * This is also the max size of the 15 | * file created to implement the pipe. 16 | * If this size is bigger than 4096, 17 | * pipes will be implemented in LARG 18 | * files, which is probably not good. 19 | */ 20 | #define PIPSIZ 4096 21 | 22 | /* 23 | * The sys-pipe entry. 24 | * Allocate an inode on the root device. 25 | * Allocate 2 file structures. 26 | * Put it all together with flags. 27 | */ 28 | pipe() 29 | { 30 | register *ip, *rf, *wf; 31 | int r; 32 | 33 | ip = ialloc(rootdev); 34 | if(ip == NULL) 35 | return; 36 | rf = falloc(); 37 | if(rf == NULL) { 38 | iput(ip); 39 | return; 40 | } 41 | r = u.u_ar0[R0]; 42 | wf = falloc(); 43 | if(wf == NULL) { 44 | rf->f_count = 0; 45 | u.u_ofile[r] = NULL; 46 | iput(ip); 47 | return; 48 | } 49 | u.u_ar0[R1] = u.u_ar0[R0]; 50 | u.u_ar0[R0] = r; 51 | wf->f_flag = FWRITE|FPIPE; 52 | wf->f_inode = ip; 53 | rf->f_flag = FREAD|FPIPE; 54 | rf->f_inode = ip; 55 | ip->i_count = 2; 56 | ip->i_flag = IACC|IUPD; 57 | ip->i_mode = IALLOC; 58 | } 59 | 60 | /* 61 | * Read call directed to a pipe. 62 | */ 63 | readp(fp) 64 | int *fp; 65 | { 66 | register *rp, *ip; 67 | 68 | rp = fp; 69 | ip = rp->f_inode; 70 | 71 | loop: 72 | /* 73 | * Very conservative locking. 74 | */ 75 | 76 | plock(ip); 77 | 78 | /* 79 | * If the head (read) has caught up with 80 | * the tail (write), reset both to 0. 81 | */ 82 | 83 | if(rp->f_offset[1] == ip->i_size1) { 84 | if(rp->f_offset[1] != 0) { 85 | rp->f_offset[1] = 0; 86 | ip->i_size1 = 0; 87 | if(ip->i_mode&IWRITE) { 88 | ip->i_mode =& ~IWRITE; 89 | wakeup(ip+1); 90 | } 91 | } 92 | 93 | /* 94 | * If there are not both reader and 95 | * writer active, return without 96 | * satisfying read. 97 | */ 98 | 99 | prele(ip); 100 | if(ip->i_count < 2) 101 | return; 102 | ip->i_mode =| IREAD; 103 | sleep(ip+2, PPIPE); 104 | goto loop; 105 | } 106 | 107 | /* 108 | * Read and return 109 | */ 110 | 111 | u.u_offset[0] = 0; 112 | u.u_offset[1] = rp->f_offset[1]; 113 | readi(ip); 114 | rp->f_offset[1] = u.u_offset[1]; 115 | prele(ip); 116 | } 117 | 118 | /* 119 | * Write call directed to a pipe. 120 | */ 121 | writep(fp) 122 | { 123 | register *rp, *ip, c; 124 | 125 | rp = fp; 126 | ip = rp->f_inode; 127 | c = u.u_count; 128 | 129 | loop: 130 | 131 | /* 132 | * If all done, return. 133 | */ 134 | 135 | plock(ip); 136 | if(c == 0) { 137 | prele(ip); 138 | u.u_count = 0; 139 | return; 140 | } 141 | 142 | /* 143 | * If there are not both read and 144 | * write sides of the pipe active, 145 | * return error and signal too. 146 | */ 147 | 148 | if(ip->i_count < 2) { 149 | prele(ip); 150 | u.u_error = EPIPE; 151 | psignal(u.u_procp, SIGPIPE); 152 | return; 153 | } 154 | 155 | /* 156 | * If the pipe is full, 157 | * wait for reads to deplete 158 | * and truncate it. 159 | */ 160 | 161 | if(ip->i_size1 == PIPSIZ) { 162 | ip->i_mode =| IWRITE; 163 | prele(ip); 164 | sleep(ip+1, PPIPE); 165 | goto loop; 166 | } 167 | 168 | /* 169 | * Write what is possible and 170 | * loop back. 171 | */ 172 | 173 | u.u_offset[0] = 0; 174 | u.u_offset[1] = ip->i_size1; 175 | u.u_count = min(c, PIPSIZ-u.u_offset[1]); 176 | c =- u.u_count; 177 | writei(ip); 178 | prele(ip); 179 | if(ip->i_mode&IREAD) { 180 | ip->i_mode =& ~IREAD; 181 | wakeup(ip+2); 182 | } 183 | goto loop; 184 | } 185 | 186 | /* 187 | * Lock a pipe. 188 | * If its already locked, 189 | * set the WANT bit and sleep. 190 | */ 191 | plock(ip) 192 | int *ip; 193 | { 194 | register *rp; 195 | 196 | rp = ip; 197 | while(rp->i_flag&ILOCK) { 198 | rp->i_flag =| IWANT; 199 | sleep(rp, PPIPE); 200 | } 201 | rp->i_flag =| ILOCK; 202 | } 203 | 204 | /* 205 | * Unlock a pipe. 206 | * If WANT bit is on, 207 | * wakeup. 208 | * This routine is also used 209 | * to unlock inodes in general. 210 | */ 211 | prele(ip) 212 | int *ip; 213 | { 214 | register *rp; 215 | 216 | rp = ip; 217 | rp->i_flag =& ~ILOCK; 218 | if(rp->i_flag&IWANT) { 219 | rp->i_flag =& ~IWANT; 220 | wakeup(rp); 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /ken/prf.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | #include "../param.h" 6 | #include "../seg.h" 7 | #include "../buf.h" 8 | #include "../conf.h" 9 | 10 | /* 11 | * Address and structure of the 12 | * KL-11 console device registers. 13 | */ 14 | struct 15 | { 16 | int rsr; 17 | int rbr; 18 | int xsr; 19 | int xbr; 20 | }; 21 | 22 | /* 23 | * In case console is off, 24 | * panicstr contains argument to last 25 | * call to panic. 26 | */ 27 | 28 | char *panicstr; 29 | 30 | /* 31 | * Scaled down version of C Library printf. 32 | * Only %s %l %d (==%l) %o are recognized. 33 | * Used to print diagnostic information 34 | * directly on console tty. 35 | * Since it is not interrupt driven, 36 | * all system activities are pretty much 37 | * suspended. 38 | * Printf should not be used for chit-chat. 39 | */ 40 | printf(fmt,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc) 41 | char fmt[]; 42 | { 43 | register char *s; 44 | register *adx, c; 45 | 46 | adx = &x1; 47 | loop: 48 | while((c = *fmt++) != '%') { 49 | if(c == '\0') 50 | return; 51 | putchar(c); 52 | } 53 | c = *fmt++; 54 | if(c == 'd' || c == 'l' || c == 'o') 55 | printn(*adx, c=='o'? 8: 10); 56 | if(c == 's') { 57 | s = *adx; 58 | while(c = *s++) 59 | putchar(c); 60 | } 61 | adx++; 62 | goto loop; 63 | } 64 | 65 | /* 66 | * Print an unsigned integer in base b. 67 | */ 68 | printn(n, b) 69 | { 70 | register a; 71 | 72 | if(a = ldiv(n, b)) 73 | printn(a, b); 74 | putchar(lrem(n, b) + '0'); 75 | } 76 | 77 | /* 78 | * Print a character on console. 79 | * Attempts to save and restore device 80 | * status. 81 | * If the switches are 0, all 82 | * printing is inhibited. 83 | */ 84 | putchar(c) 85 | { 86 | register rc, s; 87 | 88 | rc = c; 89 | if(SW->integ == 0) 90 | return; 91 | while((KL->xsr&0200) == 0) 92 | ; 93 | if(rc == 0) 94 | return; 95 | s = KL->xsr; 96 | KL->xsr = 0; 97 | KL->xbr = rc; 98 | if(rc == '\n') { 99 | putchar('\r'); 100 | putchar(0177); 101 | putchar(0177); 102 | } 103 | putchar(0); 104 | KL->xsr = s; 105 | } 106 | 107 | /* 108 | * Panic is called on unresolvable 109 | * fatal errors. 110 | * It syncs, prints "panic: mesg" and 111 | * then loops. 112 | */ 113 | panic(s) 114 | char *s; 115 | { 116 | panicstr = s; 117 | update(); 118 | printf("panic: %s\n", s); 119 | for(;;) 120 | idle(); 121 | } 122 | 123 | /* 124 | * prdev prints a warning message of the 125 | * form "mesg on dev x/y". 126 | * x and y are the major and minor parts of 127 | * the device argument. 128 | */ 129 | prdev(str, dev) 130 | { 131 | 132 | printf("%s on dev %l/%l\n", str, dev.d_major, dev.d_minor); 133 | } 134 | 135 | /* 136 | * deverr prints a diagnostic from 137 | * a device driver. 138 | * It prints the device, block number, 139 | * and an octal word (usually some error 140 | * status register) passed as argument. 141 | */ 142 | deverror(bp, o1, o2) 143 | int *bp; 144 | { 145 | register *rbp; 146 | 147 | rbp = bp; 148 | prdev("err", rbp->b_dev); 149 | printf("bn%l er%o %o\n", rbp->b_blkno, o1, o2); 150 | } 151 | -------------------------------------------------------------------------------- /ken/rdwri.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | #include "../param.h" 6 | #include "../inode.h" 7 | #include "../user.h" 8 | #include "../buf.h" 9 | #include "../conf.h" 10 | #include "../systm.h" 11 | 12 | /* 13 | * Read the file corresponding to 14 | * the inode pointed at by the argument. 15 | * The actual read arguments are found 16 | * in the variables: 17 | * u_base core address for destination 18 | * u_offset byte offset in file 19 | * u_count number of bytes to read 20 | * u_segflg read to kernel/user 21 | */ 22 | readi(aip) 23 | struct inode *aip; 24 | { 25 | int *bp; 26 | int lbn, bn, on; 27 | register dn, n; 28 | register struct inode *ip; 29 | 30 | ip = aip; 31 | if(u.u_count == 0) 32 | return; 33 | ip->i_flag =| IACC; 34 | if((ip->i_mode&IFMT) == IFCHR) { 35 | (*cdevsw[ip->i_addr[0].d_major].d_read)(ip->i_addr[0]); 36 | return; 37 | } 38 | 39 | do { 40 | lbn = bn = lshift(u.u_offset, -9); 41 | on = u.u_offset[1] & 0777; 42 | n = min(512-on, u.u_count); 43 | if((ip->i_mode&IFMT) != IFBLK) { 44 | dn = dpcmp(ip->i_size0&0377, ip->i_size1, 45 | u.u_offset[0], u.u_offset[1]); 46 | if(dn <= 0) 47 | return; 48 | n = min(n, dn); 49 | if ((bn = bmap(ip, lbn)) == 0) 50 | return; 51 | dn = ip->i_dev; 52 | } else { 53 | dn = ip->i_addr[0]; 54 | rablock = bn+1; 55 | } 56 | if (ip->i_lastr+1 == lbn) 57 | bp = breada(dn, bn, rablock); 58 | else 59 | bp = bread(dn, bn); 60 | ip->i_lastr = lbn; 61 | iomove(bp, on, n, B_READ); 62 | brelse(bp); 63 | } while(u.u_error==0 && u.u_count!=0); 64 | } 65 | 66 | /* 67 | * Write the file corresponding to 68 | * the inode pointed at by the argument. 69 | * The actual write arguments are found 70 | * in the variables: 71 | * u_base core address for source 72 | * u_offset byte offset in file 73 | * u_count number of bytes to write 74 | * u_segflg write to kernel/user 75 | */ 76 | writei(aip) 77 | struct inode *aip; 78 | { 79 | int *bp; 80 | int n, on; 81 | register dn, bn; 82 | register struct inode *ip; 83 | 84 | ip = aip; 85 | ip->i_flag =| IACC|IUPD; 86 | if((ip->i_mode&IFMT) == IFCHR) { 87 | (*cdevsw[ip->i_addr[0].d_major].d_write)(ip->i_addr[0]); 88 | return; 89 | } 90 | if (u.u_count == 0) 91 | return; 92 | 93 | do { 94 | bn = lshift(u.u_offset, -9); 95 | on = u.u_offset[1] & 0777; 96 | n = min(512-on, u.u_count); 97 | if((ip->i_mode&IFMT) != IFBLK) { 98 | if ((bn = bmap(ip, bn)) == 0) 99 | return; 100 | dn = ip->i_dev; 101 | } else 102 | dn = ip->i_addr[0]; 103 | if(n == 512) 104 | bp = getblk(dn, bn); else 105 | bp = bread(dn, bn); 106 | iomove(bp, on, n, B_WRITE); 107 | if(u.u_error != 0) 108 | brelse(bp); else 109 | if ((u.u_offset[1]&0777)==0) 110 | bawrite(bp); else 111 | bdwrite(bp); 112 | if(dpcmp(ip->i_size0&0377, ip->i_size1, 113 | u.u_offset[0], u.u_offset[1]) < 0 && 114 | (ip->i_mode&(IFBLK&IFCHR)) == 0) { 115 | ip->i_size0 = u.u_offset[0]; 116 | ip->i_size1 = u.u_offset[1]; 117 | } 118 | ip->i_flag =| IUPD; 119 | } while(u.u_error==0 && u.u_count!=0); 120 | } 121 | 122 | /* 123 | * Return the logical maximum 124 | * of the 2 arguments. 125 | */ 126 | max(a, b) 127 | char *a, *b; 128 | { 129 | 130 | if(a > b) 131 | return(a); 132 | return(b); 133 | } 134 | 135 | /* 136 | * Return the logical minimum 137 | * of the 2 arguments. 138 | */ 139 | min(a, b) 140 | char *a, *b; 141 | { 142 | 143 | if(a < b) 144 | return(a); 145 | return(b); 146 | } 147 | 148 | /* 149 | * Move 'an' bytes at byte location 150 | * &bp->b_addr[o] to/from (flag) the 151 | * user/kernel (u.segflg) area starting at u.base. 152 | * Update all the arguments by the number 153 | * of bytes moved. 154 | * 155 | * There are 2 algorithms, 156 | * if source address, dest address and count 157 | * are all even in a user copy, 158 | * then the machine language copyin/copyout 159 | * is called. 160 | * If not, its done byte-by-byte with 161 | * cpass and passc. 162 | */ 163 | iomove(bp, o, an, flag) 164 | struct buf *bp; 165 | { 166 | register char *cp; 167 | register int n, t; 168 | 169 | n = an; 170 | cp = bp->b_addr + o; 171 | if(u.u_segflg==0 && ((n | cp | u.u_base)&01)==0) { 172 | if (flag==B_WRITE) 173 | cp = copyin(u.u_base, cp, n); 174 | else 175 | cp = copyout(cp, u.u_base, n); 176 | if (cp) { 177 | u.u_error = EFAULT; 178 | return; 179 | } 180 | u.u_base =+ n; 181 | dpadd(u.u_offset, n); 182 | u.u_count =- n; 183 | return; 184 | } 185 | if (flag==B_WRITE) { 186 | while(n--) { 187 | if ((t = cpass()) < 0) 188 | return; 189 | *cp++ = t; 190 | } 191 | } else 192 | while (n--) 193 | if(passc(*cp++) < 0) 194 | return; 195 | } 196 | -------------------------------------------------------------------------------- /ken/sig.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | #include "../param.h" 6 | #include "../systm.h" 7 | #include "../user.h" 8 | #include "../proc.h" 9 | #include "../inode.h" 10 | #include "../reg.h" 11 | 12 | /* 13 | * Priority for tracing 14 | */ 15 | #define IPCPRI (-1) 16 | 17 | /* 18 | * Structure to access an array of integers. 19 | */ 20 | struct 21 | { 22 | int inta[]; 23 | }; 24 | 25 | /* 26 | * Tracing variables. 27 | * Used to pass trace command from 28 | * parent to child being traced. 29 | * This data base cannot be 30 | * shared and is locked 31 | * per user. 32 | */ 33 | struct 34 | { 35 | int ip_lock; 36 | int ip_req; 37 | int ip_addr; 38 | int ip_data; 39 | } ipc; 40 | 41 | /* 42 | * Send the specified signal to 43 | * all processes with 'tp' as its 44 | * controlling teletype. 45 | * Called by tty.c for quits and 46 | * interrupts. 47 | */ 48 | signal(tp, sig) 49 | { 50 | register struct proc *p; 51 | 52 | for(p = &proc[0]; p < &proc[NPROC]; p++) 53 | if(p->p_ttyp == tp) 54 | psignal(p, sig); 55 | } 56 | 57 | /* 58 | * Send the specified signal to 59 | * the specified process. 60 | */ 61 | psignal(p, sig) 62 | int *p; 63 | { 64 | register *rp; 65 | 66 | if(sig >= NSIG) 67 | return; 68 | rp = p; 69 | if(rp->p_sig != SIGKIL) 70 | rp->p_sig = sig; 71 | if(rp->p_stat > PUSER) 72 | rp->p_stat = PUSER; 73 | if(rp->p_stat == SWAIT) 74 | setrun(rp); 75 | } 76 | 77 | /* 78 | * Returns true if the current 79 | * process has a signal to process. 80 | * This is asked at least once 81 | * each time a process enters the 82 | * system. 83 | * A signal does not do anything 84 | * directly to a process; it sets 85 | * a flag that asks the process to 86 | * do something to itself. 87 | */ 88 | issig() 89 | { 90 | register n; 91 | register struct proc *p; 92 | 93 | p = u.u_procp; 94 | if(n = p->p_sig) { 95 | if (p->p_flag&STRC) { 96 | stop(); 97 | if ((n = p->p_sig) == 0) 98 | return(0); 99 | } 100 | if((u.u_signal[n]&1) == 0) 101 | return(n); 102 | } 103 | return(0); 104 | } 105 | 106 | /* 107 | * Enter the tracing STOP state. 108 | * In this state, the parent is 109 | * informed and the process is able to 110 | * receive commands from the parent. 111 | */ 112 | stop() 113 | { 114 | register struct proc *pp, *cp; 115 | 116 | loop: 117 | cp = u.u_procp; 118 | if(cp->p_ppid != 1) 119 | for (pp = &proc[0]; pp < &proc[NPROC]; pp++) 120 | if (pp->p_pid == cp->p_ppid) { 121 | wakeup(pp); 122 | cp->p_stat = SSTOP; 123 | swtch(); 124 | if ((cp->p_flag&STRC)==0 || procxmt()) 125 | return; 126 | goto loop; 127 | } 128 | exit(); 129 | } 130 | 131 | /* 132 | * Perform the action specified by 133 | * the current signal. 134 | * The usual sequence is: 135 | * if(issig()) 136 | * psig(); 137 | */ 138 | psig() 139 | { 140 | register n, p; 141 | register *rp; 142 | 143 | rp = u.u_procp; 144 | n = rp->p_sig; 145 | rp->p_sig = 0; 146 | if((p=u.u_signal[n]) != 0) { 147 | u.u_error = 0; 148 | if(n != SIGINS && n != SIGTRC) 149 | u.u_signal[n] = 0; 150 | n = u.u_ar0[R6] - 4; 151 | grow(n); 152 | suword(n+2, u.u_ar0[RPS]); 153 | suword(n, u.u_ar0[R7]); 154 | u.u_ar0[R6] = n; 155 | u.u_ar0[RPS] =& ~TBIT; 156 | u.u_ar0[R7] = p; 157 | return; 158 | } 159 | switch(n) { 160 | 161 | case SIGQIT: 162 | case SIGINS: 163 | case SIGTRC: 164 | case SIGIOT: 165 | case SIGEMT: 166 | case SIGFPT: 167 | case SIGBUS: 168 | case SIGSEG: 169 | case SIGSYS: 170 | u.u_arg[0] = n; 171 | if(core()) 172 | n =+ 0200; 173 | } 174 | u.u_arg[0] = (u.u_ar0[R0]<<8) | n; 175 | exit(); 176 | } 177 | 178 | /* 179 | * Create a core image on the file "core" 180 | * If you are looking for protection glitches, 181 | * there are probably a wealth of them here 182 | * when this occurs to a suid command. 183 | * 184 | * It writes USIZE block of the 185 | * user.h area followed by the entire 186 | * data+stack segments. 187 | */ 188 | core() 189 | { 190 | register s, *ip; 191 | extern schar; 192 | 193 | u.u_error = 0; 194 | u.u_dirp = "core"; 195 | ip = namei(&schar, 1); 196 | if(ip == NULL) { 197 | if(u.u_error) 198 | return(0); 199 | ip = maknode(0666); 200 | if(ip == NULL) 201 | return(0); 202 | } 203 | if(!access(ip, IWRITE) && 204 | (ip->i_mode&IFMT) == 0 && 205 | u.u_uid == u.u_ruid) { 206 | itrunc(ip); 207 | u.u_offset[0] = 0; 208 | u.u_offset[1] = 0; 209 | u.u_base = &u; 210 | u.u_count = USIZE*64; 211 | u.u_segflg = 1; 212 | writei(ip); 213 | s = u.u_procp->p_size - USIZE; 214 | estabur(0, s, 0, 0); 215 | u.u_base = 0; 216 | u.u_count = s*64; 217 | u.u_segflg = 0; 218 | writei(ip); 219 | } 220 | iput(ip); 221 | return(u.u_error==0); 222 | } 223 | 224 | /* 225 | * grow the stack to include the SP 226 | * true return if successful. 227 | */ 228 | 229 | grow(sp) 230 | char *sp; 231 | { 232 | register a, si, i; 233 | 234 | if(sp >= -u.u_ssize*64) 235 | return(0); 236 | si = ldiv(-sp, 64) - u.u_ssize + SINCR; 237 | if(si <= 0) 238 | return(0); 239 | if(estabur(u.u_tsize, u.u_dsize, u.u_ssize+si, u.u_sep)) 240 | return(0); 241 | expand(u.u_procp->p_size+si); 242 | a = u.u_procp->p_addr + u.u_procp->p_size; 243 | for(i=u.u_ssize; i; i--) { 244 | a--; 245 | copyseg(a-si, a); 246 | } 247 | for(i=si; i; i--) 248 | clearseg(--a); 249 | u.u_ssize =+ si; 250 | return(1); 251 | } 252 | 253 | /* 254 | * sys-trace system call. 255 | */ 256 | ptrace() 257 | { 258 | register struct proc *p; 259 | 260 | if (u.u_arg[2] <= 0) { 261 | u.u_procp->p_flag =| STRC; 262 | return; 263 | } 264 | for (p=proc; p < &proc[NPROC]; p++) 265 | if (p->p_stat==SSTOP 266 | && p->p_pid==u.u_arg[0] 267 | && p->p_ppid==u.u_procp->p_pid) 268 | goto found; 269 | u.u_error = ESRCH; 270 | return; 271 | 272 | found: 273 | while (ipc.ip_lock) 274 | sleep(&ipc, IPCPRI); 275 | ipc.ip_lock = p->p_pid; 276 | ipc.ip_data = u.u_ar0[R0]; 277 | ipc.ip_addr = u.u_arg[1] & ~01; 278 | ipc.ip_req = u.u_arg[2]; 279 | p->p_flag =& ~SWTED; 280 | setrun(p); 281 | while (ipc.ip_req > 0) 282 | sleep(&ipc, IPCPRI); 283 | u.u_ar0[R0] = ipc.ip_data; 284 | if (ipc.ip_req < 0) 285 | u.u_error = EIO; 286 | ipc.ip_lock = 0; 287 | wakeup(&ipc); 288 | } 289 | 290 | /* 291 | * Code that the child process 292 | * executes to implement the command 293 | * of the parent process in tracing. 294 | */ 295 | procxmt() 296 | { 297 | register int i; 298 | register int *p; 299 | 300 | if (ipc.ip_lock != u.u_procp->p_pid) 301 | return(0); 302 | i = ipc.ip_req; 303 | ipc.ip_req = 0; 304 | wakeup(&ipc); 305 | switch (i) { 306 | 307 | /* read user I */ 308 | case 1: 309 | if (fuibyte(ipc.ip_addr) == -1) 310 | goto error; 311 | ipc.ip_data = fuiword(ipc.ip_addr); 312 | break; 313 | 314 | /* read user D */ 315 | case 2: 316 | if (fubyte(ipc.ip_addr) == -1) 317 | goto error; 318 | ipc.ip_data = fuword(ipc.ip_addr); 319 | break; 320 | 321 | /* read u */ 322 | case 3: 323 | i = ipc.ip_addr; 324 | if (i<0 || i >= (USIZE<<6)) 325 | goto error; 326 | ipc.ip_data = u.inta[i>>1]; 327 | break; 328 | 329 | /* write user I (for now, always an error) */ 330 | case 4: 331 | if (suiword(ipc.ip_addr, 0) < 0) 332 | goto error; 333 | suiword(ipc.ip_addr, ipc.ip_data); 334 | break; 335 | 336 | /* write user D */ 337 | case 5: 338 | if (suword(ipc.ip_addr, 0) < 0) 339 | goto error; 340 | suword(ipc.ip_addr, ipc.ip_data); 341 | break; 342 | 343 | /* write u */ 344 | case 6: 345 | p = &u.inta[ipc.ip_addr>>1]; 346 | if (p >= u.u_fsav && p < &u.u_fsav[25]) 347 | goto ok; 348 | for (i=0; i<9; i++) 349 | if (p == &u.u_ar0[regloc[i]]) 350 | goto ok; 351 | goto error; 352 | ok: 353 | if (p == &u.u_ar0[RPS]) { 354 | ipc.ip_data =| 0170000; /* assure user space */ 355 | ipc.ip_data =& ~0340; /* priority 0 */ 356 | } 357 | *p = ipc.ip_data; 358 | break; 359 | 360 | /* set signal and continue */ 361 | case 7: 362 | u.u_procp->p_sig = ipc.ip_data; 363 | return(1); 364 | 365 | /* force exit */ 366 | case 8: 367 | exit(); 368 | 369 | default: 370 | error: 371 | ipc.ip_req = -1; 372 | } 373 | return(0); 374 | } 375 | -------------------------------------------------------------------------------- /ken/slp.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | #include "../param.h" 6 | #include "../user.h" 7 | #include "../proc.h" 8 | #include "../text.h" 9 | #include "../systm.h" 10 | #include "../file.h" 11 | #include "../inode.h" 12 | #include "../buf.h" 13 | 14 | /* 15 | * Give up the processor till a wakeup occurs 16 | * on chan, at which time the process 17 | * enters the scheduling queue at priority pri. 18 | * The most important effect of pri is that when 19 | * pri<0 a signal cannot disturb the sleep; 20 | * if pri>=0 signals will be processed. 21 | * Callers of this routine must be prepared for 22 | * premature return, and check that the reason for 23 | * sleeping has gone away. 24 | */ 25 | sleep(chan, pri) 26 | { 27 | register *rp, s; 28 | 29 | s = PS->integ; 30 | rp = u.u_procp; 31 | if(pri >= 0) { 32 | if(issig()) 33 | goto psig; 34 | spl6(); 35 | rp->p_wchan = chan; 36 | rp->p_stat = SWAIT; 37 | rp->p_pri = pri; 38 | spl0(); 39 | if(runin != 0) { 40 | runin = 0; 41 | wakeup(&runin); 42 | } 43 | swtch(); 44 | if(issig()) 45 | goto psig; 46 | } else { 47 | spl6(); 48 | rp->p_wchan = chan; 49 | rp->p_stat = SSLEEP; 50 | rp->p_pri = pri; 51 | spl0(); 52 | swtch(); 53 | } 54 | PS->integ = s; 55 | return; 56 | 57 | /* 58 | * If priority was low (>=0) and 59 | * there has been a signal, 60 | * execute non-local goto to 61 | * the qsav location. 62 | * (see trap1/trap.c) 63 | */ 64 | psig: 65 | aretu(u.u_qsav); 66 | } 67 | 68 | /* 69 | * Wake up all processes sleeping on chan. 70 | */ 71 | wakeup(chan) 72 | { 73 | register struct proc *p; 74 | register c, i; 75 | 76 | c = chan; 77 | p = &proc[0]; 78 | i = NPROC; 79 | do { 80 | if(p->p_wchan == c) { 81 | setrun(p); 82 | } 83 | p++; 84 | } while(--i); 85 | } 86 | 87 | /* 88 | * Set the process running; 89 | * arrange for it to be swapped in if necessary. 90 | */ 91 | setrun(p) 92 | { 93 | register struct proc *rp; 94 | 95 | rp = p; 96 | rp->p_wchan = 0; 97 | rp->p_stat = SRUN; 98 | if(rp->p_pri < curpri) 99 | runrun++; 100 | if(runout != 0 && (rp->p_flag&SLOAD) == 0) { 101 | runout = 0; 102 | wakeup(&runout); 103 | } 104 | } 105 | 106 | /* 107 | * Set user priority. 108 | * The rescheduling flag (runrun) 109 | * is set if the priority is higher 110 | * than the currently running process. 111 | */ 112 | setpri(up) 113 | { 114 | register *pp, p; 115 | 116 | pp = up; 117 | p = (pp->p_cpu & 0377)/16; 118 | p =+ PUSER + pp->p_nice; 119 | if(p > 127) 120 | p = 127; 121 | if(p > curpri) 122 | runrun++; 123 | pp->p_pri = p; 124 | } 125 | 126 | /* 127 | * The main loop of the scheduling (swapping) 128 | * process. 129 | * The basic idea is: 130 | * see if anyone wants to be swapped in; 131 | * swap out processes until there is room; 132 | * swap him in; 133 | * repeat. 134 | * Although it is not remarkably evident, the basic 135 | * synchronization here is on the runin flag, which is 136 | * slept on and is set once per second by the clock routine. 137 | * Core shuffling therefore takes place once per second. 138 | * 139 | * panic: swap error -- IO error while swapping. 140 | * this is the one panic that should be 141 | * handled in a less drastic way. Its 142 | * very hard. 143 | */ 144 | sched() 145 | { 146 | struct proc *p1; 147 | register struct proc *rp; 148 | register a, n; 149 | 150 | /* 151 | * find user to swap in 152 | * of users ready, select one out longest 153 | */ 154 | 155 | goto loop; 156 | 157 | sloop: 158 | runin++; 159 | sleep(&runin, PSWP); 160 | 161 | loop: 162 | spl6(); 163 | n = -1; 164 | for(rp = &proc[0]; rp < &proc[NPROC]; rp++) 165 | if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)==0 && 166 | rp->p_time > n) { 167 | p1 = rp; 168 | n = rp->p_time; 169 | } 170 | if(n == -1) { 171 | runout++; 172 | sleep(&runout, PSWP); 173 | goto loop; 174 | } 175 | 176 | /* 177 | * see if there is core for that process 178 | */ 179 | 180 | spl0(); 181 | rp = p1; 182 | a = rp->p_size; 183 | if((rp=rp->p_textp) != NULL) 184 | if(rp->x_ccount == 0) 185 | a =+ rp->x_size; 186 | if((a=malloc(coremap, a)) != NULL) 187 | goto found2; 188 | 189 | /* 190 | * none found, 191 | * look around for easy core 192 | */ 193 | 194 | spl6(); 195 | for(rp = &proc[0]; rp < &proc[NPROC]; rp++) 196 | if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD && 197 | (rp->p_stat == SWAIT || rp->p_stat==SSTOP)) 198 | goto found1; 199 | 200 | /* 201 | * no easy core, 202 | * if this process is deserving, 203 | * look around for 204 | * oldest process in core 205 | */ 206 | 207 | if(n < 3) 208 | goto sloop; 209 | n = -1; 210 | for(rp = &proc[0]; rp < &proc[NPROC]; rp++) 211 | if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD && 212 | (rp->p_stat==SRUN || rp->p_stat==SSLEEP) && 213 | rp->p_time > n) { 214 | p1 = rp; 215 | n = rp->p_time; 216 | } 217 | if(n < 2) 218 | goto sloop; 219 | rp = p1; 220 | 221 | /* 222 | * swap user out 223 | */ 224 | 225 | found1: 226 | spl0(); 227 | rp->p_flag =& ~SLOAD; 228 | xswap(rp, 1, 0); 229 | goto loop; 230 | 231 | /* 232 | * swap user in 233 | */ 234 | 235 | found2: 236 | if((rp=p1->p_textp) != NULL) { 237 | if(rp->x_ccount == 0) { 238 | if(swap(rp->x_daddr, a, rp->x_size, B_READ)) 239 | goto swaper; 240 | rp->x_caddr = a; 241 | a =+ rp->x_size; 242 | } 243 | rp->x_ccount++; 244 | } 245 | rp = p1; 246 | if(swap(rp->p_addr, a, rp->p_size, B_READ)) 247 | goto swaper; 248 | mfree(swapmap, (rp->p_size+7)/8, rp->p_addr); 249 | rp->p_addr = a; 250 | rp->p_flag =| SLOAD; 251 | rp->p_time = 0; 252 | goto loop; 253 | 254 | swaper: 255 | panic("swap error"); 256 | } 257 | 258 | /* 259 | * This routine is called to reschedule the CPU. 260 | * if the calling process is not in RUN state, 261 | * arrangements for it to restart must have 262 | * been made elsewhere, usually by calling via sleep. 263 | */ 264 | swtch() 265 | { 266 | static struct proc *p; 267 | register i, n; 268 | register struct proc *rp; 269 | 270 | if(p == NULL) 271 | p = &proc[0]; 272 | /* 273 | * Remember stack of caller 274 | */ 275 | savu(u.u_rsav); 276 | /* 277 | * Switch to scheduler's stack 278 | */ 279 | retu(proc[0].p_addr); 280 | 281 | loop: 282 | runrun = 0; 283 | rp = p; 284 | p = NULL; 285 | n = 128; 286 | /* 287 | * Search for highest-priority runnable process 288 | */ 289 | i = NPROC; 290 | do { 291 | rp++; 292 | if(rp >= &proc[NPROC]) 293 | rp = &proc[0]; 294 | if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)!=0) { 295 | if(rp->p_pri < n) { 296 | p = rp; 297 | n = rp->p_pri; 298 | } 299 | } 300 | } while(--i); 301 | /* 302 | * If no process is runnable, idle. 303 | */ 304 | if(p == NULL) { 305 | p = rp; 306 | idle(); 307 | goto loop; 308 | } 309 | rp = p; 310 | curpri = n; 311 | /* 312 | * Switch to stack of the new process and set up 313 | * his segmentation registers. 314 | */ 315 | retu(rp->p_addr); 316 | sureg(); 317 | /* 318 | * If the new process paused because it was 319 | * swapped out, set the stack level to the last call 320 | * to savu(u_ssav). This means that the return 321 | * which is executed immediately after the call to aretu 322 | * actually returns from the last routine which did 323 | * the savu. 324 | * 325 | * You are not expected to understand this. 326 | */ 327 | if(rp->p_flag&SSWAP) { 328 | rp->p_flag =& ~SSWAP; 329 | aretu(u.u_ssav); 330 | } 331 | /* 332 | * The value returned here has many subtle implications. 333 | * See the newproc comments. 334 | */ 335 | return(1); 336 | } 337 | 338 | /* 339 | * Create a new process-- the internal version of 340 | * sys fork. 341 | * It returns 1 in the new process. 342 | * How this happens is rather hard to understand. 343 | * The essential fact is that the new process is created 344 | * in such a way that appears to have started executing 345 | * in the same call to newproc as the parent; 346 | * but in fact the code that runs is that of swtch. 347 | * The subtle implication of the returned value of swtch 348 | * (see above) is that this is the value that newproc's 349 | * caller in the new process sees. 350 | */ 351 | newproc() 352 | { 353 | int a1, a2; 354 | struct proc *p, *up; 355 | register struct proc *rpp; 356 | register *rip, n; 357 | 358 | p = NULL; 359 | /* 360 | * First, just locate a slot for a process 361 | * and copy the useful info from this process into it. 362 | * The panic "cannot happen" because fork has already 363 | * checked for the existence of a slot. 364 | */ 365 | retry: 366 | mpid++; 367 | if(mpid < 0) { 368 | mpid = 0; 369 | goto retry; 370 | } 371 | for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) { 372 | if(rpp->p_stat == NULL && p==NULL) 373 | p = rpp; 374 | if (rpp->p_pid==mpid) 375 | goto retry; 376 | } 377 | if ((rpp = p)==NULL) 378 | panic("no procs"); 379 | 380 | /* 381 | * make proc entry for new proc 382 | */ 383 | 384 | rip = u.u_procp; 385 | up = rip; 386 | rpp->p_stat = SRUN; 387 | rpp->p_flag = SLOAD; 388 | rpp->p_uid = rip->p_uid; 389 | rpp->p_ttyp = rip->p_ttyp; 390 | rpp->p_nice = rip->p_nice; 391 | rpp->p_textp = rip->p_textp; 392 | rpp->p_pid = mpid; 393 | rpp->p_ppid = rip->p_pid; 394 | rpp->p_time = 0; 395 | 396 | /* 397 | * make duplicate entries 398 | * where needed 399 | */ 400 | 401 | for(rip = &u.u_ofile[0]; rip < &u.u_ofile[NOFILE];) 402 | if((rpp = *rip++) != NULL) 403 | rpp->f_count++; 404 | if((rpp=up->p_textp) != NULL) { 405 | rpp->x_count++; 406 | rpp->x_ccount++; 407 | } 408 | u.u_cdir->i_count++; 409 | /* 410 | * Partially simulate the environment 411 | * of the new process so that when it is actually 412 | * created (by copying) it will look right. 413 | */ 414 | savu(u.u_rsav); 415 | rpp = p; 416 | u.u_procp = rpp; 417 | rip = up; 418 | n = rip->p_size; 419 | a1 = rip->p_addr; 420 | rpp->p_size = n; 421 | a2 = malloc(coremap, n); 422 | /* 423 | * If there is not enough core for the 424 | * new process, swap out the current process to generate the 425 | * copy. 426 | */ 427 | if(a2 == NULL) { 428 | rip->p_stat = SIDL; 429 | rpp->p_addr = a1; 430 | savu(u.u_ssav); 431 | xswap(rpp, 0, 0); 432 | rpp->p_flag =| SSWAP; 433 | rip->p_stat = SRUN; 434 | } else { 435 | /* 436 | * There is core, so just copy. 437 | */ 438 | rpp->p_addr = a2; 439 | while(n--) 440 | copyseg(a1++, a2++); 441 | } 442 | u.u_procp = rip; 443 | return(0); 444 | } 445 | 446 | /* 447 | * Change the size of the data+stack regions of the process. 448 | * If the size is shrinking, it's easy-- just release the extra core. 449 | * If it's growing, and there is core, just allocate it 450 | * and copy the image, taking care to reset registers to account 451 | * for the fact that the system's stack has moved. 452 | * If there is no core, arrange for the process to be swapped 453 | * out after adjusting the size requirement-- when it comes 454 | * in, enough core will be allocated. 455 | * Because of the ssave and SSWAP flags, control will 456 | * resume after the swap in swtch, which executes the return 457 | * from this stack level. 458 | * 459 | * After the expansion, the caller will take care of copying 460 | * the user's stack towards or away from the data area. 461 | */ 462 | expand(newsize) 463 | { 464 | int i, n; 465 | register *p, a1, a2; 466 | 467 | p = u.u_procp; 468 | n = p->p_size; 469 | p->p_size = newsize; 470 | a1 = p->p_addr; 471 | if(n >= newsize) { 472 | mfree(coremap, n-newsize, a1+newsize); 473 | return; 474 | } 475 | savu(u.u_rsav); 476 | a2 = malloc(coremap, newsize); 477 | if(a2 == NULL) { 478 | savu(u.u_ssav); 479 | xswap(p, 1, n); 480 | p->p_flag =| SSWAP; 481 | swtch(); 482 | /* no return */ 483 | } 484 | p->p_addr = a2; 485 | for(i=0; ip_addr); 489 | sureg(); 490 | } 491 | -------------------------------------------------------------------------------- /ken/subr.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | #include "../param.h" 6 | #include "../conf.h" 7 | #include "../inode.h" 8 | #include "../user.h" 9 | #include "../buf.h" 10 | #include "../systm.h" 11 | 12 | /* 13 | * Bmap defines the structure of file system storage 14 | * by returning the physical block number on a device given the 15 | * inode and the logical block number in a file. 16 | * When convenient, it also leaves the physical 17 | * block number of the next block of the file in rablock 18 | * for use in read-ahead. 19 | */ 20 | bmap(ip, bn) 21 | struct inode *ip; 22 | int bn; 23 | { 24 | register *bp, *bap, nb; 25 | int *nbp, d, i; 26 | 27 | d = ip->i_dev; 28 | if(bn & ~077777) { 29 | u.u_error = EFBIG; 30 | return(0); 31 | } 32 | 33 | if((ip->i_mode&ILARG) == 0) { 34 | 35 | /* 36 | * small file algorithm 37 | */ 38 | 39 | if((bn & ~7) != 0) { 40 | 41 | /* 42 | * convert small to large 43 | */ 44 | 45 | if ((bp = alloc(d)) == NULL) 46 | return(NULL); 47 | bap = bp->b_addr; 48 | for(i=0; i<8; i++) { 49 | *bap++ = ip->i_addr[i]; 50 | ip->i_addr[i] = 0; 51 | } 52 | ip->i_addr[0] = bp->b_blkno; 53 | bdwrite(bp); 54 | ip->i_mode =| ILARG; 55 | goto large; 56 | } 57 | nb = ip->i_addr[bn]; 58 | if(nb == 0 && (bp = alloc(d)) != NULL) { 59 | bdwrite(bp); 60 | nb = bp->b_blkno; 61 | ip->i_addr[bn] = nb; 62 | ip->i_flag =| IUPD; 63 | } 64 | rablock = 0; 65 | if (bn<7) 66 | rablock = ip->i_addr[bn+1]; 67 | return(nb); 68 | } 69 | 70 | /* 71 | * large file algorithm 72 | */ 73 | 74 | large: 75 | i = bn>>8; 76 | if(bn & 0174000) 77 | i = 7; 78 | if((nb=ip->i_addr[i]) == 0) { 79 | ip->i_flag =| IUPD; 80 | if ((bp = alloc(d)) == NULL) 81 | return(NULL); 82 | ip->i_addr[i] = bp->b_blkno; 83 | } else 84 | bp = bread(d, nb); 85 | bap = bp->b_addr; 86 | 87 | /* 88 | * "huge" fetch of double indirect block 89 | */ 90 | 91 | if(i == 7) { 92 | i = ((bn>>8) & 0377) - 7; 93 | if((nb=bap[i]) == 0) { 94 | if((nbp = alloc(d)) == NULL) { 95 | brelse(bp); 96 | return(NULL); 97 | } 98 | bap[i] = nbp->b_blkno; 99 | bdwrite(bp); 100 | } else { 101 | brelse(bp); 102 | nbp = bread(d, nb); 103 | } 104 | bp = nbp; 105 | bap = bp->b_addr; 106 | } 107 | 108 | /* 109 | * normal indirect fetch 110 | */ 111 | 112 | i = bn & 0377; 113 | if((nb=bap[i]) == 0 && (nbp = alloc(d)) != NULL) { 114 | nb = nbp->b_blkno; 115 | bap[i] = nb; 116 | bdwrite(nbp); 117 | bdwrite(bp); 118 | } else 119 | brelse(bp); 120 | rablock = 0; 121 | if(i < 255) 122 | rablock = bap[i+1]; 123 | return(nb); 124 | } 125 | 126 | /* 127 | * Pass back c to the user at his location u_base; 128 | * update u_base, u_count, and u_offset. Return -1 129 | * on the last character of the user's read. 130 | * u_base is in the user address space unless u_segflg is set. 131 | */ 132 | passc(c) 133 | char c; 134 | { 135 | 136 | if(u.u_segflg) 137 | *u.u_base = c; else 138 | if(subyte(u.u_base, c) < 0) { 139 | u.u_error = EFAULT; 140 | return(-1); 141 | } 142 | u.u_count--; 143 | if(++u.u_offset[1] == 0) 144 | u.u_offset[0]++; 145 | u.u_base++; 146 | return(u.u_count == 0? -1: 0); 147 | } 148 | 149 | /* 150 | * Pick up and return the next character from the user's 151 | * write call at location u_base; 152 | * update u_base, u_count, and u_offset. Return -1 153 | * when u_count is exhausted. u_base is in the user's 154 | * address space unless u_segflg is set. 155 | */ 156 | cpass() 157 | { 158 | register c; 159 | 160 | if(u.u_count == 0) 161 | return(-1); 162 | if(u.u_segflg) 163 | c = *u.u_base; else 164 | if((c=fubyte(u.u_base)) < 0) { 165 | u.u_error = EFAULT; 166 | return(-1); 167 | } 168 | u.u_count--; 169 | if(++u.u_offset[1] == 0) 170 | u.u_offset[0]++; 171 | u.u_base++; 172 | return(c&0377); 173 | } 174 | 175 | /* 176 | * Routine which sets a user error; placed in 177 | * illegal entries in the bdevsw and cdevsw tables. 178 | */ 179 | nodev() 180 | { 181 | 182 | u.u_error = ENODEV; 183 | } 184 | 185 | /* 186 | * Null routine; placed in insignificant entries 187 | * in the bdevsw and cdevsw tables. 188 | */ 189 | nulldev() 190 | { 191 | } 192 | 193 | /* 194 | * copy count words from from to to. 195 | */ 196 | bcopy(from, to, count) 197 | int *from, *to; 198 | { 199 | register *a, *b, c; 200 | 201 | a = from; 202 | b = to; 203 | c = count; 204 | do 205 | *b++ = *a++; 206 | while(--c); 207 | } 208 | -------------------------------------------------------------------------------- /ken/sys1.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | #include "../param.h" 6 | #include "../systm.h" 7 | #include "../user.h" 8 | #include "../proc.h" 9 | #include "../buf.h" 10 | #include "../reg.h" 11 | #include "../inode.h" 12 | 13 | /* 14 | * exec system call. 15 | * Because of the fact that an I/O buffer is used 16 | * to store the caller's arguments during exec, 17 | * and more buffers are needed to read in the text file, 18 | * deadly embraces waiting for free buffers are possible. 19 | * Therefore the number of processes simultaneously 20 | * running in exec has to be limited to NEXEC. 21 | */ 22 | #define EXPRI -1 23 | 24 | exec() 25 | { 26 | int ap, na, nc, *bp; 27 | int ts, ds, sep; 28 | register c, *ip; 29 | register char *cp; 30 | extern uchar; 31 | 32 | /* 33 | * pick up file names 34 | * and check various modes 35 | * for execute permission 36 | */ 37 | 38 | ip = namei(&uchar, 0); 39 | if(ip == NULL) 40 | return; 41 | while(execnt >= NEXEC) 42 | sleep(&execnt, EXPRI); 43 | execnt++; 44 | bp = getblk(NODEV); 45 | if(access(ip, IEXEC) || (ip->i_mode&IFMT)!=0) 46 | goto bad; 47 | 48 | /* 49 | * pack up arguments into 50 | * allocated disk buffer 51 | */ 52 | 53 | cp = bp->b_addr; 54 | na = 0; 55 | nc = 0; 56 | while(ap = fuword(u.u_arg[1])) { 57 | na++; 58 | if(ap == -1) 59 | goto bad; 60 | u.u_arg[1] =+ 2; 61 | for(;;) { 62 | c = fubyte(ap++); 63 | if(c == -1) 64 | goto bad; 65 | *cp++ = c; 66 | nc++; 67 | if(nc > 510) { 68 | u.u_error = E2BIG; 69 | goto bad; 70 | } 71 | if(c == 0) 72 | break; 73 | } 74 | } 75 | if((nc&1) != 0) { 76 | *cp++ = 0; 77 | nc++; 78 | } 79 | 80 | /* 81 | * read in first 8 bytes 82 | * of file for segment 83 | * sizes: 84 | * w0 = 407/410/411 (410 implies RO text) (411 implies sep ID) 85 | * w1 = text size 86 | * w2 = data size 87 | * w3 = bss size 88 | */ 89 | 90 | u.u_base = &u.u_arg[0]; 91 | u.u_count = 8; 92 | u.u_offset[1] = 0; 93 | u.u_offset[0] = 0; 94 | u.u_segflg = 1; 95 | readi(ip); 96 | u.u_segflg = 0; 97 | if(u.u_error) 98 | goto bad; 99 | sep = 0; 100 | if(u.u_arg[0] == 0407) { 101 | u.u_arg[2] =+ u.u_arg[1]; 102 | u.u_arg[1] = 0; 103 | } else 104 | if(u.u_arg[0] == 0411) 105 | sep++; else 106 | if(u.u_arg[0] != 0410) { 107 | u.u_error = ENOEXEC; 108 | goto bad; 109 | } 110 | if(u.u_arg[1]!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) { 111 | u.u_error = ETXTBSY; 112 | goto bad; 113 | } 114 | 115 | /* 116 | * find text and data sizes 117 | * try them out for possible 118 | * exceed of max sizes 119 | */ 120 | 121 | ts = ((u.u_arg[1]+63)>>6) & 01777; 122 | ds = ((u.u_arg[2]+u.u_arg[3]+63)>>6) & 01777; 123 | if(estabur(ts, ds, SSIZE, sep)) 124 | goto bad; 125 | 126 | /* 127 | * allocate and clear core 128 | * at this point, committed 129 | * to the new image 130 | */ 131 | 132 | u.u_prof[3] = 0; 133 | xfree(); 134 | expand(USIZE); 135 | xalloc(ip); 136 | c = USIZE+ds+SSIZE; 137 | expand(c); 138 | while(--c >= USIZE) 139 | clearseg(u.u_procp->p_addr+c); 140 | 141 | /* 142 | * read in data segment 143 | */ 144 | 145 | estabur(0, ds, 0, 0); 146 | u.u_base = 0; 147 | u.u_offset[1] = 020+u.u_arg[1]; 148 | u.u_count = u.u_arg[2]; 149 | readi(ip); 150 | 151 | /* 152 | * initialize stack segment 153 | */ 154 | 155 | u.u_tsize = ts; 156 | u.u_dsize = ds; 157 | u.u_ssize = SSIZE; 158 | u.u_sep = sep; 159 | estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep); 160 | cp = bp->b_addr; 161 | ap = -nc - na*2 - 4; 162 | u.u_ar0[R6] = ap; 163 | suword(ap, na); 164 | c = -nc; 165 | while(na--) { 166 | suword(ap=+2, c); 167 | do 168 | subyte(c++, *cp); 169 | while(*cp++); 170 | } 171 | suword(ap+2, -1); 172 | 173 | /* 174 | * set SUID/SGID protections, if no tracing 175 | */ 176 | 177 | if ((u.u_procp->p_flag&STRC)==0) { 178 | if(ip->i_mode&ISUID) 179 | if(u.u_uid != 0) { 180 | u.u_uid = ip->i_uid; 181 | u.u_procp->p_uid = ip->i_uid; 182 | } 183 | if(ip->i_mode&ISGID) 184 | u.u_gid = ip->i_gid; 185 | } 186 | 187 | /* 188 | * clear sigs, regs and return 189 | */ 190 | 191 | c = ip; 192 | for(ip = &u.u_signal[0]; ip < &u.u_signal[NSIG]; ip++) 193 | if((*ip & 1) == 0) 194 | *ip = 0; 195 | for(cp = ®loc[0]; cp < ®loc[6];) 196 | u.u_ar0[*cp++] = 0; 197 | u.u_ar0[R7] = 0; 198 | for(ip = &u.u_fsav[0]; ip < &u.u_fsav[25];) 199 | *ip++ = 0; 200 | ip = c; 201 | 202 | bad: 203 | iput(ip); 204 | brelse(bp); 205 | if(execnt >= NEXEC) 206 | wakeup(&execnt); 207 | execnt--; 208 | } 209 | 210 | /* 211 | * exit system call: 212 | * pass back caller's r0 213 | */ 214 | rexit() 215 | { 216 | 217 | u.u_arg[0] = u.u_ar0[R0] << 8; 218 | exit(); 219 | } 220 | 221 | /* 222 | * Release resources. 223 | * Save u. area for parent to look at. 224 | * Enter zombie state. 225 | * Wake up parent and init processes, 226 | * and dispose of children. 227 | */ 228 | exit() 229 | { 230 | register int *q, a; 231 | register struct proc *p; 232 | 233 | u.u_procp->p_flag =& ~STRC; 234 | for(q = &u.u_signal[0]; q < &u.u_signal[NSIG];) 235 | *q++ = 1; 236 | for(q = &u.u_ofile[0]; q < &u.u_ofile[NOFILE]; q++) 237 | if(a = *q) { 238 | *q = NULL; 239 | closef(a); 240 | } 241 | iput(u.u_cdir); 242 | xfree(); 243 | a = malloc(swapmap, 1); 244 | if(a == NULL) 245 | panic("out of swap"); 246 | p = getblk(swapdev, a); 247 | bcopy(&u, p->b_addr, 256); 248 | bwrite(p); 249 | q = u.u_procp; 250 | mfree(coremap, q->p_size, q->p_addr); 251 | q->p_addr = a; 252 | q->p_stat = SZOMB; 253 | 254 | loop: 255 | for(p = &proc[0]; p < &proc[NPROC]; p++) 256 | if(q->p_ppid == p->p_pid) { 257 | wakeup(&proc[1]); 258 | wakeup(p); 259 | for(p = &proc[0]; p < &proc[NPROC]; p++) 260 | if(q->p_pid == p->p_ppid) { 261 | p->p_ppid = 1; 262 | if (p->p_stat == SSTOP) 263 | setrun(p); 264 | } 265 | swtch(); 266 | /* no return */ 267 | } 268 | q->p_ppid = 1; 269 | goto loop; 270 | } 271 | 272 | /* 273 | * Wait system call. 274 | * Search for a terminated (zombie) child, 275 | * finally lay it to rest, and collect its status. 276 | * Look also for stopped (traced) children, 277 | * and pass back status from them. 278 | */ 279 | wait() 280 | { 281 | register f, *bp; 282 | register struct proc *p; 283 | 284 | f = 0; 285 | 286 | loop: 287 | for(p = &proc[0]; p < &proc[NPROC]; p++) 288 | if(p->p_ppid == u.u_procp->p_pid) { 289 | f++; 290 | if(p->p_stat == SZOMB) { 291 | u.u_ar0[R0] = p->p_pid; 292 | bp = bread(swapdev, f=p->p_addr); 293 | mfree(swapmap, 1, f); 294 | p->p_stat = NULL; 295 | p->p_pid = 0; 296 | p->p_ppid = 0; 297 | p->p_sig = 0; 298 | p->p_ttyp = 0; 299 | p->p_flag = 0; 300 | p = bp->b_addr; 301 | u.u_cstime[0] =+ p->u_cstime[0]; 302 | dpadd(u.u_cstime, p->u_cstime[1]); 303 | dpadd(u.u_cstime, p->u_stime); 304 | u.u_cutime[0] =+ p->u_cutime[0]; 305 | dpadd(u.u_cutime, p->u_cutime[1]); 306 | dpadd(u.u_cutime, p->u_utime); 307 | u.u_ar0[R1] = p->u_arg[0]; 308 | brelse(bp); 309 | return; 310 | } 311 | if(p->p_stat == SSTOP) { 312 | if((p->p_flag&SWTED) == 0) { 313 | p->p_flag =| SWTED; 314 | u.u_ar0[R0] = p->p_pid; 315 | u.u_ar0[R1] = (p->p_sig<<8) | 0177; 316 | return; 317 | } 318 | p->p_flag =& ~(STRC|SWTED); 319 | setrun(p); 320 | } 321 | } 322 | if(f) { 323 | sleep(u.u_procp, PWAIT); 324 | goto loop; 325 | } 326 | u.u_error = ECHILD; 327 | } 328 | 329 | /* 330 | * fork system call. 331 | */ 332 | fork() 333 | { 334 | register struct proc *p1, *p2; 335 | 336 | p1 = u.u_procp; 337 | for(p2 = &proc[0]; p2 < &proc[NPROC]; p2++) 338 | if(p2->p_stat == NULL) 339 | goto found; 340 | u.u_error = EAGAIN; 341 | goto out; 342 | 343 | found: 344 | if(newproc()) { 345 | u.u_ar0[R0] = p1->p_pid; 346 | u.u_cstime[0] = 0; 347 | u.u_cstime[1] = 0; 348 | u.u_stime = 0; 349 | u.u_cutime[0] = 0; 350 | u.u_cutime[1] = 0; 351 | u.u_utime = 0; 352 | return; 353 | } 354 | u.u_ar0[R0] = p2->p_pid; 355 | 356 | out: 357 | u.u_ar0[R7] =+ 2; 358 | } 359 | 360 | /* 361 | * break system call. 362 | * -- bad planning: "break" is a dirty word in C. 363 | */ 364 | sbreak() 365 | { 366 | register a, n, d; 367 | int i; 368 | 369 | /* 370 | * set n to new data size 371 | * set d to new-old 372 | * set n to new total size 373 | */ 374 | 375 | n = (((u.u_arg[0]+63)>>6) & 01777); 376 | if(!u.u_sep) 377 | n =- nseg(u.u_tsize) * 128; 378 | if(n < 0) 379 | n = 0; 380 | d = n - u.u_dsize; 381 | n =+ USIZE+u.u_ssize; 382 | if(estabur(u.u_tsize, u.u_dsize+d, u.u_ssize, u.u_sep)) 383 | return; 384 | u.u_dsize =+ d; 385 | if(d > 0) 386 | goto bigger; 387 | a = u.u_procp->p_addr + n - u.u_ssize; 388 | i = n; 389 | n = u.u_ssize; 390 | while(n--) { 391 | copyseg(a-d, a); 392 | a++; 393 | } 394 | expand(i); 395 | return; 396 | 397 | bigger: 398 | expand(n); 399 | a = u.u_procp->p_addr + n; 400 | n = u.u_ssize; 401 | while(n--) { 402 | a--; 403 | copyseg(a-d, a); 404 | } 405 | while(d--) 406 | clearseg(--a); 407 | } 408 | -------------------------------------------------------------------------------- /ken/sys2.c: -------------------------------------------------------------------------------- 1 | # 2 | #include "../param.h" 3 | #include "../systm.h" 4 | #include "../user.h" 5 | #include "../reg.h" 6 | #include "../file.h" 7 | #include "../inode.h" 8 | 9 | /* 10 | * read system call 11 | */ 12 | read() 13 | { 14 | rdwr(FREAD); 15 | } 16 | 17 | /* 18 | * write system call 19 | */ 20 | write() 21 | { 22 | rdwr(FWRITE); 23 | } 24 | 25 | /* 26 | * common code for read and write calls: 27 | * check permissions, set base, count, and offset, 28 | * and switch out to readi, writei, or pipe code. 29 | */ 30 | rdwr(mode) 31 | { 32 | register *fp, m; 33 | 34 | m = mode; 35 | fp = getf(u.u_ar0[R0]); 36 | if(fp == NULL) 37 | return; 38 | if((fp->f_flag&m) == 0) { 39 | u.u_error = EBADF; 40 | return; 41 | } 42 | u.u_base = u.u_arg[0]; 43 | u.u_count = u.u_arg[1]; 44 | u.u_segflg = 0; 45 | if(fp->f_flag&FPIPE) { 46 | if(m==FREAD) 47 | readp(fp); else 48 | writep(fp); 49 | } else { 50 | u.u_offset[1] = fp->f_offset[1]; 51 | u.u_offset[0] = fp->f_offset[0]; 52 | if(m==FREAD) 53 | readi(fp->f_inode); else 54 | writei(fp->f_inode); 55 | dpadd(fp->f_offset, u.u_arg[1]-u.u_count); 56 | } 57 | u.u_ar0[R0] = u.u_arg[1]-u.u_count; 58 | } 59 | 60 | /* 61 | * open system call 62 | */ 63 | open() 64 | { 65 | register *ip; 66 | extern uchar; 67 | 68 | ip = namei(&uchar, 0); 69 | if(ip == NULL) 70 | return; 71 | u.u_arg[1]++; 72 | open1(ip, u.u_arg[1], 0); 73 | } 74 | 75 | /* 76 | * creat system call 77 | */ 78 | creat() 79 | { 80 | register *ip; 81 | extern uchar; 82 | 83 | ip = namei(&uchar, 1); 84 | if(ip == NULL) { 85 | if(u.u_error) 86 | return; 87 | ip = maknode(u.u_arg[1]&07777&(~ISVTX)); 88 | if (ip==NULL) 89 | return; 90 | open1(ip, FWRITE, 2); 91 | } else 92 | open1(ip, FWRITE, 1); 93 | } 94 | 95 | /* 96 | * common code for open and creat. 97 | * Check permissions, allocate an open file structure, 98 | * and call the device open routine if any. 99 | */ 100 | open1(ip, mode, trf) 101 | int *ip; 102 | { 103 | register struct file *fp; 104 | register *rip, m; 105 | int i; 106 | 107 | rip = ip; 108 | m = mode; 109 | if(trf != 2) { 110 | if(m&FREAD) 111 | access(rip, IREAD); 112 | if(m&FWRITE) { 113 | access(rip, IWRITE); 114 | if((rip->i_mode&IFMT) == IFDIR) 115 | u.u_error = EISDIR; 116 | } 117 | } 118 | if(u.u_error) 119 | goto out; 120 | if(trf) 121 | itrunc(rip); 122 | prele(rip); 123 | if ((fp = falloc()) == NULL) 124 | goto out; 125 | fp->f_flag = m&(FREAD|FWRITE); 126 | fp->f_inode = rip; 127 | i = u.u_ar0[R0]; 128 | openi(rip, m&FWRITE); 129 | if(u.u_error == 0) 130 | return; 131 | u.u_ofile[i] = NULL; 132 | fp->f_count--; 133 | 134 | out: 135 | iput(rip); 136 | } 137 | 138 | /* 139 | * close system call 140 | */ 141 | close() 142 | { 143 | register *fp; 144 | 145 | fp = getf(u.u_ar0[R0]); 146 | if(fp == NULL) 147 | return; 148 | u.u_ofile[u.u_ar0[R0]] = NULL; 149 | closef(fp); 150 | } 151 | 152 | /* 153 | * seek system call 154 | */ 155 | seek() 156 | { 157 | int n[2]; 158 | register *fp, t; 159 | 160 | fp = getf(u.u_ar0[R0]); 161 | if(fp == NULL) 162 | return; 163 | if(fp->f_flag&FPIPE) { 164 | u.u_error = ESPIPE; 165 | return; 166 | } 167 | t = u.u_arg[1]; 168 | if(t > 2) { 169 | n[1] = u.u_arg[0]<<9; 170 | n[0] = u.u_arg[0]>>7; 171 | if(t == 3) 172 | n[0] =& 0777; 173 | } else { 174 | n[1] = u.u_arg[0]; 175 | n[0] = 0; 176 | if(t!=0 && n[1]<0) 177 | n[0] = -1; 178 | } 179 | switch(t) { 180 | 181 | case 1: 182 | case 4: 183 | n[0] =+ fp->f_offset[0]; 184 | dpadd(n, fp->f_offset[1]); 185 | break; 186 | 187 | default: 188 | n[0] =+ fp->f_inode->i_size0&0377; 189 | dpadd(n, fp->f_inode->i_size1); 190 | 191 | case 0: 192 | case 3: 193 | ; 194 | } 195 | fp->f_offset[1] = n[1]; 196 | fp->f_offset[0] = n[0]; 197 | } 198 | 199 | /* 200 | * link system call 201 | */ 202 | link() 203 | { 204 | register *ip, *xp; 205 | extern uchar; 206 | 207 | ip = namei(&uchar, 0); 208 | if(ip == NULL) 209 | return; 210 | if(ip->i_nlink >= 127) { 211 | u.u_error = EMLINK; 212 | goto out; 213 | } 214 | if((ip->i_mode&IFMT)==IFDIR && !suser()) 215 | goto out; 216 | /* 217 | * unlock to avoid possibly hanging the namei 218 | */ 219 | ip->i_flag =& ~ILOCK; 220 | u.u_dirp = u.u_arg[1]; 221 | xp = namei(&uchar, 1); 222 | if(xp != NULL) { 223 | u.u_error = EEXIST; 224 | iput(xp); 225 | } 226 | if(u.u_error) 227 | goto out; 228 | if(u.u_pdir->i_dev != ip->i_dev) { 229 | iput(u.u_pdir); 230 | u.u_error = EXDEV; 231 | goto out; 232 | } 233 | wdir(ip); 234 | ip->i_nlink++; 235 | ip->i_flag =| IUPD; 236 | 237 | out: 238 | iput(ip); 239 | } 240 | 241 | /* 242 | * mknod system call 243 | */ 244 | mknod() 245 | { 246 | register *ip; 247 | extern uchar; 248 | 249 | if(suser()) { 250 | ip = namei(&uchar, 1); 251 | if(ip != NULL) { 252 | u.u_error = EEXIST; 253 | goto out; 254 | } 255 | } 256 | if(u.u_error) 257 | return; 258 | ip = maknode(u.u_arg[1]); 259 | if (ip==NULL) 260 | return; 261 | ip->i_addr[0] = u.u_arg[2]; 262 | 263 | out: 264 | iput(ip); 265 | } 266 | 267 | /* 268 | * sleep system call 269 | * not to be confused with the sleep internal routine. 270 | */ 271 | sslep() 272 | { 273 | char *d[2]; 274 | 275 | spl7(); 276 | d[0] = time[0]; 277 | d[1] = time[1]; 278 | dpadd(d, u.u_ar0[R0]); 279 | 280 | while(dpcmp(d[0], d[1], time[0], time[1]) > 0) { 281 | if(dpcmp(tout[0], tout[1], time[0], time[1]) <= 0 || 282 | dpcmp(tout[0], tout[1], d[0], d[1]) > 0) { 283 | tout[0] = d[0]; 284 | tout[1] = d[1]; 285 | } 286 | sleep(tout, PSLEP); 287 | } 288 | spl0(); 289 | } 290 | -------------------------------------------------------------------------------- /ken/sys3.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | #include "../param.h" 6 | #include "../systm.h" 7 | #include "../reg.h" 8 | #include "../buf.h" 9 | #include "../filsys.h" 10 | #include "../user.h" 11 | #include "../inode.h" 12 | #include "../file.h" 13 | #include "../conf.h" 14 | 15 | /* 16 | * the fstat system call. 17 | */ 18 | fstat() 19 | { 20 | register *fp; 21 | 22 | fp = getf(u.u_ar0[R0]); 23 | if(fp == NULL) 24 | return; 25 | stat1(fp->f_inode, u.u_arg[0]); 26 | } 27 | 28 | /* 29 | * the stat system call. 30 | */ 31 | stat() 32 | { 33 | register ip; 34 | extern uchar; 35 | 36 | ip = namei(&uchar, 0); 37 | if(ip == NULL) 38 | return; 39 | stat1(ip, u.u_arg[1]); 40 | iput(ip); 41 | } 42 | 43 | /* 44 | * The basic routine for fstat and stat: 45 | * get the inode and pass appropriate parts back. 46 | */ 47 | stat1(ip, ub) 48 | int *ip; 49 | { 50 | register i, *bp, *cp; 51 | 52 | iupdat(ip, time); 53 | bp = bread(ip->i_dev, ldiv(ip->i_number+31, 16)); 54 | cp = bp->b_addr + 32*lrem(ip->i_number+31, 16) + 24; 55 | ip = &(ip->i_dev); 56 | for(i=0; i<14; i++) { 57 | suword(ub, *ip++); 58 | ub =+ 2; 59 | } 60 | for(i=0; i<4; i++) { 61 | suword(ub, *cp++); 62 | ub =+ 2; 63 | } 64 | brelse(bp); 65 | } 66 | 67 | /* 68 | * the dup system call. 69 | */ 70 | dup() 71 | { 72 | register i, *fp; 73 | 74 | fp = getf(u.u_ar0[R0]); 75 | if(fp == NULL) 76 | return; 77 | if ((i = ufalloc()) < 0) 78 | return; 79 | u.u_ofile[i] = fp; 80 | fp->f_count++; 81 | } 82 | 83 | /* 84 | * the mount system call. 85 | */ 86 | smount() 87 | { 88 | int d; 89 | register *ip; 90 | register struct mount *mp, *smp; 91 | extern uchar; 92 | 93 | d = getmdev(); 94 | if(u.u_error) 95 | return; 96 | u.u_dirp = u.u_arg[1]; 97 | ip = namei(&uchar, 0); 98 | if(ip == NULL) 99 | return; 100 | if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0) 101 | goto out; 102 | smp = NULL; 103 | for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 104 | if(mp->m_bufp != NULL) { 105 | if(d == mp->m_dev) 106 | goto out; 107 | } else 108 | if(smp == NULL) 109 | smp = mp; 110 | } 111 | if(smp == NULL) 112 | goto out; 113 | (*bdevsw[d.d_major].d_open)(d, !u.u_arg[2]); 114 | if(u.u_error) 115 | goto out; 116 | mp = bread(d, 1); 117 | if(u.u_error) { 118 | brelse(mp); 119 | goto out1; 120 | } 121 | smp->m_inodp = ip; 122 | smp->m_dev = d; 123 | smp->m_bufp = getblk(NODEV); 124 | bcopy(mp->b_addr, smp->m_bufp->b_addr, 256); 125 | smp = smp->m_bufp->b_addr; 126 | smp->s_ilock = 0; 127 | smp->s_flock = 0; 128 | smp->s_ronly = u.u_arg[2] & 1; 129 | brelse(mp); 130 | ip->i_flag =| IMOUNT; 131 | prele(ip); 132 | return; 133 | 134 | out: 135 | u.u_error = EBUSY; 136 | out1: 137 | iput(ip); 138 | } 139 | 140 | /* 141 | * the umount system call. 142 | */ 143 | sumount() 144 | { 145 | int d; 146 | register struct inode *ip; 147 | register struct mount *mp; 148 | 149 | update(); 150 | d = getmdev(); 151 | if(u.u_error) 152 | return; 153 | for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 154 | if(mp->m_bufp!=NULL && d==mp->m_dev) 155 | goto found; 156 | u.u_error = EINVAL; 157 | return; 158 | 159 | found: 160 | for(ip = &inode[0]; ip < &inode[NINODE]; ip++) 161 | if(ip->i_number!=0 && d==ip->i_dev) { 162 | u.u_error = EBUSY; 163 | return; 164 | } 165 | (*bdevsw[d.d_major].d_close)(d, 0); 166 | ip = mp->m_inodp; 167 | ip->i_flag =& ~IMOUNT; 168 | iput(ip); 169 | ip = mp->m_bufp; 170 | mp->m_bufp = NULL; 171 | brelse(ip); 172 | } 173 | 174 | /* 175 | * Common code for mount and umount. 176 | * Check that the user's argument is a reasonable 177 | * thing on which to mount, and return the device number if so. 178 | */ 179 | getmdev() 180 | { 181 | register d, *ip; 182 | extern uchar; 183 | 184 | ip = namei(&uchar, 0); 185 | if(ip == NULL) 186 | return; 187 | if((ip->i_mode&IFMT) != IFBLK) 188 | u.u_error = ENOTBLK; 189 | d = ip->i_addr[0]; 190 | if(ip->i_addr[0].d_major >= nblkdev) 191 | u.u_error = ENXIO; 192 | iput(ip); 193 | return(d); 194 | } 195 | -------------------------------------------------------------------------------- /ken/sys4.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * Everything in this file is a routine implementing a system call. 7 | */ 8 | 9 | #include "../param.h" 10 | #include "../user.h" 11 | #include "../reg.h" 12 | #include "../inode.h" 13 | #include "../systm.h" 14 | #include "../proc.h" 15 | 16 | getswit() 17 | { 18 | 19 | u.u_ar0[R0] = SW->integ; 20 | } 21 | 22 | gtime() 23 | { 24 | 25 | u.u_ar0[R0] = time[0]; 26 | u.u_ar0[R1] = time[1]; 27 | } 28 | 29 | stime() 30 | { 31 | 32 | if(suser()) { 33 | time[0] = u.u_ar0[R0]; 34 | time[1] = u.u_ar0[R1]; 35 | wakeup(tout); 36 | } 37 | } 38 | 39 | setuid() 40 | { 41 | register uid; 42 | 43 | uid = u.u_ar0[R0].lobyte; 44 | if(u.u_ruid == uid.lobyte || suser()) { 45 | u.u_uid = uid; 46 | u.u_procp->p_uid = uid; 47 | u.u_ruid = uid; 48 | } 49 | } 50 | 51 | getuid() 52 | { 53 | 54 | u.u_ar0[R0].lobyte = u.u_ruid; 55 | u.u_ar0[R0].hibyte = u.u_uid; 56 | } 57 | 58 | setgid() 59 | { 60 | register gid; 61 | 62 | gid = u.u_ar0[R0].lobyte; 63 | if(u.u_rgid == gid.lobyte || suser()) { 64 | u.u_gid = gid; 65 | u.u_rgid = gid; 66 | } 67 | } 68 | 69 | getgid() 70 | { 71 | 72 | u.u_ar0[R0].lobyte = u.u_rgid; 73 | u.u_ar0[R0].hibyte = u.u_gid; 74 | } 75 | 76 | getpid() 77 | { 78 | u.u_ar0[R0] = u.u_procp->p_pid; 79 | } 80 | 81 | sync() 82 | { 83 | 84 | update(); 85 | } 86 | 87 | nice() 88 | { 89 | register n; 90 | 91 | n = u.u_ar0[R0]; 92 | if(n > 20) 93 | n = 20; 94 | if(n < 0 && !suser()) 95 | n = 0; 96 | u.u_procp->p_nice = n; 97 | } 98 | 99 | /* 100 | * Unlink system call. 101 | * panic: unlink -- "cannot happen" 102 | */ 103 | unlink() 104 | { 105 | register *ip, *pp; 106 | extern uchar; 107 | 108 | pp = namei(&uchar, 2); 109 | if(pp == NULL) 110 | return; 111 | prele(pp); 112 | ip = iget(pp->i_dev, u.u_dent.u_ino); 113 | if(ip == NULL) 114 | panic("unlink -- iget"); 115 | if((ip->i_mode&IFMT)==IFDIR && !suser()) 116 | goto out; 117 | u.u_offset[1] =- DIRSIZ+2; 118 | u.u_base = &u.u_dent; 119 | u.u_count = DIRSIZ+2; 120 | u.u_dent.u_ino = 0; 121 | writei(pp); 122 | ip->i_nlink--; 123 | ip->i_flag =| IUPD; 124 | 125 | out: 126 | iput(pp); 127 | iput(ip); 128 | } 129 | 130 | chdir() 131 | { 132 | register *ip; 133 | extern uchar; 134 | 135 | ip = namei(&uchar, 0); 136 | if(ip == NULL) 137 | return; 138 | if((ip->i_mode&IFMT) != IFDIR) { 139 | u.u_error = ENOTDIR; 140 | bad: 141 | iput(ip); 142 | return; 143 | } 144 | if(access(ip, IEXEC)) 145 | goto bad; 146 | iput(u.u_cdir); 147 | u.u_cdir = ip; 148 | prele(ip); 149 | } 150 | 151 | chmod() 152 | { 153 | register *ip; 154 | 155 | if ((ip = owner()) == NULL) 156 | return; 157 | ip->i_mode =& ~07777; 158 | if (u.u_uid) 159 | u.u_arg[1] =& ~ISVTX; 160 | ip->i_mode =| u.u_arg[1]&07777; 161 | ip->i_flag =| IUPD; 162 | iput(ip); 163 | } 164 | 165 | chown() 166 | { 167 | register *ip; 168 | 169 | if (!suser() || (ip = owner()) == NULL) 170 | return; 171 | ip->i_uid = u.u_arg[1].lobyte; 172 | ip->i_gid = u.u_arg[1].hibyte; 173 | ip->i_flag =| IUPD; 174 | iput(ip); 175 | } 176 | 177 | /* 178 | * Change modified date of file: 179 | * time to r0-r1; sys smdate; file 180 | * This call has been withdrawn because it messes up 181 | * incremental dumps (pseudo-old files aren't dumped). 182 | * It works though and you can uncomment it if you like. 183 | 184 | smdate() 185 | { 186 | register struct inode *ip; 187 | register int *tp; 188 | int tbuf[2]; 189 | 190 | if ((ip = owner()) == NULL) 191 | return; 192 | ip->i_flag =| IUPD; 193 | tp = &tbuf[2]; 194 | *--tp = u.u_ar0[R1]; 195 | *--tp = u.u_ar0[R0]; 196 | iupdat(ip, tp); 197 | ip->i_flag =& ~IUPD; 198 | iput(ip); 199 | } 200 | */ 201 | 202 | ssig() 203 | { 204 | register a; 205 | 206 | a = u.u_arg[0]; 207 | if(a<=0 || a>=NSIG || a ==SIGKIL) { 208 | u.u_error = EINVAL; 209 | return; 210 | } 211 | u.u_ar0[R0] = u.u_signal[a]; 212 | u.u_signal[a] = u.u_arg[1]; 213 | if(u.u_procp->p_sig == a) 214 | u.u_procp->p_sig = 0; 215 | } 216 | 217 | kill() 218 | { 219 | register struct proc *p, *q; 220 | register a; 221 | int f; 222 | 223 | f = 0; 224 | a = u.u_ar0[R0]; 225 | q = u.u_procp; 226 | for(p = &proc[0]; p < &proc[NPROC]; p++) { 227 | if(p == q) 228 | continue; 229 | if(a != 0 && p->p_pid != a) 230 | continue; 231 | if(a == 0 && (p->p_ttyp != q->p_ttyp || p <= &proc[1])) 232 | continue; 233 | if(u.u_uid != 0 && u.u_uid != p->p_uid) 234 | continue; 235 | f++; 236 | psignal(p, u.u_arg[0]); 237 | } 238 | if(f == 0) 239 | u.u_error = ESRCH; 240 | } 241 | 242 | times() 243 | { 244 | register *p; 245 | 246 | for(p = &u.u_utime; p < &u.u_utime+6;) { 247 | suword(u.u_arg[0], *p++); 248 | u.u_arg[0] =+ 2; 249 | } 250 | } 251 | 252 | profil() 253 | { 254 | 255 | u.u_prof[0] = u.u_arg[0] & ~1; /* base of sample buf */ 256 | u.u_prof[1] = u.u_arg[1]; /* size of same */ 257 | u.u_prof[2] = u.u_arg[2]; /* pc offset */ 258 | u.u_prof[3] = (u.u_arg[3]>>1) & 077777; /* pc scale */ 259 | } 260 | -------------------------------------------------------------------------------- /ken/sysent.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | /* 6 | * This table is the switch used to transfer 7 | * to the appropriate routine for processing a system call. 8 | * Each row contains the number of arguments expected 9 | * and a pointer to the routine. 10 | */ 11 | int sysent[] 12 | { 13 | 0, &nullsys, /* 0 = indir */ 14 | 0, &rexit, /* 1 = exit */ 15 | 0, &fork, /* 2 = fork */ 16 | 2, &read, /* 3 = read */ 17 | 2, &write, /* 4 = write */ 18 | 2, &open, /* 5 = open */ 19 | 0, &close, /* 6 = close */ 20 | 0, &wait, /* 7 = wait */ 21 | 2, &creat, /* 8 = creat */ 22 | 2, &link, /* 9 = link */ 23 | 1, &unlink, /* 10 = unlink */ 24 | 2, &exec, /* 11 = exec */ 25 | 1, &chdir, /* 12 = chdir */ 26 | 0, >ime, /* 13 = time */ 27 | 3, &mknod, /* 14 = mknod */ 28 | 2, &chmod, /* 15 = chmod */ 29 | 2, &chown, /* 16 = chown */ 30 | 1, &sbreak, /* 17 = break */ 31 | 2, &stat, /* 18 = stat */ 32 | 2, &seek, /* 19 = seek */ 33 | 0, &getpid, /* 20 = getpid */ 34 | 3, &smount, /* 21 = mount */ 35 | 1, &sumount, /* 22 = umount */ 36 | 0, &setuid, /* 23 = setuid */ 37 | 0, &getuid, /* 24 = getuid */ 38 | 0, &stime, /* 25 = stime */ 39 | 3, &ptrace, /* 26 = ptrace */ 40 | 0, &nosys, /* 27 = x */ 41 | 1, &fstat, /* 28 = fstat */ 42 | 0, &nosys, /* 29 = x */ 43 | 1, &nullsys, /* 30 = smdate; inoperative */ 44 | 1, &stty, /* 31 = stty */ 45 | 1, >ty, /* 32 = gtty */ 46 | 0, &nosys, /* 33 = x */ 47 | 0, &nice, /* 34 = nice */ 48 | 0, &sslep, /* 35 = sleep */ 49 | 0, &sync, /* 36 = sync */ 50 | 1, &kill, /* 37 = kill */ 51 | 0, &getswit, /* 38 = switch */ 52 | 0, &nosys, /* 39 = x */ 53 | 0, &nosys, /* 40 = x */ 54 | 0, &dup, /* 41 = dup */ 55 | 0, &pipe, /* 42 = pipe */ 56 | 1, ×, /* 43 = times */ 57 | 4, &profil, /* 44 = prof */ 58 | 0, &nosys, /* 45 = tiu */ 59 | 0, &setgid, /* 46 = setgid */ 60 | 0, &getgid, /* 47 = getgid */ 61 | 2, &ssig, /* 48 = sig */ 62 | 0, &nosys, /* 49 = x */ 63 | 0, &nosys, /* 50 = x */ 64 | 0, &nosys, /* 51 = x */ 65 | 0, &nosys, /* 52 = x */ 66 | 0, &nosys, /* 53 = x */ 67 | 0, &nosys, /* 54 = x */ 68 | 0, &nosys, /* 55 = x */ 69 | 0, &nosys, /* 56 = x */ 70 | 0, &nosys, /* 57 = x */ 71 | 0, &nosys, /* 58 = x */ 72 | 0, &nosys, /* 59 = x */ 73 | 0, &nosys, /* 60 = x */ 74 | 0, &nosys, /* 61 = x */ 75 | 0, &nosys, /* 62 = x */ 76 | 0, &nosys /* 63 = x */ 77 | }; 78 | -------------------------------------------------------------------------------- /ken/text.c: -------------------------------------------------------------------------------- 1 | # 2 | /* 3 | */ 4 | 5 | #include "../param.h" 6 | #include "../systm.h" 7 | #include "../user.h" 8 | #include "../proc.h" 9 | #include "../text.h" 10 | #include "../inode.h" 11 | 12 | /* 13 | * Swap out process p. 14 | * The ff flag causes its core to be freed-- 15 | * it may be off when called to create an image for a 16 | * child process in newproc. 17 | * Os is the old size of the data area of the process, 18 | * and is supplied during core expansion swaps. 19 | * 20 | * panic: out of swap space 21 | * panic: swap error -- IO error 22 | */ 23 | xswap(p, ff, os) 24 | int *p; 25 | { 26 | register *rp, a; 27 | 28 | rp = p; 29 | if(os == 0) 30 | os = rp->p_size; 31 | a = malloc(swapmap, (rp->p_size+7)/8); 32 | if(a == NULL) 33 | panic("out of swap space"); 34 | xccdec(rp->p_textp); 35 | rp->p_flag =| SLOCK; 36 | if(swap(a, rp->p_addr, os, 0)) 37 | panic("swap error"); 38 | if(ff) 39 | mfree(coremap, os, rp->p_addr); 40 | rp->p_addr = a; 41 | rp->p_flag =& ~(SLOAD|SLOCK); 42 | rp->p_time = 0; 43 | if(runout) { 44 | runout = 0; 45 | wakeup(&runout); 46 | } 47 | } 48 | 49 | /* 50 | * relinquish use of the shared text segment 51 | * of a process. 52 | */ 53 | xfree() 54 | { 55 | register *xp, *ip; 56 | 57 | if((xp=u.u_procp->p_textp) != NULL) { 58 | u.u_procp->p_textp = NULL; 59 | xccdec(xp); 60 | if(--xp->x_count == 0) { 61 | ip = xp->x_iptr; 62 | if((ip->i_mode&ISVTX) == 0) { 63 | xp->x_iptr = NULL; 64 | mfree(swapmap, (xp->x_size+7)/8, xp->x_daddr); 65 | ip->i_flag =& ~ITEXT; 66 | iput(ip); 67 | } 68 | } 69 | } 70 | } 71 | 72 | /* 73 | * Attach to a shared text segment. 74 | * If there is no shared text, just return. 75 | * If there is, hook up to it: 76 | * if it is not currently being used, it has to be read 77 | * in from the inode (ip) and established in the swap space. 78 | * If it is being used, but is not currently in core, 79 | * a swap has to be done to get it back. 80 | * The full coroutine glory has to be invoked-- 81 | * see slp.c-- because if the calling process 82 | * is misplaced in core the text image might not fit. 83 | * Quite possibly the code after "out:" could check to 84 | * see if the text does fit and simply swap it in. 85 | * 86 | * panic: out of swap space 87 | */ 88 | xalloc(ip) 89 | int *ip; 90 | { 91 | register struct text *xp; 92 | register *rp, ts; 93 | 94 | if(u.u_arg[1] == 0) 95 | return; 96 | rp = NULL; 97 | for(xp = &text[0]; xp < &text[NTEXT]; xp++) 98 | if(xp->x_iptr == NULL) { 99 | if(rp == NULL) 100 | rp = xp; 101 | } else 102 | if(xp->x_iptr == ip) { 103 | xp->x_count++; 104 | u.u_procp->p_textp = xp; 105 | goto out; 106 | } 107 | if((xp=rp) == NULL) 108 | panic("out of text"); 109 | xp->x_count = 1; 110 | xp->x_ccount = 0; 111 | xp->x_iptr = ip; 112 | ts = ((u.u_arg[1]+63)>>6) & 01777; 113 | xp->x_size = ts; 114 | if((xp->x_daddr = malloc(swapmap, (ts+7)/8)) == NULL) 115 | panic("out of swap space"); 116 | expand(USIZE+ts); 117 | estabur(0, ts, 0, 0); 118 | u.u_count = u.u_arg[1]; 119 | u.u_offset[1] = 020; 120 | u.u_base = 0; 121 | readi(ip); 122 | rp = u.u_procp; 123 | rp->p_flag =| SLOCK; 124 | swap(xp->x_daddr, rp->p_addr+USIZE, ts, 0); 125 | rp->p_flag =& ~SLOCK; 126 | rp->p_textp = xp; 127 | rp = ip; 128 | rp->i_flag =| ITEXT; 129 | rp->i_count++; 130 | expand(USIZE); 131 | 132 | out: 133 | if(xp->x_ccount == 0) { 134 | savu(u.u_rsav); 135 | savu(u.u_ssav); 136 | xswap(u.u_procp, 1, 0); 137 | u.u_procp->p_flag =| SSWAP; 138 | swtch(); 139 | /* no return */ 140 | } 141 | xp->x_ccount++; 142 | } 143 | 144 | /* 145 | * Decrement the in-core usage count of a shared text segment. 146 | * When it drops to zero, free the core space. 147 | */ 148 | xccdec(xp) 149 | int *xp; 150 | { 151 | register *rp; 152 | 153 | if((rp=xp)!=NULL && rp->x_ccount!=0) 154 | if(--rp->x_ccount == 0) 155 | mfree(coremap, rp->x_size, rp->x_caddr); 156 | } 157 | -------------------------------------------------------------------------------- /ken/trap.c: -------------------------------------------------------------------------------- 1 | # 2 | #include "../param.h" 3 | #include "../systm.h" 4 | #include "../user.h" 5 | #include "../proc.h" 6 | #include "../reg.h" 7 | #include "../seg.h" 8 | 9 | #define EBIT 1 /* user error bit in PS: C-bit */ 10 | #define UMODE 0170000 /* user-mode bits in PS word */ 11 | #define SETD 0170011 /* SETD instruction */ 12 | #define SYS 0104400 /* sys (trap) instruction */ 13 | #define USER 020 /* user-mode flag added to dev */ 14 | 15 | /* 16 | * structure of the system entry table (sysent.c) 17 | */ 18 | struct sysent { 19 | int count; /* argument count */ 20 | int (*call)(); /* name of handler */ 21 | } sysent[64]; 22 | 23 | /* 24 | * Offsets of the user's registers relative to 25 | * the saved r0. See reg.h 26 | */ 27 | char regloc[9] 28 | { 29 | R0, R1, R2, R3, R4, R5, R6, R7, RPS 30 | }; 31 | 32 | /* 33 | * Called from l40.s or l45.s when a processor trap occurs. 34 | * The arguments are the words saved on the system stack 35 | * by the hardware and software during the trap processing. 36 | * Their order is dictated by the hardware and the details 37 | * of C's calling sequence. They are peculiar in that 38 | * this call is not 'by value' and changed user registers 39 | * get copied back on return. 40 | * dev is the kind of trap that occurred. 41 | */ 42 | trap(dev, sp, r1, nps, r0, pc, ps) 43 | { 44 | register i, a; 45 | register struct sysent *callp; 46 | 47 | savfp(); 48 | if ((ps&UMODE) == UMODE) 49 | dev =| USER; 50 | u.u_ar0 = &r0; 51 | switch(dev) { 52 | 53 | /* 54 | * Trap not expected. 55 | * Usually a kernel mode bus error. 56 | * The numbers printed are used to 57 | * find the hardware PS/PC as follows. 58 | * (all numbers in octal 18 bits) 59 | * address_of_saved_ps = 60 | * (ka6*0100) + aps - 0140000; 61 | * address_of_saved_pc = 62 | * address_of_saved_ps - 2; 63 | */ 64 | default: 65 | printf("ka6 = %o\n", *ka6); 66 | printf("aps = %o\n", &ps); 67 | printf("trap type %o\n", dev); 68 | panic("trap"); 69 | 70 | case 0+USER: /* bus error */ 71 | i = SIGBUS; 72 | break; 73 | 74 | /* 75 | * If illegal instructions are not 76 | * being caught and the offending instruction 77 | * is a SETD, the trap is ignored. 78 | * This is because C produces a SETD at 79 | * the beginning of every program which 80 | * will trap on CPUs without 11/45 FPU. 81 | */ 82 | case 1+USER: /* illegal instruction */ 83 | if(fuiword(pc-2) == SETD && u.u_signal[SIGINS] == 0) 84 | goto out; 85 | i = SIGINS; 86 | break; 87 | 88 | case 2+USER: /* bpt or trace */ 89 | i = SIGTRC; 90 | break; 91 | 92 | case 3+USER: /* iot */ 93 | i = SIGIOT; 94 | break; 95 | 96 | case 5+USER: /* emt */ 97 | i = SIGEMT; 98 | break; 99 | 100 | case 6+USER: /* sys call */ 101 | u.u_error = 0; 102 | ps =& ~EBIT; 103 | callp = &sysent[fuiword(pc-2)&077]; 104 | if (callp == sysent) { /* indirect */ 105 | a = fuiword(pc); 106 | pc =+ 2; 107 | i = fuword(a); 108 | if ((i & ~077) != SYS) 109 | i = 077; /* illegal */ 110 | callp = &sysent[i&077]; 111 | for(i=0; icount; i++) 112 | u.u_arg[i] = fuword(a =+ 2); 113 | } else { 114 | for(i=0; icount; i++) { 115 | u.u_arg[i] = fuiword(pc); 116 | pc =+ 2; 117 | } 118 | } 119 | u.u_dirp = u.u_arg[0]; 120 | trap1(callp->call); 121 | if(u.u_intflg) 122 | u.u_error = EINTR; 123 | if(u.u_error < 100) { 124 | if(u.u_error) { 125 | ps =| EBIT; 126 | r0 = u.u_error; 127 | } 128 | goto out; 129 | } 130 | i = SIGSYS; 131 | break; 132 | 133 | /* 134 | * Since the floating exception is an 135 | * imprecise trap, a user generated 136 | * trap may actually come from kernel 137 | * mode. In this case, a signal is sent 138 | * to the current process to be picked 139 | * up later. 140 | */ 141 | case 8: /* floating exception */ 142 | psignal(u.u_procp, SIGFPT); 143 | return; 144 | 145 | case 8+USER: 146 | i = SIGFPT; 147 | break; 148 | 149 | /* 150 | * If the user SP is below the stack segment, 151 | * grow the stack automatically. 152 | * This relies on the ability of the hardware 153 | * to restart a half executed instruction. 154 | * On the 11/40 this is not the case and 155 | * the routine backup/l40.s may fail. 156 | * The classic example is on the instruction 157 | * cmp -(sp),-(sp) 158 | */ 159 | case 9+USER: /* segmentation exception */ 160 | a = sp; 161 | if(backup(u.u_ar0) == 0) 162 | if(grow(a)) 163 | goto out; 164 | i = SIGSEG; 165 | break; 166 | } 167 | psignal(u.u_procp, i); 168 | 169 | out: 170 | if(issig()) 171 | psig(); 172 | setpri(u.u_procp); 173 | } 174 | 175 | /* 176 | * Call the system-entry routine f (out of the 177 | * sysent table). This is a subroutine for trap, and 178 | * not in-line, because if a signal occurs 179 | * during processing, an (abnormal) return is simulated from 180 | * the last caller to savu(qsav); if this took place 181 | * inside of trap, it wouldn't have a chance to clean up. 182 | * 183 | * If this occurs, the return takes place without 184 | * clearing u_intflg; if it's still set, trap 185 | * marks an error which means that a system 186 | * call (like read on a typewriter) got interrupted 187 | * by a signal. 188 | */ 189 | trap1(f) 190 | int (*f)(); 191 | { 192 | 193 | u.u_intflg = 1; 194 | savu(u.u_qsav); 195 | (*f)(); 196 | u.u_intflg = 0; 197 | } 198 | 199 | /* 200 | * nonexistent system call-- set fatal error code. 201 | */ 202 | nosys() 203 | { 204 | u.u_error = 100; 205 | } 206 | 207 | /* 208 | * Ignored system call 209 | */ 210 | nullsys() 211 | { 212 | } 213 | -------------------------------------------------------------------------------- /param.h: -------------------------------------------------------------------------------- 1 | /* 2 | * tunable variables 3 | */ 4 | 5 | #define NBUF 15 /* size of buffer cache */ 6 | #define NINODE 100 /* number of in core inodes */ 7 | #define NFILE 100 /* number of in core file structures */ 8 | #define NMOUNT 5 /* number of mountable file systems */ 9 | #define NEXEC 3 /* number of simultaneous exec's */ 10 | #define MAXMEM (64*32) /* max core per process - first # is Kw */ 11 | #define SSIZE 20 /* initial stack size (*64 bytes) */ 12 | #define SINCR 20 /* increment of stack (*64 bytes) */ 13 | #define NOFILE 15 /* max open files per process */ 14 | #define CANBSIZ 256 /* max size of typewriter line */ 15 | #define CMAPSIZ 100 /* size of core allocation area */ 16 | #define SMAPSIZ 100 /* size of swap allocation area */ 17 | #define NCALL 20 /* max simultaneous time callouts */ 18 | #define NPROC 50 /* max number of processes */ 19 | #define NTEXT 40 /* max number of pure texts */ 20 | #define NCLIST 100 /* max total clist size */ 21 | #define HZ 60 /* Ticks/second of the clock */ 22 | 23 | /* 24 | * priorities 25 | * probably should not be 26 | * altered too much 27 | */ 28 | 29 | #define PSWP -100 30 | #define PINOD -90 31 | #define PRIBIO -50 32 | #define PPIPE 1 33 | #define PWAIT 40 34 | #define PSLEP 90 35 | #define PUSER 100 36 | 37 | /* 38 | * signals 39 | * dont change 40 | */ 41 | 42 | #define NSIG 20 43 | #define SIGHUP 1 /* hangup */ 44 | #define SIGINT 2 /* interrupt (rubout) */ 45 | #define SIGQIT 3 /* quit (FS) */ 46 | #define SIGINS 4 /* illegal instruction */ 47 | #define SIGTRC 5 /* trace or breakpoint */ 48 | #define SIGIOT 6 /* iot */ 49 | #define SIGEMT 7 /* emt */ 50 | #define SIGFPT 8 /* floating exception */ 51 | #define SIGKIL 9 /* kill */ 52 | #define SIGBUS 10 /* bus error */ 53 | #define SIGSEG 11 /* segmentation violation */ 54 | #define SIGSYS 12 /* sys */ 55 | #define SIGPIPE 13 /* end of pipe */ 56 | 57 | /* 58 | * fundamental constants 59 | * cannot be changed 60 | */ 61 | 62 | #define USIZE 16 /* size of user block (*64) */ 63 | #define NULL 0 64 | #define NODEV (-1) 65 | #define ROOTINO 1 /* i number of all roots */ 66 | #define DIRSIZ 14 /* max characters per directory */ 67 | 68 | /* 69 | * structure to access an 70 | * integer in bytes 71 | */ 72 | struct 73 | { 74 | char lobyte; 75 | char hibyte; 76 | }; 77 | 78 | /* 79 | * structure to access an integer 80 | */ 81 | struct 82 | { 83 | int integ; 84 | }; 85 | 86 | /* 87 | * Certain processor registers 88 | */ 89 | #define PS 0177776 90 | #define KL 0177560 91 | #define SW 0177570 92 | -------------------------------------------------------------------------------- /proc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * One structure allocated per active 3 | * process. It contains all data needed 4 | * about the process while the 5 | * process may be swapped out. 6 | * Other per process data (user.h) 7 | * is swapped with the process. 8 | */ 9 | struct proc 10 | { 11 | char p_stat; /* 상태, NULL인 경우 해당하는 PROC[]를 비어있다고 여긴다. */ 12 | char p_flag; /* 플래그 */ 13 | char p_pri; /* 실행 우선순위, 값이 작을 수록 우선순위가 높다. */ 14 | char p_sig; /* 수신된 시그날 */ 15 | char p_uid; /* 사용자 ID (정수) */ 16 | char p_time; /* 메모리나 스왑영역에 머물렀던 시간 (초) */ 17 | char p_cpu; /* CPU를 사용한 누적 시간 (tick) */ 18 | char p_nice; /* 디폴트는 0으로, nice시스템콜에 의해서 사용자가 값을 설정한다. */ 19 | int p_ttyp; /* 프로세스를 조작하고 있는 단말 */ 20 | int p_pid; /* 프로세스 ID */ 21 | int p_ppid; /* 부모 프로세스 ID */ 22 | int p_addr; /* 할당 받은 물리 메모리 어드레스 (64바이트 단위) */ 23 | int p_size; /* 할당 받은 메모리 사이즈 (64바이트 단위) */ 24 | int p_wchan; /* 슬립되고 있는 이유 */ 25 | int *p_textp; /* 사용하고 있는 텍스트세그먼트 */ 26 | } proc[NPROC]; 27 | 28 | /* stat codes */ 29 | #define SSLEEP 1 /* 잠자기, 실행 우선순위가 음수 값으로 슬립 중*/ 30 | #define SWAIT 2 /* 잠자기, 실행 우선순위가 0이상 값으로 슬립 중*/ 31 | #define SRUN 3 /* 실행 가능 상태 */ 32 | #define SIDL 4 /* 프로세스 생성 처리 중 */ 33 | #define SZOMB 5 /* 좀비 상태 */ 34 | #define SSTOP 6 /* 트레이스에 따르는 개입을 기다림*/ 35 | 36 | /* flag codes */ 37 | #define SLOAD 01 /* in core */ 38 | #define SSYS 02 /* scheduling process */ 39 | #define SLOCK 04 /* process cannot be swapped */ 40 | #define SSWAP 010 /* process is being swapped out */ 41 | #define STRC 020 /* process is being traced */ 42 | #define SWTED 040 /* another tracing flag */ 43 | -------------------------------------------------------------------------------- /reg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Location of the users' stored 3 | * registers relative to R0. 4 | * Usage is u.u_ar0[XX]. 5 | */ 6 | #define R0 (0) 7 | #define R1 (-2) 8 | #define R2 (-9) 9 | #define R3 (-8) 10 | #define R4 (-7) 11 | #define R5 (-6) 12 | #define R6 (-3) 13 | #define R7 (1) 14 | #define RPS (2) 15 | 16 | #define TBIT 020 /* PS trace bit */ 17 | -------------------------------------------------------------------------------- /seg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * KT-11 addresses and bits. 3 | */ 4 | 5 | #define UISD 0177600 /* first user I-space descriptor register */ 6 | #define UISA 0177640 /* first user I-space address register */ 7 | #define UDSA 0177660 /* first user D-space address register */ 8 | #define RO 02 /* access abilities */ 9 | #define WO 04 10 | #define RW 06 11 | #define ED 010 /* extend direction */ 12 | 13 | /* 14 | * structure used to address 15 | * a sequence of integers. 16 | */ 17 | struct 18 | { 19 | int r[]; 20 | }; 21 | int *ka6; /* 11/40 KISA6; 11/45 KDSA6 */ 22 | 23 | /* 24 | * address to access 11/70 UNIBUS map 25 | */ 26 | #define UBMAP 0170200 27 | -------------------------------------------------------------------------------- /systm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Random set of variables 3 | * used by more than one 4 | * routine. 5 | */ 6 | char canonb[CANBSIZ]; /* buffer for erase and kill (#@) */ 7 | int coremap[CMAPSIZ]; /* space for core allocation */ 8 | int swapmap[SMAPSIZ]; /* space for swap allocation */ 9 | int *rootdir; /* pointer to inode of root directory */ 10 | int cputype; /* type of cpu =40, 45, or 70 */ 11 | int execnt; /* number of processes in exec */ 12 | int lbolt; /* time of day in 60th not in time */ 13 | int time[2]; /* time in sec from 1970 */ 14 | int tout[2]; /* time of day of next sleep */ 15 | /* 16 | * The callout structure is for 17 | * a routine arranging 18 | * to be called by the clock interrupt 19 | * (clock.c) with a specified argument, 20 | * in a specified amount of time. 21 | * Used, for example, to time tab 22 | * delays on teletypes. 23 | */ 24 | struct callo 25 | { 26 | int c_time; /* incremental time */ 27 | int c_arg; /* argument to routine */ 28 | int (*c_func)(); /* routine */ 29 | } callout[NCALL]; 30 | /* 31 | * Mount structure. 32 | * One allocated on every mount. 33 | * Used to find the super block. 34 | */ 35 | struct mount 36 | { 37 | int m_dev; /* device mounted */ 38 | int *m_bufp; /* pointer to superblock */ 39 | int *m_inodp; /* pointer to mounted on inode */ 40 | } mount[NMOUNT]; 41 | int mpid; /* generic for unique process id's */ 42 | char runin; /* scheduling flag */ 43 | char runout; /* scheduling flag */ 44 | char runrun; /* scheduling flag */ 45 | char curpri; /* more scheduling */ 46 | int maxmem; /* actual max memory per process */ 47 | int *lks; /* pointer to clock device */ 48 | int rootdev; /* dev of root see conf.c */ 49 | int swapdev; /* dev of swap see conf.c */ 50 | int swplo; /* block number of swap space */ 51 | int nswap; /* size of swap space */ 52 | int updlock; /* lock for sync */ 53 | int rablock; /* block to be read ahead */ 54 | char regloc[]; /* locs. of saved user registers (trap.c) */ 55 | -------------------------------------------------------------------------------- /text.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Text structure. 3 | * One allocated per pure 4 | * procedure on swap device. 5 | * Manipulated by text.c 6 | */ 7 | struct text 8 | { 9 | int x_daddr; /* disk address of segment */ 10 | int x_caddr; /* core address, if loaded */ 11 | int x_size; /* size (*64) */ 12 | int *x_iptr; /* inode of prototype */ 13 | char x_count; /* reference count */ 14 | char x_ccount; /* number of loaded references */ 15 | } text[NTEXT]; 16 | -------------------------------------------------------------------------------- /tty.h: -------------------------------------------------------------------------------- 1 | /* 2 | * A clist structure is the head 3 | * of a linked list queue of characters. 4 | * The characters are stored in 4-word 5 | * blocks containing a link and 6 characters. 6 | * The routines getc and putc (m45.s or m40.s) 7 | * manipulate these structures. 8 | */ 9 | struct clist 10 | { 11 | int c_cc; /* character count */ 12 | int c_cf; /* pointer to first block */ 13 | int c_cl; /* pointer to last block */ 14 | }; 15 | 16 | /* 17 | * A tty structure is needed for 18 | * each UNIX character device that 19 | * is used for normal terminal IO. 20 | * The routines in tty.c handle the 21 | * common code associated with 22 | * these structures. 23 | * The definition and device dependent 24 | * code is in each driver. (kl.c dc.c dh.c) 25 | */ 26 | struct tty 27 | { 28 | struct clist t_rawq; /* input chars right off device */ 29 | struct clist t_canq; /* input chars after erase and kill */ 30 | struct clist t_outq; /* output list to device */ 31 | int t_flags; /* mode, settable by stty call */ 32 | int *t_addr; /* device address (register or startup fcn) */ 33 | char t_delct; /* number of delimiters in raw q */ 34 | char t_col; /* printing column of device */ 35 | char t_erase; /* erase character */ 36 | char t_kill; /* kill character */ 37 | char t_state; /* internal state, not visible externally */ 38 | char t_char; /* character temporary */ 39 | int t_speeds; /* output+input line speed */ 40 | int t_dev; /* device name */ 41 | }; 42 | 43 | char partab[]; /* ASCII table: parity, character class */ 44 | 45 | #define TTIPRI 10 46 | #define TTOPRI 20 47 | 48 | #define CERASE '#' /* default special characters */ 49 | #define CEOT 004 50 | #define CKILL '@' 51 | #define CQUIT 034 /* FS, cntl shift L */ 52 | #define CINTR 0177 /* DEL */ 53 | 54 | /* limits */ 55 | #define TTHIWAT 50 56 | #define TTLOWAT 30 57 | #define TTYHOG 256 58 | 59 | /* modes */ 60 | #define HUPCL 01 61 | #define XTABS 02 62 | #define LCASE 04 63 | #define ECHO 010 64 | #define CRMOD 020 65 | #define RAW 040 66 | #define ODDP 0100 67 | #define EVENP 0200 68 | #define NLDELAY 001400 69 | #define TBDELAY 006000 70 | #define CRDELAY 030000 71 | #define VTDELAY 040000 72 | 73 | /* Hardware bits */ 74 | #define DONE 0200 75 | #define IENABLE 0100 76 | 77 | /* Internal state bits */ 78 | #define TIMEOUT 01 /* Delay timeout in progress */ 79 | #define WOPEN 02 /* Waiting for open to complete */ 80 | #define ISOPEN 04 /* Device is open */ 81 | #define SSTART 010 /* Has special start routine at addr */ 82 | #define CARR_ON 020 /* Software copy of carrier-present */ 83 | #define BUSY 040 /* Output in progress */ 84 | #define ASLEEP 0100 /* Wakeup when output done */ 85 | -------------------------------------------------------------------------------- /user.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The user structure. 3 | * One allocated per process. 4 | * Contains all per process data 5 | * that doesn't need to be referenced 6 | * while the process is swapped. 7 | * The user block is USIZE*64 bytes 8 | * long; resides at virtual kernel 9 | * loc 140000; contains the system 10 | * stack per user; is cross referenced 11 | * with the proc structure for the 12 | * same process. 13 | */ 14 | struct user 15 | { 16 | int u_rsav[2]; /* save r5,r6 when exchanging stacks */ 17 | int u_fsav[25]; /* save fp registers */ 18 | /* rsav and fsav must be first in structure */ 19 | char u_segflg; /* flag for IO; user or kernel space */ 20 | char u_error; /* return error code */ 21 | char u_uid; /* effective user id */ 22 | char u_gid; /* effective group id */ 23 | char u_ruid; /* real user id */ 24 | char u_rgid; /* real group id */ 25 | int u_procp; /* pointer to proc structure */ 26 | char *u_base; /* base address for IO */ 27 | char *u_count; /* bytes remaining for IO */ 28 | char *u_offset[2]; /* offset in file for IO */ 29 | int *u_cdir; /* pointer to inode of current directory */ 30 | char u_dbuf[DIRSIZ]; /* current pathname component */ 31 | char *u_dirp; /* current pointer to inode */ 32 | struct { /* current directory entry */ 33 | int u_ino; 34 | char u_name[DIRSIZ]; 35 | } u_dent; 36 | int *u_pdir; /* inode of parent directory of dirp */ 37 | int u_uisa[16]; /* prototype of segmentation addresses */ 38 | int u_uisd[16]; /* prototype of segmentation descriptors */ 39 | int u_ofile[NOFILE]; /* pointers to file structures of open files */ 40 | int u_arg[5]; /* arguments to current system call */ 41 | int u_tsize; /* text size (*64) */ 42 | int u_dsize; /* data size (*64) */ 43 | int u_ssize; /* stack size (*64) */ 44 | int u_sep; /* flag for I and D separation */ 45 | int u_qsav[2]; /* label variable for quits and interrupts */ 46 | int u_ssav[2]; /* label variable for swapping */ 47 | int u_signal[NSIG]; /* disposition of signals */ 48 | int u_utime; /* this process user time */ 49 | int u_stime; /* this process system time */ 50 | int u_cutime[2]; /* sum of childs' utimes */ 51 | int u_cstime[2]; /* sum of childs' stimes */ 52 | int *u_ar0; /* address of users saved R0 */ 53 | int u_prof[4]; /* profile arguments */ 54 | char u_intflg; /* catch intr from sys */ 55 | /* kernel stack per user 56 | * extends from u + USIZE*64 57 | * backward not to reach here 58 | */ 59 | } u; 60 | 61 | /* u_error codes */ 62 | #define EFAULT 106 63 | #define EPERM 1 64 | #define ENOENT 2 65 | #define ESRCH 3 66 | #define EINTR 4 67 | #define EIO 5 68 | #define ENXIO 6 69 | #define E2BIG 7 70 | #define ENOEXEC 8 71 | #define EBADF 9 72 | #define ECHILD 10 73 | #define EAGAIN 11 74 | #define ENOMEM 12 75 | #define EACCES 13 76 | #define ENOTBLK 15 77 | #define EBUSY 16 78 | #define EEXIST 17 79 | #define EXDEV 18 80 | #define ENODEV 19 81 | #define ENOTDIR 20 82 | #define EISDIR 21 83 | #define EINVAL 22 84 | #define ENFILE 23 85 | #define EMFILE 24 86 | #define ENOTTY 25 87 | #define ETXTBSY 26 88 | #define EFBIG 27 89 | #define ENOSPC 28 90 | #define ESPIPE 29 91 | #define EROFS 30 92 | #define EMLINK 31 93 | #define EPIPE 32 94 | --------------------------------------------------------------------------------