BSD 4 development
[unix-history] / usr / src / sys / dev / uba.c
/* uba.c 4.2 11/9/80 */
#include "../h/param.h"
#include "../h/map.h"
#include "../h/pte.h"
#include "../h/uba.h"
#include "../h/buf.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/proc.h"
#include "../h/vm.h"
#include "../h/conf.h"
/*
* Allocate as many contiguous UBA mapping registers
* as are necessary to do transfer of bcnt bytes
* to/from location baddr. Wait for enough map registers.
*
* Bdpflg is non-zero if a "buffered data path" (BDP) is
* to be used, else 0 -> use direct data path (DDP). Return
*
* Bits 0-8 Byte offset
* Bits 9-17 Start map reg. no.
* Bits 18-27 No. mapping reg's
* Bits 28-31 BDP no.
*/
ubasetup(bp, bdpflg)
struct buf *bp;
{
register int temp, i;
int npf, reg, bdp;
unsigned v;
register struct pte *pte, *io;
struct proc *rp;
int a, o, ubinfo;
v = btop(bp->b_un.b_addr);
o = (int)bp->b_un.b_addr & PGOFSET;
npf = btoc(bp->b_bcount + o) + 1;
a = spl6();
while ((reg = malloc(ubamap, npf)) == 0) {
panic("ran out of uba map");
umrwant++;
sleep((caddr_t)ubamap, PSWP);
}
reg--;
bdp = 0;
if (bdpflg)
while ((bdp = malloc(bdpmap, 1)) == 0) {
panic("ran out of bdp's");
bdpwant++;
sleep((caddr_t)bdpmap, PSWP);
}
splx(a);
ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o;
io = &(((struct uba_regs *)UBA0)->uba_map[reg]);
temp = (bdp << 21) | MRV;
rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
if (bdp && (o & 01))
temp |= BO;
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)];
while (--npf != 0)
*(int *)io++ = pte++->pg_pfnum | temp;
} else {
if (bp->b_flags & B_PAGET)
pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
else
pte = vtopte(rp, v);
while (--npf != 0) {
if (pte->pg_pfnum == 0)
panic("uba zero uentry");
*(int *)io++ = pte++->pg_pfnum | temp;
}
}
*(int *)io++ = 0;
return (ubinfo);
}
/*
* Non buffer unibus interface... set up a buffer and call ubasetup.
*/
uballoc(addr, bcnt, bdpflg)
caddr_t addr;
unsigned short bcnt;
{
struct buf ubabuf;
ubabuf.b_un.b_addr = addr;
ubabuf.b_flags = B_BUSY;
ubabuf.b_bcount = bcnt;
/* that's all the fields ubasetup() needs */
return (ubasetup(&ubabuf, bdpflg));
}
ubafree(mr)
int mr;
{
register int bdp, reg, npf, a;
a = spl6();
bdp = (mr >> 28) & 0x0f;
if (bdp) {
((struct uba_regs *)UBA0)->uba_dpr[bdp] |= BNE; /* purge */
mfree(bdpmap, 1, bdp);
if (bdpwant) {
bdpwant = 0;
wakeup((caddr_t)bdpmap);
}
}
npf = (mr >> 18) & 0x3ff;
reg = ((mr >> 9) & 0x1ff) + 1;
mfree(ubamap, npf, reg);
if (umrwant) {
umrwant = 0;
wakeup((caddr_t)ubamap);
}
splx(a);
}
ubainit()
{
mfree(ubamap, 496, 1);
mfree(bdpmap, 15, 1);
}
#define DELAY(N) { register int d; d = N; while (--d > 0); }
ubareset()
{
struct uba_regs *up = (struct uba_regs *)UBA0;
register struct cdevsw *cdp;
int s;
s = spl6();
printf("UBA RESET:");
up->uba_cr = ADINIT;
up->uba_cr = IFS|BRIE|USEFIE|SUEFIE;
while ((up->uba_cnfgr & UBIC) == 0)
;
for (cdp = cdevsw; cdp->d_open; cdp++)
(*cdp->d_reset)();
printf("\n");
splx(s);
}