* Allocate and setup UBA map registers, and bdp's
* Flags says whether bdp is needed, whether the caller can't
* wait (e.g. if the caller is at interrupt level).
* Bits 9-17 Start map reg. no.
* Bits 18-27 No. mapping reg's
ubasetup(uban
, bp
, flags
)
register struct uba_hd
*uh
= &uba_hd
[uban
];
register struct pte
*pte
, *io
;
v
= btop(bp
->b_un
.b_addr
);
o
= (int)bp
->b_un
.b_addr
& PGOFSET
;
npf
= btoc(bp
->b_bcount
+ o
) + 1;
while ((reg
= malloc(uh
->uh_map
, npf
)) == 0) {
if (flags
& UBA_CANTWAIT
)
sleep((caddr_t
)uh
->uh_map
, PSWP
);
if (flags
& UBA_NEEDBDP
) {
while ((bdp
= ffs(uh
->uh_bdpfree
)) == 0) {
if (flags
& UBA_CANTWAIT
) {
mfree(uh
->uh_map
, npf
, reg
);
sleep((caddr_t
)uh
->uh_map
, PSWP
);
uh
->uh_bdpfree
&= ~ (1<<bdp
);
ubinfo
= (bdp
<< 28) | (npf
<< 18) | (reg
<< 9) | o
;
io
= &uh
->uh_uba
->uba_map
[reg
];
temp
= (bdp
<< 21) | UBA_MRV
;
rp
= bp
->b_flags
&B_DIRTY
? &proc
[2] : bp
->b_proc
;
if (bp
->b_flags
& B_UAREA
) {
for (i
= UPAGES
- bp
->b_bcount
/ NBPG
; i
< UPAGES
; i
++) {
if (rp
->p_addr
[i
].pg_pfnum
== 0)
panic("uba: zero upage");
*(int *)io
++ = rp
->p_addr
[i
].pg_pfnum
| temp
;
} else if ((bp
->b_flags
& B_PHYS
) == 0) {
pte
= &Sysmap
[btop(((int)bp
->b_un
.b_addr
)&0x7fffffff)];
*(int *)io
++ = pte
++->pg_pfnum
| temp
;
if (bp
->b_flags
& B_PAGET
)
pte
= &Usrptmap
[btokmx((struct pte
*)bp
->b_un
.b_addr
)];
panic("uba zero uentry");
*(int *)io
++ = pte
++->pg_pfnum
| temp
;
* Non buffer unibus interface... set up a buffer and call ubasetup.
uballoc(uban
, addr
, bcnt
, flags
)
ubabuf
.b_un
.b_addr
= addr
;
/* that's all the fields ubasetup() needs */
return (ubasetup(uban
, &ubabuf
, flags
));
* Old ubafree(info) is now ubarelse(&info) to avoid races.
register struct uba_hd
*uh
= &uba_hd
[uban
];
register int bdp
, reg
, npf
, a
;
uh
->uh_uba
->uba_dpr
[bdp
] |= UBA_BNE
;
uh
->uh_uba
->uba_dpr
[bdp
] |= UBA_PURGE
|UBA_NXM
|UBA_UCE
;
uh
->uh_bdpfree
|= 1 << bdp
;
wakeup((caddr_t
)uh
->uh_map
);
npf
= (mr
>> 18) & 0x3ff;
reg
= ((mr
>> 9) & 0x1ff) + 1;
mfree(uh
->uh_map
, npf
, reg
);
wakeup((caddr_t
)uh
->uh_map
);
#define DELAY(N) { register int d; d = N; while (--d > 0); }
register struct cdevsw
*cdp
;
printf("UBA RESET %d:", uban
);
ubainit(uba_hd
[uban
].uh_uba
);
for (cdp
= cdevsw
; cdp
->d_open
; cdp
++)
/* pointer rather than number so we can be called with virt and phys addrs */
register struct uba_regs
*uba
;
uba
->uba_cr
= UBA_ADINIT
;
uba
->uba_cr
= UBA_IFS
|UBA_BRIE
|UBA_USEFIE
|UBA_SUEFIE
;
while ((uba
->uba_cnfgr
& UBA_UBIC
) == 0)
for (uban
= 0; uban
< numuba
; uban
++) {
register struct uba_hd
*uh
= &uba_hd
[uban
];
register struct uba_regs
*up
= uh
->uh_uba
;
if (uh
->uh_hangcnt
> 5*HZ
) {
/* timeout routine to decrement ``i forgot to interrupt counts */
/* this prevents the counts from growing slowly, which isn't interesting */
register struct uba_hd
*uh
;
for (uban
= 0; uban
< numuba
; uban
++) {
/* called from locore.s; parameters here (i.e. uvec) are value-result! */
ubaerror(uban
, uh
, xx
, uvec
, uba
)
register struct uba_hd
*uh
;
register struct uba_regs
*uba
;
if (uh
->uh_zvcnt
> 250000) {
if (uba
->uba_cnfgr
& NEX_CFGFLT
) {
printf("UBA%d SBI FAULT sr %x cnfgr %x\n",
uban
, uba
->uba_sr
, uba
->uba_cnfgr
);
printf("UBA%d ERROR SR %x FMER %x FUBAR %o\n",
uban
, uba
->uba_sr
, uba
->uba_fmer
, uba
->uba_fubar
);