xref: /original-bsd/sys/tahoe/tahoe/autoconf.c (revision 74bf68f5)
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