|
|
researchv10 Norman
/*
* unibus adapter routines for DWBUA
*/
#include "sys/param.h"
#include "sys/ubaddr.h"
#include "sys/nexus.h"
#include "sys/biaddr.h"
#include "sys/biic.h"
#include "sys/map.h"
#include "sys/uba.h"
#include "sys/pte.h"
#include "sys/vmparam.h"
extern struct uba uba[];
extern struct biaddr ubaaddr[];
extern int ubacnt;
/*
* 0x2000 bytes of nexus space, followed by the address window
*/
#define NMAP 496
#define NBDP 5
struct ubadev {
struct biic bi;
long junk0[392];
long csr;
long vor;
long fubar;
long bifar;
long junk1[8];
long dpr[16]; /* 0 == DDP, 5 BDPs, rest unused */
long junk2[28];
long mreg[512];
long junk3[0x400];
char ubspace[NXWSIZE];
};
/*
* bits in the data path register
*/
#define PURGE 0x1 /* purge datapath */
/*
* bits in map register
*/
#define BO 0x2000000 /* offset address by one */
#define MRV 0x80000000 /* map register valid */
#define PSHIFT 21 /* shift data path number this much */
/*
* bits in csr
*/
#define BUAERR 0x80000000 /* BUA error summary */
#define USSTO 0x8000000 /* VAXBI-to-UNIBUS SSYN timeout */
#define BUAEIE 0x100000 /* error interrupt enable */
#define BUAONE 0x8000 /* set when adapter is answering */
/*
* bits in gpr0
*/
#define UBPUP 0x1 /* unibus is powered up */
/*
* return the register address for a unibus device
*/
caddr_t
ubaddr(up)
register struct ubaddr *up;
{
register struct uba *ub;
if (up->ubno < 0 || up->ubno > ubacnt) {
printf("bad ubano %d\n", up->ubno);
return (0);
}
ub = &uba[up->ubno];
if ((ub->flags & UBINIT) == 0)
if (ubstart(up->ubno) == 0)
return (0);
return ((caddr_t)&ub->addr->ubspace[up->uboff]);
}
/*
* init the unibus adapter
*/
ubstart(u)
int u;
{
register struct uba *ub;
ub = &uba[u];
if ((ub->addr = (struct ubadev *)biaddr(&ubaaddr[u])) == 0)
return (0);
if (badaddr(&ub->addr->bi.bitype, sizeof(long))) {
printf("ub%d absent\n");
return (0);
}
rminit(ub->map, UBNMAP, NMAP-1, 1); /* NMAP-1 because can't alloc 0 */
ub->path = ((1<<NBDP)-1)<<1;
if (ubmstart(u) == 0)
return (0);
if (ubinit(u) == 0)
return (0);
ub->flags |= UBINIT;
return (1);
}
/*
* init the unibus adapter hardware
*/
#define PUSTALL 200000
ubinit(u)
register int u;
{
register struct uba *ub;
register struct ubadev *up;
register int i;
register int s;
register long *p;
ub = &uba[u];
up = ub->addr;
s = spl7();
DELAY(80000);
up->bi.bicsr |= BINRST|BISTS;
DELAY(80000);
for (i = 0; i < PUSTALL; i++)
if (up->bi.bicsr & BISTS)
break;
for (i = 0; i < PUSTALL; i++)
if (up->csr & BUAONE)
break;
for (i = 0; i < PUSTALL; i++)
if (up->bi.bigpr0 & UBPUP)
break;
splx(s);
if ((up->bi.bigpr0 & UBPUP) == 0) {
printf("ub%d not responding; csr x%x\n", u, up->csr);
return (0);
}
biinit(&ubaaddr[u], 1);
up->vor = ubaaddr[u].ovec;
up->bi.bieir = ubaaddr[u].vec|EIBR7;
up->bi.biuir = UIEXVEC;
up->bi.biber = BIBERCLR;
up->bi.bicsr |= BIHEIE|BISEIE|BIHIARB;
up->csr |= BUAEIE; /* also clears error latches */
for (i = 0, p = ub->addr->mreg; i < NMAP; i++)
*p++ = 0;
ubminit(u);
return (1);
}
/*
* determine whether a particular address,
* which happens to be in UNIBUS space,
* exists
*/
ubbadaddr(u, a, s)
int u, s;
caddr_t a;
{
register int p;
register struct ubadev *up;
if (u < 0 || u >= ubacnt)
return (1);
up = uba[u].addr;
p = spl7();
up->csr = up->csr; /* clear errors */
s = badaddr(a, s);
if (up->csr & USSTO) /* or perhaps any error? */
s = 1;
up->csr = up->csr; /* clear errors again */
splx(p);
return (s);
}
/*
* unibus adapter interrupts
*/
uba0int(dev)
int dev;
{
register struct ubadev *up;
register long biber, bicsr, ubcsr;
if (dev < 0 || dev >= ubacnt) {
printf("stray intr from ub%d\n", dev);
return;
}
up = uba[dev].addr;
if (up == 0) {
printf("ub%d unexpected intr\n", dev);
return;
}
biber = up->bi.biber;
bicsr = up->bi.bicsr;
ubcsr = up->csr;
up->bi.biber = biber; /* clear latches */
up->bi.biber &=~ EIFORCE; /* needed? */
up->csr |= BUAEIE;
if (cknofault())
return;
if (bicsr & (BIHES|BISES))
printf("ub%d bicsr x%x biber x%x\n", dev, bicsr, biber);
if (ubcsr & BUAERR)
printf("ub%d csr x%x fubar 0%o bifar x%x\n", dev,
ubcsr, up->fubar<<2, up->bifar);
}
/*
* allocate a buffered data path
* return the ddp if none available
*/
int ubnopath;
int
ubmapath(u)
int u;
{
register struct uba *ub;
register int path;
register int s;
ub = &uba[u];
s = spl6();
for (path = NBDP; path > 0; path--)
if (ub->path & (1<<path)) {
ub->path &=~ (1<<path);
break;
}
splx(s);
if (path == 0)
ubnopath++;
return (path);
}
/*
* flush (in hardware) a bdp
*/
ubmflush(u, path)
int u;
int path;
{
if (path == 0 || path > NBDP)
return;
uba[u].addr->dpr[path] = PURGE;
}
/*
* fill in a piece of unibus map
* return the address of the base
*/
uaddr_t
ubmsetmap(u, p, nreg, um)
int u;
register struct pte *p;
register int nreg;
ubm_t um;
{
register long *m;
register long x;
m = &uba[u].addr->mreg[ubmfirst(um)];
x = (ubmpath(um)<<PSHIFT)|MRV;
if (nreg > ubmsize(um)-1)
panic("ubmsetmap");
while (--nreg >= 0)
*m++ = p++->pg_pfnum | x;
return (ctob(ubmfirst(um)));
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.