|
|
researchv10 Norman
/*
* general UNIBUS map setup routines
*/
#include "sys/param.h"
#include "sys/ubaddr.h"
#include "sys/map.h"
#include "sys/uba.h"
#include "sys/buf.h"
#include "sys/stream.h"
#include "sys/vmmac.h"
#include "sys/pte.h"
extern struct uba uba[];
extern struct block cblock[];
extern struct buf *cblkbuf[];
extern int blkcnt, blkbcnt;
extern uaddr_t ubmsetmap();
/*
* init data structures:
* grab a place to store map for the stream buffers
*/
ubmstart(u)
int u;
{
register struct uba *ub;
register struct buf *bp;
ub = &uba[u];
if ((bp = geteblk()) == NULL)
return (0);
if ((blkbcnt*sizeof(ubm_t) + blkbcnt*sizeof(uaddr_t)) > bp->b_bcount) {
printf("ub%d: too many stream bufs\n", u);
brelse(bp);
return (0);
}
clrbuf(bp);
ub->sbmap = (ubm_t *)bp->b_un.b_addr;
ub->sbaddr = (uaddr_t *)(ub->sbmap + blkbcnt);
ub->shmap = 0;
return (1);
}
/*
* after hardware reset:
* clear out junk for stream data
*/
ubminit(u)
int u;
{
register struct uba *ub;
register int i;
ub = &uba[u];
for (i = 0; i < blkbcnt; i++)
if (ub->sbmap[i]) {
ubmfree(u, ub->sbmap[i]);
ub->sbmap[i] = 0;
}
if (ub->shmap) {
ubmfree(u, ub->shmap);
ub->shmap = 0;
}
}
/*
* general map-allocation routine
*/
ubm_t
ubmalloc(u, size, flag)
int u;
int size;
register int flag;
{
register struct uba *ub;
int base, nreg, path;
int s;
ub = &uba[u];
nreg = btoc(size);
if ((flag & UPAG) == 0)
nreg++; /* allow for alignment */
nreg++; /* allow for endmarker for DW780 */
s = spl6();
while ((base = rmalloc(ub->map, nreg)) == 0) {
if ((flag & USLP) == 0)
return (0);
ub->flags |= UBMWANT;
sleep((caddr_t)ub->map, PZERO);
}
splx(s);
if (flag & UBDP)
path = ubmapath(u);
else
path = 0;
return ((base<<UMFIRST) | ((nreg-UMSZERO)<<UMSIZE) | (path<<UMDP));
}
ubmfree(u, um)
ubm_t um;
{
register struct uba *ub;
register int path;
register int s;
if (um == NOMAP)
return;
ub = &uba[u];
s = spl6();
if ((path = ubmpath(um)) != 0) {
ubmflush(u, path);
ub->path |= 1<<path;
}
rmfree(ub->map, ubmsize(um), ubmfirst(um));
if (ub->flags & UBMWANT) {
wakeup((caddr_t)ub->map);
ub->flags &=~ UBMWANT;
}
splx(s);
}
/*
* general-purpose address mapper
* for kernel address space
* don't use this if there's a better choice below
*/
uaddr_t
ubmaddr(u, cp, size, um)
int u;
caddr_t cp;
ubm_t um;
int size;
{
register int off;
off = (int)cp & PGOFSET;
return (ubmsetmap(u, &Sysmap[btop((int)cp & ~KSTART)],
btoc(size + off), um) + off);
}
/*
* allocate/set maps for various kinds of object
* ubmxxx returns a map sufficient for the object;
* ubadxxx sets the map, and returns a unibus-space address
* sometimes ubmxxx will return NOMAP,
* which means the space was pre-mapped (and any data path will be ignored)
*/
/*
* io buffers
*/
ubm_t
ubmbuf(u, bp, flags)
int u;
register struct buf *bp;
int flags;
{
if ((bp->b_flags & B_PHYS) == 0)
flags |= UPAG;
return (ubmalloc(u, bp->b_bcount, flags));
}
uaddr_t
ubadbuf(u, bp, um)
int u;
register struct buf *bp;
ubm_t um;
{
register int off;
off = (int)bp->b_un.b_addr & PGOFSET;
return (ubmsetmap(u, btopte(bp), btoc(bp->b_bcount + off), um) + off);
}
/*
* stream blocks
* headers (and the tiny bit of data in them) pre-mapped
* the rest of the data mapped a buf at a time, when first touched
*/
ubm_t
ubmblk(u, bp, flags)
int u;
register struct block *bp;
int flags;
{
register int i;
register struct uba *ub;
register struct buf *bf;
ub = &uba[u];
flags &=~ UBDP;
if ((i = bp->bufix) == NOBUFIX) { /* data all in the header */
if (ub->shmap)
return (NOMAP);
if ((ub->shmap = ubmalloc(u, blkcnt*sizeof(struct block), flags)) == 0)
return (0);
ub->shaddr = ubmaddr(u, (char *)cblock, blkcnt*sizeof(struct block), ub->shmap);
return (NOMAP);
}
if (ub->sbmap[i]) /* this buf already mapped */
return (NOMAP);
bf = cblkbuf[i];
if ((ub->sbmap[i] = ubmbuf(u, bf, flags)) == 0)
return (0);
ub->sbaddr[i] = ubmsetmap(u, btopte(bf), btoc(bf->b_bcount), ub->sbmap[i]);
return (NOMAP);
}
/*
* ubadwptr returns the unibus address of the write pointer
* ubadrptr for the read pointer
*/
uaddr_t
ubadwptr(u, bp, um)
int u;
register struct block *bp;
ubm_t um;
{
register struct uba *ub;
register int i;
ub = &uba[u];
if ((i = bp->bufix) == NOBUFIX)
return ((uaddr_t)(bp->wptr-(u_char *)cblock + (int)ub->shaddr));
if (ub->sbmap[i] == 0)
panic("ubadwptr");
return (ub->sbaddr[i]+bp->wptr-(u_char *)cblkbuf[i]->b_un.b_addr);
}
uaddr_t
ubadrptr(u, bp, um)
int u;
register struct block *bp;
ubm_t um;
{
register struct uba *ub;
register int i;
ub = &uba[u];
if ((i = bp->bufix) == NOBUFIX)
return ((uaddr_t)(bp->rptr-(u_char *)cblock + (int)ub->shaddr));
if (ub->sbmap[i] == 0)
panic("ubadrptr");
return (ub->sbaddr[i]+bp->rptr-(u_char *)cblkbuf[i]->b_un.b_addr);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.