1: /* 2: * Copyright (c) 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)machdep2.c 2.9 (2.11BSD) 1999/2/19 7: */ 8: 9: #include "param.h" 10: #include "../machine/seg.h" 11: #include "../machine/iopage.h" 12: 13: #include "dir.h" 14: #include "inode.h" 15: #include "user.h" 16: #include "proc.h" 17: #include "fs.h" 18: #include "map.h" 19: #include "buf.h" 20: #include "text.h" 21: #include "file.h" 22: #include "clist.h" 23: #include "uba.h" 24: #include "callout.h" 25: #include "reboot.h" 26: #include "systm.h" 27: #include "ram.h" 28: #include "msgbuf.h" 29: #include "namei.h" 30: #include "ra.h" 31: #include "tms.h" 32: #include "ingres.h" 33: #include "disklabel.h" 34: #include "mount.h" 35: 36: #if NINGRES > 0 37: #include <sys/ingreslock.h> 38: #endif 39: 40: #ifdef QUOTA 41: #include "quota.h" 42: #endif 43: 44: size_t physmem; /* total amount of physical memory (for savecore) */ 45: #if NRAC > 0 || NTMSCP > 0 46: memaddr _iostart, _iobase; 47: ubadr_t _ioumr; 48: u_short _iosize = ((NTMSCP * (ctob(btoc(1864)))) + (NRAC * (ctob(btoc(1096))))); 49: #endif 50: 51: #ifdef SOFUB_MAP 52: extern size_t sofub_addr, sofub_off; 53: extern memaddr sofub_base; 54: extern u_int sofub_size; 55: #endif 56: 57: segm seg5; /* filled in by initialization */ 58: 59: /* 60: * Machine dependent startup code 61: */ 62: startup() 63: { 64: #ifdef UCB_CLIST 65: extern memaddr clststrt; 66: #endif 67: extern ubadr_t clstaddr; 68: extern int end; 69: register memaddr i, freebase, maxclick; 70: #if NRAM > 0 71: size_t ramsize; 72: #endif 73: 74: printf("\n%s\n", version); 75: 76: saveseg5(seg5); /* must be done before clear() is called */ 77: /* 78: * REMAP_AREA is the start of possibly-mapped area, for consistency 79: * check. Only proc, text and file tables are after it, and it must 80: * lie at <= 0120000, or other kernel data will be mapped out. 81: */ 82: if (REMAP_AREA > SEG5) 83: panic("remap > SEG5"); 84: 85: /* 86: * Zero and free all of core: 87: * 88: * MAXCLICK is the maximum accessible physical memory, assuming an 8K 89: * I/O page. On systems without a Unibus map the end of memory is 90: * heralded by the beginning of the I/O page (some people have dz's 91: * at 0160000). On systems with a Unibus map, the last 256K of the 92: * 4M address space is off limits since 017000000 to 017777777 is the 93: * actual 18 bit Unibus address space. 61440 is btoc(4M - 256K), 94: * and 65408 is btoc(4M - 8K). 95: * 96: * Previous cautions about 18bit devices on a 22bit Qbus were misguided. 97: * Since the GENERIC kernel was built with Q22 defined the limiting 98: * effect on memory size was not achieved, thus an 18bit controller 99: * could not be used to load the distribution. ALSO, the kernel 100: * plus associated data structures do not leave enough room in 248kb 101: * to run the programs necessary to do _anything_. 102: */ 103: #define MAXCLICK_22U 61440 /* 22 bit UNIBUS (UNIBUS mapping) */ 104: #define MAXCLICK_22 65408 /* 22 bit QBUS */ 105: 106: maxclick = ubmap ? MAXCLICK_22U : MAXCLICK_22; 107: 108: i = freebase = *ka6 + USIZE; 109: UISD[0] = ((stoc(1) - 1) << 8) | RW; 110: for (;;) { 111: UISA[0] = i; 112: if (fuibyte((caddr_t)0) < 0) 113: break; 114: ++maxmem; 115: /* avoid testing locations past "real" memory. */ 116: if (++i >= maxclick) 117: break; 118: } 119: clear(freebase,i - freebase); 120: mem_parity(); /* enable parity checking */ 121: clear(freebase,i - freebase); /* quick check for parities */ 122: mfree(coremap,i - freebase,freebase); 123: physmem = i; 124: 125: procNPROC = proc + nproc; 126: textNTEXT = text + ntext; 127: inodeNINODE = inode + ninode; 128: fileNFILE = file + nfile; 129: 130: /* 131: * IMPORTANT! Mapped out clists should always be allocated first! 132: * This prevents needlessly having to restrict all memory use 133: * (maxclick) to 248K just because an 18-bit DH is present on a 134: * 22-bit Q-BUS machine. The maximum possible location for mapped 135: * out clists this way is 232K (56K base + 15 * 8K overlays + 48K 136: * data space + 8K (maximum) user structure, which puts the maximum 137: * top of mapped out clists at 240K ... 138: */ 139: #ifdef UCB_CLIST 140: #define C (nclist * sizeof(struct cblock)) 141: if ((clststrt = malloc(coremap, btoc(C))) == 0) 142: panic("clists"); 143: clstaddr = ((ubadr_t)clststrt) << 6; 144: #undef C 145: #else 146: clstaddr = (ubadr_t)cfree; 147: #endif 148: 149: /* 150: * IMPORTANT. The software Unibus/Qbus map is allocated now if support for 151: * 18 bit controllers in a 22 bit system has been selected. This buffer must 152: * reside _entirely_ within the low 256kb of memory. A 10kb buffer is 153: * allocated, this is sufficient to handle 'dump', 'restor' and the default 154: * blocking factor of 'tar' (20 sectors). 155: * 156: * NOTE: There is only 1 software map. Multiple 18 bit controllers will 157: * have their access to the 'bounce buffer' single threaded by the soft 158: * map allocation routine sofub_alloc() in machdep.c. 159: * 160: * For more details see machdep.c. 161: */ 162: 163: #ifdef SOFUB_MAP 164: #define B (10240+64) 165: 166: sofub_size = (unsigned) B; 167: 168: if ((sofub_base = malloc(coremap, btoc(B))) == 0) 169: panic("sofmap"); /* Paranoia */ 170: else if (((sofub_base + btoc(B)) >> 10) > 3) /* > 256kb! */ 171: { 172: printf("sofmap > 256kb\n"); 173: mfree(coremap, btoc(B), sofub_base); /* give it back */ 174: sofub_base = 0; 175: } 176: else 177: { 178: sofub_addr = sofub_base; 179: sofub_off = (sofub_base>>10)&3; 180: } 181: #undef B 182: #endif /* SOFUB_MAP */ 183: 184: #ifdef EXTERNALITIMES 185: #define C (btoc(ninode * sizeof (struct icommon2))) 186: if ((xitimes = malloc(coremap, C)) == 0) 187: panic("xitimes"); 188: xitdesc = ((C - 1) << 8) | RW; 189: #undef C 190: #endif 191: 192: #ifdef QUOTA 193: #define C (btoc(8192)) 194: if ((quotreg = malloc(coremap, C)) == 0) 195: panic("quotamem"); 196: quotdesc = ((C - 1) << 8) | RW; 197: QUOini(); 198: #undef C 199: #endif 200: 201: { 202: register int B; 203: 204: nchsize = 8192 / sizeof(struct namecache); 205: if (nchsize > (ninode * 11 / 10)) 206: nchsize = ninode * 11 / 10; 207: B = (btoc(nchsize * sizeof(struct namecache))); 208: if ((nmidesc.se_addr = malloc(coremap, B)) == 0) 209: panic("nmidesc"); 210: nmidesc.se_desc = ((B - 1) << 8) | RW; 211: namecache = (struct namecache *)SEG5; 212: } 213: 214: #if NRAC > 0 || NTMSCP > 0 215: if ((_iobase = malloc(coremap, btoc(_iosize))) == 0) 216: panic("_iobase"); 217: #endif 218: 219: #define B (size_t)(((long)nbuf * (MAXBSIZE)) / ctob(1)) 220: if ((bpaddr = malloc(coremap, B)) == 0) 221: panic("buffers"); 222: #undef B 223: 224: /* 225: * Now initialize the log driver (kernel logger, error logger and accounting) 226: */ 227: loginit(); 228: 229: #define C (btoc(sizeof (struct xmount))) 230: for (i = 0; i < NMOUNT; i++) 231: mount[i].m_extern = (memaddr)malloc(coremap, C); 232: #undef C 233: 234: #if NINGRES > 0 235: #define C (btoc(LOCKTABSIZE)) 236: 237: if (Locktabseg.se_addr = malloc(coremap, C)) 238: Locktabseg.se_desc = ((C - 1) << 8) | RW; 239: #undef C 240: #endif 241: 242: /* 243: * Allocate the initial disklabels. 244: */ 245: (void) initdisklabels(); 246: 247: #if NRAM > 0 248: ramsize = raminit(); 249: #endif 250: 251: /* 252: * Initialize callouts 253: */ 254: callfree = callout; 255: for (i = 1; i < ncallout; i++) 256: callout[i-1].c_next = &callout[i]; 257: 258: UISA[7] = ka6[1]; /* io segment */ 259: UISD[7] = ((stoc(1) - 1) << 8) | RW; 260: } 261: 262: mem_parity() 263: { 264: register int cnt; 265: 266: for (cnt = 0;cnt < 16;++cnt) { 267: if (fioword((caddr_t)(MEMSYSMCR+cnt)) == -1) 268: return; 269: *(MEMSYSMCR+cnt) = MEMMCR_EIE; /* enable parity interrupts */ 270: } 271: } 272: 273: #if defined(PROFILE) && !defined(ENABLE34) 274: /* 275: * Allocate memory for system profiling. Called once at boot time. 276: * Returns number of clicks used by profiling. 277: * 278: * The system profiler uses supervisor I space registers 2 and 3 279: * (virtual addresses 040000 through 0100000) to hold the profile. 280: */ 281: msprof() 282: { 283: memaddr proloc; 284: int nproclicks; 285: 286: nproclicks = btoc(8192*2); 287: proloc = malloc(coremap, nproclicks); 288: if (proloc == 0) 289: panic("msprof"); 290: 291: *SISA2 = proloc; 292: *SISA3 = proloc + btoc(8192); 293: *SISD2 = 077400|RW; 294: *SISD3 = 077400|RW; 295: *SISD0 = RW; 296: *SISD1 = RW; 297: 298: /* 299: * Enable system profiling. Zero out the profile buffer 300: * and then turn the clock (KW11-P) on. 301: */ 302: clear(proloc, nproclicks); 303: isprof(); 304: printf("profiling on\n"); 305: 306: return (nproclicks); 307: } 308: #endif 309: 310: /* 311: * Re-initialize the Unibus map registers to statically map 312: * the clists and buffers. Free the remaining registers for 313: * physical I/O. At this time the [T]MSCP arena is also mapped. 314: */ 315: ubinit() 316: { 317: register int i, ub_nreg; 318: long paddr; 319: register struct ubmap *ubp; 320: 321: if (!ubmap) 322: return; 323: /* 324: * Clists start at UNIBUS virtual address 0. The size of 325: * the clist segment can be no larger than UBPAGE bytes. 326: * Clstaddt was the physical address of clists. 327: */ 328: if (nclist * sizeof(struct cblock) > ctob(stoc(1))) 329: panic("clist > 8k"); 330: setubregno(0, clstaddr); 331: clstaddr = (ubadr_t)0; 332: 333: /* 334: * Buffers start at UNIBUS virtual address BUF_UBADDR. 335: */ 336: paddr = ((long)bpaddr) << 6; 337: ub_nreg = nubreg(nbuf, MAXBSIZE); 338: for (i = BUF_UBADDR/UBPAGE; i < ub_nreg + (BUF_UBADDR/UBPAGE); i++) { 339: setubregno(i, paddr); 340: paddr += (long)UBPAGE; 341: } 342: /* 343: * The 3Com ethernet board is hardwired to use UNIBUS registers 28, 29 344: * and 30 (counting from 0) and UNIBUS register 31 isn't usable. 345: */ 346: #include "ec.h" 347: #if NEC > 0 348: mfree(ub_map, 28 - ub_nreg - 1, 1 + ub_nreg); /* 3Com board */ 349: #else 350: mfree(ub_map, 31 - ub_nreg - 1, 1 + ub_nreg); 351: #endif 352: 353: /* 354: * this early in the system's life there had better be a UMR or two 355: * available!! N.B. This was moved from where the [T]MSCP memory was 356: * allocated because at that point the UMR map was not initialized. 357: */ 358: 359: #if NRAC > 0 || NTMSCP > 0 360: _iostart = _iobase; 361: i = (int)btoub(_iosize); 362: ub_nreg = malloc(ub_map, i); 363: _ioumr = (ubadr_t)ub_nreg << 13; 364: ubp = &UBMAP[ub_nreg]; 365: paddr = ctob((ubadr_t)_iostart); 366: while (i--) { 367: ubp->ub_lo = loint(paddr); 368: ubp->ub_hi = hiint(paddr); 369: ubp++; 370: paddr += (ubadr_t)UBPAGE; 371: } 372: #endif 373: } 374: 375: int waittime = -1; 376: 377: boot(dev, howto) 378: register dev_t dev; 379: register int howto; 380: { 381: register struct fs *fp; 382: 383: /* 384: * Force the root filesystem's superblock to be updated, 385: * so the date will be as current as possible after 386: * rebooting. 387: */ 388: if (fp = getfs(rootdev)) 389: fp->fs_fmod = 1; 390: if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) { 391: waittime = 0; 392: printf("syncing disks... "); 393: (void) _splnet(); 394: /* 395: * Release inodes held by texts before update. 396: */ 397: xumount(NODEV); 398: sync(); 399: { register struct buf *bp; 400: int iter, nbusy; 401: 402: for (iter = 0; iter < 20; iter++) { 403: nbusy = 0; 404: for (bp = &buf[nbuf]; --bp >= buf; ) 405: if (bp->b_flags & B_BUSY) 406: nbusy++; 407: if (nbusy == 0) 408: break; 409: printf("%d ", nbusy); 410: delay(40000L * iter); 411: } 412: } 413: printf("done\n"); 414: } 415: (void) _splhigh(); 416: if (howto & RB_HALT) { 417: printf("halting\n"); 418: halt(); 419: /*NOTREACHED*/ 420: } 421: else { 422: if (howto & RB_DUMP) { 423: /* 424: * save the registers in low core. 425: */ 426: saveregs(); 427: dumpsys(); 428: } 429: doboot(dev, howto); 430: /*NOTREACHED*/ 431: } 432: } 433: 434: /* 435: * Dumpsys takes a dump of memory by calling (*dump)(), which must 436: * correspond to dumpdev. *(dump)() should dump from dumplo blocks 437: * to the end of memory or to the end of the logical device. 438: */ 439: dumpsys() 440: { 441: extern int (*dump)(); 442: register int error; 443: 444: if (dumpdev != NODEV) { 445: printf("\ndumping to dev %o off %D\ndump ",dumpdev,dumplo); 446: error = (*dump)(dumpdev); 447: switch(error) { 448: 449: case EFAULT: 450: printf("dev !ready:EFAULT\n"); 451: break; 452: case EINVAL: 453: printf("args:EINVAL\n"); 454: break; 455: case EIO: 456: printf("err:EIO\n"); 457: break; 458: default: 459: printf("unknown err:%d\n",error); 460: break; 461: case 0: 462: printf("succeeded\n"); 463: break; 464: } 465: } 466: } 467: 468: #if NRAC > 0 || NTMSCP > 0 469: memaddr 470: _ioget(size) 471: u_int size; 472: { 473: register memaddr base; 474: register u_int csize; 475: 476: csize = btoc(size); 477: size = ctob(csize); 478: if (size > _iosize) 479: return(0); 480: _iosize -= size; 481: base = _iobase; 482: _iobase += csize; 483: return(base); 484: } 485: 486: ubadr_t 487: _iomap(addr) 488: register memaddr addr; 489: { 490: return(((ubadr_t)(addr - _iostart) << 6) + _ioumr); 491: } 492: #endif 493: 494: #define NLABELS 6 495: 496: memaddr _dlabelbase; 497: int _dlabelnum = NLABELS; 498: 499: void 500: initdisklabels() 501: { 502: #define C (NLABELS * (btoc(sizeof (struct disklabel)))) 503: 504: _dlabelbase = malloc(coremap, C); 505: } 506: 507: memaddr 508: disklabelalloc() 509: { 510: register memaddr base; 511: 512: if (--_dlabelnum) 513: { 514: base = _dlabelbase; 515: _dlabelbase += btoc(sizeof (struct disklabel)); 516: return(base); 517: } 518: base = malloc(coremap, btoc (sizeof (struct disklabel))); 519: return(base); 520: }