V8/usr/sys/dev/ds.c
/* 5-29-84 dsrelease checks for zombie state or even death */
/* dsclose() shuts down device */
/* DSWAIT added */
/* 5-25-84 process pointer saved in dsopen for dsintr() */
/* vsunlock must then be duplicated using correct process structure */
/* the interrelation of dsstart-sleeping, dsintr, and dscleanup
needs to be cleaned up
Probably dscleanup should not call wakeup */
#include "ds.h"
# if NDS > 0
/*
* DSC System 200 driver
* via DSC dma11.
* vax 4.1bsd version
*/
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/mount.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/pte.h"
#include "../h/map.h"
#include "../h/buf.h"
#include "../h/ubareg.h"
#include "../h/ubavar.h"
#include "../h/conf.h"
#include "../h/proc.h"
#include "../h/file.h"
#include "../h/vmmac.h"
#include "../h/dsreg.h"
#include "../h/dsc.h"
/*
* THESE ARE SITE-SPECIFIC
*
* starting base for the
* d/a and a/d converters,
* for setting up sequence ram.
*/
/*
* reset device
*/
# define RESETDEV bit(4)
# define dsseq(sc, reg, conv, dir) \
(sc->c_ascseq[reg] = conv | ((dir & 01) << 6))
/*
* ds flags
*/
# define DS_CLOSED 0
# define DS_OPEN bit(0)
# define DS_IDLE bit(1)
# define DS_NDSK bit(2)
# define DS_MON bit(3)
# define DS_BRD bit(4)
# define DS_READ bit(5)
# define DS_WRITE bit(6)
# define DSPRI (PZERO+1)
/*
* Redundant book-keeping
* to help avoid page-wise overlap of buffers
* remember that this device is both asynchronous and
* uses user-supplied buffers
*/
struct dspageinfo {
int firstunit,
lastunit; /* in units of CLSIZE*NBPG, i.e. 1024 */
};
/*
* relevant information
* about the dma and asc
*/
struct ds_softc {
short c_dmacsr; /* copy of dma csr */
short c_asccsr; /* copy of asc csr */
short c_ascflags; /* initial asc flags */
short c_ascsrt; /* sampling rate */
short c_ascseq[8];
int c_flags; /* internal flags */
int c_errs; /* errors, returned via ioctl */
int c_bufno; /* dsubinfo/buffer */
int c_outbufno;
int c_uid; /* user id */
short c_pid; /* process id */
struct proc *c_procp; /* process structure pointer */
int c_ubinfo[NDSB]; /* uba info */
struct dspageinfo c_pageinfo[NDSB];
struct buf c_dsb[NDSB]; /* buffer list */
struct buf *c_ibp, *c_obp; /* buffer list pointers */
int c_nbytes; /* total # of bytes xferred since reset */
int c_to_idle; /* total # times idle flag set */
int c_to_active; /* total # times idle flag cleared */
} ds_softc[NDS];
int dsprobe(), dsattach(), dsintr();
struct uba_device *dsdinfo[NDS];
struct uba_ctlr dsctlr[NDS], *dscinfo[NDS]; /* dsattach() sets dscinfo to point to this */
u_short dsstd[] = {
0165400, 0
};
struct uba_driver dsdriver = {
dsprobe, 0, dsattach, 0, dsstd, "ds", dsdinfo, "ds", dscinfo
};
int dsdebug;
/*
* all this just to generate
* an interrupt; rather
* involved isn't it?
*/
dsprobe(reg)
caddr_t reg;
{
register int br, cvec; /* value-result */
register struct dsdevice *dsaddr;
int dummy;
# ifdef lint
br = 0; cvec = br; br = cvec;
# endif lint
dsaddr = (struct dsdevice *) reg;
dsaddr->dmacsr = 0;
dsaddr->dmacls = 0;
dsaddr->ascseq[0] = DABASE+0 | ((DA & 01) << 6);
dsaddr->ascseq[0] |= LAST_SEQ; /* last sequence register */
dsaddr->ascsrt = 0100;
dsaddr->dmacsr = DMA_IE;
dsaddr->asccsr = ASC_RUN | ASC_IE;
DELAY(40000);
/*
* now shut everything down.
* too bad we have to duplicate
* the code from dsinit but to
* call dsinit we need to give
* it a unit.
*/
dsaddr->dmacls = 0;
dummy = dsaddr->dmasar; /* clears sar flag */
dsaddr->dmaclr = 0;
dummy = dsaddr->ascrst;
dsaddr->ascrst = 0;
return(1);
}
dsattach(ui)
struct uba_device *ui;
{
register struct uba_ctlr *um;
register int unit;
register int i;
unit = ui->ui_unit;
um = &dsctlr[unit];
dscinfo[unit] = um;
ui->ui_ctlr = unit;
ui->ui_mi = um;
um->um_driver = ui->ui_driver;
um->um_ctlr = unit;
um->um_ubanum = ui->ui_ubanum;
um->um_alive = 1;
um->um_intr = ui->ui_intr;
um->um_addr = ui->ui_addr;
um->um_hd = ui->ui_hd;
ds_softc[unit].c_flags = DS_IDLE;
for(i=0;i<NDSB;i++)
ds_softc[unit].c_dsb[i].b_flags &= ~B_BUSY;
}
/* ARGSUSED */
dsopen(dev, flag)
dev_t dev;
{
register struct dsdevice *dsaddr;
register struct uba_device *ui;
register struct ds_softc *sc;
register int unit, i;
register struct buf *bp;
int dummy;
if ((unit = (minor(dev) & ~RESETDEV)) >= NDS)
goto bad;
if ((ui = dsdinfo[unit]) == NULL)
goto bad;
if (ui->ui_alive == 0)
goto bad;
sc = &ds_softc[ui->ui_unit];
dsaddr = (struct dsdevice *)ui->ui_addr;
if(dsdebug)printf("dsopen: unit %d, flag %x\n",unit,flag);
if (dsaddr->dmacsr & DMA_OFL) {
u.u_error = ENXIO;
return;
}
/*
* if this is the reset device
* then just do a reset and return.
*/
if (minor(dev) & RESETDEV) {
/*
* if the converters are in use then
* only the current user or root can
* do a reset.
*/
if (sc->c_flags & DS_OPEN) {
if ((sc->c_uid != u.u_ruid) && (u.u_uid != 0)) {
u.u_error = ENXIO;
return;
}
}
ds_softc[unit].c_flags = DS_CLOSED | DS_IDLE;
dscleanup(unit);
printf("ds%d: reset\n",unit);
return;
}
/*
* only one person can use it at a time
* and it can't be opened for both reading and writing
*/
if (sc->c_flags & DS_OPEN || (flag & (FREAD|FWRITE)) == (FREAD|FWRITE)) {
bad: u.u_error = ENXIO;
return;
}
/*
* initialize
*/
/* set defaults and initial conditions in ds_softc */
sc->c_flags = DS_IDLE;
sc->c_errs = 0;
sc->c_nbytes = sc->c_to_idle = sc->c_to_active = 0;
sc->c_ascflags = (flag & FWRITE ? ASC_PLAY : ASC_RECORD) | ASC_HZ04;
sc->c_ascseq[0] = (
(flag & FWRITE) ?
(DABASE+0 | (DA << 6)) : (ADBASE+0 | (AD << 6))
) | LAST_SEQ;
sc->c_ascsrt = 399;
sc->c_uid = u.u_ruid;
sc->c_pid = u.u_procp->p_pid;
sc->c_procp = u.u_procp;
if(dsdebug)printf("pid %d %d, flag %x stat %x\n",
sc->c_pid,sc->c_procp->p_pid,sc->c_procp->p_stat);
sc->c_flags |= DS_OPEN | (flag & FREAD ? DS_READ : DS_WRITE);
u.u_procp->p_flag |= SPHYSIO;
dsaddr->dmacsr = 0;
dummy = dsaddr->dmasar;
}
/* ARGSUSED */
dsclose(dev, flag) {
register int unit;
register struct dsdevice *dsaddr;
register struct uba_device *ui;
register struct ds_softc *sc;
unit = minor(dev) & ~RESETDEV;
sc = &ds_softc[unit];
ui = dsdinfo[unit];
dsaddr = (struct dsdevice *)ui->ui_addr;
if(dsdebug)printf("X");
if (sc->c_outbufno != sc->c_bufno &&
sc->c_errs == 0 && !(sc->c_flags & DS_IDLE))
tsleep((caddr_t)&ds_softc[unit], DSPRI,0);
dsaddr->asccsr = 0;
ds_softc[unit].c_flags = DS_CLOSED | DS_IDLE;
dscleanup(unit);
u.u_procp->p_flag &= ~ SPHYSIO;
if(dsdebug){
printf("to_active %d, to_idle %d, c_nbytes %d\n",
sc->c_to_active,
sc->c_to_idle,
sc->c_nbytes);
printf("c_ascseq[0] %x\n",sc->c_ascseq[0]);
dsdb(dsaddr);
}
}
/*
*
* Using u.u_count, u.u_base, each buffer header is set up.
* The converters only need the base address of the buffer and the word
* count.
*
*/
dsstart(dev, rw)
register dev_t dev;
{
register struct dsdevice *dsaddr;
register struct uba_device *ui;
register struct ds_softc *sc;
register struct buf *bp;
register int unit, c, bufno, ps;
int dummy,i, count;
caddr_t base;
int bits;
if(dsdebug)printf("S");
unit = minor(dev) & ~RESETDEV;
sc = &ds_softc[unit];
ui = dsdinfo[unit];
dsaddr = (struct dsdevice *)ui->ui_addr;
/*
* check user access rights to buffer
*/
if (useracc(u.u_base, u.u_count, rw==B_READ?B_WRITE:B_READ) == NULL) {
u.u_error = EFAULT;
return;
}
if (sc->c_errs) {
u.u_error = EIO;
return;
}
/*
* Get a buffer for each 64K block
* point each device buffer somewhere into
* the user's buffer
*/
/* NOTE that in order to get reasonable performance,
* buffer lengths (initial u.u_count) must be either
* less than 64K or sufficiently greater than a multiple
* of 64K.
*/
base = u.u_base;
count = u.u_count;
while(count > 0) {
if(dsdebug)printf("LT ");
/*
* no hardware buffers left, sleep till interrupt
* wakes us up
*/
ps = spl6();
if ((sc->c_dmacsr = dsaddr->dmacsr) & DMA_SFL) {
register ts;
if(dsdebug)printf("s");
ts = tsleep((caddr_t) &ds_softc[unit], DSPRI, 0);
if(dsdebug)printf("w");
switch(ts) {
case TS_SIG:
u.u_error = EINTR;
/* stop dsc, if active */
dsaddr->asccsr = dummy = 0;
dscleanup(unit);
return;
case TS_OK:
if ((sc->c_dmacsr = dsaddr->dmacsr) & DMA_SFL) {
u.u_error = EIO;
printf("ds%d still full after tsleep\n",unit);
dscleanup(unit);
return;
}
/* I don't think this allows for a clean dsclose()
in all cases */
if((sc->c_flags & DS_CLOSED) ||
!(sc->c_flags & DS_OPEN)){
if(dsdebug)
printf("ds: wakeup unopen\n");
u.u_error = EIO;
dscleanup(unit);
return;
}
break;
default:
printf("ds: %x from tsleep\n",ts);
dscleanup(unit);
u.u_error = EIO;
return;
}
}
splx(ps);
ps = spl6();
/*
* If device is IDLE (initial read/write, or datalate condition
* has been detected in dsintr()), (re)initialize dsc
*/
if (sc->c_flags & DS_IDLE) {
if(dsdebug)
printf("I1 ");
dsaddr->asccsr = sc->c_asccsr = sc->c_ascflags;
dummy = dsaddr->ascrst;
dsaddr->asccsr = (sc->c_asccsr |= ASC_IE);
dsaddr->ascsrt = sc->c_ascsrt;
{register j, i = 0;
do {
dsaddr->ascseq[i] = sc->c_ascseq[i];
j = i++;
} while(!(sc->c_ascseq[j] & LAST_SEQ) && i<8);
}
dsaddr->dmacsr = sc->c_dmacsr = 0;
dsaddr->dmacls = 0;
dummy = dsaddr->dmasar; /* clears sfl flag */
dsaddr->dmawc = -1;
dsaddr->dmacsr = sc->c_dmacsr = (DMA_IE | DMA_CHN
| (rw == B_READ ? DMA_W2M : 0) );
sc->c_bufno = sc->c_outbufno = 0;
sc->c_ibp = sc->c_obp = &sc->c_dsb[0]; /* correct? */
}
/* get next device buffer and set it up */
bp = sc->c_ibp++;
if (sc->c_ibp > &sc->c_dsb[NDSB-1])
sc->c_ibp = &sc->c_dsb[0];
/* hopefully redundant check against going to fast */
if(bp->b_flags & B_BUSY){
printf("dsstart: about to set up BUSY buffer!\n");
u.u_error = EIO;
return;
}
c = MIN(count, 1024*64);
bp->b_un.b_addr = base;
bp->b_error = 0;
bp->b_proc = u.u_procp;
bp->b_dev = dev;
bp->b_blkno = sc->c_bufno;
bp->b_bcount = c;
bufno = sc->c_bufno % NDSB;
/* the page computations should be relative to param.h defs */
sc->c_pageinfo[bufno].firstunit = (int)base >> 10;
sc->c_pageinfo[bufno].lastunit=(((int)base+c+1023)>>10)-1;
for(i=0;i<NDSB;i++)
if((sc->c_dsb[i].b_flags & B_BUSY)
&&
(!(sc->c_pageinfo[bufno].firstunit >
sc->c_pageinfo[i].lastunit)
&&
!(sc->c_pageinfo[bufno].lastunit <
sc->c_pageinfo[i].firstunit))) {
printf("ds: buf %d overlaps %d\n",i,bufno);
u.u_error=EIO;
return;
}
/* lock the buffer and send it off */
bp->b_flags = B_BUSY | B_PHYS | rw;
if(dsdebug)printf("lk%d %x %d ",bufno,base,c);
dslock(base, (int) c); /* fasten seat belts */
sc->c_ubinfo[bufno] = ubasetup(ui->ui_ubanum, bp, UBA_WANTBDP);
dsaddr->dmablr = ~ (c >> 1);
dsaddr->dmasax = (sc->c_ubinfo[bufno] >> 16) & 03;
dsaddr->dmasar = sc->c_ubinfo[bufno];
sc->c_bufno++;
/*
* start the dsc, if necessary
*/
if(sc->c_flags & DS_IDLE){
if(dsdebug)printf("I2 ");
sc->c_flags &= ~DS_IDLE;
++sc->c_to_active;
dsaddr->asccsr = (sc->c_asccsr |= ASC_RUN);
}
splx(ps);
base += c;
count -= c;
if(dsdebug)printf("LB%x",u.u_error);
}
u.u_count = count;
}
dsdb(dsaddr)
register struct dsdevice *dsaddr;
{
printf("dmacsr %b\n", dsaddr->dmacsr, DMA_BITS);
printf("asccsr %b\n", dsaddr->asccsr, ASC_BITS);
printf("dmawc %o\t", dsaddr->dmawc);
printf("dmablr %o\n", dsaddr->dmablr);
printf("dmaac %o\t", dsaddr->dmaac);
printf("dmasar %o\n", dsaddr->dmasar);
printf("dmaacx %o\t", dsaddr->dmaacx);
printf("dmasax %o\n", dsaddr->dmasax);
printf("ascsrt(decimal) %d\n", dsaddr->ascsrt);
printf("ascseq[0] %o\n", dsaddr->ascseq[0]);
}
/*
* this is where the real work is done. we copy any device registers that
* we will be looking at to decrease the amount of traffic on the ds 200
* bus.
*
*/
dsintr(dev)
dev_t dev;
{
register struct dsdevice *dsaddr;
register struct uba_device *ui;
register struct ds_softc *sc;
register struct buf *bp;
register int bufno;
register int i;
int unit, dummy;
unit = minor(dev) & ~RESETDEV;
sc = &ds_softc[unit];
ui = dsdinfo[unit];
dsaddr = (struct dsdevice *) dsdinfo[unit]->ui_addr;
sc->c_dmacsr = dsaddr->dmacsr;
dsaddr->dmacls = 0;
if(dsdebug)printf("i");
if (sc->c_flags & DS_IDLE) {
printf("ds%d: interrupt while idle\n", unit);
return;
}
if (sc->c_dmacsr & DMA_ERR) {
if(dsdebug)printf("e");
sc->c_asccsr = (sc->c_dmacsr & DMA_XIN ? dsaddr->asccsr : 0);
dsaddr->asccsr = dummy = 0;
dsaddr->dmacsr = (sc->c_dmacsr &= ~DMA_CHN);
if ((sc->c_dmacsr & (DMA_XER|DMA_UBA|DMA_AMPE|DMA_XBA))
|| (sc->c_asccsr & (ASC_BA|ASC_DCN|ASC_DNP))) {
++sc->c_errs;
printf("ds%d error: asccsr=%b dmacsr=%b\n",
unit, sc->c_asccsr, ASC_BITS,
sc->c_dmacsr, DMA_BITS);
} else
sc->c_nbytes += sc->c_obp->b_bcount;
/* the above may be wrong, since DLT interrupt seems to occur
* separately from (and later than) DMA completion
* interrupt */
dscleanup(unit);
return;
}
/*
* get current buffer and release it
*/
bp = sc->c_obp++;
if (sc->c_obp > &sc->c_dsb[NDSB-1])
sc->c_obp = &sc->c_dsb[0];
sc->c_outbufno++;
if(dsdebug)printf("b ");
dsrelease(sc, ui, bp);
/*
* update byte count.
*/
sc->c_nbytes += bp->b_bcount;
wakeup((caddr_t) &ds_softc[unit]);
}
/*
* release resources, if any, associated with a buffer
*/
dsrelease(sc, ui, bp)
register struct ds_softc *sc;
struct uba_device *ui;
register struct buf *bp;
{
register int ps;
register struct pte *pte;
register int npf;
int bufno;
bufno = bp->b_blkno % NDSB;
if(dsdebug)printf("R%d ",bufno);
/*
* release uba resources
* and memory resources if process seems healthy
*/
ps = spl6();
if (bp->b_flags & B_BUSY) {
if(dsdebug)printf("%x %d ",bp->b_un.b_addr,bp->b_bcount);
ubarelse(ui->ui_ubanum, &sc->c_ubinfo[bufno]);
/* we can't call vsunlock() because u.u_procp may be
different */
if( !(sc->c_pid == sc->c_procp->p_pid) ||
(sc->c_procp->p_flag & SWEXIT) ||
(sc->c_procp->p_stat == SZOMB)){
/* process is dying or dead */
/* exit() will release memory (does it unlock???) */
/* but will not release uba resources */
printf(" REL pid %d %d flag %x stat %x ",sc->c_pid,
sc->c_procp->p_pid,sc->c_procp->p_flag,
sc->c_procp->p_stat);
sc->c_flags |= DS_CLOSED;
}
else {
pte = vtopte(sc->c_procp,btop(bp->b_un.b_addr));
npf = btoc(bp->b_bcount + ((int)(bp->b_un.b_addr)&CLOFSET));
if(dsdebug)printf("U%x %d ",pte->pg_pfnum,npf);
while(npf > 0) {
munlock(pte->pg_pfnum);
if(sc->c_ascflags & ASC_RECORD)
pte->pg_m = 1; /* memory written */
pte += CLSIZE;
npf -= CLSIZE;
}
}
bp->b_flags = 0; /* better than resetting B_BUSY */
}
splx(ps);
}
/*
* release all buffers and do general cleanup
*/
dscleanup(unit)
int unit;
{
register struct dsdevice *dsaddr;
register struct uba_device *ui;
register struct ds_softc *sc;
register struct buf *bp;
int dummy;
unit = (unit & ~RESETDEV);
sc = &ds_softc[unit];
ui = dsdinfo[unit];
dsaddr = (struct dsdevice *) dsdinfo[unit]->ui_addr;
if(dsdebug)printf("C ");
if (!(sc->c_flags & DS_IDLE))
++sc->c_to_idle;
sc->c_flags |= DS_IDLE;
dsaddr->asccsr = dummy = 0;
dummy = dsaddr->ascrst;
dsaddr->dmacsr = dummy = 0;
dummy = dsaddr->dmasar;
for (bp = &(sc->c_dsb[0]); bp < &(sc->c_dsb[NDSB]); ++bp)
dsrelease(sc, ui, bp);
/* if called from dsintr while dsstart is sleeping */
wakeup((caddr_t) &ds_softc[unit]);
}
/*
* a/d conversion
*/
dsread(dev)
dev_t dev;
{
dsstart(dev, B_READ); /* writes on disk */
}
/*
* d/a conversion
*/
dswrite(dev)
dev_t dev;
{
dsstart(dev, B_WRITE); /* reads from disk */
}
/* ARGSUSED */
dsioctl(dev, cmd, addr, flag)
dev_t dev;
caddr_t addr;
{
register struct dsdevice *dsaddr;
register struct ds_softc *sc;
register struct ds_seq *dq;
register struct ds_err *de;
register struct ds_trans *dt;
struct uba_device *ui;
struct ds_seq ds_seq;
struct ds_err ds_err;
struct ds_trans ds_trans;
int unit;
int flts;
int i;
int iarg[2];
if (minor(dev) & RESETDEV) {
u.u_error = EINVAL;
return;
}
unit = minor(dev) & ~RESETDEV;
sc = &ds_softc[unit];
ui = dsdinfo[unit];
dsaddr = (struct dsdevice *) ui->ui_addr;
switch (cmd) {
/* set sample rate */
case DSRATE:
if (copyin(addr, (caddr_t) iarg, (unsigned) sizeof(int))) {
u.u_error = EFAULT;
return;
}
sc->c_ascsrt = 4000000/iarg[0] - 1;
break;
case DS08KHZ:
sc->c_ascflags &= ~ ASC_HZMSK;
sc->c_ascflags |= ASC_HZ08; /* set 8kHz filter */
break;
case DS04KHZ:
sc->c_ascflags &= ~ ASC_HZMSK;
sc->c_ascflags |= ASC_HZ04; /* set 4kHz filter */
break;
case DSBYPAS:
sc->c_ascflags &= ~ ASC_HZMSK;
sc->c_ascflags |= ASC_BYPASS; /* set bypass */
break;
/* fetch errors */
case DSERRS:
de = &ds_err;
de->dma_csr = sc->c_dmacsr;
de->asc_csr = sc->c_asccsr;
de->errors = sc->c_errs;
if (copyout((caddr_t) de, addr, (unsigned) sizeof(struct ds_err))) {
u.u_error = EFAULT;
return;
}
break;
/* fetch transition counts */
case DSTRANS:
dt = &ds_trans;
dt->to_idle = sc->c_to_idle;
dt->to_active = sc->c_to_active;
if (copyout((caddr_t) dt, addr, sizeof(struct ds_trans))) {
u.u_error = EFAULT;
return;
}
break;
/* how many samples actually converted */
case DSDONE:
if (copyout((caddr_t) sc->c_nbytes, addr, (unsigned) sizeof(int))) {
u.u_error = EFAULT;
return;
}
break;
case DSSTEREO:
while(!sc->c_flags & DS_IDLE);
if (sc->c_flags & DS_READ) {
dsseq(sc, 0, ADBASE, AD);
dsseq(sc, 1, ADBASE+1 | LAST_SEQ, AD);
} else {
dsseq(sc, 0, DABASE, DA);
dsseq(sc, 1, DABASE+1 | LAST_SEQ, DA);
}
break;
case DSMONO:
while(!sc->c_flags & DS_IDLE);
if (sc->c_flags & DS_READ)
dsseq(sc, 0, ADBASE | LAST_SEQ, AD);
else
dsseq(sc, 0, DABASE | LAST_SEQ, DA);
break;
case DSRESET:
/* not adequate */
sc->c_flags = DS_CLOSED | DS_IDLE;
dscleanup(unit);
break;
case DSDEBUG:
dsdebug = 1 - dsdebug;
break;
case DSWAIT:
while(sc->c_outbufno != sc->c_bufno
&& !(sc->c_flags & DS_IDLE))
tsleep((caddr_t)&ds_softc[unit],DSPRI,0);
break;
default:
u.u_error = ENOTTY;
break;
}
}
/*
* zero uba vector.
* shut off converters.
* set error bit.
*/
dsreset(uban) {
register struct uba_device *ui;
register struct ds_softc *sc;
register int ds;
for (ds = 0; ds < NDS; ds++) {
if ((ui = dsdinfo[ds]) == NULL)
continue;
if (ui->ui_alive == 0)
continue;
if (ui->ui_ubanum != uban)
continue;
printf(" ds%d", ds);
sc = &ds_softc[ds];
/*
* release unibus resources
*/
sc->c_flags = DS_CLOSED | DS_IDLE;
dscleanup(ds);
}
}
/*
equivalent to vslock() from vmmem.c
inserted differently here for debugging convenience only.
*/
dslock(base, count)
caddr_t base;
{
register unsigned v;
register int npf;
register struct pte *pte;
u.u_procp->p_flag |= SDLYU;
v = btop(base);
pte = vtopte(u.u_procp, v);
npf = btoc(count + ((int)base & CLOFSET));
if(dsdebug)printf("Lk %x %d ",pte->pg_pfnum,npf);
while (npf > 0) {
if (pte->pg_v)
mlock(pte->pg_pfnum);
else
if (fubyte((caddr_t)ctob(v)) < 0)
panic("vslock");
pte += CLSIZE;
v += CLSIZE;
npf -= CLSIZE;
}
u.u_procp->p_flag &= ~SDLYU;
}
# endif