Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
da7c5cc6 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
0880b18e | 6 | * @(#)uba.c 7.1 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
961945a8 SL |
8 | |
9 | #include "../machine/pte.h" | |
c14fd247 | 10 | |
ff360633 JB |
11 | #include "param.h" |
12 | #include "systm.h" | |
13 | #include "map.h" | |
14 | #include "buf.h" | |
15 | #include "vm.h" | |
16 | #include "dir.h" | |
17 | #include "user.h" | |
18 | #include "proc.h" | |
19 | #include "conf.h" | |
20 | #include "dk.h" | |
21 | #include "kernel.h" | |
b7333467 | 22 | |
896962b1 BJ |
23 | #include "../vax/cpu.h" |
24 | #include "../vax/mtpr.h" | |
25 | #include "../vax/nexus.h" | |
ff360633 JB |
26 | #include "ubareg.h" |
27 | #include "ubavar.h" | |
896962b1 | 28 | |
bce08673 | 29 | #if defined(VAX780) || defined(VAX8600) |
5af3f3f7 BJ |
30 | char ubasr_bits[] = UBASR_BITS; |
31 | #endif | |
32 | ||
8011f5df MK |
33 | #define spluba spl7 /* IPL 17 */ |
34 | ||
b7333467 BJ |
35 | /* |
36 | * Do transfer on device argument. The controller | |
37 | * and uba involved are implied by the device. | |
38 | * We queue for resource wait in the uba code if necessary. | |
39 | * We return 1 if the transfer was started, 0 if it was not. | |
40 | * If you call this routine with the head of the queue for a | |
41 | * UBA, it will automatically remove the device from the UBA | |
42 | * queue before it returns. If some other device is given | |
43 | * as argument, it will be added to the request queue if the | |
44 | * request cannot be started immediately. This means that | |
45 | * passing a device which is on the queue but not at the head | |
46 | * of the request queue is likely to be a disaster. | |
47 | */ | |
48 | ubago(ui) | |
5ab42896 | 49 | register struct uba_device *ui; |
b7333467 | 50 | { |
5ab42896 | 51 | register struct uba_ctlr *um = ui->ui_mi; |
b7333467 BJ |
52 | register struct uba_hd *uh; |
53 | register int s, unit; | |
54 | ||
55 | uh = &uba_hd[um->um_ubanum]; | |
8011f5df | 56 | s = spluba(); |
28ca05a9 | 57 | if (um->um_driver->ud_xclu && uh->uh_users > 0 || uh->uh_xclu) |
0801d37f | 58 | goto rwait; |
b7333467 BJ |
59 | um->um_ubinfo = ubasetup(um->um_ubanum, um->um_tab.b_actf->b_actf, |
60 | UBA_NEEDBDP|UBA_CANTWAIT); | |
0801d37f BJ |
61 | if (um->um_ubinfo == 0) |
62 | goto rwait; | |
0801d37f | 63 | uh->uh_users++; |
28ca05a9 | 64 | if (um->um_driver->ud_xclu) |
0801d37f | 65 | uh->uh_xclu = 1; |
b7333467 BJ |
66 | splx(s); |
67 | if (ui->ui_dk >= 0) { | |
68 | unit = ui->ui_dk; | |
69 | dk_busy |= 1<<unit; | |
cc7ff771 BJ |
70 | dk_xfer[unit]++; |
71 | dk_wds[unit] += um->um_tab.b_actf->b_actf->b_bcount>>6; | |
b7333467 BJ |
72 | } |
73 | if (uh->uh_actf == ui) | |
74 | uh->uh_actf = ui->ui_forw; | |
75 | (*um->um_driver->ud_dgo)(um); | |
b7333467 | 76 | return (1); |
0801d37f BJ |
77 | rwait: |
78 | if (uh->uh_actf != ui) { | |
79 | ui->ui_forw = NULL; | |
80 | if (uh->uh_actf == NULL) | |
81 | uh->uh_actf = ui; | |
82 | else | |
83 | uh->uh_actl->ui_forw = ui; | |
84 | uh->uh_actl = ui; | |
85 | } | |
86 | splx(s); | |
87 | return (0); | |
88 | } | |
89 | ||
90 | ubadone(um) | |
5ab42896 | 91 | register struct uba_ctlr *um; |
0801d37f BJ |
92 | { |
93 | register struct uba_hd *uh = &uba_hd[um->um_ubanum]; | |
94 | ||
28ca05a9 | 95 | if (um->um_driver->ud_xclu) |
0801d37f BJ |
96 | uh->uh_xclu = 0; |
97 | uh->uh_users--; | |
0801d37f | 98 | ubarelse(um->um_ubanum, &um->um_ubinfo); |
b7333467 | 99 | } |
c14fd247 BJ |
100 | |
101 | /* | |
3f3a34c3 BJ |
102 | * Allocate and setup UBA map registers, and bdp's |
103 | * Flags says whether bdp is needed, whether the caller can't | |
104 | * wait (e.g. if the caller is at interrupt level). | |
c14fd247 | 105 | * |
b7333467 | 106 | * Return value: |
c14fd247 BJ |
107 | * Bits 0-8 Byte offset |
108 | * Bits 9-17 Start map reg. no. | |
109 | * Bits 18-27 No. mapping reg's | |
110 | * Bits 28-31 BDP no. | |
111 | */ | |
3f3a34c3 BJ |
112 | ubasetup(uban, bp, flags) |
113 | struct buf *bp; | |
c14fd247 | 114 | { |
3f3a34c3 | 115 | register struct uba_hd *uh = &uba_hd[uban]; |
553d288e | 116 | int pfnum, temp; |
c14fd247 BJ |
117 | int npf, reg, bdp; |
118 | unsigned v; | |
119 | register struct pte *pte, *io; | |
120 | struct proc *rp; | |
121 | int a, o, ubinfo; | |
122 | ||
9d2503c6 BK |
123 | #if defined(VAX730) || defined(VAX630) |
124 | if (cpu == VAX_730 || cpu == VAX_630) | |
a3812a04 BJ |
125 | flags &= ~UBA_NEEDBDP; |
126 | #endif | |
c14fd247 BJ |
127 | v = btop(bp->b_un.b_addr); |
128 | o = (int)bp->b_un.b_addr & PGOFSET; | |
129 | npf = btoc(bp->b_bcount + o) + 1; | |
8011f5df | 130 | a = spluba(); |
5d30e870 | 131 | while ((reg = rmalloc(uh->uh_map, (long)npf)) == 0) { |
dd56673b BJ |
132 | if (flags & UBA_CANTWAIT) { |
133 | splx(a); | |
3f3a34c3 | 134 | return (0); |
dd56673b | 135 | } |
3f3a34c3 | 136 | uh->uh_mrwant++; |
174d2438 | 137 | sleep((caddr_t)&uh->uh_mrwant, PSWP); |
c14fd247 | 138 | } |
ee0fdd94 MK |
139 | if ((flags & UBA_NEED16) && reg + npf > 128) { |
140 | /* | |
141 | * Could hang around and try again (if we can ever succeed). | |
142 | * Won't help any current device... | |
143 | */ | |
144 | rmfree(uh->uh_map, (long)npf, (long)reg); | |
145 | splx(a); | |
146 | return (0); | |
147 | } | |
c14fd247 | 148 | bdp = 0; |
3f3a34c3 | 149 | if (flags & UBA_NEEDBDP) { |
8011f5df | 150 | while ((bdp = ffs((long)uh->uh_bdpfree)) == 0) { |
3f3a34c3 | 151 | if (flags & UBA_CANTWAIT) { |
5d30e870 | 152 | rmfree(uh->uh_map, (long)npf, (long)reg); |
dd56673b | 153 | splx(a); |
3f3a34c3 BJ |
154 | return (0); |
155 | } | |
156 | uh->uh_bdpwant++; | |
174d2438 | 157 | sleep((caddr_t)&uh->uh_bdpwant, PSWP); |
c14fd247 | 158 | } |
658110d5 | 159 | uh->uh_bdpfree &= ~(1 << (bdp-1)); |
64614526 BJ |
160 | } else if (flags & UBA_HAVEBDP) |
161 | bdp = (flags >> 28) & 0xf; | |
c14fd247 | 162 | splx(a); |
658110d5 | 163 | reg--; |
c14fd247 | 164 | ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o; |
5ab42896 | 165 | temp = (bdp << 21) | UBAMR_MRV; |
c14fd247 | 166 | if (bdp && (o & 01)) |
5ab42896 | 167 | temp |= UBAMR_BO; |
309cfbf4 BJ |
168 | rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; |
169 | if ((bp->b_flags & B_PHYS) == 0) | |
da1392b6 | 170 | pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)]; |
309cfbf4 BJ |
171 | else if (bp->b_flags & B_UAREA) |
172 | pte = &rp->p_addr[v]; | |
173 | else if (bp->b_flags & B_PAGET) | |
174 | pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; | |
175 | else | |
176 | pte = vtopte(rp, v); | |
177 | io = &uh->uh_uba->uba_map[reg]; | |
178 | while (--npf != 0) { | |
553d288e KM |
179 | pfnum = pte->pg_pfnum; |
180 | if (pfnum == 0) | |
309cfbf4 | 181 | panic("uba zero uentry"); |
553d288e KM |
182 | pte++; |
183 | *(int *)io++ = pfnum | temp; | |
c14fd247 BJ |
184 | } |
185 | *(int *)io++ = 0; | |
186 | return (ubinfo); | |
187 | } | |
188 | ||
c14fd247 | 189 | /* |
b7333467 | 190 | * Non buffer setup interface... set up a buffer and call ubasetup. |
c14fd247 | 191 | */ |
3f3a34c3 | 192 | uballoc(uban, addr, bcnt, flags) |
a0eab615 | 193 | int uban; |
c14fd247 | 194 | caddr_t addr; |
a0eab615 | 195 | int bcnt, flags; |
c14fd247 | 196 | { |
89e0f717 | 197 | struct buf ubabuf; |
c14fd247 | 198 | |
c14fd247 BJ |
199 | ubabuf.b_un.b_addr = addr; |
200 | ubabuf.b_flags = B_BUSY; | |
201 | ubabuf.b_bcount = bcnt; | |
89e0f717 | 202 | /* that's all the fields ubasetup() needs */ |
3f3a34c3 | 203 | return (ubasetup(uban, &ubabuf, flags)); |
c14fd247 BJ |
204 | } |
205 | ||
b28deaf8 | 206 | /* |
b7333467 BJ |
207 | * Release resources on uba uban, and then unblock resource waiters. |
208 | * The map register parameter is by value since we need to block | |
209 | * against uba resets on 11/780's. | |
b28deaf8 | 210 | */ |
3f3a34c3 | 211 | ubarelse(uban, amr) |
b28deaf8 | 212 | int *amr; |
c14fd247 | 213 | { |
3f3a34c3 | 214 | register struct uba_hd *uh = &uba_hd[uban]; |
b7333467 | 215 | register int bdp, reg, npf, s; |
b28deaf8 | 216 | int mr; |
c14fd247 | 217 | |
b7333467 BJ |
218 | /* |
219 | * Carefully see if we should release the space, since | |
220 | * it may be released asynchronously at uba reset time. | |
221 | */ | |
8011f5df | 222 | s = spluba(); |
b28deaf8 BJ |
223 | mr = *amr; |
224 | if (mr == 0) { | |
b7333467 BJ |
225 | /* |
226 | * A ubareset() occurred before we got around | |
227 | * to releasing the space... no need to bother. | |
228 | */ | |
229 | splx(s); | |
b28deaf8 BJ |
230 | return; |
231 | } | |
88149598 | 232 | *amr = 0; |
c14fd247 BJ |
233 | bdp = (mr >> 28) & 0x0f; |
234 | if (bdp) { | |
27bf6b55 | 235 | switch (cpu) { |
bce08673 JB |
236 | #if defined(VAX780) || defined(VAX8600) |
237 | case VAX_8600: | |
5aa9d5ea | 238 | case VAX_780: |
5ab42896 | 239 | uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; |
5aa9d5ea RE |
240 | break; |
241 | #endif | |
242 | #if VAX750 | |
243 | case VAX_750: | |
5ab42896 BJ |
244 | uh->uh_uba->uba_dpr[bdp] |= |
245 | UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; | |
5aa9d5ea RE |
246 | break; |
247 | #endif | |
248 | } | |
b7333467 | 249 | uh->uh_bdpfree |= 1 << (bdp-1); /* atomic */ |
3f3a34c3 BJ |
250 | if (uh->uh_bdpwant) { |
251 | uh->uh_bdpwant = 0; | |
174d2438 | 252 | wakeup((caddr_t)&uh->uh_bdpwant); |
c14fd247 BJ |
253 | } |
254 | } | |
b7333467 BJ |
255 | /* |
256 | * Put back the registers in the resource map. | |
ee0fdd94 MK |
257 | * The map code must not be reentered, |
258 | * nor can the registers be freed twice. | |
259 | * Unblock interrupts once this is done. | |
b7333467 | 260 | */ |
c14fd247 BJ |
261 | npf = (mr >> 18) & 0x3ff; |
262 | reg = ((mr >> 9) & 0x1ff) + 1; | |
5d30e870 | 263 | rmfree(uh->uh_map, (long)npf, (long)reg); |
b7333467 BJ |
264 | splx(s); |
265 | ||
266 | /* | |
267 | * Wakeup sleepers for map registers, | |
268 | * and also, if there are processes blocked in dgo(), | |
269 | * give them a chance at the UNIBUS. | |
270 | */ | |
3f3a34c3 BJ |
271 | if (uh->uh_mrwant) { |
272 | uh->uh_mrwant = 0; | |
174d2438 | 273 | wakeup((caddr_t)&uh->uh_mrwant); |
c14fd247 | 274 | } |
b7333467 BJ |
275 | while (uh->uh_actf && ubago(uh->uh_actf)) |
276 | ; | |
c14fd247 BJ |
277 | } |
278 | ||
27bf6b55 | 279 | ubapurge(um) |
5ab42896 | 280 | register struct uba_ctlr *um; |
27bf6b55 BJ |
281 | { |
282 | register struct uba_hd *uh = um->um_hd; | |
283 | register int bdp = (um->um_ubinfo >> 28) & 0x0f; | |
284 | ||
285 | switch (cpu) { | |
bce08673 JB |
286 | #if defined(VAX780) || defined(VAX8600) |
287 | case VAX_8600: | |
27bf6b55 | 288 | case VAX_780: |
5ab42896 | 289 | uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE; |
27bf6b55 BJ |
290 | break; |
291 | #endif | |
292 | #if VAX750 | |
293 | case VAX_750: | |
5ab42896 | 294 | uh->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE; |
27bf6b55 BJ |
295 | break; |
296 | #endif | |
297 | } | |
298 | } | |
299 | ||
9305c2b9 BJ |
300 | ubainitmaps(uhp) |
301 | register struct uba_hd *uhp; | |
302 | { | |
303 | ||
5d30e870 | 304 | rminit(uhp->uh_map, (long)NUBMREG, (long)1, "uba", UAMSIZ); |
9305c2b9 | 305 | switch (cpu) { |
bce08673 JB |
306 | #if defined(VAX780) || defined(VAX8600) |
307 | case VAX_8600: | |
9305c2b9 BJ |
308 | case VAX_780: |
309 | uhp->uh_bdpfree = (1<<NBDP780) - 1; | |
310 | break; | |
311 | #endif | |
312 | #if VAX750 | |
313 | case VAX_750: | |
314 | uhp->uh_bdpfree = (1<<NBDP750) - 1; | |
315 | break; | |
316 | #endif | |
9d2503c6 | 317 | #if defined(VAX730) || defined(VAX630) |
10f66600 | 318 | case VAX_730: |
9d2503c6 | 319 | case VAX_630: |
9305c2b9 BJ |
320 | break; |
321 | #endif | |
322 | } | |
323 | } | |
324 | ||
b7333467 BJ |
325 | /* |
326 | * Generate a reset on uba number uban. Then | |
327 | * call each device in the character device table, | |
328 | * giving it a chance to clean up so as to be able to continue. | |
329 | */ | |
3f3a34c3 | 330 | ubareset(uban) |
b7333467 | 331 | int uban; |
2e74ef16 | 332 | { |
2e74ef16 | 333 | register struct cdevsw *cdp; |
a3cb8f60 | 334 | register struct uba_hd *uh = &uba_hd[uban]; |
49c84d3f | 335 | int s; |
2e74ef16 | 336 | |
8011f5df | 337 | s = spluba(); |
a3cb8f60 BJ |
338 | uh->uh_users = 0; |
339 | uh->uh_zvcnt = 0; | |
340 | uh->uh_xclu = 0; | |
a3cb8f60 BJ |
341 | uh->uh_actf = uh->uh_actl = 0; |
342 | uh->uh_bdpwant = 0; | |
343 | uh->uh_mrwant = 0; | |
9305c2b9 | 344 | ubainitmaps(uh); |
a3cb8f60 BJ |
345 | wakeup((caddr_t)&uh->uh_bdpwant); |
346 | wakeup((caddr_t)&uh->uh_mrwant); | |
5ab42896 BJ |
347 | printf("uba%d: reset", uban); |
348 | ubainit(uh->uh_uba); | |
ee0fdd94 | 349 | ubameminit(uban); |
512bbccd | 350 | for (cdp = cdevsw; cdp < cdevsw + nchrdev; cdp++) |
3f3a34c3 | 351 | (*cdp->d_reset)(uban); |
4c3f4cb1 | 352 | ifubareset(uban); |
2e74ef16 | 353 | printf("\n"); |
4ea0bfc4 | 354 | splx(s); |
2e74ef16 | 355 | } |
3f3a34c3 | 356 | |
b7333467 BJ |
357 | /* |
358 | * Init a uba. This is called with a pointer | |
359 | * rather than a virtual address since it is called | |
360 | * by code which runs with memory mapping disabled. | |
361 | * In these cases we really don't need the interrupts | |
362 | * enabled, but since we run with ipl high, we don't care | |
363 | * if they are, they will never happen anyways. | |
364 | */ | |
5aa9d5ea RE |
365 | ubainit(uba) |
366 | register struct uba_regs *uba; | |
3f3a34c3 BJ |
367 | { |
368 | ||
5ab42896 | 369 | switch (cpu) { |
bce08673 JB |
370 | #if defined(VAX780) || defined(VAX8600) |
371 | case VAX_8600: | |
d2f165e5 | 372 | case VAX_780: |
5ab42896 BJ |
373 | uba->uba_cr = UBACR_ADINIT; |
374 | uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE; | |
375 | while ((uba->uba_cnfgr & UBACNFGR_UBIC) == 0) | |
376 | ; | |
377 | break; | |
378 | #endif | |
379 | #if VAX750 | |
d2f165e5 | 380 | case VAX_750: |
a3812a04 | 381 | #endif |
10f66600 SL |
382 | #if VAX730 |
383 | case VAX_730: | |
fed9edca | 384 | #endif |
9d2503c6 BK |
385 | #if VAX630 |
386 | case VAX_630: | |
387 | #endif | |
388 | #if defined(VAX750) || defined(VAX730) || defined(VAX630) | |
fed9edca BJ |
389 | mtpr(IUR, 0); |
390 | /* give devices time to recover from power fail */ | |
391 | /* THIS IS PROBABLY UNNECESSARY */ | |
392 | DELAY(500000); | |
393 | /* END PROBABLY UNNECESSARY */ | |
5ab42896 BJ |
394 | break; |
395 | #endif | |
396 | } | |
3f3a34c3 BJ |
397 | } |
398 | ||
46bfb00b | 399 | #if defined(VAX780) || defined(VAX8600) |
3e04ba6a BJ |
400 | int ubawedgecnt = 10; |
401 | int ubacrazy = 500; | |
ee0fdd94 | 402 | int zvcnt_max = 5000; /* in 8 sec */ |
b7333467 | 403 | /* |
46bfb00b JB |
404 | * This routine is called by the locore code to process a UBA |
405 | * error on an 11/780 or 8600. The arguments are passed | |
b7333467 BJ |
406 | * on the stack, and value-result (through some trickery). |
407 | * In particular, the uvec argument is used for further | |
408 | * uba processing so the result aspect of it is very important. | |
409 | * It must not be declared register. | |
410 | */ | |
5aa9d5ea | 411 | /*ARGSUSED*/ |
ee0fdd94 | 412 | ubaerror(uban, uh, ipl, uvec, uba) |
3f3a34c3 BJ |
413 | register int uban; |
414 | register struct uba_hd *uh; | |
ee0fdd94 | 415 | int ipl, uvec; |
3f3a34c3 BJ |
416 | register struct uba_regs *uba; |
417 | { | |
418 | register sr, s; | |
419 | ||
420 | if (uvec == 0) { | |
45d4a789 MK |
421 | /* |
422 | * Declare dt as unsigned so that negative values | |
423 | * are handled as >8 below, in case time was set back. | |
424 | */ | |
425 | u_long dt = time.tv_sec - uh->uh_zvtime; | |
426 | ||
427 | uh->uh_zvtotal++; | |
ee0fdd94 | 428 | if (dt > 8) { |
45d4a789 | 429 | uh->uh_zvtime = time.tv_sec; |
ee0fdd94 MK |
430 | uh->uh_zvcnt = 0; |
431 | } | |
432 | if (++uh->uh_zvcnt > zvcnt_max) { | |
433 | printf("uba%d: too many zero vectors (%d in <%d sec)\n", | |
434 | uban, uh->uh_zvcnt, dt + 1); | |
435 | printf("\tIPL 0x%x\n\tcnfgr: %b Adapter Code: 0x%x\n", | |
436 | ipl, uba->uba_cnfgr&(~0xff), UBACNFGR_BITS, | |
437 | uba->uba_cnfgr&0xff); | |
438 | printf("\tsr: %b\n\tdcr: %x (MIC %sOK)\n", | |
439 | uba->uba_sr, ubasr_bits, uba->uba_dcr, | |
440 | (uba->uba_dcr&0x8000000)?"":"NOT "); | |
3f3a34c3 BJ |
441 | ubareset(uban); |
442 | } | |
3f3a34c3 BJ |
443 | return; |
444 | } | |
445 | if (uba->uba_cnfgr & NEX_CFGFLT) { | |
5af3f3f7 BJ |
446 | printf("uba%d: sbi fault sr=%b cnfgr=%b\n", |
447 | uban, uba->uba_sr, ubasr_bits, | |
d2f165e5 | 448 | uba->uba_cnfgr, NEXFLT_BITS); |
3f3a34c3 BJ |
449 | ubareset(uban); |
450 | uvec = 0; | |
451 | return; | |
452 | } | |
453 | sr = uba->uba_sr; | |
8011f5df | 454 | s = spluba(); |
ec28fe15 BJ |
455 | printf("uba%d: uba error sr=%b fmer=%x fubar=%o\n", |
456 | uban, uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar); | |
3f3a34c3 BJ |
457 | splx(s); |
458 | uba->uba_sr = sr; | |
5ab42896 | 459 | uvec &= UBABRRVR_DIV; |
3e04ba6a BJ |
460 | if (++uh->uh_errcnt % ubawedgecnt == 0) { |
461 | if (uh->uh_errcnt > ubacrazy) | |
462 | panic("uba crazy"); | |
463 | printf("ERROR LIMIT "); | |
464 | ubareset(uban); | |
465 | uvec = 0; | |
466 | return; | |
467 | } | |
3f3a34c3 BJ |
468 | return; |
469 | } | |
470 | #endif | |
1c1f6ecf | 471 | |
ee0fdd94 MK |
472 | /* |
473 | * Look for devices with unibus memory, allow them to configure, then disable | |
474 | * map registers as necessary. Called during autoconfiguration and ubareset. | |
475 | * The device ubamem routine returns 0 on success, 1 on success if it is fully | |
476 | * configured (has no csr or interrupt, so doesn't need to be probed), | |
477 | * and -1 on failure. | |
478 | */ | |
479 | ubameminit(uban) | |
480 | { | |
481 | register struct uba_device *ui; | |
482 | register struct uba_hd *uh = &uba_hd[uban]; | |
483 | caddr_t umembase = umem[uban] + 0x3e000, addr; | |
484 | #define ubaoff(off) ((int)(off) & 0x1fff) | |
485 | ||
486 | uh->uh_lastmem = 0; | |
487 | for (ui = ubdinit; ui->ui_driver; ui++) { | |
488 | if (ui->ui_ubanum != uban && ui->ui_ubanum != '?') | |
489 | continue; | |
490 | if (ui->ui_driver->ud_ubamem) { | |
491 | /* | |
492 | * During autoconfiguration, need to fudge ui_addr. | |
493 | */ | |
494 | addr = ui->ui_addr; | |
495 | ui->ui_addr = umembase + ubaoff(addr); | |
496 | switch ((*ui->ui_driver->ud_ubamem)(ui, uban)) { | |
497 | case 1: | |
498 | ui->ui_alive = 1; | |
499 | /* FALLTHROUGH */ | |
500 | case 0: | |
501 | ui->ui_ubanum = uban; | |
502 | break; | |
503 | } | |
504 | ui->ui_addr = addr; | |
505 | } | |
506 | } | |
bce08673 | 507 | #if defined(VAX780) || defined(VAX8600) |
ee0fdd94 MK |
508 | /* |
509 | * On a 780, throw away any map registers disabled by rounding | |
510 | * the map disable in the configuration register | |
511 | * up to the next 8K boundary, or below the last unibus memory. | |
512 | */ | |
bce08673 | 513 | if ((cpu == VAX_780) || (cpu == VAX_8600)) { |
ee0fdd94 MK |
514 | register i; |
515 | ||
516 | i = btop(((uh->uh_lastmem + 8191) / 8192) * 8192); | |
517 | while (i) | |
518 | (void) rmget(uh->uh_map, 1, i--); | |
519 | } | |
520 | #endif | |
521 | } | |
522 | ||
1c1f6ecf | 523 | /* |
002dfe8e SL |
524 | * Allocate UNIBUS memory. Allocates and initializes |
525 | * sufficient mapping registers for access. On a 780, | |
526 | * the configuration register is setup to disable UBA | |
527 | * response on DMA transfers to addresses controlled | |
528 | * by the disabled mapping registers. | |
ee0fdd94 MK |
529 | * On a 780, should only be called from ubameminit, or in ascending order |
530 | * from 0 with 8K-sized and -aligned addresses; freeing memory that isn't | |
531 | * the last unibus memory would free unusable map registers. | |
532 | * Doalloc is 1 to allocate, 0 to deallocate. | |
1c1f6ecf | 533 | */ |
002dfe8e SL |
534 | ubamem(uban, addr, npg, doalloc) |
535 | int uban, addr, npg, doalloc; | |
1c1f6ecf BF |
536 | { |
537 | register struct uba_hd *uh = &uba_hd[uban]; | |
002dfe8e | 538 | register int a; |
ee0fdd94 | 539 | int s; |
1c1f6ecf | 540 | |
ee0fdd94 | 541 | a = (addr >> 9) + 1; |
8011f5df | 542 | s = spluba(); |
ee0fdd94 MK |
543 | if (doalloc) |
544 | a = rmget(uh->uh_map, npg, a); | |
545 | else | |
546 | rmfree(uh->uh_map, (long)npg, (long)a); | |
547 | splx(s); | |
1c1f6ecf | 548 | if (a) { |
002dfe8e SL |
549 | register int i, *m; |
550 | ||
551 | m = (int *)&uh->uh_uba->uba_map[a - 1]; | |
552 | for (i = 0; i < npg; i++) | |
1c1f6ecf | 553 | *m++ = 0; /* All off, especially 'valid' */ |
ee0fdd94 MK |
554 | i = addr + npg * 512; |
555 | if (doalloc && i > uh->uh_lastmem) | |
556 | uh->uh_lastmem = i; | |
557 | else if (doalloc == 0 && i == uh->uh_lastmem) | |
558 | uh->uh_lastmem = addr; | |
bce08673 | 559 | #if defined(VAX780) || defined(VAX8600) |
002dfe8e SL |
560 | /* |
561 | * On a 780, set up the map register disable | |
562 | * field in the configuration register. Beware | |
ee0fdd94 MK |
563 | * of callers that request memory ``out of order'' |
564 | * or in sections other than 8K multiples. | |
565 | * Ubameminit handles such requests properly, however. | |
002dfe8e | 566 | */ |
bce08673 | 567 | if ((cpu == VAX_780) || (cpu == VAX_8600)) { |
ee0fdd94 MK |
568 | i = uh->uh_uba->uba_cr &~ 0x7c000000; |
569 | i |= ((uh->uh_lastmem + 8191) / 8192) << 26; | |
570 | uh->uh_uba->uba_cr = i; | |
a26646de BF |
571 | } |
572 | #endif | |
1c1f6ecf | 573 | } |
002dfe8e | 574 | return (a); |
1c1f6ecf | 575 | } |
8e61f556 | 576 | |
413f33da | 577 | #include "ik.h" |
37ccce8f JG |
578 | #include "vs.h" |
579 | #if NIK > 0 || NVS > 0 | |
8e61f556 SL |
580 | /* |
581 | * Map a virtual address into users address space. Actually all we | |
582 | * do is turn on the user mode write protection bits for the particular | |
583 | * page of memory involved. | |
584 | */ | |
585 | maptouser(vaddress) | |
586 | caddr_t vaddress; | |
587 | { | |
588 | ||
589 | Sysmap[(((unsigned)(vaddress))-0x80000000) >> 9].pg_prot = (PG_UW>>27); | |
590 | } | |
591 | ||
592 | unmaptouser(vaddress) | |
593 | caddr_t vaddress; | |
594 | { | |
595 | ||
596 | Sysmap[(((unsigned)(vaddress))-0x80000000) >> 9].pg_prot = (PG_KW>>27); | |
597 | } | |
3b1e560f | 598 | #endif |