1 /* autoconf.c 1.5 86/01/20 */ 2 3 /* 4 * Setup the system to run on the current machine. 5 * 6 * Configure() is called at boot time and initializes the vba 7 * device tables and the memory controller monitoring. Available 8 * devices are determined (from possibilities mentioned in ioconf.c), 9 * and the drivers are initialized. 10 */ 11 #include "../tahoe/pte.h" 12 #include "../tahoe/mem.h" 13 #include "../tahoe/mtpr.h" 14 #include "../tahoe/scb.h" 15 16 #include "vba.h" 17 18 #include "param.h" 19 #include "systm.h" 20 #include "map.h" 21 #include "buf.h" 22 #include "dk.h" 23 #include "vm.h" 24 #include "conf.h" 25 #include "dmap.h" 26 27 #include "../tahoevba/vbavar.h" 28 #include "../tahoevba/vbaparam.h" 29 30 /* 31 * The following several variables are related to 32 * the configuration process, and are used in initializing 33 * the machine. 34 */ 35 int dkn; /* number of iostat dk numbers assigned so far */ 36 int cold; /* cold start flag initialized in locore.s */ 37 38 /* 39 * This allocates the space for the per-vba information. 40 */ 41 struct vba_hd vba_hd[NVBA]; 42 43 /* 44 * Determine mass storage configuration for a machine. 45 */ 46 configure() 47 { 48 register int *ip; 49 extern caddr_t Sysbase; 50 51 printf("vba%d at %x\n", numvba, VBIOBASE); 52 vbafind(numvba, vmem, VMEMmap); 53 numvba++; 54 /* 55 * Write protect the scb. It is strange 56 * that this code is here, but this is as soon 57 * as we are done mucking with it, and the 58 * write-enable was done in assembly language 59 * to which we will never return. 60 */ 61 ip = (int *)&Sysmap[2]; *ip &= ~PG_PROT; *ip |= PG_KR; 62 mtpr(TBIS, Sysbase+2*NBPG); 63 #if GENERIC 64 setconf(); 65 #endif 66 swapconf(); 67 cold = 0; 68 } 69 70 /* 71 * Make the controllers accessible at physical address phys 72 * by mapping kernel ptes starting at pte. 73 */ 74 vbaccess(pte, iobase, n) 75 register struct pte *pte; 76 caddr_t iobase; 77 register int n; 78 { 79 register unsigned v = btop(iobase); 80 81 do 82 *(int *)pte++ = PG_V|PG_KW|v++; 83 while (--n > 0); 84 mtpr(TBIA, 0); 85 } 86 87 /* 88 * Fixctlrmask fixes the masks of the driver ctlr routines 89 * which otherwise save r11 and r12 where the interrupt and br 90 * level are passed through. 91 */ 92 fixctlrmask() 93 { 94 register struct vba_ctlr *vm; 95 register struct vba_device *vi; 96 register struct vba_driver *vd; 97 #define phys(a,b) ((b)(((int)(a))&~0xc0000000)) 98 99 vm = phys(vbminit, struct vba_ctlr *); 100 for (; vd = phys(vm->um_driver, struct vba_driver *); vm++) 101 *phys(vd->ud_probe, short *) &= ~0x1800; 102 vi = phys(vbdinit, struct vba_device *); 103 for (; vd = phys(vi->ui_driver, struct vba_driver *); vi++) 104 *phys(vd->ud_probe, short *) &= ~0x1800; 105 } 106 107 /* 108 * Find devices on the VERSAbus. 109 * Uses per-driver routine to see who is on the bus 110 * and then fills in the tables, with help from a per-driver 111 * slave initialization routine. 112 */ 113 vbafind(vban, vumem, memmap) 114 int vban; 115 caddr_t vumem; 116 struct pte memmap[]; 117 { 118 register int br, cvec; /* must be r12, r11 */ 119 register struct vba_device *ui; 120 register struct vba_ctlr *um; 121 u_short *reg; 122 long addr, *ap; 123 struct vba_hd *vhp; 124 struct vba_driver *udp; 125 int i, (**ivec)(); 126 extern long cold, catcher[SCB_LASTIV*2]; 127 128 #ifdef lint 129 br = 0; cvec = 0; 130 #endif 131 vhp = &vba_hd[vban]; 132 /* 133 * Make the controllers accessible at physical address phys 134 * by mapping kernel ptes starting at pte. 135 */ 136 vbaccess(memmap, VBIOBASE, VBIOSIZE); 137 /* 138 * Setup scb device entries to point into catcher array. 139 */ 140 for (i = 0; i < SCB_LASTIV; i++) 141 scb.scb_devint[i] = (int (*)())&catcher[i*2]; 142 /* 143 * Set last free interrupt vector for devices with 144 * programmable interrupt vectors. Use is to decrement 145 * this number and use result as interrupt vector. 146 */ 147 vhp->vh_lastiv = SCB_LASTIV; 148 149 /* 150 * Check each VERSAbus mass storage controller. 151 * For each one which is potentially on this vba, 152 * see if it is really there, and if it is record it and 153 * then go looking for slaves. 154 */ 155 #define vbaddr(off) (u_short *)((int)vumem + ((off) & 0x0fffff)) 156 for (um = vbminit; udp = um->um_driver; um++) { 157 if (um->um_vbanum != vban && um->um_vbanum != '?') 158 continue; 159 /* 160 * Use the particular address specified first, 161 * or if it is given as "0", if there is no device 162 * at that address, try all the standard addresses 163 * in the driver until we find it. 164 */ 165 addr = (long)um->um_addr; 166 for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { 167 #ifdef notdef 168 if (vballoc[vbaoff(addr)]) 169 continue; 170 #endif 171 reg = vbaddr(addr); 172 um->um_hd = vhp; 173 cvec = SCB_LASTIV, cold &= ~0x2; 174 i = (*udp->ud_probe)(reg, um); 175 cold |= 0x2; 176 if (i == 0) 177 continue; 178 printf("%s%d at vba%d csr %x ", 179 udp->ud_mname, um->um_ctlr, vban, addr); 180 if (cvec < 0 && vhp->vh_lastiv == cvec) { 181 printf("no space for vector(s)\n"); 182 continue; 183 } 184 if (cvec == SCB_LASTIV) { 185 printf("didn't interrupt\n"); 186 continue; 187 } 188 printf("vec %x, ipl %x\n", cvec, br); 189 um->um_alive = 1; 190 um->um_vbanum = vban; 191 um->um_addr = (caddr_t)reg; 192 udp->ud_minfo[um->um_ctlr] = um; 193 for (ivec = um->um_intr; *ivec; ivec++) 194 ((long *)&scb)[cvec++] = (long)*ivec; 195 for (ui = vbdinit; ui->ui_driver; ui++) { 196 if (ui->ui_driver != udp || ui->ui_alive || 197 ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?' || 198 ui->ui_vbanum != vban && ui->ui_vbanum != '?') 199 continue; 200 if ((*udp->ud_slave)(ui, reg)) { 201 ui->ui_alive = 1; 202 ui->ui_ctlr = um->um_ctlr; 203 ui->ui_vbanum = vban; 204 ui->ui_addr = (caddr_t)reg; 205 ui->ui_physaddr = 206 (caddr_t)VBIOBASE + (addr&0x0fffff); 207 if (ui->ui_dk && dkn < DK_NDRIVE) 208 ui->ui_dk = dkn++; 209 else 210 ui->ui_dk = -1; 211 ui->ui_mi = um; 212 ui->ui_hd = vhp; 213 /* ui_type comes from driver */ 214 udp->ud_dinfo[ui->ui_unit] = ui; 215 printf("%s%d at %s%d slave %d\n", 216 udp->ud_dname, ui->ui_unit, 217 udp->ud_mname, um->um_ctlr, 218 ui->ui_slave); 219 (*udp->ud_attach)(ui); 220 } 221 } 222 break; 223 } 224 } 225 /* 226 * Now look for non-mass storage peripherals. 227 */ 228 for (ui = vbdinit; udp = ui->ui_driver; ui++) { 229 if (ui->ui_vbanum != vban && ui->ui_vbanum != '?' || 230 ui->ui_alive || ui->ui_slave != -1) 231 continue; 232 addr = (long)ui->ui_addr; 233 for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) { 234 reg = vbaddr(addr); 235 ui->ui_hd = vhp; 236 cvec = SCB_LASTIV, cold &= ~0x2; 237 i = (*udp->ud_probe)(reg, ui); 238 cold |= 0x2; 239 if (i == 0) 240 continue; 241 printf("%s%d at vba%d csr %x ", 242 ui->ui_driver->ud_dname, ui->ui_unit, vban, addr); 243 if (cvec < 0 && vhp->vh_lastiv == cvec) { 244 printf("no space for vector(s)\n"); 245 continue; 246 } 247 if (cvec == SCB_LASTIV) { 248 printf("didn't interrupt\n"); 249 continue; 250 } 251 printf("vec %x, ipl %x\n", cvec, br); 252 #ifdef notdef 253 while (--i >= 0) 254 vballoc[vbaoff(addr+i)] = 1; 255 #endif 256 for (ivec = ui->ui_intr; *ivec; ivec++) 257 ((long *)&scb)[cvec++] = (long)*ivec; 258 ui->ui_alive = 1; 259 ui->ui_vbanum = vban; 260 ui->ui_addr = (caddr_t)reg; 261 ui->ui_physaddr = (caddr_t)VBIOBASE + (addr&0x0fffff); 262 ui->ui_dk = -1; 263 /* ui_type comes from driver */ 264 udp->ud_dinfo[ui->ui_unit] = ui; 265 (*udp->ud_attach)(ui); 266 break; 267 } 268 } 269 } 270 271 /* 272 * Tahoe VERSAbus adapator support routines. 273 */ 274 275 caddr_t vbcur = (caddr_t)&vbbase; 276 int vbx = 0; 277 /* 278 * Allocate page tables for mapping intermediate i/o buffers. 279 * Called by device drivers during autoconfigure. 280 */ 281 vbmapalloc(npf, ppte, putl) 282 int npf; 283 struct pte **ppte; 284 caddr_t *putl; 285 { 286 287 if (vbcur + npf*NBPG >= (caddr_t)&vbend) 288 panic("vbmapalloc"); 289 *ppte = &VBmap[vbx]; 290 *putl = vbcur; 291 vbx += npf; 292 vbcur += npf*NBPG; 293 } 294 295 caddr_t vbmcur = (caddr_t)&vmem1; 296 int vbmx = 0; 297 /* 298 * Allocate page tables and map VERSAbus i/o space. 299 * Called by device drivers during autoconfigure. 300 */ 301 vbmemalloc(npf, addr, ppte, putl) 302 int npf; 303 caddr_t addr; 304 struct pte **ppte; 305 caddr_t *putl; 306 { 307 308 if (vbmcur + npf*NBPG >= (caddr_t)&vmemend) 309 panic("vbmemalloc"); 310 *ppte = &VMEMmap1[vbmx]; 311 *putl = vbmcur; 312 vbmx += npf; 313 vbmcur += npf*NBPG; 314 vbaccess(*ppte, addr, npf); /* map i/o space */ 315 } 316 317 /* 318 * Configure swap space and related parameters. 319 */ 320 swapconf() 321 { 322 register struct swdevt *swp; 323 register int nblks; 324 325 for (swp = swdevt; swp->sw_dev; swp++) 326 if (bdevsw[major(swp->sw_dev)].d_psize) { 327 nblks = 328 (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev); 329 if (swp->sw_nblks == 0 || swp->sw_nblks > nblks) 330 swp->sw_nblks = nblks; 331 } 332 if (dumplo == 0 && bdevsw[major(dumpdev)].d_psize) 333 dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) - physmem; 334 if (dumplo < 0) 335 dumplo = 0; 336 } 337