Import 4.4BSD-Lite for reference
This commit is contained in:
parent
77eeaedfe8
commit
b50e39fa45
72
sys/conf/systags.sh
Normal file
72
sys/conf/systags.sh
Normal file
@ -0,0 +1,72 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Copyright (c) 1992, 1993
|
||||
# The Regents of the University of California. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. All advertising materials mentioning features or use of this software
|
||||
# must display the following acknowledgement:
|
||||
# This product includes software developed by the University of
|
||||
# California, Berkeley and its contributors.
|
||||
# 4. Neither the name of the University nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# @(#)systags.sh 8.1 (Berkeley) 6/10/93
|
||||
#
|
||||
# systags.sh - construct a system tags file using dependence relations
|
||||
# in a .depend file
|
||||
#
|
||||
# First written May 16, 1992 by Van Jacobson, Lawrence Berkeley Laboratory.
|
||||
#
|
||||
# from: $Header: /cvsroot/src/sys/conf/Attic/systags.sh,v 1.1.1.1 1998/03/01 02:09:33 fvdl Exp $
|
||||
|
||||
rm -f tags tags.tmp tags.cfiles tags.sfiles tags.hfiles
|
||||
MACHINE=`machine`
|
||||
sed -e "s,\./machine/,../../$MACHINE/include/,g" \
|
||||
-e 's,[a-z][^/ ]*/\.\./,,g' .depend | awk '{
|
||||
for (i = 1; i <= NF; ++i) {
|
||||
t = substr($i, length($i) - 1)
|
||||
if (t == ".c")
|
||||
cfiles[$i] = 1;
|
||||
else if (t == ".h")
|
||||
hfiles[$i] = 1;
|
||||
else if (t == ".s")
|
||||
sfiles[$i] = 1;
|
||||
}
|
||||
};
|
||||
END {
|
||||
for (i in cfiles)
|
||||
print i > "tags.cfiles";
|
||||
for (i in sfiles)
|
||||
print i > "tags.sfiles";
|
||||
for (i in hfiles)
|
||||
print i > "tags.hfiles";
|
||||
}'
|
||||
|
||||
ctags -t -d -w `cat tags.cfiles tags.hfiles tags.sfiles`
|
||||
egrep -o "^ENTRY\(.*\)|^ALTENTRY\(.*\)" `cat tags.sfiles` | \
|
||||
sed "s;\([^:]*\):\([^(]*\)(\([^, )]*\)\(.*\);\3 \1 /^\2(\3\4$/;" >> tags
|
||||
|
||||
mv tags tags.tmp
|
||||
sort -u tags.tmp > tags
|
||||
rm tags.tmp tags.cfiles tags.sfiles tags.hfiles
|
709
sys/dev/cd.c
Normal file
709
sys/dev/cd.c
Normal file
@ -0,0 +1,709 @@
|
||||
/*
|
||||
* Copyright (c) 1988 University of Utah.
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Systems Programming Group of the University of Utah Computer
|
||||
* Science Department.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: Utah $Hdr: cd.c 1.6 90/11/28$
|
||||
*
|
||||
* @(#)cd.c 8.2 (Berkeley) 11/16/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* "Concatenated" disk driver.
|
||||
*/
|
||||
#include "cd.h"
|
||||
#if NCD > 0
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/dkstat.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef COMPAT_NOLABEL
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <dev/cdvar.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
int cddebug = 0x00;
|
||||
#define CDB_FOLLOW 0x01
|
||||
#define CDB_INIT 0x02
|
||||
#define CDB_IO 0x04
|
||||
#endif
|
||||
|
||||
struct buf *cdbuffer();
|
||||
char *cddevtostr();
|
||||
void cdiodone();
|
||||
|
||||
#define cdunit(x) ((minor(x) >> 3) & 0xf) /* for consistency */
|
||||
|
||||
#define getcbuf() \
|
||||
((struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK))
|
||||
#define putcbuf(bp) \
|
||||
free((caddr_t)(bp), M_DEVBUF)
|
||||
|
||||
struct cd_softc {
|
||||
int sc_flags; /* flags */
|
||||
size_t sc_size; /* size of cd */
|
||||
int sc_ileave; /* interleave */
|
||||
int sc_ncdisks; /* number of components */
|
||||
struct cdcinfo sc_cinfo[NCDISKS]; /* component info */
|
||||
struct cdiinfo *sc_itable; /* interleave table */
|
||||
int sc_usecnt; /* number of requests active */
|
||||
int sc_dk; /* disk index */
|
||||
};
|
||||
|
||||
/* sc_flags */
|
||||
#define CDF_ALIVE 0x01
|
||||
#define CDF_INITED 0x02
|
||||
|
||||
struct cd_softc *cd_softc;
|
||||
int numcd;
|
||||
|
||||
/*
|
||||
* Since this is called after auto-configuration of devices,
|
||||
* we can handle the initialization here.
|
||||
*
|
||||
* XXX this will not work if you want to use a cd as your primary
|
||||
* swap device since swapconf() has been called before now.
|
||||
*/
|
||||
void
|
||||
cdattach(num)
|
||||
int num;
|
||||
{
|
||||
char *mem;
|
||||
register u_long size;
|
||||
register struct cddevice *cd;
|
||||
extern int dkn;
|
||||
|
||||
if (num <= 0)
|
||||
return;
|
||||
size = num * sizeof(struct cd_softc);
|
||||
mem = malloc(size, M_DEVBUF, M_NOWAIT);
|
||||
if (mem == NULL) {
|
||||
printf("WARNING: no memory for concatonated disks\n");
|
||||
return;
|
||||
}
|
||||
bzero(mem, size);
|
||||
cd_softc = (struct cd_softc *)mem;
|
||||
numcd = num;
|
||||
for (cd = cddevice; cd->cd_unit >= 0; cd++) {
|
||||
/*
|
||||
* XXX
|
||||
* Assign disk index first so that init routine
|
||||
* can use it (saves having the driver drag around
|
||||
* the cddevice pointer just to set up the dk_*
|
||||
* info in the open routine).
|
||||
*/
|
||||
if (dkn < DK_NDRIVE)
|
||||
cd->cd_dk = dkn++;
|
||||
else
|
||||
cd->cd_dk = -1;
|
||||
if (cdinit(cd))
|
||||
printf("cd%d configured\n", cd->cd_unit);
|
||||
else if (cd->cd_dk >= 0) {
|
||||
cd->cd_dk = -1;
|
||||
dkn--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cdinit(cd)
|
||||
struct cddevice *cd;
|
||||
{
|
||||
register struct cd_softc *cs = &cd_softc[cd->cd_unit];
|
||||
register struct cdcinfo *ci;
|
||||
register size_t size;
|
||||
register int ix;
|
||||
size_t minsize;
|
||||
dev_t dev;
|
||||
struct bdevsw *bsw;
|
||||
int error;
|
||||
struct proc *p = curproc; /* XXX */
|
||||
|
||||
#ifdef DEBUG
|
||||
if (cddebug & (CDB_FOLLOW|CDB_INIT))
|
||||
printf("cdinit: unit %d\n", cd->cd_unit);
|
||||
#endif
|
||||
cs->sc_dk = cd->cd_dk;
|
||||
cs->sc_size = 0;
|
||||
cs->sc_ileave = cd->cd_interleave;
|
||||
cs->sc_ncdisks = 0;
|
||||
/*
|
||||
* Verify that each component piece exists and record
|
||||
* relevant information about it.
|
||||
*/
|
||||
minsize = 0;
|
||||
for (ix = 0; ix < NCDISKS; ix++) {
|
||||
if ((dev = cd->cd_dev[ix]) == NODEV)
|
||||
break;
|
||||
ci = &cs->sc_cinfo[ix];
|
||||
ci->ci_dev = dev;
|
||||
bsw = &bdevsw[major(dev)];
|
||||
/*
|
||||
* Open the partition
|
||||
*/
|
||||
if (bsw->d_open &&
|
||||
(error = (*bsw->d_open)(dev, 0, S_IFBLK, p))) {
|
||||
printf("cd%d: component %s open failed, error = %d\n",
|
||||
cd->cd_unit, cddevtostr(dev), error);
|
||||
return(0);
|
||||
}
|
||||
/*
|
||||
* Calculate size (truncated to interleave boundary
|
||||
* if necessary.
|
||||
*/
|
||||
if (bsw->d_psize) {
|
||||
size = (size_t) (*bsw->d_psize)(dev);
|
||||
if ((int)size < 0)
|
||||
size = 0;
|
||||
} else
|
||||
size = 0;
|
||||
if (cs->sc_ileave > 1)
|
||||
size -= size % cs->sc_ileave;
|
||||
if (size == 0) {
|
||||
printf("cd%d: not configured (component %s missing)\n",
|
||||
cd->cd_unit, cddevtostr(dev));
|
||||
return(0);
|
||||
}
|
||||
#ifdef COMPAT_NOLABEL
|
||||
/*
|
||||
* XXX if this is a 'c' partition then we need to mark the
|
||||
* label area writeable since there cannot be a label.
|
||||
*/
|
||||
if ((minor(dev) & 7) == 2 && bsw->d_open) {
|
||||
int i, flag;
|
||||
|
||||
for (i = 0; i < nchrdev; i++)
|
||||
if (cdevsw[i].d_open == bsw->d_open)
|
||||
break;
|
||||
if (i != nchrdev && cdevsw[i].d_ioctl) {
|
||||
flag = 1;
|
||||
(void)(*cdevsw[i].d_ioctl)(dev, DIOCWLABEL,
|
||||
(caddr_t)&flag, FWRITE, p);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (minsize == 0 || size < minsize)
|
||||
minsize = size;
|
||||
ci->ci_size = size;
|
||||
cs->sc_size += size;
|
||||
cs->sc_ncdisks++;
|
||||
}
|
||||
/*
|
||||
* If uniform interleave is desired set all sizes to that of
|
||||
* the smallest component.
|
||||
*/
|
||||
if (cd->cd_flags & CDF_UNIFORM) {
|
||||
for (ci = cs->sc_cinfo;
|
||||
ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++)
|
||||
ci->ci_size = minsize;
|
||||
cs->sc_size = cs->sc_ncdisks * minsize;
|
||||
}
|
||||
/*
|
||||
* Construct the interleave table
|
||||
*/
|
||||
if (!cdinterleave(cs))
|
||||
return(0);
|
||||
if (cd->cd_dk >= 0)
|
||||
dk_wpms[cd->cd_dk] = 32 * (60 * DEV_BSIZE / 2); /* XXX */
|
||||
printf("cd%d: %d components ", cd->cd_unit, cs->sc_ncdisks);
|
||||
for (ix = 0; ix < cs->sc_ncdisks; ix++)
|
||||
printf("%c%s%c",
|
||||
ix == 0 ? '(' : ' ',
|
||||
cddevtostr(cs->sc_cinfo[ix].ci_dev),
|
||||
ix == cs->sc_ncdisks - 1 ? ')' : ',');
|
||||
printf(", %d blocks ", cs->sc_size);
|
||||
if (cs->sc_ileave)
|
||||
printf("interleaved at %d blocks\n", cs->sc_ileave);
|
||||
else
|
||||
printf("concatenated\n");
|
||||
cs->sc_flags = CDF_ALIVE | CDF_INITED;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX not really cd specific.
|
||||
* Could be called something like bdevtostr in machine/conf.c.
|
||||
*/
|
||||
char *
|
||||
cddevtostr(dev)
|
||||
dev_t dev;
|
||||
{
|
||||
static char dbuf[5];
|
||||
|
||||
switch (major(dev)) {
|
||||
#ifdef hp300
|
||||
case 2:
|
||||
dbuf[0] = 'r'; dbuf[1] = 'd';
|
||||
break;
|
||||
case 4:
|
||||
dbuf[0] = 's'; dbuf[1] = 'd';
|
||||
break;
|
||||
case 5:
|
||||
dbuf[0] = 'c'; dbuf[1] = 'd';
|
||||
break;
|
||||
case 6:
|
||||
dbuf[0] = 'v'; dbuf[1] = 'n';
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
dbuf[0] = dbuf[1] = '?';
|
||||
break;
|
||||
}
|
||||
dbuf[2] = (minor(dev) >> 3) + '0';
|
||||
dbuf[3] = (minor(dev) & 7) + 'a';
|
||||
dbuf[4] = '\0';
|
||||
return (dbuf);
|
||||
}
|
||||
|
||||
cdinterleave(cs)
|
||||
register struct cd_softc *cs;
|
||||
{
|
||||
register struct cdcinfo *ci, *smallci;
|
||||
register struct cdiinfo *ii;
|
||||
register daddr_t bn, lbn;
|
||||
register int ix;
|
||||
u_long size;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (cddebug & CDB_INIT)
|
||||
printf("cdinterleave(%x): ileave %d\n", cs, cs->sc_ileave);
|
||||
#endif
|
||||
/*
|
||||
* Allocate an interleave table.
|
||||
* Chances are this is too big, but we don't care.
|
||||
*/
|
||||
size = (cs->sc_ncdisks + 1) * sizeof(struct cdiinfo);
|
||||
cs->sc_itable = (struct cdiinfo *)malloc(size, M_DEVBUF, M_WAITOK);
|
||||
bzero((caddr_t)cs->sc_itable, size);
|
||||
/*
|
||||
* Trivial case: no interleave (actually interleave of disk size).
|
||||
* Each table entry represent a single component in its entirety.
|
||||
*/
|
||||
if (cs->sc_ileave == 0) {
|
||||
bn = 0;
|
||||
ii = cs->sc_itable;
|
||||
for (ix = 0; ix < cs->sc_ncdisks; ix++) {
|
||||
ii->ii_ndisk = 1;
|
||||
ii->ii_startblk = bn;
|
||||
ii->ii_startoff = 0;
|
||||
ii->ii_index[0] = ix;
|
||||
bn += cs->sc_cinfo[ix].ci_size;
|
||||
ii++;
|
||||
}
|
||||
ii->ii_ndisk = 0;
|
||||
#ifdef DEBUG
|
||||
if (cddebug & CDB_INIT)
|
||||
printiinfo(cs->sc_itable);
|
||||
#endif
|
||||
return(1);
|
||||
}
|
||||
/*
|
||||
* The following isn't fast or pretty; it doesn't have to be.
|
||||
*/
|
||||
size = 0;
|
||||
bn = lbn = 0;
|
||||
for (ii = cs->sc_itable; ; ii++) {
|
||||
/*
|
||||
* Locate the smallest of the remaining components
|
||||
*/
|
||||
smallci = NULL;
|
||||
for (ci = cs->sc_cinfo;
|
||||
ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++)
|
||||
if (ci->ci_size > size &&
|
||||
(smallci == NULL ||
|
||||
ci->ci_size < smallci->ci_size))
|
||||
smallci = ci;
|
||||
/*
|
||||
* Nobody left, all done
|
||||
*/
|
||||
if (smallci == NULL) {
|
||||
ii->ii_ndisk = 0;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Record starting logical block and component offset
|
||||
*/
|
||||
ii->ii_startblk = bn / cs->sc_ileave;
|
||||
ii->ii_startoff = lbn;
|
||||
/*
|
||||
* Determine how many disks take part in this interleave
|
||||
* and record their indices.
|
||||
*/
|
||||
ix = 0;
|
||||
for (ci = cs->sc_cinfo;
|
||||
ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++)
|
||||
if (ci->ci_size >= smallci->ci_size)
|
||||
ii->ii_index[ix++] = ci - cs->sc_cinfo;
|
||||
ii->ii_ndisk = ix;
|
||||
bn += ix * (smallci->ci_size - size);
|
||||
lbn = smallci->ci_size / cs->sc_ileave;
|
||||
size = smallci->ci_size;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (cddebug & CDB_INIT)
|
||||
printiinfo(cs->sc_itable);
|
||||
#endif
|
||||
return(1);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printiinfo(ii)
|
||||
struct cdiinfo *ii;
|
||||
{
|
||||
register int ix, i;
|
||||
|
||||
for (ix = 0; ii->ii_ndisk; ix++, ii++) {
|
||||
printf(" itab[%d]: #dk %d sblk %d soff %d",
|
||||
ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff);
|
||||
for (i = 0; i < ii->ii_ndisk; i++)
|
||||
printf(" %d", ii->ii_index[i]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
cdopen(dev, flags)
|
||||
dev_t dev;
|
||||
{
|
||||
int unit = cdunit(dev);
|
||||
register struct cd_softc *cs = &cd_softc[unit];
|
||||
|
||||
#ifdef DEBUG
|
||||
if (cddebug & CDB_FOLLOW)
|
||||
printf("cdopen(%x, %x)\n", dev, flags);
|
||||
#endif
|
||||
if (unit >= numcd || (cs->sc_flags & CDF_ALIVE) == 0)
|
||||
return(ENXIO);
|
||||
return(0);
|
||||
}
|
||||
|
||||
cdstrategy(bp)
|
||||
register struct buf *bp;
|
||||
{
|
||||
register int unit = cdunit(bp->b_dev);
|
||||
register struct cd_softc *cs = &cd_softc[unit];
|
||||
register daddr_t bn;
|
||||
register int sz, s;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (cddebug & CDB_FOLLOW)
|
||||
printf("cdstrategy(%x): unit %d\n", bp, unit);
|
||||
#endif
|
||||
if ((cs->sc_flags & CDF_INITED) == 0) {
|
||||
bp->b_error = ENXIO;
|
||||
bp->b_flags |= B_ERROR;
|
||||
goto done;
|
||||
}
|
||||
bn = bp->b_blkno;
|
||||
sz = howmany(bp->b_bcount, DEV_BSIZE);
|
||||
if (bn < 0 || bn + sz > cs->sc_size) {
|
||||
sz = cs->sc_size - bn;
|
||||
if (sz == 0) {
|
||||
bp->b_resid = bp->b_bcount;
|
||||
goto done;
|
||||
}
|
||||
if (sz < 0) {
|
||||
bp->b_error = EINVAL;
|
||||
bp->b_flags |= B_ERROR;
|
||||
goto done;
|
||||
}
|
||||
bp->b_bcount = dbtob(sz);
|
||||
}
|
||||
bp->b_resid = bp->b_bcount;
|
||||
/*
|
||||
* "Start" the unit.
|
||||
*/
|
||||
s = splbio();
|
||||
cdstart(cs, bp);
|
||||
splx(s);
|
||||
return;
|
||||
done:
|
||||
biodone(bp);
|
||||
}
|
||||
|
||||
cdstart(cs, bp)
|
||||
register struct cd_softc *cs;
|
||||
register struct buf *bp;
|
||||
{
|
||||
register long bcount, rcount;
|
||||
struct buf *cbp;
|
||||
caddr_t addr;
|
||||
daddr_t bn;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (cddebug & CDB_FOLLOW)
|
||||
printf("cdstart(%x, %x)\n", cs, bp);
|
||||
#endif
|
||||
/*
|
||||
* Instumentation (not real meaningful)
|
||||
*/
|
||||
cs->sc_usecnt++;
|
||||
if (cs->sc_dk >= 0) {
|
||||
dk_busy |= 1 << cs->sc_dk;
|
||||
dk_xfer[cs->sc_dk]++;
|
||||
dk_wds[cs->sc_dk] += bp->b_bcount >> 6;
|
||||
}
|
||||
/*
|
||||
* Allocate component buffers and fire off the requests
|
||||
*/
|
||||
bn = bp->b_blkno;
|
||||
addr = bp->b_data;
|
||||
for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) {
|
||||
cbp = cdbuffer(cs, bp, bn, addr, bcount);
|
||||
rcount = cbp->b_bcount;
|
||||
(*bdevsw[major(cbp->b_dev)].d_strategy)(cbp);
|
||||
bn += btodb(rcount);
|
||||
addr += rcount;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Build a component buffer header.
|
||||
*/
|
||||
struct buf *
|
||||
cdbuffer(cs, bp, bn, addr, bcount)
|
||||
register struct cd_softc *cs;
|
||||
struct buf *bp;
|
||||
daddr_t bn;
|
||||
caddr_t addr;
|
||||
long bcount;
|
||||
{
|
||||
register struct cdcinfo *ci;
|
||||
register struct buf *cbp;
|
||||
register daddr_t cbn, cboff;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (cddebug & CDB_IO)
|
||||
printf("cdbuffer(%x, %x, %d, %x, %d)\n",
|
||||
cs, bp, bn, addr, bcount);
|
||||
#endif
|
||||
/*
|
||||
* Determine which component bn falls in.
|
||||
*/
|
||||
cbn = bn;
|
||||
cboff = 0;
|
||||
/*
|
||||
* Serially concatenated
|
||||
*/
|
||||
if (cs->sc_ileave == 0) {
|
||||
register daddr_t sblk;
|
||||
|
||||
sblk = 0;
|
||||
for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++)
|
||||
sblk += ci->ci_size;
|
||||
cbn -= sblk;
|
||||
}
|
||||
/*
|
||||
* Interleaved
|
||||
*/
|
||||
else {
|
||||
register struct cdiinfo *ii;
|
||||
int cdisk, off;
|
||||
|
||||
cboff = cbn % cs->sc_ileave;
|
||||
cbn /= cs->sc_ileave;
|
||||
for (ii = cs->sc_itable; ii->ii_ndisk; ii++)
|
||||
if (ii->ii_startblk > cbn)
|
||||
break;
|
||||
ii--;
|
||||
off = cbn - ii->ii_startblk;
|
||||
if (ii->ii_ndisk == 1) {
|
||||
cdisk = ii->ii_index[0];
|
||||
cbn = ii->ii_startoff + off;
|
||||
} else {
|
||||
cdisk = ii->ii_index[off % ii->ii_ndisk];
|
||||
cbn = ii->ii_startoff + off / ii->ii_ndisk;
|
||||
}
|
||||
cbn *= cs->sc_ileave;
|
||||
ci = &cs->sc_cinfo[cdisk];
|
||||
}
|
||||
/*
|
||||
* Fill in the component buf structure.
|
||||
*/
|
||||
cbp = getcbuf();
|
||||
cbp->b_flags = bp->b_flags | B_CALL;
|
||||
cbp->b_iodone = cdiodone;
|
||||
cbp->b_proc = bp->b_proc;
|
||||
cbp->b_dev = ci->ci_dev;
|
||||
cbp->b_blkno = cbn + cboff;
|
||||
cbp->b_data = addr;
|
||||
cbp->b_vp = 0;
|
||||
if (cs->sc_ileave == 0)
|
||||
cbp->b_bcount = dbtob(ci->ci_size - cbn);
|
||||
else
|
||||
cbp->b_bcount = dbtob(cs->sc_ileave - cboff);
|
||||
if (cbp->b_bcount > bcount)
|
||||
cbp->b_bcount = bcount;
|
||||
/*
|
||||
* XXX context for cdiodone
|
||||
*/
|
||||
cbp->b_saveaddr = (caddr_t)bp;
|
||||
cbp->b_pfcent = ((cs - cd_softc) << 16) | (ci - cs->sc_cinfo);
|
||||
#ifdef DEBUG
|
||||
if (cddebug & CDB_IO)
|
||||
printf(" dev %x(u%d): cbp %x bn %d addr %x bcnt %d\n",
|
||||
ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->b_blkno,
|
||||
cbp->b_data, cbp->b_bcount);
|
||||
#endif
|
||||
return(cbp);
|
||||
}
|
||||
|
||||
cdintr(cs, bp)
|
||||
register struct cd_softc *cs;
|
||||
register struct buf *bp;
|
||||
{
|
||||
|
||||
#ifdef DEBUG
|
||||
if (cddebug & CDB_FOLLOW)
|
||||
printf("cdintr(%x, %x)\n", cs, bp);
|
||||
#endif
|
||||
/*
|
||||
* Request is done for better or worse, wakeup the top half.
|
||||
*/
|
||||
if (--cs->sc_usecnt == 0 && cs->sc_dk >= 0)
|
||||
dk_busy &= ~(1 << cs->sc_dk);
|
||||
if (bp->b_flags & B_ERROR)
|
||||
bp->b_resid = bp->b_bcount;
|
||||
biodone(bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by biodone at interrupt time.
|
||||
* Mark the component as done and if all components are done,
|
||||
* take a cd interrupt.
|
||||
*/
|
||||
void
|
||||
cdiodone(cbp)
|
||||
register struct buf *cbp;
|
||||
{
|
||||
register struct buf *bp = (struct buf *)cbp->b_saveaddr;/* XXX */
|
||||
register int unit = (cbp->b_pfcent >> 16) & 0xFFFF; /* XXX */
|
||||
int count, s;
|
||||
|
||||
s = splbio();
|
||||
#ifdef DEBUG
|
||||
if (cddebug & CDB_FOLLOW)
|
||||
printf("cdiodone(%x)\n", cbp);
|
||||
if (cddebug & CDB_IO) {
|
||||
printf("cdiodone: bp %x bcount %d resid %d\n",
|
||||
bp, bp->b_bcount, bp->b_resid);
|
||||
printf(" dev %x(u%d), cbp %x bn %d addr %x bcnt %d\n",
|
||||
cbp->b_dev, cbp->b_pfcent & 0xFFFF, cbp,
|
||||
cbp->b_blkno, cbp->b_data, cbp->b_bcount);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cbp->b_flags & B_ERROR) {
|
||||
bp->b_flags |= B_ERROR;
|
||||
bp->b_error = biowait(cbp);
|
||||
#ifdef DEBUG
|
||||
printf("cd%d: error %d on component %d\n",
|
||||
unit, bp->b_error, cbp->b_pfcent & 0xFFFF);
|
||||
#endif
|
||||
}
|
||||
count = cbp->b_bcount;
|
||||
putcbuf(cbp);
|
||||
|
||||
/*
|
||||
* If all done, "interrupt".
|
||||
*/
|
||||
bp->b_resid -= count;
|
||||
if (bp->b_resid < 0)
|
||||
panic("cdiodone: count");
|
||||
if (bp->b_resid == 0)
|
||||
cdintr(&cd_softc[unit], bp);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
cdread(dev, uio)
|
||||
dev_t dev;
|
||||
struct uio *uio;
|
||||
{
|
||||
register int unit = cdunit(dev);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (cddebug & CDB_FOLLOW)
|
||||
printf("cdread(%x, %x)\n", dev, uio);
|
||||
#endif
|
||||
return(physio(cdstrategy, NULL, dev, B_READ, minphys, uio));
|
||||
}
|
||||
|
||||
cdwrite(dev, uio)
|
||||
dev_t dev;
|
||||
struct uio *uio;
|
||||
{
|
||||
register int unit = cdunit(dev);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (cddebug & CDB_FOLLOW)
|
||||
printf("cdwrite(%x, %x)\n", dev, uio);
|
||||
#endif
|
||||
return(physio(cdstrategy, NULL, dev, B_WRITE, minphys, uio));
|
||||
}
|
||||
|
||||
cdioctl(dev, cmd, data, flag)
|
||||
dev_t dev;
|
||||
int cmd;
|
||||
caddr_t data;
|
||||
int flag;
|
||||
{
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
cdsize(dev)
|
||||
dev_t dev;
|
||||
{
|
||||
int unit = cdunit(dev);
|
||||
register struct cd_softc *cs = &cd_softc[unit];
|
||||
|
||||
if (unit >= numcd || (cs->sc_flags & CDF_INITED) == 0)
|
||||
return(-1);
|
||||
return(cs->sc_size);
|
||||
}
|
||||
|
||||
cddump(dev)
|
||||
{
|
||||
return(ENXIO);
|
||||
}
|
||||
#endif
|
104
sys/dev/cdvar.h
Normal file
104
sys/dev/cdvar.h
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 1988 University of Utah.
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Systems Programming Group of the University of Utah Computer
|
||||
* Science Department.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: Utah $Hdr: cdvar.h 1.1 90/07/09$
|
||||
*
|
||||
* @(#)cdvar.h 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
#define NCDISKS 8 /* max # of component disks */
|
||||
|
||||
/*
|
||||
* A concatenated disk is described at config time by this structure.
|
||||
*/
|
||||
struct cddevice {
|
||||
int cd_unit; /* logical unit of this cd */
|
||||
int cd_interleave; /* interleave (DEV_BSIZE blocks) */
|
||||
int cd_flags; /* misc. information */
|
||||
int cd_dk; /* disk number */
|
||||
dev_t cd_dev[NCDISKS]; /* component devices */
|
||||
};
|
||||
|
||||
/* cd_flags */
|
||||
#define CDF_SWAP 0x01 /* interleave should be dmmax */
|
||||
#define CDF_UNIFORM 0x02 /* use LCD of sizes for uniform interleave */
|
||||
|
||||
/*
|
||||
* Component info table.
|
||||
* Describes a single component of a concatenated disk.
|
||||
*/
|
||||
struct cdcinfo {
|
||||
dev_t ci_dev; /* devno */
|
||||
size_t ci_size; /* size */
|
||||
};
|
||||
|
||||
/*
|
||||
* Interleave description table.
|
||||
* Computed at boot time to speed irregular-interleave lookups.
|
||||
* The idea is that we interleave in "groups". First we interleave
|
||||
* evenly over all component disks up to the size of the smallest
|
||||
* component (the first group), then we interleave evenly over all
|
||||
* remaining disks up to the size of the next-smallest (second group),
|
||||
* and so on.
|
||||
*
|
||||
* Each table entry describes the interleave characteristics of one
|
||||
* of these groups. For example if a concatenated disk consisted of
|
||||
* three components of 5, 3, and 7 DEV_BSIZE blocks interleaved at
|
||||
* DEV_BSIZE (1), the table would have three entries:
|
||||
*
|
||||
* ndisk startblk startoff dev
|
||||
* 3 0 0 0, 1, 2
|
||||
* 2 9 3 0, 2
|
||||
* 1 13 5 2
|
||||
* 0 - - -
|
||||
*
|
||||
* which says that the first nine blocks (0-8) are interleaved over
|
||||
* 3 disks (0, 1, 2) starting at block offset 0 on any component disk,
|
||||
* the next 4 blocks (9-12) are interleaved over 2 disks (0, 2) starting
|
||||
* at component block 3, and the remaining blocks (13-14) are on disk
|
||||
* 2 starting at offset 5.
|
||||
*/
|
||||
struct cdiinfo {
|
||||
int ii_ndisk; /* # of disks range is interleaved over */
|
||||
daddr_t ii_startblk; /* starting scaled block # for range */
|
||||
daddr_t ii_startoff; /* starting component offset (block #) */
|
||||
char ii_index[NCDISKS];/* ordered list of components in range */
|
||||
};
|
||||
|
||||
#ifdef KERNEL
|
||||
extern struct cddevice cddevice[];
|
||||
#endif
|
384
sys/dev/scsi/disk.h
Normal file
384
sys/dev/scsi/disk.h
Normal file
@ -0,0 +1,384 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratories.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)disk.h 8.1 (Berkeley) 6/10/93
|
||||
*
|
||||
* from: $Header: /cvsroot/src/sys/dev/scsi/Attic/disk.h,v 1.1.1.1 1998/03/01 02:09:34 fvdl Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCSI definitions for Direct Access Devices (disks).
|
||||
* This includes WORMs and CD-ROMs (although a few commands, such as
|
||||
* format or write, are nonsensical on some).
|
||||
*
|
||||
* Commands defined in common headers (scsi.h or disktape.h) appear here
|
||||
* as comments.
|
||||
*/
|
||||
|
||||
/* group 0 */
|
||||
/* CMD_TEST_UNIT_READY 0x00 test unit ready */
|
||||
#define CMD_REZERO 0x01 /* rezero unit */
|
||||
/* CMD_REQUEST_SENSE 0x03 request sense */
|
||||
#define CMD_FORMAT_UNIT 0x04 /* format unit (disk) */
|
||||
#define CMD_REASSIGN_BLOCKS 0x07 /* reassign blocks (disk, WORM) */
|
||||
#define CMD_READ6 0x08 /* read (6 byte cdb) */
|
||||
#define CMD_WRITE6 0x0a /* write (6 byte cdb) */
|
||||
#define CMD_SEEK6 0x0b /* seek (6 byte cdb) */
|
||||
/* CMD_INQUIRY 0x12 inquiry */
|
||||
/* CMD_MODE_SELECT 0x15 mode select */
|
||||
#define CMD_RESERVE 0x16 /* reserve */
|
||||
#define CMD_RELEASE 0x17 /* release */
|
||||
/* CMD_COPY 0x18 copy */
|
||||
/* CMD_MODE_SENSE 0x1a mode sense */
|
||||
#define CMD_SSU 0x1b /* start/stop unit */
|
||||
/* CMD_RECEIVE_DIAG 0x1c receive diagnostic results */
|
||||
/* CMD_SEND_DIAG 0x1d send diagnostic */
|
||||
#define CMD_PAMR 0x1e /* prevent/allow medium removal */
|
||||
|
||||
/* group 1 */
|
||||
#define CMD_READ_CAPACITY 0x25 /* read capacity */
|
||||
#define CMD_READ10 0x28 /* read (10 byte cdb) */
|
||||
#define CMD_WRITE10 0x2a /* write (10 byte cdb) */
|
||||
#define CMD_SEEK10 0x2b /* write (10 byte cdb) */
|
||||
#define CMD_WRITE_VERIFY 0x2e /* write and verify */
|
||||
#define CMD_VERIFY 0x2f /* verify */
|
||||
#define CMD_SEARCH_H 0x30 /* search data high */
|
||||
#define CMD_SEARCH_E 0x31 /* search data equal */
|
||||
#define CMD_SEARCH_L 0x32 /* search data low */
|
||||
#define CMD_SET_LIMITS 0x33 /* set limits */
|
||||
/* CMD_COMPARE 0x39 compare */
|
||||
#define CMD_COPY_VERIFY 0x3a /* copy and verify */
|
||||
|
||||
/* this one is in van's but not in my 17B documents */
|
||||
#define CMD_READ_DEFECT_DATA 0x37 /* read defect data */ /* ??? */
|
||||
|
||||
/*
|
||||
* Structure of a FORMAT UNIT command (i.e., the cdb):
|
||||
* byte 0: opcode<8>
|
||||
* byte 1: lun<3> format_data<1> complete_list<1> defect_list_format<3>
|
||||
* byte 2: vendor unique
|
||||
* byte 3: interleave (MSB)
|
||||
* byte 4: interleave (LSB)
|
||||
* byte 5: control
|
||||
*/
|
||||
struct scsi_cdb_fu {
|
||||
u_char cdb_cmd; /* SCSI_CMD_FU */
|
||||
u_char cdb_lun_etc; /* lun+FD+CL+DLF */
|
||||
u_char cdb_vu; /* vendor unique */
|
||||
u_char cdb_ilvh; /* interleave (MSB) */
|
||||
u_char cdb_ilvl; /* interleave (LSB) */
|
||||
u_char cdb_ctrl; /* control byte */
|
||||
};
|
||||
|
||||
/*
|
||||
* If format data are supplied, they give either additional (cl=0) or
|
||||
* new (cl=1) defect list in one of the following formats.
|
||||
* Formats 1, 2, and 3 are the same as 0; formats 6 and 7 are
|
||||
* vendor unique and reserved, respectively. (The `backwards'
|
||||
* in `backwards compatible'...)
|
||||
*/
|
||||
#define SCSI_DLF_BLOCK 0 /* dlf = blocks */
|
||||
#define SCSI_DLF_BFI 4 /* dlf = bytes from index */
|
||||
#define SCSI_DLF_PS 5 /* dlf = physical sectors */
|
||||
|
||||
/*
|
||||
* Defect list header, block format (`defect block address').
|
||||
*
|
||||
* N.B.: this structure is also used for the Reassign Blocks command;
|
||||
* there the `defect block address' becomes a `defect logical block address'.
|
||||
*/
|
||||
struct scsi_dlf_dba {
|
||||
u_short dlf_xxx; /* reserved */
|
||||
u_char dlf_lenh, /* defect list length (MSB) */
|
||||
dlf_lenl; /* defect list length (LSB) */
|
||||
struct scsi_dlf_dba_desc {
|
||||
u_char dbah, /* defect block address (MSB) */
|
||||
dbahm, /* defect block address */
|
||||
dbalm, /* defect block address */
|
||||
dbal; /* defect block address (LSB) */
|
||||
} dlf_dba[1]; /* actually longer */
|
||||
};
|
||||
|
||||
/*
|
||||
* Defect list header, Bytes From Index format.
|
||||
*/
|
||||
struct scsi_dlf_bfi {
|
||||
u_short dlf_xxx; /* reserved */
|
||||
u_char dlf_lenh, /* defect list length (MSB) */
|
||||
dlf_lenl; /* defect list length (LSB) */
|
||||
struct scsi_dlf_bfi_desc {
|
||||
u_char cylh, /* cylinder number of defect (MSB) */
|
||||
cylm, /* cylinder number of defect */
|
||||
cyll, /* cylinder number of defect (LSB) */
|
||||
head, /* head number of defect */
|
||||
bfih, /* defect bytes from index (MSB) */
|
||||
bfihm, /* defect bytes from index */
|
||||
bfilm, /* defect bytes from index */
|
||||
bfil; /* defect bytes from index (LSB) */
|
||||
} dlf_bfi[1]; /* actually longer */
|
||||
};
|
||||
|
||||
/*
|
||||
* Defect list header, Physical Sector format.
|
||||
*/
|
||||
struct scsi_dlf_ps {
|
||||
u_short dlf_xxx; /* reserved */
|
||||
u_char dlf_lenh, /* defect list length (MSB) */
|
||||
dlf_lenl; /* defect list length (LSB) */
|
||||
struct scsi_dlf_ps_desc {
|
||||
u_char cylh, /* cylinder number of defect (MSB) */
|
||||
cylm, /* cylinder number of defect */
|
||||
cyll, /* cylinder number of defect (LSB) */
|
||||
head, /* head number of defect */
|
||||
dsnh, /* defect sector number (MSB) */
|
||||
dsnhm, /* defect sector number */
|
||||
dsnlm, /* defect sector number */
|
||||
dsnl; /* defect sector number (LSB) */
|
||||
} dlf_ps[1]; /* actually longer */
|
||||
};
|
||||
|
||||
/*
|
||||
* For MODE SENSE and MODE SELECT: Mode page codes for disks.
|
||||
*/
|
||||
/* 0x00 vendor specific */
|
||||
#define SCSI_MS_PC_RWERRREC 0x01 /* r/w error recovery parameters */
|
||||
/* SCSI_MS_PC_DR 0x02 disconnect/reconnect control */
|
||||
#define SCSI_MS_PC_FMT 0x03 /* format parameters */
|
||||
#define SCSI_MS_PC_RDGEOM 0x04 /* Rigid Disk geometry */
|
||||
#define SCSI_MS_PC_FD 0x05 /* flexible disk page */
|
||||
/* 0x06 reserved */
|
||||
#define SCSI_MS_PC_VERRREC 0x07 /* verify error recovery page */
|
||||
#define SCSI_MS_PC_CACHE 0x08 /* cache page */
|
||||
/* SCSI_MS_PC_PDEV 0x09 peripheral device page */
|
||||
/* SCSI_MS_PC_CTLMODE 0x0a control mode page */
|
||||
#define SCSI_MS_PC_MTSUPP 0x0b /* medium types supported */
|
||||
#define SCSI_MS_PC_NOTCH 0x0c /* notch page */
|
||||
/* 0x0d..0x1f reserved */
|
||||
/* 0x20..0x3e vendor specific */
|
||||
#define SCSI_MS_PC_CDCCACHECTL 0x38 /* CDC (Wren) cache control page */
|
||||
|
||||
/*
|
||||
* Structure of a Read/Write Error Recovery mode page.
|
||||
* N.B.: CDC Wren V, at least, does not include write retry & time limit.
|
||||
*/
|
||||
struct scsi_page_rwerrrec {
|
||||
u_char rw_flags, /* flags, see below */
|
||||
rw_read_retry, /* read retry count */
|
||||
rw_corr_span, /* correction span */
|
||||
rw_hd_off, /* head offset count */
|
||||
rw_ds_off, /* data strobe offset count */
|
||||
rw_xxx0, /* reserved */
|
||||
rw_write_retry, /* write retry count */
|
||||
rw_xxx1, /* reserved */
|
||||
rw_rtlh, /* recovery time limit (MSB) */
|
||||
rw_rtll; /* recovery time limit (LSB) */
|
||||
};
|
||||
/* rw_flags */
|
||||
#define SCSI_RWE_AWRE 0x80 /* reallocate defective blocks on write */
|
||||
#define SCSI_RWE_ARRE 0x40 /* reallocate defective blocks on read */
|
||||
#define SCSI_RWE_TB 0x20 /* transfer unrecoverable block */
|
||||
#define SCSI_RWE_RC 0x10 /* recovery may not cause delay: may lie */
|
||||
#define SCSI_RWE_EER 0x08 /* use most expedient recovery, not best */
|
||||
#define SCSI_RWE_PER 0x04 /* report recovered errors */
|
||||
#define SCSI_RWE_DTE 0x02 /* stop after recovered error */
|
||||
#define SCSI_RWE_DCR 0x01 /* use ECC for detection only */
|
||||
|
||||
/*
|
||||
* Structure of a Format Device mode page.
|
||||
*/
|
||||
struct scsi_page_fmt {
|
||||
u_char fmt_tpzh, /* tracks per zone (MSB) */
|
||||
fmt_tpzl, /* tracks per zone (LSB) */
|
||||
fmt_aspzh, /* alternate sectors per zone (MSB) */
|
||||
fmt_aspzl, /* alternate sectors per zone (LSB) */
|
||||
fmt_atpzh, /* alternate tracks per zone (MSB) */
|
||||
fmt_atpzl, /* alternate tracks per zone (LSB) */
|
||||
fmt_atpvh, /* alternate tracks per volume (MSB) */
|
||||
fmt_atpvl, /* alternate tracks per volume (LSB) */
|
||||
fmt_spth, /* sectors per track (MSB) */
|
||||
fmt_sptl, /* sectors per track (LSB) */
|
||||
fmt_dbppsh, /* data bytes per physical sector (MSB) */
|
||||
fmt_dbppsl, /* data bytes per physical sector (LSB) */
|
||||
fmt_ilh, /* interleave (MSB) */
|
||||
fmt_ill, /* interleave (LSB) */
|
||||
fmt_tsfh, /* track skew factor (MSB) */
|
||||
fmt_tsfl, /* track skew factor (LSB) */
|
||||
fmt_csfh, /* cylinder skew factor (MSB) */
|
||||
fmt_csfl, /* cylinder skew factor (LSB) */
|
||||
fmt_flags, /* flags, see below */
|
||||
fmt_xxx[3]; /* reserved */
|
||||
};
|
||||
/* fmt_flags. Note, HSEC|SSEC meaning varies all over the map! */
|
||||
#define SCSI_FMT_HSEC 0x80 /* hard sector */
|
||||
#define SCSI_FMT_SSEC 0x40 /* soft sector */
|
||||
#define SCSI_FMT_RMB 0x20 /* removable media */
|
||||
#define SCSI_FMT_SURF 0x10 /* format by surface (vs. by cylinder) */
|
||||
/* 0x0f reserved */
|
||||
|
||||
/*
|
||||
* Structure of a Rigid Disk Geometry mode page.
|
||||
* N.B.: CDC Wren V, at least, does not include rpm.
|
||||
*/
|
||||
struct scsi_page_rdgeom {
|
||||
u_char rd_ncylh, /* number of cylinders (MSB) */
|
||||
rd_ncylm, /* number of cylinders */
|
||||
rd_ncyll, /* number of cylinders (LSB) */
|
||||
rd_nheads, /* number of heads */
|
||||
rd_wpcylh, /* start cyl for write precomp. (MSB) */
|
||||
rd_wpcylm, /* start cyl for write precomp. */
|
||||
rd_wpcyll, /* start cyl for write precomp. (LSB) */
|
||||
rd_rwcylh, /* start cyl for reduced write current (MSB) */
|
||||
rd_rwcylm, /* start cyl for reduced write current */
|
||||
rd_rwcyll, /* start cyl for reduced write current (LSB) */
|
||||
rd_steph, /* drive step rate (.1 us units) (MSB) */
|
||||
rd_stepl, /* drive step rate (LSB) */
|
||||
rd_lcylh, /* landing zone cylinder (MSB) */
|
||||
rd_lcylm, /* landing zone cylinder */
|
||||
rd_lcyll, /* landing zone cylinder (LSB) */
|
||||
rd_rpl, /* spindle synch control, see below */
|
||||
rd_roff, /* rotational offset (for rpl) */
|
||||
rd_xxx1, /* reserved */
|
||||
rd_rpmh, /* medium rotation rate (rpm) (MSB) */
|
||||
rd_rpml, /* medium rotation rate (rpm) (LSB) */
|
||||
rd_xxx2[2]; /* reserved */
|
||||
};
|
||||
/* values for rd_rpl. */
|
||||
#define SCSI_RD_RPL_MASK 0x03 /* mask for RPL field */
|
||||
#define SCSI_RD_RPL_NONE 0x00 /* sync disabled or not supported */
|
||||
#define SCSI_RD_RPL_SLAVE 0x01 /* disk is a Slave */
|
||||
#define SCSI_RD_RPL_MASTER 0x02 /* disk is a Master */
|
||||
#define SCSI_RD_RPL_MCONTROL 0x03 /* disk is a Master Control */
|
||||
|
||||
/*
|
||||
* Structure of a Verify Error Recovery mode page.
|
||||
*/
|
||||
struct scsi_page_verrrec {
|
||||
u_char v_flags, /* flags, see below */
|
||||
v_verify_retry, /* verify retry count */
|
||||
v_corr_span, /* verify correction span */
|
||||
v_xxx[5], /* reserved */
|
||||
v_rtlh, /* verify recovery time limit (MSB) */
|
||||
v_rtll; /* verify recovery time limit (LSB) */
|
||||
};
|
||||
#define SCSI_V_EER 0x08 /* use most expedient recovery, not best */
|
||||
#define SCSI_V_PER 0x04 /* report recovered errors */
|
||||
#define SCSI_V_DTE 0x02 /* stop after recovered error */
|
||||
#define SCSI_V_DCR 0x01 /* use ECC for detection only */
|
||||
|
||||
/*
|
||||
* Structure of a Caching mode page.
|
||||
*/
|
||||
struct scsi_page_cache {
|
||||
u_char cache_flags, /* flags, see below */
|
||||
cache_reten, /* cache retention priorities (rd + wr) */
|
||||
cache_dptlh, /* disable prefetch transfer length (MSB) */
|
||||
cache_dptll, /* disable prefetch transfer length (LSB) */
|
||||
cache_minpfh, /* minimum prefetch (MSB) */
|
||||
cache_minpfl, /* minimum prefetch (LSB) */
|
||||
cache_maxpfh, /* maximum prefetch (MSB) */
|
||||
cache_maxpfl, /* maximum prefetch (LSB) */
|
||||
cache_mpch, /* maximum prefetch ceiling (MSB) */
|
||||
cache_mpcl; /* maximum prefetch ceiling (LSB) */
|
||||
};
|
||||
#define SCSI_CACHE_WCE 0x04 /* write cache enable */
|
||||
#define SCSI_CACHE_MF 0x02 /* if set, prefetch depends on xfer length */
|
||||
#define SCSI_CACHE_RCD 0x01 /* read cache disable */
|
||||
|
||||
#define SCSI_CACHE_RDPOLICY(x) ((x) >> 4)
|
||||
#define SCSI_CACHE_WRPOLICY(x) ((x) & 0xf)
|
||||
#define SCSI_CACHE_DEFAULT 0 /* use target default */
|
||||
#define SCSI_CACHE_KEEPPF 1 /* keep prefetch data over cmd data */
|
||||
#define SCSI_CACHE_KEEPCMD 15 /* keep cmd data over prefetch data */
|
||||
|
||||
/*
|
||||
* Structure of a Control Mode mode page.
|
||||
*/
|
||||
struct scsi_page_ctlmode {
|
||||
u_char cm_rlec, /* report log-activity exception condition */
|
||||
cm_qctl, /* queue control (below) */
|
||||
cm_ecaaen, /* ECA and AEN flags (below) */
|
||||
cm_xxx, /* reserved */
|
||||
cm_aenholdh, /* AEN holdoff period (ms) (MSB) */
|
||||
cm_aenholdl; /* AEN holdoff period (ms) (LSB) */
|
||||
};
|
||||
#define SCSI_CM_RLEC 0x01 /* RLEC flag occupies only low bit */
|
||||
#define SCSI_CM_QMOD(x) ((x) >> 4) /* queue algorithm modifier */
|
||||
#define SCSI_CM_QERR 0x02 /* abort cmd queue after error */
|
||||
#define SCSI_CM_DQUE 0x01 /* disable tagged queueing */
|
||||
#define SCSI_CM_ECA 0x80 /* enable Extended Contingent Alliance */
|
||||
#define SCSI_CM_RAENP 0x04 /* target may do Async Err Notif after init */
|
||||
#define SCSI_CM_UAAENP 0x02 /* target may do AEN for Unit Attention */
|
||||
#define SCSI_CM_EAENP 0x01 /* target may do AEN for deferred errors */
|
||||
|
||||
/*
|
||||
* Structure of a CDC-specific Cache Control mode page.
|
||||
*/
|
||||
struct scsi_page_CDCcachectlmode {
|
||||
u_char ccm_flags, /* flags (below) */
|
||||
ccm_pfthresh, /* prefetch threshold */
|
||||
ccm_maxthresh, /* maximum threshold (?) */
|
||||
ccm_maxpfmult, /* maximum prefetch multiplier */
|
||||
ccm_minthresh, /* minimum thresold (?) */
|
||||
ccm_minpfmult, /* minimum prefetch multiplier */
|
||||
ccm_xxx[8]; /* reserved */
|
||||
};
|
||||
#define SCSI_CDC_CCM_WIE 0x40 /* write index enable */
|
||||
#define SCSI_CDC_CCM_CE 0x10 /* cache enable */
|
||||
#define SCSI_CDC_CCM_TBLSZ(x) ((x) & 0xf) /* table size */
|
||||
|
||||
/*
|
||||
* Bits in cdb_lenl for a READ CAPACITY command,
|
||||
* and structure returned as data.
|
||||
*
|
||||
* If PMI is off, the lba in the cdb must be 0.
|
||||
*/
|
||||
#define SCSI_CMD_RC_PMI 0x01 /* Partial Medium Indicator */
|
||||
|
||||
struct scsi_rc {
|
||||
u_char rc_lbah; /* logical block address (MSB) */
|
||||
u_char rc_lbahm; /* logical block address */
|
||||
u_char rc_lbalm; /* logical block address */
|
||||
u_char rc_lbal; /* logical block address (LSB) */
|
||||
u_char rc_blh; /* block length (MSB) */
|
||||
u_char rc_blhm; /* block length */
|
||||
u_char rc_bllm; /* block length */
|
||||
u_char rc_bll; /* block length (LSB) */
|
||||
};
|
260
sys/dev/scsi/disktape.h
Normal file
260
sys/dev/scsi/disktape.h
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratories.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)disktape.h 8.1 (Berkeley) 6/10/93
|
||||
*
|
||||
* from: $Header: /cvsroot/src/sys/dev/scsi/Attic/disktape.h,v 1.1.1.1 1998/03/01 02:09:34 fvdl Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Commands common to disk and tape devices, but not other SCSI devices.
|
||||
*/
|
||||
#define CMD_MODE_SELECT6 0x15 /* mode select (6 byte cdb) */
|
||||
#define CMD_MODE_SENSE6 0x1a /* mode sense (6 byte cdb) */
|
||||
|
||||
#define CMD_MODE_SELECT10 0x55 /* mode select (10 byte cdb) */
|
||||
#define CMD_MODE_SENSE10 0x5a /* mode sense (10 byte cdb) */
|
||||
|
||||
/*
|
||||
* Structure of MODE SELECT commands (i.e., the cdb; 6 & 10 byte flavors).
|
||||
* The only difference is that the 10-byte version can give more parameter
|
||||
* bytes.
|
||||
*/
|
||||
struct scsi_cdb_modeselect6 {
|
||||
u_char cdb_cmd, /* 0x15 */
|
||||
cdb_lun_flags, /* LUN + flags */
|
||||
cdb_xxx[2], /* reserved */
|
||||
cdb_len, /* parameter list length */
|
||||
cdb_ctrl; /* control byte */
|
||||
};
|
||||
struct scsi_cdb_modeselect10 {
|
||||
u_char cdb_cmd, /* 0x55 */
|
||||
cdb_lun_flags, /* LUN + flags */
|
||||
cdb_xxx[5], /* reserved */
|
||||
cdb_lenh, /* parameter list length (MSB) */
|
||||
cdb_lenl, /* parameter list length (LSB) */
|
||||
cdb_ctrl; /* control byte */
|
||||
};
|
||||
/* flags in SCSI_MODESELECT commands */
|
||||
#define SCSI_MSEL_SCSI1_DATA 0x00 /* SCSI-1 data format */
|
||||
#define SCSI_MSEL_SCSI2_DATA 0x10 /* SCSI-2 data format */
|
||||
#define SCSI_MSEL_DONTSAVE 0x00 /* don't save pages */
|
||||
#define SCSI_MSEL_SAVEPAGES 0x01 /* save mode pages */
|
||||
|
||||
/*
|
||||
* Structure of MODE SENSE command (i.e., the cdb; 6 & 10 byte flavors).
|
||||
* Again, the 10-byte version merely allows more parameter bytes.
|
||||
* Note that these lengths include the MODE SENSE headers, while those
|
||||
* for individual mode pages do not. (Consistency? What's that?)
|
||||
*/
|
||||
struct scsi_cdb_modesense6 {
|
||||
u_char cdb_cmd, /* 0x1a */
|
||||
cdb_lun_flags, /* logical unit number + flags */
|
||||
cdb_pcc, /* page control & code */
|
||||
cdb_xxx, /* reserved */
|
||||
cdb_len, /* allocation length */
|
||||
cdb_ctrl; /* control byte */
|
||||
};
|
||||
struct scsi_cdb_modesense10 {
|
||||
u_char cdb_cmd, /* 0x5a */
|
||||
cdb_lun_flags, /* logical unit number + flags */
|
||||
cdb_pcc, /* page control & code */
|
||||
cdb_xxx[4], /* reserved */
|
||||
cdb_lenh, /* allocation length (MSB) */
|
||||
cdb_lenl, /* allocation length (MSB) */
|
||||
cdb_ctrl; /* control byte */
|
||||
};
|
||||
/* flags in SCSI_MODESENSE commands */
|
||||
#define SCSI_MSENSE_DBD 0x08 /* device returns db descriptors */
|
||||
|
||||
/* page controls */
|
||||
#define SCSI_MSENSE_PCTL_CUR 0x00 /* return current parameters */
|
||||
#define SCSI_MSENSE_PCTL_VAR 0x40 /* return variable parameters */
|
||||
#define SCSI_MSENSE_PCTL_DFLT 0x80 /* return default parameters */
|
||||
#define SCSI_MSENSE_PCTL_SAVED 0xc0 /* return saved parameters */
|
||||
|
||||
/*
|
||||
* Both MODE_SENSE and MODE_SELECT use a Mode Parameter Header,
|
||||
* followed by an array of Block Descriptors, followed by an array
|
||||
* of Pages. We define structures for the Block Descriptor and Page
|
||||
* header first, then the two (6 and 10 byte) Mode Parameter headers
|
||||
* (not including the Block Descriptor(s) and any mode pages themselves).
|
||||
*/
|
||||
struct scsi_ms_bd { /* mode sense/select block descriptor */
|
||||
u_char bd_dc, /* density code (tapes only) */
|
||||
bd_nbh, /* number of blocks (MSB) */
|
||||
bd_nbm, /* number of blocks */
|
||||
bd_nbl, /* number of blocks (LSB) */
|
||||
bd_xxx, /* reserved */
|
||||
bd_blh, /* block length (MSB) */
|
||||
bd_blm, /* block length */
|
||||
bd_bll; /* block length (LSB) */
|
||||
};
|
||||
struct scsi_ms_page_hdr { /* mode sense/select page header */
|
||||
u_char mp_psc, /* saveable flag + code */
|
||||
mp_len; /* parameter length (excludes this header) */
|
||||
/* followed by parameters */
|
||||
};
|
||||
#define SCSI_MS_MP_SAVEABLE 0x80 /* page can be saved */
|
||||
/* 0x40 reserved */
|
||||
#define SCSI_MS_PC_MASK 0x3f /* page code mask */
|
||||
|
||||
/*
|
||||
* Structure of returned mode sense6 / mode select6 (hence "ms6") data.
|
||||
*/
|
||||
struct scsi_ms6 {
|
||||
u_char ms_len, /* total sense data length */
|
||||
ms_mt, /* medium type (disks only?) */
|
||||
ms_dsp, /* device specific parameter */
|
||||
ms_bdl; /* block descriptor length (bytes) */
|
||||
/* followed by block descriptors, if any */
|
||||
/* followed by pages, if any */
|
||||
};
|
||||
/*
|
||||
* Same, but for ms10.
|
||||
*/
|
||||
struct scsi_ms10 {
|
||||
u_char ms_lenh, /* total sense length (MSB) */
|
||||
ms_lenl, /* total sense length (LSB) */
|
||||
ms_mt, /* medium type (disks only?) */
|
||||
ms_dsp, /* device specific parameter */
|
||||
ms_xxx[2], /* reserved */
|
||||
ms_bdlh, /* block descriptor length (bytes) (MSB) */
|
||||
ms_bdll; /* block descriptor length (bytes) (LSB) */
|
||||
/* followed by block descriptors, if any */
|
||||
/* followed by pages, if any */
|
||||
};
|
||||
|
||||
/* values for the Medium Type field - disks */
|
||||
#define SCSI_MS_MT_DEFAULT 0x00 /* whatever is current */
|
||||
#define SCSI_MS_MT_SS 0x01 /* single sided, unspecified medium */
|
||||
#define SCSI_MS_MT_DS 0x02 /* double sided, unspecified medium */
|
||||
#define SCSI_MS_MT_8SSSD 0x05 /* 8" floppy, SSSD (X3.73-1980) */
|
||||
#define SCSI_MS_MT_8DSSD 0x06 /* 8" floppy, DSSD (X3B8-140) */
|
||||
#define SCSI_MS_MT_8SSDD 0x09 /* 8" floppy, SSDD (X3B8/78-139) */
|
||||
#define SCSI_MS_MT_8DSDD 0x0a /* 8" floppy, DSDD (X3.121-1984) */
|
||||
#define SCSI_MS_MT_5SSSD 0x0d /* 5.25" floppy, SSSD (X3.82-1980) */
|
||||
#define SCSI_MS_MT_5DSDD 0x12 /* 5.25" floppy, DSDD (X3.125-1984) */
|
||||
#define SCSI_MS_MT_5DSDD96 0x16 /* 5.25", DSDD, 96tpi (X3.126-198X) */
|
||||
#define SCSI_MS_MT_5DSQD 0x1a /* 5.25", DSQD, 96tpi (DIS 8630) */
|
||||
#define SCSI_MS_MT_3DS 0x1e /* 3.5", double sided (X3.137-198X) */
|
||||
|
||||
/* values for the Medium Type field - tapes */
|
||||
#define SCSI_MS_MT_QIC_12T 0x40 /* 0.25", 12 tracks */
|
||||
#define SCSI_MS_MT_QIC_24T 0x44 /* 0.25", 24 tracks */
|
||||
|
||||
/* values for the Device Specific Parameter field */
|
||||
#define SCSI_MS_DSP_WP 0x80 /* write protect (both disk & tape) */
|
||||
|
||||
/* if disk */
|
||||
#define SCSI_MS_DSP_DPO_FUA 0x10 /* cache flags DPO, FUA supported */
|
||||
|
||||
/* if tape */
|
||||
#define SCSI_MS_DSP_UNBUFFERED 0x00 /* unbuffered writes */
|
||||
#define SCSI_MS_DSP_BUFFERED 0x10 /* buffered writes */
|
||||
#define SCSI_MS_DSP_BUF2 0x20 /* buffered, for shared tapes */
|
||||
/* 0x30..0x70 reserved */
|
||||
#define SCSI_MS_DSP_SPEED_DFLT 0x00 /* use device default speed */
|
||||
#define SCSI_MS_DSP_SPEED_MASK 0x0f /* mask for non-default speeds */
|
||||
|
||||
/* values for the Density Code field - tapes */
|
||||
#define SCSI_MS_DC_DEFAULT 0 /* use device default density */
|
||||
#define SCSI_MS_DC_9T_800BPI 1 /* 9 track, 800 bpi */
|
||||
#define SCSI_MS_DC_9T_1600BPI 2 /* 9 track, 1600 bpi */
|
||||
#define SCSI_MS_DC_9T_6250BPI 3 /* 9 track, 6250 bpi */
|
||||
#define SCSI_MS_DC_QIC_XX1 4 /* QIC-11? 4 or 9 track, 8000 bpi */
|
||||
#define SCSI_MS_DC_QIC_XX2 5 /* QIC-11? 4 or 9 track, 8000 bpi */
|
||||
#define SCSI_MS_DC_9T_3200BPI 6 /* 9 track, 3200 bpi */
|
||||
#define SCSI_MS_DC_QIC_XX3 7 /* QIC, 4 track, 6400 bpi */
|
||||
#define SCSI_MS_DC_CS_XX4 8 /* cassette 4 track, 8000 bpi */
|
||||
#define SCSI_MS_DC_HIC_XX5 9 /* half inch cartridge, 18 track */
|
||||
#define SCSI_MS_DC_HIC_XX6 10 /* HIC, 22 track, 6667 bpi */
|
||||
#define SCSI_MS_DC_QIC_XX7 11 /* QIC, 4 track, 1600 bpi */
|
||||
#define SCSI_MS_DC_HIC_XX8 12 /* HIC, 24 track, 12690 bpi */
|
||||
#define SCSI_MS_DC_HIC_XX9 13 /* HIC, 24 track, 25380 bpi */
|
||||
|
||||
/*
|
||||
* Common page codes.
|
||||
*/
|
||||
/* 0x01 device specific */
|
||||
#define SCSI_MS_PC_DR 0x02 /* disconnect/reconnect control */
|
||||
/* 0x03..0x08 device specific */
|
||||
#define SCSI_MS_PC_PDEV 0x09 /* peripheral device page */
|
||||
#define SCSI_MS_PC_CTLMODE 0x0a /* control mode page */
|
||||
/* 0x0b..0x1f device specific */
|
||||
/* 0x20..0x3e vendor specific */
|
||||
#define SCSI_MS_PC_ALL 0x3f /* all pages */
|
||||
|
||||
/*
|
||||
* Structure of a Disconnect/Reconnect Control mode page.
|
||||
*/
|
||||
struct scsi_page_dr {
|
||||
u_char dr_full, /* buffer full ratio */
|
||||
dr_empty, /* buffer empty ratio */
|
||||
dr_inacth, /* bus inactivity timeout (MSB) */
|
||||
dr_inactl, /* bus inactivity timeout (LSB) */
|
||||
dr_disconh, /* disconnect time limit (MSB) */
|
||||
dr_disconl, /* disconnect time limit (LSB) */
|
||||
dr_conh, /* connect time limit (MSB) */
|
||||
dr_conl, /* connect time limit (LSB) */
|
||||
dr_bursth, /* maximum burst size (MSB) */
|
||||
dr_burstl, /* maximum burst size (LSB) */
|
||||
dr_dtdc, /* Data Transfer Disconnect Control (below) */
|
||||
dr_xxx[3]; /* reserved */
|
||||
};
|
||||
/* Data Transfer Disconnect Control */
|
||||
#define SCSI_DR_DTDC_MASK 0x03 /* mask for valid bits */
|
||||
#define SCSI_DR_DTDC_NONE 0x00 /* no control */
|
||||
#define SCSI_DR_DTDC_NOTDATA 0x01 /* never during data transfer */
|
||||
#define SCSI_DR_DTDC_RSVD 0x02 /* reserved */
|
||||
#define SCSI_DR_DTDC_NOTD2 0x03 /* never during/after data transfer */
|
||||
|
||||
/*
|
||||
* Structure of a PREVENT/ALLOW MEDIUM REMOVAL command.
|
||||
*/
|
||||
struct scsi_cdb_pamr {
|
||||
u_char cdb_cmd, /* 0x1e */
|
||||
cdb_lun_xxx, /* logical unit number + reserved */
|
||||
cdb_xxx1, /* reserved */
|
||||
cdb_xxx2, /* reserved */
|
||||
cdb_prevent, /* 1=prevent, 0=allow */
|
||||
cdb_ctrl;
|
||||
};
|
59
sys/dev/scsi/printer.h
Normal file
59
sys/dev/scsi/printer.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratories.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)printer.h 8.1 (Berkeley) 6/10/93
|
||||
*
|
||||
* from: $Header: /cvsroot/src/sys/dev/scsi/Attic/printer.h,v 1.1.1.1 1998/03/01 02:09:34 fvdl Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCSI definitions for Printer Devices.
|
||||
*/
|
||||
#define CMD_FORMAT 0x04 /* (set) format */
|
||||
#define CMD_PRINT 0x0a /* print */
|
||||
#define CMD_SLEW_PRINT 0x0b /* slew and print */
|
||||
#define CMD_FLUSH_BUFFER 0x10 /* flush buffer */
|
||||
#define CMD_RBD 0x14 /* recover buffered data */
|
||||
#define CMD_MODE_SELECT 0x15 /* mode select */
|
||||
#define CMD_RESERVE_UNIT 0x16 /* reserve unit */
|
||||
#define CMD_RELEASE_UNIT 0x17 /* release unit */
|
||||
#define CMD_MODE_SENSE 0x1a /* mode sense */
|
||||
#define CMD_STOP_PRINT 0x1b /* stop print */
|
63
sys/dev/scsi/processor.h
Normal file
63
sys/dev/scsi/processor.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratories.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)processor.h 8.1 (Berkeley) 6/10/93
|
||||
*
|
||||
* from: $Header: /cvsroot/src/sys/dev/scsi/Attic/processor.h,v 1.1.1.1 1998/03/01 02:09:34 fvdl Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCSI definitions for Processor Devices.
|
||||
*/
|
||||
#define CMD_RECEIVE 0x08 /* receive */
|
||||
#define CMD_SEND 0x0a /* send */
|
||||
|
||||
/*
|
||||
* Structure of a RECEIVE or SEND command (i.e., the cdb).
|
||||
*/
|
||||
struct scsi_cdb_rs {
|
||||
u_char cdb_cmd, /* 0x8 or 0xa */
|
||||
cdb_lun_xxx, /* logical unit number + reserved */
|
||||
cdb_lenh, /* buffer or data length (MSB) */
|
||||
cdb_lenm, /* buffer or data length */
|
||||
cdb_lenl, /* buffer or data length (LSB) */
|
||||
cdb_ctrl; /* control byte */
|
||||
};
|
361
sys/dev/scsi/scsi.h
Normal file
361
sys/dev/scsi/scsi.h
Normal file
@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratories.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)scsi.h 8.1 (Berkeley) 6/10/93
|
||||
*
|
||||
* from: $Header: /cvsroot/src/sys/dev/scsi/Attic/scsi.h,v 1.1.1.1 1998/03/01 02:09:34 fvdl Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Machine independent SCSI defintions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Mostly-generic command descriptor blocks (6 and 10 bytes).
|
||||
* Note that no SCSI command uses the 12 byte variety, hence it
|
||||
* is not defined here.
|
||||
*/
|
||||
struct scsi_cdb6 {
|
||||
u_char cdb_cmd, /* command code */
|
||||
cdb_lun_lbah, /* logical unit number, & lba (MSB) */
|
||||
cdb_lbam, /* logical block address */
|
||||
cdb_lbal, /* logical block address (LSB) */
|
||||
cdb_len, /* transfer length */
|
||||
cdb_ctrl; /* control byte */
|
||||
};
|
||||
|
||||
struct scsi_cdb10 {
|
||||
u_char cdb_cmd, /* command code */
|
||||
cdb_lun_rel, /* logical unit number, rsvd, & reladr flag */
|
||||
cdb_lbah, /* logical block address (MSB) */
|
||||
cdb_lbahm, /* logical block address (high middle byte) */
|
||||
cdb_lbalm, /* logical block address (low middle byte) */
|
||||
cdb_lbal, /* logical block address (LSB) */
|
||||
cdb_xxx, /* reserved */
|
||||
cdb_lenh, /* transfer length (MSB) */
|
||||
cdb_lenl, /* transfer length (LSB) */
|
||||
cdb_ctrl; /* control byte */
|
||||
};
|
||||
|
||||
/*
|
||||
* SCSI `generic' cdb.
|
||||
* The length of the cdb is implicit in the first byte (see scsivar.h).
|
||||
* This is 16 bytes, rather than 10 or 12, just to help out alignment.
|
||||
*/
|
||||
struct scsi_cdb {
|
||||
u_char cdb_bytes[16]; /* up to 16 bytes of command */
|
||||
};
|
||||
#define CDB6(cdb) ((struct scsi_cdb6 *)&(cdb)->cdb_bytes[0])
|
||||
#define CDB10(cdb) ((struct scsi_cdb10 *)&(cdb)->cdb_bytes[0])
|
||||
|
||||
/*
|
||||
* SCSI command (cdb_cmd/cdb_bytes[0]) byte definitions. Only those
|
||||
* that are common across all devices are actually defined here.
|
||||
* (The SCSI standard defines six groups of devices: direct access,
|
||||
* sequential access, printer, processor, WORM direct access, and
|
||||
* ROM direct access. DADs and SADs are basically `disk' and `tape';
|
||||
* printers and processors are obvious; and WORMs and ROMs are really
|
||||
* just disks that are missing one or two operations. A few commands
|
||||
* are required of all devices; these are defined here, and the others
|
||||
* are defined in separate headers.)
|
||||
*
|
||||
* Letter flags in parentheses in the comment column indicate:
|
||||
* M = mandatory (command is implemented on all SCSI devices)
|
||||
* E = extended (command implemented if SCSI device does extended SCSI)
|
||||
* O = optional
|
||||
* R = reserved to future SCSI standard
|
||||
* V = vendor unique
|
||||
* * = depends on device type
|
||||
*
|
||||
* Note that SCSI commands are broken into 8 `groups' given by bits 7..5.
|
||||
* Group 0 is 6-byte commands, 1 is 10-byte commands, and 5 is 12-byte
|
||||
* commands (of which none exist); groups 6 and 7 are vendor unique.
|
||||
* Commands are normally just treated as a simple 8-bit number,
|
||||
* but the size of the associated cdb is implied by the group.
|
||||
*/
|
||||
/* group 0 */
|
||||
#define CMD_TEST_UNIT_READY 0x00 /* (O) test unit ready */
|
||||
/* 0x01 (*) */
|
||||
/* 0x02 (V) */
|
||||
#define CMD_REQUEST_SENSE 0x03 /* (M) request sense */
|
||||
/* 0x04..0x05 (*) */
|
||||
/* 0x06 (V) */
|
||||
/* 0x07..0x08 (*) */
|
||||
/* 0x09 (V) */
|
||||
/* 0x0a..0x0b (*) */
|
||||
/* 0x0c..0x0e (V) */
|
||||
/* 0x0f..0x11 (*) */
|
||||
#define CMD_INQUIRY 0x12 /* (E) inquiry */
|
||||
/* 0x13..0x17 (*) */
|
||||
#define CMD_COPY 0x18 /* (O) copy */
|
||||
/* 0x19..0x1b (*) */
|
||||
#define CMD_RECEIVE_DIAG 0x1c /* (O) receive diagnostic results */
|
||||
#define CMD_SEND_DIAG 0x1d /* (O) send diagnostic */
|
||||
/* 0x1e (*) */
|
||||
/* 0x1f (R) */
|
||||
/* group 1 */
|
||||
/* 0x20..0x24 (V) */
|
||||
/* 0x25 (*) */
|
||||
/* 0x26..0x27 (V) */
|
||||
/* 0x28 (*) */
|
||||
/* 0x29 (V) */
|
||||
/* 0x2a..0x2b (*) */
|
||||
/* 0x2c..0x2d (V) */
|
||||
/* 0x2e..0x33 (*) */
|
||||
/* 0x34..0x37 (R) */
|
||||
#define CMD_COMPARE 0x38 /* (O) compare */
|
||||
#define CMD_COMPARE_VERIFY 0x39 /* (O) compare and verify */
|
||||
/* 0x3a..0x3f (R) */
|
||||
/* group 2 (40-5f) reserved */
|
||||
/* group 3 (60-7f) reserved */
|
||||
/* group 4 (80-9f) reserved */
|
||||
/* group 5 (a0-bf) reserved */
|
||||
/* group 6 (c0-df) vendor unique */
|
||||
/* group 7 (e0-ff) vendor unique */
|
||||
|
||||
/*
|
||||
* SCSI control byte.
|
||||
* Bits 7 and 6 are vendor unique; bits 5, 4, 3, and 2 are reserved.
|
||||
* Bit 1 may be 1 only if bit 0 is 1; if so, it tells the target to
|
||||
* send a LINKED COMMAND COMPLETE (WITH FLAG) message. If not, but
|
||||
* bit 0 is set, this tells the target to send a LINKED COMMAND COMPLETE
|
||||
* message.
|
||||
*/
|
||||
#define CTRL_VU_MASK 0xc0 /* vendor unique */
|
||||
#define CTRL_RSVD 0x3c /* reserved, must be zero */
|
||||
#define CTRL_LCCF 0x02 /* send LCCF if sending LCC */
|
||||
#define CTRL_LINK 0x01 /* linked command */
|
||||
|
||||
/*
|
||||
* Generic sense: regular and extended.
|
||||
* A sense operation returned an extended sense iff the error class
|
||||
* is 7. The format is vendor unique unless the error code is 0.
|
||||
* The regular and extended formats are completely different; we
|
||||
* define macros to obtain values from them.
|
||||
*/
|
||||
struct scsi_sense {
|
||||
u_char sn_vcc; /* valid bit, error class, & error code */
|
||||
u_char sn_var[7]; /* bytes 1-3, or 1-7; variant formats */
|
||||
u_char sn_addl[32-8]; /* additional sense data, if extended */
|
||||
};
|
||||
|
||||
#define SENSE_ECLASS(sn) (((sn)->sn_vcc >> 4) & 7)
|
||||
#define SENSE_ECODE(sn) ((sn)->sn_vcc & 0xf)
|
||||
#define SENSE_ISXSENSE(sn) (SENSE_ECLASS(sn) == 7)
|
||||
|
||||
/* for non-extended sense (`r'egular or `r'estricted sense) */
|
||||
#define RSENSE_LVALID(sn) ((sn)->sn_vcc & 0x80)
|
||||
#define RSENSE_VU(sn) ((sn)->sn_var[0] >> 5)
|
||||
#define RSENSE_LBA(sn) \
|
||||
((((sn)->sn_var[0] & 0x1f) << 16) | ((sn)->sn_var[1] << 8) | (sn)->sn_var[2])
|
||||
|
||||
/* for extended sense */
|
||||
#define XSENSE_ISSTD(sn) (SENSE_ECODE(sn) == 0)
|
||||
/* if not standard, cannot interpret it at all */
|
||||
#define XSENSE_IVALID(sn) ((sn)->sn_vcc & 0x80)
|
||||
#define XSENSE_SEG(sn) ((sn)->sn_var[0])
|
||||
#define XSENSE_FM(sn) ((sn)->sn_var[1] & 0x80) /* filemark */
|
||||
#define XSENSE_EOM(sn) ((sn)->sn_var[1] & 0x40) /* end of media */
|
||||
#define XSENSE_ILI(sn) ((sn)->sn_var[1] & 0x20) /* incor length ind */
|
||||
#define XSENSE_KEY(sn) ((sn)->sn_var[1] & 0x0f) /* sense key */
|
||||
#define XSENSE_INFO(sn) \
|
||||
(((sn)->sn_var[2] << 24) | ((sn)->sn_var[3] << 16) | \
|
||||
((sn)->sn_var[4] << 8) | (sn)->sn_var[5])
|
||||
#define XSENSE_ADDL(sn) ((sn)->sn_var[6]) /* add'l sense len */
|
||||
|
||||
/*
|
||||
* SCSI INQUIRY data: general, and ANSI versions 1 and 2
|
||||
* (including common command set).
|
||||
*/
|
||||
struct scsi_inquiry {
|
||||
u_char si_type; /* peripheral device type (below) */
|
||||
u_char si_qual; /* qualifier (see below) */
|
||||
u_char si_version; /* version (see below) */
|
||||
u_char si_v2info; /* scsi version 2 stuff (see below) */
|
||||
u_char si_len; /* additional length */
|
||||
u_char si_more[252-5]; /* actually si_len bytes */
|
||||
};
|
||||
struct scsi_inq_ansi {
|
||||
u_char si_type; /* peripheral qualifier and device type */
|
||||
u_char si_qual; /* RMB and device type qualifier */
|
||||
u_char si_version; /* ISO, ECMA and ANSI-approved versions */
|
||||
u_char si_v2info; /* ? */
|
||||
u_char si_len; /* addition length */
|
||||
char si_xxx1[2]; /* reserved */
|
||||
char si_flags; /* (see below) */
|
||||
char si_vendor[8]; /* vendor (blank padded) */
|
||||
char si_product[16]; /* product (blank padded) */
|
||||
char si_rev[4]; /* revision (blank padded) */
|
||||
|
||||
/* scsi version 2 stuff follows */
|
||||
char si_vend1[20]; /* vendor specific */
|
||||
char si_xxx2[40]; /* reserved */
|
||||
char si_vend2[252-96]; /* vendor specific parameters */
|
||||
};
|
||||
|
||||
/* peripheral device types */
|
||||
#define TYPE_QUAL_MASK 0xe0 /* peripheral qualifer mask */
|
||||
#define TYPE_TYPE_MASK 0x1f /* peripheral device type mask */
|
||||
#define TYPE_QUAL_NORM 0x00 /* device is normal */
|
||||
#define TYPE_QUAL_NOTCONN 0x20 /* not connected */
|
||||
#define TYPE_QUAL_XXX 0x40 /* reserved */
|
||||
#define TYPE_QUAL_NOLUN 0x60 /* logical unit not supported */
|
||||
#define TYPE_QUAL_VT4 0x80 /* vendor specific type 4 */
|
||||
#define TYPE_QUAL_VT5 0xa0 /* vendor specific type 5 */
|
||||
#define TYPE_QUAL_VT6 0xc0 /* vendor specific type 6 */
|
||||
#define TYPE_QUAL_VT7 0xe0 /* vendor specific type 7 */
|
||||
|
||||
#define TYPE_DAD 0x00 /* direct access device (disk) */
|
||||
#define TYPE_SAD 0x01 /* sequential access device (tape) */
|
||||
#define TYPE_PRINTER 0x02 /* printer */
|
||||
#define TYPE_PROCESSOR 0x03 /* processor */
|
||||
#define TYPE_WORM 0x04 /* WORM disk */
|
||||
#define TYPE_ROM 0x05 /* CD-ROM disk */
|
||||
#define TYPE_SCANNER 0x06 /* scanner */
|
||||
#define TYPE_MO 0x07 /* magneto-optical */
|
||||
#define TYPE_JUKEBOX 0x08 /* medium changer */
|
||||
#define TYPE_LAN 0x09 /* communications device */
|
||||
#define TYPE_NP 0x1f /* unknown or no device */
|
||||
|
||||
/* qualifiers */
|
||||
#define QUAL_RMB 0x80 /* removable medium bit */
|
||||
#define QUAL_MASK 0x7f /* mask for `user' bits */
|
||||
|
||||
/* version (shifts and masks for subfields) */
|
||||
#define VER_ISO_SHIFT 6 /* ISO version: top 2 bits */
|
||||
#define VER_ISO_MASK 3
|
||||
#define VER_ECMA_SHIFT 3 /* ECMA version: middle 3 bits */
|
||||
#define VER_ECMA_MASK 7
|
||||
#define VER_ANSI_SHIFT 0 /* ANSI version: bottom 3 bits */
|
||||
#define VER_ANSI_MASK 7
|
||||
|
||||
/* v2 info */
|
||||
#define V2INFO_AENC 0x80 /* device can accept AEN data */
|
||||
#define V2INFO_TRMIOP 0x40 /* supports TERMINATE I/O PROC msg */
|
||||
#define V2INFO_XXX 0x30 /* reserved */
|
||||
#define V2INFO_RDF_MASK 0x0f /* response data format mask */
|
||||
#define V2INFO_RDF_SCSI1 0x00 /* SCSI-1 standard INQUIRY data */
|
||||
#define V2INFO_RDF_CCS 0x01 /* common command set INQUIRY data */
|
||||
#define V2INFO_RDF_SCSI2 0x02 /* SCSI-2 standard INQUIRY data */
|
||||
|
||||
/* flags */
|
||||
#define V2FLAG_RELADR 0x80 /* supports relative addressing */
|
||||
#define V2FLAG_WBUS32 0x40 /* supports 32 bit data xfer */
|
||||
#define V2FLAG_WBUS16 0x20 /* supports 32 bit data xfer */
|
||||
#define V2FLAG_SYNC 0x10 /* supports synchronous data xfer */
|
||||
#define V2FLAG_LINKED 0x08 /* supports linked commands */
|
||||
#define V2FLAG_XXX 0x04 /* reserved */
|
||||
#define V2FLAG_CMDQUE 0x02 /* supports tagged command queueing */
|
||||
#define V2FLAG_SOFTRESET 0x01 /* RST causes soft reset */
|
||||
|
||||
/*
|
||||
* SCSI message codes bytes. The `command complete' code is required;
|
||||
* all others are optional. `Identify' is a flag bit, not a code (thus
|
||||
* codes are actually at most 7 bits).
|
||||
*/
|
||||
#define MSG_IDENTIFY 0x80 /* flag => this is an identify msg */
|
||||
#define MSG_IDENTIFY_DR 0x40 /* IDENTIFY: flag => discon/resel ok */
|
||||
#define MSG_IDENTIFY_RSVD 0x38 /* IDENTIFY: these bits are reserved */
|
||||
#define MSG_IDENTIFY_LUN 0x07 /* IDENTIFY: these bits give LUN */
|
||||
|
||||
#define MSG_CMD_COMPLETE 0x00 /* command complete */
|
||||
#define MSG_EXT_MESSAGE 0x01 /* extended message */
|
||||
#define MSG_SAVE_DATA_PTR 0x02 /* save data pointer */
|
||||
#define MSG_RESTORE_PTR 0x03 /* restore pointers */
|
||||
#define MSG_DISCONNECT 0x04 /* disconnect */
|
||||
#define MSG_INIT_DETECT_ERROR 0x05 /* initiator detected error */
|
||||
#define MSG_ABORT 0x06 /* abort */
|
||||
#define MSG_REJECT 0x07 /* message reject */
|
||||
#define MSG_NOOP 0x08 /* no operation */
|
||||
#define MSG_PARITY_ERROR 0x09 /* message parity error */
|
||||
#define MSG_LCC 0x0a /* linked command complete */
|
||||
#define MSG_LCCF 0x0b /* linked command complete (w/ flag) */
|
||||
#define MSG_BUS_DEVICE_RESET 0x0c /* bus device reset */
|
||||
#define MSG_ABORT_TAG 0x0d /* abort tagged msg */
|
||||
#define MSG_CLEAR_QUEUE 0x0e /* clear queue */
|
||||
#define MSG_INITIATE_RECOVERY 0x0f /* initiate recovery */
|
||||
#define MSG_RELEASE_RECOVERY 0x10 /* release recovery */
|
||||
#define MSG_TERMINATE_PROCESS 0x11 /* ? */
|
||||
#define MSG_SIMPLE_Q_TAG 0x20 /* ? */
|
||||
#define MSG_HEAD_Q_TAG 0x21 /* ? */
|
||||
#define MSG_ORDERED_Q_TAG 0x22 /* ? */
|
||||
#define MSG_IGNORE_WIDE_RESID 0x23 /* ? */
|
||||
|
||||
/*
|
||||
* SCSI extended message format.
|
||||
*/
|
||||
struct scsi_xmsg {
|
||||
u_char xm_xmsg, /* value 1, i.e., SMSG_EXT_MESSAGE */
|
||||
xm_len, /* length of this extended message */
|
||||
xm_code, /* actual code */
|
||||
xm_args[253]; /* actualy xm_len-1 bytes */
|
||||
};
|
||||
|
||||
/*
|
||||
* SCSI extended message codes.
|
||||
*/
|
||||
#define XMSG_MDP 0x00 /* modify data pointer */
|
||||
#define XMSG_SDTR 0x01 /* synchronous data transfer request */
|
||||
#define XMSG_XID 0x02 /* extended identify */
|
||||
|
||||
/*
|
||||
* SCSI status byte values. Bits 6, 5, and 0 are Vendor Unique.
|
||||
*/
|
||||
#define STS_EXT 0x80 /* flag => extended status valid */
|
||||
#define STS_MASK 0x1e /* mask for non-VU bits */
|
||||
#define STS_VU 0x61 /* mask for Vendor Unique bits */
|
||||
|
||||
#define STS_GOOD 0x00 /* success, command done */
|
||||
#define STS_CHECKCOND 0x02 /* check condition (do a REQ SENSE) */
|
||||
#define STS_CONDMET 0x04 /* condition met (search succeeded) */
|
||||
/* 0x06 reserved */
|
||||
#define STS_BUSY 0x08 /* busy */
|
||||
/* 0x0a reserved */
|
||||
/* 0x0c reserved */
|
||||
/* 0x0e reserved */
|
||||
#define STS_INTERMED 0x10 /* succeeded, doing linked cmd */
|
||||
/* 0x12 reserved */
|
||||
#define STS_INTERMED_CONDMET 0x14 /* condition met, doing linked cmd */
|
||||
/* 0x16 reserved */
|
||||
#define STS_RESERV_CONFLICT 0x18 /* reservation conflict */
|
||||
/* 0x1a reserved */
|
||||
/* 0x1c reserved */
|
||||
/* 0x1e reserved */
|
71
sys/dev/scsi/scsi_ioctl.h
Normal file
71
sys/dev/scsi/scsi_ioctl.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratories.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)scsi_ioctl.h 8.1 (Berkeley) 6/10/93
|
||||
*
|
||||
* from: $Header: /cvsroot/src/sys/dev/scsi/Attic/scsi_ioctl.h,v 1.1.1.1 1998/03/01 02:09:34 fvdl Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCSI ioctls (`format' mode).
|
||||
*
|
||||
* Format mode allows a privileged process to issue direct SCSI commands
|
||||
* to a drive (it is intended primarily to allow on-line formatting).
|
||||
* SDIOCSFORMAT sets format mode (nonzero arg => on, zero arg => off).
|
||||
* When in format mode, only the process that issued the SDIOCSFORMAT
|
||||
* can read or write the drive.
|
||||
*
|
||||
* In format mode, the process is expected to
|
||||
* - do SDIOCSCSICOMMAND to supply cdb for next SCSI op
|
||||
* - do read or write as appropriate for cdb
|
||||
* - if I/O error, optionally do SDIOCSENSE to get completion
|
||||
* status and sense data from last SCSI operation.
|
||||
*/
|
||||
|
||||
struct scsi_fmt_sense {
|
||||
u_int status; /* completion status of last op */
|
||||
u_char sense[28]; /* sense data (if any) from last op */
|
||||
};
|
||||
|
||||
#define SDIOCSFORMAT _IOW('S', 1, int)
|
||||
#define SDIOCGFORMAT _IOR('S', 2, int)
|
||||
#define SDIOCSCSICOMMAND _IOW('S', 3, struct scsi_cdb)
|
||||
#define SDIOCSENSE _IOR('S', 4, struct scsi_fmt_sense)
|
532
sys/dev/scsi/scsi_subr.c
Normal file
532
sys/dev/scsi/scsi_subr.c
Normal file
@ -0,0 +1,532 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratories.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)scsi_subr.c 8.1 (Berkeley) 6/16/93
|
||||
*
|
||||
* from: $Header: /cvsroot/src/sys/dev/scsi/Attic/scsi_subr.c,v 1.1.1.1 1998/03/01 02:09:34 fvdl Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generic SCSI host adapter driver.
|
||||
* Does almost nothing (most work is relegated to per-hba drivers).
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <dev/scsi/scsi.h>
|
||||
#include <dev/scsi/scsivar.h>
|
||||
|
||||
/*
|
||||
* General subroutines, and scsi data.
|
||||
*/
|
||||
|
||||
/* table of lengths of scsi commands */
|
||||
const char scsicmdlen[8] = { 6, 10, 0, 0, 0, 12, 0, 0 };
|
||||
|
||||
/* table of lengths of scsi messages */
|
||||
const signed char scsimsglen[0x24] = {
|
||||
SMLEN_DONE, /* MSG_CMD_COMPLETE */
|
||||
SMLEN_EXTENDED, /* MSG_EXT_MESSAGE */
|
||||
1, /* MSG_SAVE_DATA_PTR */
|
||||
1, /* MSG_RESTORE_PTR */
|
||||
1, /* MSG_DISCONNECT */
|
||||
1, /* MSG_INIT_DETECT_ERROR */
|
||||
1, /* MSG_ABORT */
|
||||
1, /* MSG_REJECT */
|
||||
1, /* MSG_NOOP */
|
||||
1, /* MSG_PARITY_ERROR */
|
||||
1, /* MSG_LCC */
|
||||
1, /* MSG_LCCF */
|
||||
1, /* MSG_BUS_DEVICE_RESET */
|
||||
1, /* MSG_ABORT_TAG */
|
||||
1, /* MSG_CLEAR_QUEUE */
|
||||
1, /* MSG_INITIATE_RECOVERY */
|
||||
1, /* MSG_RELEASE_RECOVERY */
|
||||
1, /* MSG_TERMINATE_PROCESS */
|
||||
SMLEN_UNDEF, /* 0x12 */
|
||||
SMLEN_UNDEF, /* 0x13 */
|
||||
SMLEN_UNDEF, /* 0x14 */
|
||||
SMLEN_UNDEF, /* 0x15 */
|
||||
SMLEN_UNDEF, /* 0x16 */
|
||||
SMLEN_UNDEF, /* 0x17 */
|
||||
SMLEN_UNDEF, /* 0x18 */
|
||||
SMLEN_UNDEF, /* 0x19 */
|
||||
SMLEN_UNDEF, /* 0x1a */
|
||||
SMLEN_UNDEF, /* 0x1b */
|
||||
SMLEN_UNDEF, /* 0x1c */
|
||||
SMLEN_UNDEF, /* 0x1d */
|
||||
SMLEN_UNDEF, /* 0x1e */
|
||||
SMLEN_UNDEF, /* 0x1f */
|
||||
2, /* MSG_SIMPLE_QTAG */
|
||||
2, /* MSG_HEAD_QTAG */
|
||||
2, /* MSG_ORDERED_QTAG */
|
||||
2, /* MSG_IGNORE_WIDE_RESID */
|
||||
};
|
||||
|
||||
/* definition of `tg' target driver for autoconfig */
|
||||
static int scsi_targmatch __P((struct device *, struct cfdata *, void *));
|
||||
static void scsi_targattach __P((struct device *, struct device *, void *));
|
||||
struct cfdriver tgcd =
|
||||
{ NULL, "tg", scsi_targmatch, scsi_targattach,
|
||||
DV_DULL, sizeof(struct targ) };
|
||||
|
||||
void scsi_targstart __P((struct device *, struct sq *, struct buf *,
|
||||
scdgo_fn, struct device *));
|
||||
int scsi_targgo __P((struct device *, int targ,
|
||||
scintr_fn, struct device *, struct buf *, int));
|
||||
void scsi_targintr __P((struct device *, int, int));
|
||||
void scsi_targrel __P((struct device *));
|
||||
|
||||
#define NOBUF ((caddr_t)0)
|
||||
|
||||
/*
|
||||
* Perform a TEST UNIT READY immediate (polled) command
|
||||
* on the given <target,unit> pair. Return the status byte
|
||||
* returned, or -1 for none.
|
||||
*/
|
||||
int
|
||||
scsi_test_unit_ready(hba, targ, unit)
|
||||
struct hba_softc *hba;
|
||||
int targ, unit;
|
||||
{
|
||||
struct scsi_cdb cdb;
|
||||
|
||||
CDB6(&cdb)->cdb_cmd = CMD_TEST_UNIT_READY;
|
||||
CDB6(&cdb)->cdb_lun_lbah = unit << 5;
|
||||
*(short *)&CDB6(&cdb)->cdb_lbam = 0;
|
||||
*(short *)&CDB6(&cdb)->cdb_len = 0;
|
||||
return (hba->hba_driver->hd_icmd(hba, targ, &cdb, NOBUF, 0, 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* Request sense. The sense is to be written into the given buffer.
|
||||
* The given length must be < 256.
|
||||
*/
|
||||
int
|
||||
scsi_request_sense(hba, targ, unit, buf, len)
|
||||
struct hba_softc *hba;
|
||||
int targ, unit;
|
||||
caddr_t buf;
|
||||
int len;
|
||||
{
|
||||
struct scsi_cdb cdb;
|
||||
|
||||
CDB6(&cdb)->cdb_cmd = CMD_REQUEST_SENSE;
|
||||
CDB6(&cdb)->cdb_lun_lbah = unit << 5;
|
||||
*(short *)&CDB6(&cdb)->cdb_lbam = 0;
|
||||
CDB6(&cdb)->cdb_len = len;
|
||||
CDB6(&cdb)->cdb_ctrl = 0;
|
||||
return (hba->hba_driver->hd_icmd(hba, targ, &cdb, buf, len, B_READ));
|
||||
}
|
||||
|
||||
/*
|
||||
* Called (indirectly, via config_found) from scsi_hbaattach.
|
||||
* Print target number, and if no device was configured there,
|
||||
* the hba as well.
|
||||
*/
|
||||
int
|
||||
scsi_targprint(aux, hba)
|
||||
void *aux;
|
||||
char *hba;
|
||||
{
|
||||
|
||||
if (hba) {
|
||||
printf("target %d on %s", *(int *)aux, hba);
|
||||
return (UNCONF);
|
||||
}
|
||||
printf(" target %d", *(int *)aux);
|
||||
return (QUIET);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print information about a unit found on some target.
|
||||
* If the unit was not configured, `targ' is the name of the target
|
||||
* on which the unit was found. If it was, targ is NULL and we
|
||||
* let the unit's attach routine print the INQUIRE result if
|
||||
* appropriate.
|
||||
*/
|
||||
static int
|
||||
scsi_unitprint(aux, targ)
|
||||
void *aux;
|
||||
char *targ;
|
||||
{
|
||||
register struct scsi_attach_args *sa = aux;
|
||||
|
||||
if (targ) {
|
||||
printf("unit %d at %s", sa->sa_unit, targ);
|
||||
if ((sa->sa_inq_status & STS_MASK) == STS_GOOD) {
|
||||
printf(" (");
|
||||
scsi_printinq(&sa->sa_si);
|
||||
printf(")");
|
||||
}
|
||||
return (UNCONF);
|
||||
}
|
||||
printf(" unit %d", sa->sa_unit);
|
||||
return (QUIET);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic target-match.
|
||||
*/
|
||||
static int
|
||||
scsi_targmatch(parent, cf, aux)
|
||||
struct device *parent;
|
||||
register struct cfdata *cf;
|
||||
void *aux;
|
||||
{
|
||||
int targ = *(int *)aux;
|
||||
|
||||
return (cf->cf_loc[0] == targ || cf->cf_loc[0] == -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* And now, a generic `target attach' routine.
|
||||
* We assume that INQUIRY works.
|
||||
*/
|
||||
static void
|
||||
scsi_targattach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
register struct targ *t = (struct targ *)self;
|
||||
register struct hba_softc *hba;
|
||||
register struct hbadriver *hd;
|
||||
register int targ, unit;
|
||||
struct scsi_attach_args sa;
|
||||
struct scsi_cdb si;
|
||||
|
||||
printf("\n");
|
||||
t->t_targ = targ = *(int *)aux;
|
||||
hba = (struct hba_softc *)parent;
|
||||
hba->hba_targets[targ] = t;
|
||||
|
||||
/*
|
||||
* Probe each of the 8 units using the sequence
|
||||
* TEST UNIT READY
|
||||
* REQUEST SENSE
|
||||
* INQUIRY
|
||||
* The first should not be necessary, but some SCSI devices
|
||||
* refuse to speak until it is done. The second is only necessary
|
||||
* if the first returns a CHECK CONDITION status, but we do it
|
||||
* anyway.
|
||||
*/
|
||||
hd = hba->hba_driver;
|
||||
sa.sa_targ = targ;
|
||||
CDB6(&si)->cdb_cmd = CMD_INQUIRY;
|
||||
*(short *)&CDB6(&si)->cdb_lbam = 0;
|
||||
CDB6(&si)->cdb_len = sizeof sa.sa_si;
|
||||
CDB6(&si)->cdb_ctrl = 0;
|
||||
for (unit = 0; unit < 8; unit++) {
|
||||
if (scsi_test_unit_ready(hba, targ, unit) == -1)
|
||||
continue;
|
||||
sa.sa_unit = unit;
|
||||
sa.sa_req_status = scsi_request_sense(hba, targ, unit,
|
||||
(caddr_t)&sa.sa_sn, sizeof sa.sa_sn);
|
||||
CDB6(&si)->cdb_lun_lbah = unit << 5;
|
||||
sa.sa_inq_status = (*hd->hd_icmd)(hba, targ, &si,
|
||||
(caddr_t)&sa.sa_si, sizeof sa.sa_si, B_READ);
|
||||
if ((sa.sa_inq_status & STS_MASK) == STS_GOOD &&
|
||||
#ifdef notdef /* XXX don't know if this is a reasonable test */
|
||||
(sa.sa_si.si_type & TYPE_QUAL_MASK) == TYPE_QUAL_NOTCONN &&
|
||||
#endif
|
||||
(sa.sa_si.si_type & TYPE_TYPE_MASK) == TYPE_NP) {
|
||||
continue;
|
||||
}
|
||||
config_found(&t->t_dev, (void *)&sa, scsi_unitprint);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Each unit calls scsi_establish to tell the hba and target of
|
||||
* its existence.
|
||||
*/
|
||||
void
|
||||
scsi_establish(u, dev, unit)
|
||||
register struct unit *u;
|
||||
struct device *dev;
|
||||
register int unit;
|
||||
{
|
||||
register struct targ *t;
|
||||
register struct hba_softc *hba;
|
||||
register struct hbadriver *hbd;
|
||||
|
||||
u->u_dev = dev;
|
||||
t = (struct targ *)dev->dv_parent;
|
||||
hba = (struct hba_softc *)t->t_dev.dv_parent;
|
||||
hbd = hba->hba_driver;
|
||||
t->t_units[unit] = u;
|
||||
if (t->t_nunits == 0) {
|
||||
/*
|
||||
* This is the first unit on the target. We can
|
||||
* probably just call the hba start code, avoiding
|
||||
* one level of calls and queueing. If we attach
|
||||
* another target we will fix this in the code below.
|
||||
*/
|
||||
u->u_start = hbd->hd_start;
|
||||
u->u_go = hbd->hd_go;
|
||||
u->u_rel = hbd->hd_rel;
|
||||
u->u_updev = &hba->hba_dev;
|
||||
t->t_firstunit = unit;
|
||||
} else {
|
||||
/*
|
||||
* This is not the only unit on the target, so we
|
||||
* must call the target start code rather than the
|
||||
* hba start code. Fix the linkage on the first
|
||||
* target too (possibly for the 2nd, 3rd, ..., time).
|
||||
*/
|
||||
t->t_units[t->t_firstunit]->u_start = scsi_targstart;
|
||||
t->t_units[t->t_firstunit]->u_go = scsi_targgo;
|
||||
t->t_units[t->t_firstunit]->u_rel = scsi_targrel;
|
||||
t->t_units[t->t_firstunit]->u_updev = &t->t_dev;
|
||||
u->u_start = scsi_targstart;
|
||||
u->u_go = scsi_targgo;
|
||||
u->u_rel = scsi_targrel;
|
||||
u->u_updev = &t->t_dev;
|
||||
}
|
||||
t->t_nunits++; /* another unit is alive */
|
||||
u->u_unit = unit;
|
||||
u->u_targ = t->t_targ; /* record target number, */
|
||||
u->u_hba = hba; /* hba ... */
|
||||
u->u_hbd = hbd; /* and driver */
|
||||
}
|
||||
|
||||
/* NO DOUBT SOME OF THE STUFF PRINTED HERE IS USELESS */
|
||||
void
|
||||
scsi_printinq(inq)
|
||||
register struct scsi_inquiry *inq;
|
||||
{
|
||||
register int iso, ecma, ansi, t;
|
||||
static char *types[] = { "disk", "tape", "printer", "processor",
|
||||
"WORM", "ROM disk", "scanner", "magneto-optical",
|
||||
"jukebox", "lan" };
|
||||
|
||||
if ((t = (inq->si_type & TYPE_QUAL_MASK)) != 0)
|
||||
printf("type-qual=0x%x ", t);
|
||||
t = inq->si_type & TYPE_TYPE_MASK;
|
||||
if (t < sizeof types / sizeof *types)
|
||||
printf("%s", types[t]);
|
||||
else
|
||||
printf("<type %d>", t);
|
||||
if (inq->si_qual & QUAL_RMB)
|
||||
printf(" (removable)");
|
||||
printf(" qual=0x%x", inq->si_qual & QUAL_MASK);
|
||||
iso = (inq->si_qual >> VER_ISO_SHIFT) & VER_ISO_MASK;
|
||||
ecma = (inq->si_qual >> VER_ECMA_SHIFT) & VER_ECMA_MASK;
|
||||
ansi = (inq->si_qual >> VER_ANSI_SHIFT) & VER_ANSI_MASK;
|
||||
printf(" version=<iso %d, ecma %d, ansi %d>", iso, ecma, ansi);
|
||||
if (ansi == 1 || ansi == 2) {
|
||||
char v[9], p[17], r[5];
|
||||
|
||||
scsi_inq_ansi((struct scsi_inq_ansi *)inq, v, p, r);
|
||||
printf(" vendor %s, product %s, rev %s", v, p, r);
|
||||
}
|
||||
}
|
||||
|
||||
/* copy a counted string but trim trailing blanks; make the dest a C string */
|
||||
static void
|
||||
scsi_str(src, dst, len)
|
||||
register char *src, *dst;
|
||||
register int len;
|
||||
{
|
||||
|
||||
while (src[len - 1] == ' ') {
|
||||
if (--len == 0) {
|
||||
*dst = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
bcopy(src, dst, len);
|
||||
dst[len] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
scsi_inq_ansi(si, vendor, product, rev)
|
||||
register struct scsi_inq_ansi *si;
|
||||
char *vendor, *product, *rev;
|
||||
{
|
||||
register int i, len;
|
||||
|
||||
/* if too short, extend with blanks */
|
||||
len = si->si_len + 5; /* 5 fixed; len is `additional' */
|
||||
if (len < sizeof(*si))
|
||||
for (i = len; i < sizeof *si; i++)
|
||||
((char *)si)[i] = ' ';
|
||||
scsi_str(si->si_vendor, vendor, sizeof si->si_vendor);
|
||||
scsi_str(si->si_product, product, sizeof si->si_product);
|
||||
scsi_str(si->si_rev, rev, sizeof si->si_rev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell all the devices on the given hba that it has been reset.
|
||||
* SHOULD PROBABLY DO MORE HERE
|
||||
*/
|
||||
void
|
||||
scsi_reset_units(hba)
|
||||
register struct hba_softc *hba;
|
||||
{
|
||||
register int targ, unit;
|
||||
register struct targ *t;
|
||||
register struct unit *u;
|
||||
|
||||
for (targ = 0; targ < 8; targ++) {
|
||||
if ((t = hba->hba_targets[targ]) == NULL)
|
||||
continue;
|
||||
for (unit = 0; unit < 8; unit++)
|
||||
if ((u = t->t_units[unit]) != NULL)
|
||||
(*u->u_driver->ud_reset)(u);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Start a unit on a target.
|
||||
* If the target is busy, just enqueue the unit;
|
||||
* once the target becomes free, we will call the hba start routine.
|
||||
* Otherwise, call the hba start routine now, and then when the hba
|
||||
* becomes free it will call the unit's dgo routine.
|
||||
*/
|
||||
void
|
||||
scsi_targstart(self, sq, bp, dgo, dev)
|
||||
struct device *self;
|
||||
register struct sq *sq;
|
||||
struct buf *bp;
|
||||
scdgo_fn dgo;
|
||||
struct device *dev;
|
||||
{
|
||||
register struct targ *t = (struct targ *)self;
|
||||
register struct hba_softc *hba;
|
||||
|
||||
sq->sq_forw = NULL;
|
||||
if (t->t_head == NULL)
|
||||
t->t_head = sq;
|
||||
else
|
||||
t->t_tail->sq_forw = sq;
|
||||
t->t_tail = sq;
|
||||
if (t->t_busy == 0) {
|
||||
t->t_busy = 1;
|
||||
hba = (struct hba_softc *)t->t_dev.dv_parent;
|
||||
(*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw, bp,
|
||||
dgo, dev);
|
||||
} else {
|
||||
sq->sq_bp = bp;
|
||||
sq->sq_dgo = dgo;
|
||||
sq->sq_dev = dev;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The unit got the bus, and wants the hba to go.
|
||||
* Remember its interrupt handler; substitute ours instead.
|
||||
*/
|
||||
int
|
||||
scsi_targgo(self, targ, intr, dev, bp, pad)
|
||||
struct device *self;
|
||||
int targ;
|
||||
scintr_fn intr;
|
||||
struct device *dev;
|
||||
struct buf *bp;
|
||||
int pad;
|
||||
{
|
||||
register struct targ *t = (struct targ *)self;
|
||||
register struct hba_softc *hba;
|
||||
|
||||
t->t_intr = intr;
|
||||
t->t_intrdev = dev;
|
||||
hba = (struct hba_softc *)t->t_dev.dv_parent;
|
||||
return ((*hba->hba_driver->hd_go)(&hba->hba_dev, targ,
|
||||
scsi_targintr, &t->t_dev, bp, pad));
|
||||
}
|
||||
|
||||
/*
|
||||
* The hba got an interrupt. Dequeue the unit from the target
|
||||
* (the target is already off the hba queue) and then call the
|
||||
* underlying interrupt handler.
|
||||
*/
|
||||
void
|
||||
scsi_targintr(self, stat, resid)
|
||||
struct device *self;
|
||||
int stat, resid;
|
||||
{
|
||||
register struct targ *t = (struct targ *)self;
|
||||
register struct hba_softc *hba;
|
||||
register struct sq *sq;
|
||||
|
||||
sq = t->t_head;
|
||||
if (sq == NULL) panic("scsi_targintr");
|
||||
t->t_head = sq = sq->sq_forw;
|
||||
(*t->t_intr)(t->t_intrdev, stat, resid);
|
||||
if (sq != NULL) {
|
||||
hba = (struct hba_softc *)t->t_dev.dv_parent;
|
||||
(*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw,
|
||||
sq->sq_bp, sq->sq_dgo, sq->sq_dev);
|
||||
} else
|
||||
t->t_busy = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The unit decided that it needed to `give up' its hold on the bus early.
|
||||
*/
|
||||
void
|
||||
scsi_targrel(self)
|
||||
struct device *self;
|
||||
{
|
||||
register struct targ *t = (struct targ *)self;
|
||||
register struct hba_softc *hba;
|
||||
register struct sq *sq;
|
||||
|
||||
hba = (struct hba_softc *)t->t_dev.dv_parent;
|
||||
sq = t->t_head;
|
||||
if (sq == NULL) panic("scsi_targrel");
|
||||
/*
|
||||
* This target is at the head of the hba queue.
|
||||
* Remove it by calling hba bus release. Then, if the
|
||||
* target queue is not empty, put it back on the hba queue.
|
||||
* (This produces round robin service.)
|
||||
*/
|
||||
(*hba->hba_driver->hd_rel)(&hba->hba_dev);
|
||||
sq = sq->sq_forw;
|
||||
if ((t->t_head = sq) != NULL)
|
||||
(*hba->hba_driver->hd_start)(&hba->hba_dev, &t->t_forw,
|
||||
sq->sq_bp, sq->sq_dgo, sq->sq_dev);
|
||||
else
|
||||
t->t_busy = 0;
|
||||
}
|
216
sys/dev/scsi/scsivar.h
Normal file
216
sys/dev/scsi/scsivar.h
Normal file
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratories.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)scsivar.h 8.1 (Berkeley) 6/10/93
|
||||
*
|
||||
* from: $Header: /cvsroot/src/sys/dev/scsi/Attic/scsivar.h,v 1.1.1.1 1998/03/01 02:09:34 fvdl Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCSI variables.
|
||||
*
|
||||
* Each SCSI Host Bus Adapter (hba) has:
|
||||
* a target queue head and tail
|
||||
* eight targets (for units to enqueue on)
|
||||
* a list of all units on all targets
|
||||
* its target number (the number cpu uses in initiating requests)
|
||||
* a driver
|
||||
* Each SCSI target has:
|
||||
* a forward link so that it can sit on a SCSI host bus adapter queue
|
||||
* a unit queue head and tail
|
||||
* Each SCSI unit has:
|
||||
* a forward link so that it can sit on a SCSI target queue
|
||||
* a driver
|
||||
* an hba & driver (so that we need not chase parent pointers)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Downcalls. These are usually made from hba to unit, but can be
|
||||
* hba->target->unit (when there are multiple units on a target).
|
||||
*/
|
||||
/* device go function (`you got bus') */
|
||||
typedef void (*scdgo_fn) __P((struct device *, struct scsi_cdb *));
|
||||
|
||||
/* intr function (`you no got bus no more') */
|
||||
typedef void (*scintr_fn) __P((struct device *, int stat, int resid));
|
||||
|
||||
/*
|
||||
* Upcalls. These are usually made from unit to hba, but can be
|
||||
* unit->target->hba.
|
||||
*/
|
||||
/* bus alloc function (`please get me bus') */
|
||||
struct sq; struct buf;
|
||||
typedef void (*scstart_fn) __P((struct device *, struct sq *, struct buf *,
|
||||
scdgo_fn, struct device *));
|
||||
|
||||
/* bus go function (`I have bus and I set up cmd, so start it up') */
|
||||
typedef int (*scbusgo_fn) __P((struct device *, int targ,
|
||||
scintr_fn, struct device *,
|
||||
struct buf *, int pad));
|
||||
|
||||
/* bus release function (`I have bus but do not need it after all') */
|
||||
typedef void (*scbusrel_fn) __P((struct device *));
|
||||
|
||||
/*
|
||||
* SCSI Queue. This is an element in a queue of devices (targets
|
||||
* and/or units) waiting for the bus.
|
||||
*/
|
||||
struct sq {
|
||||
struct sq *sq_forw; /* forward link */
|
||||
struct buf *sq_bp; /* buffer for transfer */
|
||||
scdgo_fn sq_dgo; /* device-go to call when got bus */
|
||||
struct device *sq_dev; /* device argument to sq_dgo */
|
||||
};
|
||||
|
||||
struct hba_softc {
|
||||
struct device hba_dev; /* generic part */
|
||||
struct sq *hba_head, *hba_tail;/* io queue (u's/t's wanting bus) */
|
||||
char hba_busy; /* true => will inspect qhead later */
|
||||
struct targ *hba_targets[8]; /* the 8 possible targets */
|
||||
struct hbadriver *hba_driver; /* hba driver */
|
||||
scintr_fn hba_intr; /* current interrupt function */
|
||||
struct device *hba_intrdev; /* arg 0 for hba_intr */
|
||||
};
|
||||
|
||||
struct targ {
|
||||
struct device t_dev; /* generic part */
|
||||
struct sq t_forw; /* forward link, etc, on hba queue */
|
||||
struct sq *t_head, *t_tail; /* io queue */
|
||||
char t_busy; /* true => will inspect qhead later */
|
||||
char t_targ; /* target number */
|
||||
char t_nunits; /* count of live units */
|
||||
char t_firstunit; /* the first live unit */
|
||||
struct unit *t_units[8]; /* the 8 possible units */
|
||||
scintr_fn t_intr; /* current interrupt function */
|
||||
struct device *t_intrdev; /* arg 0 for t_intr */
|
||||
};
|
||||
|
||||
/* since a unit may be a disk, tape, etc., it has only pointer to dev */
|
||||
struct unit {
|
||||
struct device *u_dev; /* backpointer to generic */
|
||||
int u_unit; /* unit number on target */
|
||||
scstart_fn u_start; /* upcall to get bus */
|
||||
scbusgo_fn u_go; /* upcall to use bus */
|
||||
scbusrel_fn u_rel; /* upcall to release bus early */
|
||||
struct device *u_updev; /* device for upcalls */
|
||||
struct sq u_forw; /* forward link on target or hba q */
|
||||
struct unitdriver *u_driver; /* unit driver */
|
||||
/* the following three fields are copied from target & hba, for quick lookup */
|
||||
int u_targ; /* target number */
|
||||
struct hba_softc *u_hba; /* hba, from parent */
|
||||
struct hbadriver *u_hbd; /* hba driver, from parent */
|
||||
};
|
||||
|
||||
/*
|
||||
* SCSI hba driver.
|
||||
*/
|
||||
struct hbadriver {
|
||||
/* immediate command; should not depend on receiving interrupts */
|
||||
int (*hd_icmd) __P((struct hba_softc *, int targ,
|
||||
struct scsi_cdb *cmd,
|
||||
caddr_t addr, int len, int rw));
|
||||
/* crash dump: like icmd(B_WRITE), but possibly from physmem */
|
||||
int (*hd_dump) __P((struct hba_softc *, int targ,
|
||||
struct scsi_cdb *cmd, caddr_t addr, int len));
|
||||
scstart_fn hd_start; /* allocate DMA & bus */
|
||||
scbusgo_fn hd_go; /* start DMA xfer on bus */
|
||||
scbusrel_fn hd_rel; /* release bus early */
|
||||
void (*hd_reset) __P((struct hba_softc *, int));
|
||||
};
|
||||
|
||||
/*
|
||||
* SCSI unit driver (`downcalls' from hba to unit).
|
||||
*/
|
||||
struct unitdriver {
|
||||
void (*ud_reset) __P((struct unit *)); /* SCSI bus reset */
|
||||
};
|
||||
|
||||
/*
|
||||
* The generic SCSI target probe code passes the following to
|
||||
* unit configuration `match' routines.
|
||||
*/
|
||||
struct scsi_attach_args {
|
||||
int sa_targ; /* target number */
|
||||
int sa_unit; /* unit number */
|
||||
int sa_req_status; /* status from REQUEST SENSE */
|
||||
struct scsi_sense sa_sn; /* contents from same */
|
||||
int sa_inq_status; /* status from INQUIRY command */
|
||||
struct scsi_inquiry sa_si; /* contents from same */
|
||||
};
|
||||
|
||||
/*
|
||||
* The SCSICMDLEN macro gives the SCSI-standard-defined length of
|
||||
* a given SCSI command. This is 0 if the command is in an undefined
|
||||
* group (see scsi.h).
|
||||
*/
|
||||
extern const char scsicmdlen[8];
|
||||
#define SCSICMDLEN(cmd) scsicmdlen[(cmd) >> 5]
|
||||
|
||||
/*
|
||||
* The SCSIMSGLEN macro gives the SCSI-standard-defined length of
|
||||
* a given SCSI message byte. This is -1 if the message byte is
|
||||
* undefined, -3 if it is an identify, -2 for an extended message,
|
||||
* 0 if it is normal completion, otherwise positive.
|
||||
*/
|
||||
#define SMLEN_IDENTIFY -3
|
||||
#define SMLEN_EXTENDED -2
|
||||
#define SMLEN_UNDEF -1
|
||||
#define SMLEN_DONE 0
|
||||
extern const signed char scsimsglen[0x24];
|
||||
#define SCSIMSGLEN(msg) ((msg) & MSG_IDENTIFY ? SMLEN_IDENTIFY : \
|
||||
(msg) > 0x24 ? SMLEN_UNDEF : scsimsglen[msg])
|
||||
|
||||
/*
|
||||
* Declarations for exported functions in scsi_subr.c
|
||||
*/
|
||||
int scsi_test_unit_ready __P((struct hba_softc *, int targ, int unit));
|
||||
int scsi_request_sense __P((struct hba_softc *, int, int, caddr_t, int));
|
||||
void scsi_hbaattach __P((struct hba_softc *));
|
||||
void scsi_establish __P((struct unit *, struct device *, int));
|
||||
void scsi_printinq __P((struct scsi_inquiry *));
|
||||
void scsi_inq_ansi __P((struct scsi_inq_ansi *, char *, char *, char *));
|
||||
void scsi_reset_units __P((struct hba_softc *));
|
||||
|
||||
#define SCSI_FOUNDTARGET(hba, targ) { \
|
||||
extern int scsi_targprint(void *, char *); \
|
||||
int _t = targ; \
|
||||
config_found(&(hba)->hba_dev, (void *)&_t, scsi_targprint); \
|
||||
}
|
909
sys/dev/scsi/sd.c
Normal file
909
sys/dev/scsi/sd.c
Normal file
@ -0,0 +1,909 @@
|
||||
/*
|
||||
* Copyright (c) 1990, 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)sd.c 8.1 (Berkeley) 6/10/93
|
||||
*
|
||||
* from: $Header: /cvsroot/src/sys/dev/scsi/Attic/sd.c,v 1.1.1.1 1998/03/01 02:09:34 fvdl Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCSI CCS (Command Command Set) disk driver.
|
||||
*
|
||||
* MACHINE INDEPENDENT (do not put machine dependent goo in here!)
|
||||
*
|
||||
* (from sd.c,v 1.7 90/12/15 14:11:26 van Exp)
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/dkstat.h>
|
||||
#include <sys/disk.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <dev/scsi/scsi.h>
|
||||
#include <dev/scsi/disk.h>
|
||||
#include <dev/scsi/scsivar.h>
|
||||
#include <dev/scsi/scsi_ioctl.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#include <dev/scsi/sdtrace.h>
|
||||
|
||||
#ifdef sparc /* XXX */
|
||||
#define SUN_LABEL_HACK /* XXX */
|
||||
#endif /* XXX */
|
||||
|
||||
#ifdef SUN_LABEL_HACK
|
||||
#include <sparc/sunos/sun_disklabel.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Per-disk variables.
|
||||
*
|
||||
* sd_dk contains all the `disk' specific stuff (label/partitions,
|
||||
* transfer rate, etc). We need only things that are special to
|
||||
* scsi disks. Note that our blocks are in terms of DEV_BSIZE blocks.
|
||||
*/
|
||||
struct sd_softc {
|
||||
struct dkdevice sc_dk; /* base disk device, must be first */
|
||||
struct unit sc_unit; /* scsi unit */
|
||||
pid_t sc_format_pid; /* process using "format" mode */
|
||||
u_char sc_type; /* drive type */
|
||||
u_char sc_bshift; /* convert device blocks to DEV_BSIZE blks */
|
||||
short sc_flags; /* see below */
|
||||
u_int sc_blks; /* number of blocks on device */
|
||||
int sc_blksize; /* device block size in bytes */
|
||||
|
||||
/* should be in dkdevice?? */
|
||||
struct buf sc_tab; /* transfer queue */
|
||||
|
||||
/* statistics */
|
||||
long sc_resets; /* number of times reset */
|
||||
long sc_transfers; /* count of total transfers */
|
||||
long sc_partials; /* count of `partial' transfers */
|
||||
|
||||
/* for user formatting */
|
||||
struct scsi_cdb sc_cmd;
|
||||
struct scsi_fmt_sense sc_sense;
|
||||
};
|
||||
|
||||
#define SDF_ALIVE 1 /* drive OK for regular kernel use */
|
||||
|
||||
/* definition of the autoconfig driver */
|
||||
int sdmatch __P((struct device *, struct cfdata *, void *));
|
||||
void sdattach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct cfdriver sdcd =
|
||||
{ NULL, "sd", sdmatch, sdattach, DV_DISK, sizeof(struct sd_softc) };
|
||||
|
||||
/* definition of the unit driver, for hba */
|
||||
void sdigo __P((struct device *, struct scsi_cdb *));
|
||||
void sdgo __P((struct device *, struct scsi_cdb *));
|
||||
void sdintr __P((struct device *, int, int));
|
||||
void sdreset __P((struct unit *));
|
||||
|
||||
static struct unitdriver sdunitdriver = { /*sdgo, sdintr*/ sdreset };
|
||||
|
||||
/* definition of the disk driver, for kernel */
|
||||
void sdstrategy __P((struct buf *));
|
||||
|
||||
static struct dkdriver sddkdriver = { sdstrategy };
|
||||
|
||||
#ifdef DEBUG
|
||||
int sddebug = 1;
|
||||
#define SDB_ERROR 0x01
|
||||
#define SDB_PARTIAL 0x02
|
||||
#endif
|
||||
|
||||
#define sdunit(x) (minor(x) >> 3)
|
||||
#define sdpart(x) (minor(x) & 0x7)
|
||||
|
||||
#define b_cylin b_resid
|
||||
|
||||
#define SDRETRY 2
|
||||
|
||||
/*
|
||||
* Table of scsi commands users are allowed to access via `format'
|
||||
* mode. 0 means not legal. 1 means `immediate' (doesn't need dma).
|
||||
* -1 means needs dma and/or wait for intr (i.e., `slow').
|
||||
*/
|
||||
static char legal_cmds[256] = {
|
||||
/***** 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
||||
/*00*/ 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*10*/ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
|
||||
/*20*/ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*a0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
int
|
||||
sdmatch(parent, cf, aux)
|
||||
struct device *parent;
|
||||
register struct cfdata *cf;
|
||||
void *aux;
|
||||
{
|
||||
register struct scsi_attach_args *sa = aux;
|
||||
#ifdef DEBUG
|
||||
char *whynot;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* unit number must match, or be given as `any'
|
||||
*/
|
||||
if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != sa->sa_unit)
|
||||
return (0);
|
||||
/*
|
||||
* drive must be a disk, and of a kind we recognize
|
||||
*/
|
||||
if ((sa->sa_inq_status & STS_MASK) != STS_GOOD) {
|
||||
#ifdef DEBUG
|
||||
whynot = "INQUIRY failed";
|
||||
#endif
|
||||
goto notdisk;
|
||||
}
|
||||
|
||||
switch (sa->sa_si.si_type & TYPE_TYPE_MASK) {
|
||||
|
||||
case TYPE_DAD: /* disk */
|
||||
case TYPE_WORM: /* WORM */
|
||||
case TYPE_ROM: /* CD-ROM */
|
||||
case TYPE_MO: /* Magneto-optical */
|
||||
case TYPE_JUKEBOX: /* medium changer */
|
||||
break;
|
||||
|
||||
default:
|
||||
notdisk:
|
||||
#ifdef DEBUG
|
||||
whynot = "not a disk";
|
||||
printf("[not matching `sd' at unit %d: %s]\n",
|
||||
sa->sa_unit, whynot);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* It is a disk of some kind; take it. We will figure out
|
||||
* the rest in the attach routine.
|
||||
*/
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach a disk (called after sdmatch returns true).
|
||||
* Note that this routine is never reentered (so we can use statics).
|
||||
*/
|
||||
void
|
||||
sdattach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
register struct sd_softc *sc = (struct sd_softc *)self;
|
||||
register struct scsi_attach_args *sa = aux;
|
||||
register int i;
|
||||
char vendor[10], drive[17], rev[5];
|
||||
static u_char capbuf[8];
|
||||
static struct scsi_cdb cap = { CMD_READ_CAPACITY };
|
||||
#ifdef SUN_LABEL_HACK
|
||||
static struct scsi_cdb rd0 = { CMD_READ10, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
|
||||
caddr_t sector;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Declare our existence.
|
||||
*/
|
||||
sc->sc_unit.u_driver = &sdunitdriver;
|
||||
scsi_establish(&sc->sc_unit, &sc->sc_dk.dk_dev, sa->sa_unit);
|
||||
|
||||
/*
|
||||
* Figure out what kind of disk this is.
|
||||
* We only accepted it if the inquiry succeeded, so
|
||||
* we can inspect those fields.
|
||||
*/
|
||||
i = (sa->sa_si.si_version >> VER_ANSI_SHIFT) & VER_ANSI_MASK;
|
||||
if (i == 1 || i == 2) {
|
||||
scsi_inq_ansi((struct scsi_inq_ansi *)&sa->sa_si,
|
||||
vendor, drive, rev);
|
||||
printf(": %s %s", vendor, drive);
|
||||
/* XXX should we even ever bother printing this? */
|
||||
if (rev[0])
|
||||
printf(" %s", rev);
|
||||
} else {
|
||||
/* bleah */
|
||||
bcopy("<unknown>", vendor, 10);
|
||||
bcopy("<unknown>", drive, 10);
|
||||
printf(": type 0x%x, qual 0x%x, ver %d",
|
||||
sa->sa_si.si_type, sa->sa_si.si_qual,
|
||||
sa->sa_si.si_version);
|
||||
}
|
||||
|
||||
CDB10(&cap)->cdb_lun_rel = sc->sc_unit.u_unit << 5;
|
||||
i = (*sc->sc_unit.u_hbd->hd_icmd)(sc->sc_unit.u_hba,
|
||||
sc->sc_unit.u_targ, &cap, (char *)capbuf, sizeof capbuf, B_READ);
|
||||
i &= STS_MASK;
|
||||
if (i == STS_GOOD) {
|
||||
#define NUMBER(p) (((p)[0] << 24) | ((p)[1] << 16) | ((p)[2] << 8) | (p)[3])
|
||||
sc->sc_blks = NUMBER(&capbuf[0]);
|
||||
sc->sc_blksize = NUMBER(&capbuf[4]);
|
||||
} else if (i == STS_CHECKCOND &&
|
||||
(strcmp(vendor, "HP") == 0 && strcmp(drive, "S6300.650A") == 0)) {
|
||||
/* XXX unformatted or nonexistent MO medium: fake it */
|
||||
sc->sc_blks = 318664;
|
||||
sc->sc_blksize = 1024;
|
||||
} else {
|
||||
/* XXX shouldn't bail for removable media */
|
||||
printf(": unable to determine drive capacity [sts=%x]\n", i);
|
||||
return;
|
||||
}
|
||||
/* return value from read capacity is last valid block, not nblocks */
|
||||
sc->sc_blks++;
|
||||
printf(", %u %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
|
||||
if (sc->sc_blksize != DEV_BSIZE) {
|
||||
for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1)
|
||||
++sc->sc_bshift;
|
||||
if (i != DEV_BSIZE) {
|
||||
printf("%s: blksize not multiple of %d: cannot use\n",
|
||||
sc->sc_dk.dk_dev.dv_xname, DEV_BSIZE);
|
||||
return;
|
||||
}
|
||||
sc->sc_blks <<= sc->sc_bshift;
|
||||
}
|
||||
sc->sc_type = sa->sa_si.si_type; /* sufficient? */
|
||||
|
||||
sc->sc_dk.dk_driver = &sddkdriver;
|
||||
#ifdef notyet
|
||||
dk_establish(&sc->sc_dk);
|
||||
/* READ DISK LABEL HERE, UNLESS REMOVABLE MEDIUM... NEEDS THOUGHT */
|
||||
#else
|
||||
sc->sc_dk.dk_label.d_secsize = 512; /* XXX */
|
||||
sc->sc_dk.dk_bps = (3600/60) * 32 * 512;/* XXX */
|
||||
|
||||
#ifdef SUN_LABEL_HACK
|
||||
sector = (caddr_t)malloc(sc->sc_blksize, M_DEVBUF, M_NOWAIT);
|
||||
CDB10(&rd0)->cdb_lun_rel = sc->sc_unit.u_unit << 5;
|
||||
i = (*sc->sc_unit.u_hbd->hd_icmd)(sc->sc_unit.u_hba,
|
||||
sc->sc_unit.u_targ, &rd0, sector, sc->sc_blksize, B_READ);
|
||||
if (i == STS_GOOD) {
|
||||
printf("%s: <%s>\n", sc->sc_dk.dk_dev.dv_xname,
|
||||
((struct sun_disklabel *)sector)->sl_text);
|
||||
if (sun_disklabel(sector, &sc->sc_dk.dk_label))
|
||||
sc->sc_flags |= SDF_ALIVE;
|
||||
else
|
||||
printf("%s: sun_disklabel fails\n",
|
||||
sc->sc_dk.dk_dev.dv_xname);
|
||||
} else
|
||||
printf("%s: could not read sector 0 for disk label\n",
|
||||
sc->sc_dk.dk_dev.dv_xname);
|
||||
free(sector, M_DEVBUF);
|
||||
#endif
|
||||
#endif /* notyet */
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset a disk, after a SCSI bus reset.
|
||||
*
|
||||
* XXX untested and probably incomplete/incorrect
|
||||
*/
|
||||
void
|
||||
sdreset(u)
|
||||
register struct unit *u;
|
||||
{
|
||||
register struct sd_softc *sc = (struct sd_softc *)u->u_dev;
|
||||
|
||||
printf(" %s", sc->sc_dk.dk_dev.dv_xname);
|
||||
sc->sc_resets++;
|
||||
}
|
||||
|
||||
/* dev_t is short, must use prototype syntax */
|
||||
int
|
||||
sdopen(dev_t dev, int flags, int ifmt, struct proc *p)
|
||||
{
|
||||
register int unit = sdunit(dev);
|
||||
register struct sd_softc *sc;
|
||||
|
||||
if (unit >= sdcd.cd_ndevs || (sc = sdcd.cd_devs[unit]) == NULL)
|
||||
return (ENXIO);
|
||||
if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag))
|
||||
return (ENXIO);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
sdclose(dev_t dev, int flags, int ifmt, struct proc *p)
|
||||
{
|
||||
register struct sd_softc *sc = sdcd.cd_devs[sdunit(dev)];
|
||||
|
||||
sc->sc_format_pid = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is called for partial block transfers and non-aligned
|
||||
* transfers (the latter only being possible on devices with a block size
|
||||
* larger than DEV_BSIZE). The operation is performed in three steps
|
||||
* using a locally allocated buffer:
|
||||
* 1. transfer any initial partial block
|
||||
* 2. transfer full blocks
|
||||
* 3. transfer any final partial block
|
||||
*/
|
||||
static void
|
||||
sdlblkstrat(bp, bsize)
|
||||
register struct buf *bp;
|
||||
register int bsize;
|
||||
{
|
||||
register int bn, resid, boff, count;
|
||||
register caddr_t addr, cbuf;
|
||||
struct buf *tbp;
|
||||
|
||||
/* should probably use geteblk() here, but I fear consequences */
|
||||
cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK);
|
||||
tbp = (struct buf *)malloc(sizeof *tbp, M_DEVBUF, M_WAITOK);
|
||||
bzero((caddr_t)tbp, sizeof *tbp);
|
||||
tbp->b_proc = curproc;
|
||||
tbp->b_dev = bp->b_dev;
|
||||
bn = bp->b_blkno;
|
||||
resid = bp->b_bcount;
|
||||
addr = bp->b_un.b_addr;
|
||||
#ifdef DEBUG
|
||||
if (sddebug & SDB_PARTIAL)
|
||||
printf("sdlblkstrat: bp %x flags %x bn %x resid %x addr %x\n",
|
||||
bp, bp->b_flags, bn, resid, addr);
|
||||
#endif
|
||||
|
||||
while (resid > 0) {
|
||||
boff = dbtob(bn) & (bsize - 1);
|
||||
if (boff || resid < bsize) {
|
||||
struct sd_softc *sc = sdcd.cd_devs[sdunit(bp->b_dev)];
|
||||
sc->sc_partials++;
|
||||
count = min(resid, bsize - boff);
|
||||
tbp->b_flags = B_BUSY | B_READ;
|
||||
tbp->b_blkno = bn - btodb(boff);
|
||||
tbp->b_un.b_addr = cbuf;
|
||||
tbp->b_bcount = bsize;
|
||||
#ifdef DEBUG
|
||||
if (sddebug & SDB_PARTIAL)
|
||||
printf(" readahead: bn %x cnt %x off %x addr %x\n",
|
||||
tbp->b_blkno, count, boff, addr);
|
||||
#endif
|
||||
sdstrategy(tbp);
|
||||
biowait(tbp);
|
||||
if (tbp->b_flags & B_ERROR) {
|
||||
bp->b_flags |= B_ERROR;
|
||||
bp->b_error = tbp->b_error;
|
||||
break;
|
||||
}
|
||||
if (bp->b_flags & B_READ) {
|
||||
bcopy(&cbuf[boff], addr, count);
|
||||
goto done;
|
||||
}
|
||||
bcopy(addr, &cbuf[boff], count);
|
||||
#ifdef DEBUG
|
||||
if (sddebug & SDB_PARTIAL)
|
||||
printf(" writeback: bn %x cnt %x off %x addr %x\n",
|
||||
tbp->b_blkno, count, boff, addr);
|
||||
#endif
|
||||
} else {
|
||||
count = resid & ~(bsize - 1);
|
||||
tbp->b_blkno = bn;
|
||||
tbp->b_un.b_addr = addr;
|
||||
tbp->b_bcount = count;
|
||||
#ifdef DEBUG
|
||||
if (sddebug & SDB_PARTIAL)
|
||||
printf(" fulltrans: bn %x cnt %x addr %x\n",
|
||||
tbp->b_blkno, count, addr);
|
||||
#endif
|
||||
}
|
||||
tbp->b_flags = B_BUSY | (bp->b_flags & B_READ);
|
||||
sdstrategy(tbp);
|
||||
biowait(tbp);
|
||||
if (tbp->b_flags & B_ERROR) {
|
||||
bp->b_flags |= B_ERROR;
|
||||
bp->b_error = tbp->b_error;
|
||||
break;
|
||||
}
|
||||
done:
|
||||
bn += btodb(count);
|
||||
resid -= count;
|
||||
addr += count;
|
||||
#ifdef DEBUG
|
||||
if (sddebug & SDB_PARTIAL)
|
||||
printf(" done: bn %x resid %x addr %x\n",
|
||||
bn, resid, addr);
|
||||
#endif
|
||||
}
|
||||
free(cbuf, M_DEVBUF);
|
||||
free((caddr_t)tbp, M_DEVBUF);
|
||||
biodone(bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start a transfer on sc as described by bp
|
||||
* (i.e., call hba or target start).
|
||||
* If in format mode, we may not need dma.
|
||||
*/
|
||||
#define sdstart(sc, bp) { \
|
||||
SD_TRACE(T_START, sc, bp); \
|
||||
if ((sc)->sc_format_pid && legal_cmds[(sc)->sc_cmd.cdb_bytes[0]] > 0) \
|
||||
(*(sc)->sc_unit.u_start)((sc)->sc_unit.u_updev, \
|
||||
&(sc)->sc_unit.u_forw, (struct buf *)NULL, \
|
||||
sdigo, &(sc)->sc_dk.dk_dev); \
|
||||
else \
|
||||
(*(sc)->sc_unit.u_start)((sc)->sc_unit.u_updev, \
|
||||
&(sc)->sc_unit.u_forw, bp, sdgo, &(sc)->sc_dk.dk_dev); \
|
||||
}
|
||||
|
||||
void
|
||||
sdstrategy(bp)
|
||||
register struct buf *bp;
|
||||
{
|
||||
register struct sd_softc *sc = sdcd.cd_devs[sdunit(bp->b_dev)];
|
||||
register int s;
|
||||
|
||||
if (sc->sc_format_pid) {
|
||||
/* XXXXXXXXX SHOULD NOT COMPARE curproc IN HERE!?! */
|
||||
/*
|
||||
* In format mode, only allow the owner to mess
|
||||
* with the drive. Skip all the partition checks.
|
||||
*/
|
||||
if (sc->sc_format_pid != curproc->p_pid) {
|
||||
bp->b_error = EPERM;
|
||||
bp->b_flags |= B_ERROR;
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
bp->b_cylin = 0;
|
||||
} else {
|
||||
register daddr_t bn = bp->b_blkno;
|
||||
register int sz = howmany(bp->b_bcount, DEV_BSIZE);
|
||||
register struct partition *p;
|
||||
|
||||
/*
|
||||
* Make sure transfer is within partition.
|
||||
* If it starts at the end, return EOF; if
|
||||
* it extends past the end, truncate it.
|
||||
*/
|
||||
p = &sc->sc_dk.dk_label.d_partitions[sdpart(bp->b_dev)];
|
||||
if ((unsigned)bn >= p->p_size) {
|
||||
if ((unsigned)bn > p->p_size) {
|
||||
bp->b_error = EINVAL;
|
||||
bp->b_flags |= B_ERROR;
|
||||
} else
|
||||
bp->b_resid = bp->b_bcount;
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
if (bn + sz > p->p_size) {
|
||||
sz = p->p_size - bn;
|
||||
bp->b_bcount = dbtob(sz);
|
||||
}
|
||||
/*
|
||||
* Non-aligned or partial-block transfers handled specially.
|
||||
* SHOULD THIS BE AT A HIGHER LEVEL?
|
||||
*/
|
||||
s = sc->sc_blksize - 1;
|
||||
if ((dbtob(bn) & s) || (bp->b_bcount & s)) {
|
||||
sdlblkstrat(bp, sc->sc_blksize);
|
||||
return;
|
||||
}
|
||||
bp->b_cylin = (bn + p->p_offset) >> sc->sc_bshift;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transfer valid, or format mode. Queue the request
|
||||
* on the drive, and maybe try to start it.
|
||||
*/
|
||||
s = splbio();
|
||||
disksort(&sc->sc_tab, bp);
|
||||
if (sc->sc_tab.b_active == 0) {
|
||||
sc->sc_tab.b_active = 1;
|
||||
sdstart(sc, bp);
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
||||
int
|
||||
sderror(sc, stat)
|
||||
register struct sd_softc *sc;
|
||||
register int stat;
|
||||
{
|
||||
register struct scsi_sense *sn;
|
||||
int retry = 0;
|
||||
|
||||
sc->sc_sense.status = stat;
|
||||
if ((stat & STS_MASK) == STS_CHECKCOND) {
|
||||
sn = (struct scsi_sense *)sc->sc_sense.sense;
|
||||
stat = scsi_request_sense(sc->sc_unit.u_hba,
|
||||
sc->sc_unit.u_targ, sc->sc_unit.u_unit,
|
||||
(caddr_t)sn, sizeof sc->sc_sense.sense);
|
||||
sc->sc_sense.status = stat; /* ??? */
|
||||
if ((stat & STS_MASK) != STS_GOOD) {
|
||||
printf("%s: sense failed, status %x\n",
|
||||
sc->sc_dk.dk_dev.dv_xname, stat);
|
||||
return (0);
|
||||
}
|
||||
printf("%s: scsi sense class %d, code %d",
|
||||
sc->sc_dk.dk_dev.dv_xname,
|
||||
SENSE_ECLASS(sn), SENSE_ECODE(sn));
|
||||
if (SENSE_ISXSENSE(sn) && XSENSE_ISSTD(sn)) {
|
||||
int key;
|
||||
|
||||
/*
|
||||
* Standard extended sense: can examine sense key
|
||||
* and (if valid) info.
|
||||
*/
|
||||
key = XSENSE_KEY(sn);
|
||||
printf(", key %d", key);
|
||||
if (XSENSE_IVALID(sn))
|
||||
printf(", blk %d", XSENSE_INFO(sn));
|
||||
/* no sense or recovered error, try again */
|
||||
if (key == 0 || key == 1)
|
||||
retry = 1;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
return (retry);
|
||||
}
|
||||
|
||||
/*
|
||||
* sdigo is called from the hba driver when it has got the scsi bus
|
||||
* for us, and we were doing a format op that did not need dma.
|
||||
*/
|
||||
void
|
||||
sdigo(sc0, cdb)
|
||||
struct device *sc0;
|
||||
struct scsi_cdb *cdb;
|
||||
{
|
||||
register struct sd_softc *sc = (struct sd_softc *)sc0;
|
||||
register struct buf *bp = sc->sc_tab.b_actf;
|
||||
register int stat;
|
||||
|
||||
stat = (*sc->sc_unit.u_hbd->hd_icmd)(sc->sc_unit.u_hba,
|
||||
sc->sc_unit.u_targ, &sc->sc_cmd, bp->b_un.b_addr, bp->b_bcount,
|
||||
bp->b_flags & B_READ);
|
||||
sc->sc_sense.status = stat;
|
||||
if (stat & 0xfe) { /* XXX */
|
||||
(void) sderror(sc, stat);
|
||||
bp->b_flags |= B_ERROR;
|
||||
bp->b_error = EIO;
|
||||
}
|
||||
/*
|
||||
* Done with SCSI bus, before we `ought' to be. Release it.
|
||||
*/
|
||||
(*sc->sc_unit.u_rel)(sc->sc_unit.u_updev);
|
||||
bp->b_resid = 0;
|
||||
sc->sc_tab.b_errcnt = 0;
|
||||
sc->sc_tab.b_actf = bp->b_actf;
|
||||
biodone(bp);
|
||||
if ((bp = sc->sc_tab.b_actf) == NULL)
|
||||
sc->sc_tab.b_active = 0;
|
||||
else
|
||||
sdstart(sc, bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* sdgo is called from the hba driver or target code when it has
|
||||
* allocated the scsi bus and DMA resources and target datapath for us.
|
||||
*/
|
||||
void
|
||||
sdgo(sc0, cdb)
|
||||
struct device *sc0;
|
||||
register struct scsi_cdb *cdb;
|
||||
{
|
||||
register struct sd_softc *sc = (struct sd_softc *)sc0;
|
||||
register struct buf *bp = sc->sc_tab.b_actf;
|
||||
register int n;
|
||||
register unsigned int u;
|
||||
|
||||
SD_TRACE(T_MKCDB, sc, bp);
|
||||
if (sc->sc_format_pid) {
|
||||
*cdb = sc->sc_cmd;
|
||||
n = 0;
|
||||
} else {
|
||||
CDB10(cdb)->cdb_cmd = bp->b_flags & B_READ ? CMD_READ10 :
|
||||
CMD_WRITE10;
|
||||
CDB10(cdb)->cdb_lun_rel = sc->sc_unit.u_unit << 5;
|
||||
u = bp->b_cylin;
|
||||
CDB10(cdb)->cdb_lbah = u >> 24;
|
||||
CDB10(cdb)->cdb_lbahm = u >> 16;
|
||||
CDB10(cdb)->cdb_lbalm = u >> 8;
|
||||
CDB10(cdb)->cdb_lbal = u;
|
||||
CDB10(cdb)->cdb_xxx = 0;
|
||||
n = sc->sc_blksize - 1;
|
||||
u = (bp->b_bcount + n) >> (DEV_BSHIFT + sc->sc_bshift);
|
||||
CDB10(cdb)->cdb_lenh = u >> 8;
|
||||
CDB10(cdb)->cdb_lenl = u;
|
||||
CDB10(cdb)->cdb_ctrl = 0;
|
||||
n = (bp->b_bcount & n) != 0;
|
||||
#ifdef DEBUG
|
||||
if (n)
|
||||
printf("%s: partial block xfer -- %x bytes\n",
|
||||
sc->sc_dk.dk_dev.dv_xname, bp->b_bcount);
|
||||
#endif
|
||||
sc->sc_transfers++;
|
||||
}
|
||||
if ((*sc->sc_unit.u_go)(sc->sc_unit.u_updev, sc->sc_unit.u_targ,
|
||||
sdintr, (void *)sc, bp, n) == 0) {
|
||||
#ifdef notyet
|
||||
sc->sc_dk.dk_busy = 1;
|
||||
sc->sc_dk.dk_seek++; /* XXX */
|
||||
sc->sc_dk.dk_xfer++;
|
||||
sc->sc_dk.dk_wds += bp->b_bcount >> 6;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Some sort of nasty unrecoverable error: clobber the
|
||||
* transfer. Call the bus release function first, though.
|
||||
*/
|
||||
(*sc->sc_unit.u_rel)(sc->sc_unit.u_updev);
|
||||
#ifdef DEBUG
|
||||
if (sddebug & SDB_ERROR)
|
||||
printf("%s: sdgo: %s adr %d blk %d len %d ecnt %d\n",
|
||||
sc->sc_dk.dk_dev.dv_xname,
|
||||
bp->b_flags & B_READ? "read" : "write",
|
||||
bp->b_un.b_addr, bp->b_cylin, bp->b_bcount,
|
||||
sc->sc_tab.b_errcnt);
|
||||
#endif
|
||||
bp->b_flags |= B_ERROR;
|
||||
bp->b_error = EIO;
|
||||
bp->b_resid = 0;
|
||||
sc->sc_tab.b_errcnt = 0;
|
||||
sc->sc_tab.b_actf = bp->b_actf;
|
||||
biodone(bp);
|
||||
if ((bp = sc->sc_tab.b_actf) == NULL)
|
||||
sc->sc_tab.b_active = 0;
|
||||
else
|
||||
sdstart(sc, bp);
|
||||
}
|
||||
|
||||
/*
|
||||
* A transfer finished (or, someday, disconnected).
|
||||
* We are already off the target/hba queues.
|
||||
* Restart this one for error recovery, or start the next, as appropriate.
|
||||
*/
|
||||
void
|
||||
sdintr(sc0, stat, resid)
|
||||
struct device *sc0;
|
||||
int stat, resid;
|
||||
{
|
||||
register struct sd_softc *sc = (struct sd_softc *)sc0;
|
||||
register struct buf *bp = sc->sc_tab.b_actf;
|
||||
int retry;
|
||||
|
||||
if (bp == NULL)
|
||||
panic("sdintr");
|
||||
SD_TRACE(T_INTR, sc, bp);
|
||||
#ifdef notyet
|
||||
sc->sc_dk.dk_busy = 0;
|
||||
#endif
|
||||
if ((stat & STS_MASK) != STS_GOOD) {
|
||||
#ifdef DEBUG
|
||||
if (sddebug & SDB_ERROR)
|
||||
printf("%s: sdintr scsi status 0x%x resid %d\n",
|
||||
sc->sc_dk.dk_dev.dv_xname, stat, resid);
|
||||
#endif
|
||||
retry = sderror(sc, stat);
|
||||
if (retry && ++sc->sc_tab.b_errcnt <= SDRETRY) {
|
||||
printf("%s: retry %d\n",
|
||||
sc->sc_dk.dk_dev.dv_xname, sc->sc_tab.b_errcnt);
|
||||
goto restart;
|
||||
}
|
||||
bp->b_flags |= B_ERROR;
|
||||
bp->b_error = EIO;
|
||||
}
|
||||
bp->b_resid = resid;
|
||||
sc->sc_tab.b_errcnt = 0;
|
||||
sc->sc_tab.b_actf = bp->b_actf;
|
||||
biodone(bp);
|
||||
if ((bp = sc->sc_tab.b_actf) == NULL)
|
||||
sc->sc_tab.b_active = 0;
|
||||
else {
|
||||
restart:
|
||||
sdstart(sc, bp);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
sdioctl(dev_t dev, int cmd, register caddr_t data, int flag, struct proc *p)
|
||||
{
|
||||
register struct sd_softc *sc = sdcd.cd_devs[sdunit(dev)];
|
||||
#ifdef COMPAT_SUNOS
|
||||
int error;
|
||||
|
||||
error = sun_dkioctl(&sc->sc_dk, cmd, data, sdpart(dev));
|
||||
if (error >= 0)
|
||||
return (error);
|
||||
#endif
|
||||
switch (cmd) {
|
||||
|
||||
case SDIOCSFORMAT:
|
||||
/* take this device into or out of "format" mode */
|
||||
if (suser(p->p_ucred, &p->p_acflag))
|
||||
return (EPERM);
|
||||
if (*(int *)data) {
|
||||
if (sc->sc_format_pid)
|
||||
return (EPERM);
|
||||
sc->sc_format_pid = p->p_pid;
|
||||
} else
|
||||
sc->sc_format_pid = 0;
|
||||
break;
|
||||
|
||||
case SDIOCGFORMAT:
|
||||
/* find out who has the device in format mode */
|
||||
*(int *)data = sc->sc_format_pid;
|
||||
break;
|
||||
|
||||
case SDIOCSCSICOMMAND:
|
||||
#define cdb ((struct scsi_cdb *)data)
|
||||
/*
|
||||
* Save what user gave us as SCSI cdb to use with next
|
||||
* read or write to the char device. Be sure to replace
|
||||
* the lun field with the actual unit number.
|
||||
*/
|
||||
if (sc->sc_format_pid != p->p_pid)
|
||||
return (EPERM);
|
||||
if (legal_cmds[cdb->cdb_bytes[0]] == 0)
|
||||
return (EINVAL);
|
||||
sc->sc_cmd = *cdb;
|
||||
sc->sc_cmd.cdb_bytes[1] =
|
||||
(sc->sc_cmd.cdb_bytes[1] & ~(7 << 5)) |
|
||||
(sc->sc_unit.u_unit << 5);
|
||||
#undef cdb
|
||||
break;
|
||||
|
||||
case SDIOCSENSE:
|
||||
/*
|
||||
* return the SCSI sense data saved after the last
|
||||
* operation that completed with "check condition" status.
|
||||
*/
|
||||
sc->sc_sense = *(struct scsi_fmt_sense *)data;
|
||||
break;
|
||||
|
||||
case DIOCGDINFO:
|
||||
*(struct disklabel *)data = sc->sc_dk.dk_label;
|
||||
break;
|
||||
|
||||
case DIOCGPART:
|
||||
((struct partinfo *)data)->disklab = &sc->sc_dk.dk_label;
|
||||
((struct partinfo *)data)->part =
|
||||
&sc->sc_dk.dk_label.d_partitions[sdpart(dev)];
|
||||
break;
|
||||
|
||||
default:
|
||||
return (ENOTTY);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
sdsize(dev_t dev)
|
||||
{
|
||||
register int unit = sdunit(dev);
|
||||
register struct sd_softc *sc;
|
||||
|
||||
if (unit >= sdcd.cd_ndevs || (sc = sdcd.cd_devs[unit]) == NULL ||
|
||||
(sc->sc_flags & SDF_ALIVE) == 0)
|
||||
return (-1);
|
||||
return (sc->sc_dk.dk_label.d_partitions[sdpart(dev)].p_size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write `len' bytes from address `addr' to drive and partition in `dev',
|
||||
* at block blkoff from the beginning of the partition. The address is
|
||||
* either kernel virtual or physical (some machines may never use one or
|
||||
* the other, but we need it in the protocol to stay machine-independent).
|
||||
*/
|
||||
int
|
||||
sddump(dev_t dev, daddr_t blkoff, caddr_t addr, int len)
|
||||
{
|
||||
register struct sd_softc *sc;
|
||||
register struct partition *p;
|
||||
register daddr_t bn, n, nblks;
|
||||
register struct hba_softc *hba;
|
||||
register int stat, unit;
|
||||
struct scsi_cdb cdb;
|
||||
|
||||
/* drive ok? */
|
||||
unit = sdunit(dev);
|
||||
if (unit >= sdcd.cd_ndevs || (sc = sdcd.cd_devs[unit]) == NULL ||
|
||||
(sc->sc_flags & SDF_ALIVE) == 0)
|
||||
return (ENXIO);
|
||||
|
||||
/* blocks in range? */
|
||||
p = &sc->sc_dk.dk_label.d_partitions[sdpart(dev)];
|
||||
n = (len + sc->sc_blksize - 1) >> DEV_BSHIFT;
|
||||
if (blkoff < 0 || blkoff >= p->p_size || blkoff + n > p->p_size)
|
||||
return (EINVAL);
|
||||
bn = blkoff + p->p_offset;
|
||||
bn >>= sc->sc_bshift;
|
||||
|
||||
/* scsi bus idle? */
|
||||
hba = sc->sc_unit.u_hba;
|
||||
if (hba->hba_head) {
|
||||
(*hba->hba_driver->hd_reset)(hba, 0);
|
||||
printf("[reset %s] ", sc->sc_dk.dk_dev.dv_xname);
|
||||
}
|
||||
|
||||
CDB10(&cdb)->cdb_cmd = CMD_WRITE10;
|
||||
CDB10(&cdb)->cdb_lun_rel = sc->sc_unit.u_unit << 5;
|
||||
CDB10(&cdb)->cdb_xxx = 0;
|
||||
CDB10(&cdb)->cdb_ctrl = 0;
|
||||
|
||||
#define DUMP_MAX (32 * 1024) /* no more than 32k per write */
|
||||
for (;;) {
|
||||
if ((n = len) > DUMP_MAX)
|
||||
n = DUMP_MAX;
|
||||
CDB10(&cdb)->cdb_lbah = bn >> 24;
|
||||
CDB10(&cdb)->cdb_lbahm = bn >> 16;
|
||||
CDB10(&cdb)->cdb_lbalm = bn >> 8;
|
||||
CDB10(&cdb)->cdb_lbal = bn;
|
||||
nblks = n >> (DEV_BSHIFT + sc->sc_bshift);
|
||||
CDB10(&cdb)->cdb_lenh = nblks >> 8;
|
||||
CDB10(&cdb)->cdb_lenl = nblks;
|
||||
stat = hba->hba_driver->hd_dump(hba, sc->sc_unit.u_targ,
|
||||
&cdb, addr, n);
|
||||
if ((stat & STS_MASK) != STS_GOOD) {
|
||||
printf("%s: scsi write error 0x%x\ndump ",
|
||||
sc->sc_dk.dk_dev.dv_xname, stat);
|
||||
return (EIO);
|
||||
}
|
||||
if ((len -= n) == 0)
|
||||
return (0);
|
||||
addr += n;
|
||||
bn += nblks;
|
||||
}
|
||||
}
|
92
sys/dev/scsi/sdtrace.h
Normal file
92
sys/dev/scsi/sdtrace.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratories.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)sdtrace.h 8.1 (Berkeley) 6/10/93
|
||||
*
|
||||
* from: $Header: /cvsroot/src/sys/dev/scsi/Attic/sdtrace.h,v 1.1.1.1 1998/03/01 02:09:34 fvdl Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCSI disk command tracing
|
||||
*/
|
||||
|
||||
#if defined(SDTRACE) || !defined(KERNEL)
|
||||
struct sdtrace {
|
||||
struct timeval time; /* timestamp */
|
||||
u_int block; /* disk block */
|
||||
u_int bcount; /* # bytes transferred */
|
||||
u_char tcode; /* trace code */
|
||||
u_char target; /* target number */
|
||||
u_char unit; /* unit number on target */
|
||||
u_char read; /* read operation */
|
||||
};
|
||||
|
||||
#define T_START 0x01
|
||||
#define T_MKCDB 0x02
|
||||
#define T_INTR 0x03
|
||||
#endif
|
||||
|
||||
#ifdef SDTRACE
|
||||
/* Allow kernel config to override number of entries */
|
||||
#ifndef NSDOPBUF
|
||||
#define NSDOPBUF 1024
|
||||
#endif
|
||||
|
||||
struct sdtrace sdopbuf[NSDOPBUF];
|
||||
struct sdtrace *sdopptr = sdopbuf;
|
||||
int nsdopbuf = NSDOPBUF; /* for sdtrace */
|
||||
u_long sdopcnt;
|
||||
|
||||
#define SD_TRACE(code, sc, bp) { \
|
||||
if (++sdopptr >= &sdopbuf[NSDOPBUF]) \
|
||||
sdopptr = sdopbuf; \
|
||||
microtime(&sdopptr->time); \
|
||||
sdopptr->tcode = code; \
|
||||
sdopptr->read = bp->b_flags & B_READ; \
|
||||
sdopptr->block = bp->b_blkno; \
|
||||
sdopptr->bcount = bp->b_bcount; \
|
||||
sdopptr->target = sc->sc_unit.u_targ; \
|
||||
sdopptr->unit = sc->sc_unit.u_unit; \
|
||||
++sdopcnt; \
|
||||
}
|
||||
#else
|
||||
#define SD_TRACE(code, sc, bp) { }
|
||||
#endif
|
150
sys/dev/scsi/tape.h
Normal file
150
sys/dev/scsi/tape.h
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Lawrence Berkeley Laboratories.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)tape.h 8.1 (Berkeley) 6/10/93
|
||||
*
|
||||
* from: $Header: /cvsroot/src/sys/dev/scsi/Attic/tape.h,v 1.1.1.1 1998/03/01 02:09:34 fvdl Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCSI definitions for Sequential Access Devices (tapes).
|
||||
*
|
||||
* Commands defined in common headers (scsi.h or disktape.h) are omitted.
|
||||
*/
|
||||
#define CMD_REWIND 0x01 /* rewind */
|
||||
#define CMD_READ_BLOCK_LIMITS 0x05 /* read block limits */
|
||||
#define CMD_READ 0x08 /* read */
|
||||
#define CMD_WRITE 0x0a /* write */
|
||||
#define CMD_TRACK_SELECT 0x0b /* track select */
|
||||
#define CMD_READ_REVERSE 0x0f /* read reverse */
|
||||
#define CMD_WRITE_FILEMARK 0x10 /* write file marks */
|
||||
#define CMD_SPACE 0x11 /* space */
|
||||
#define CMD_VERIFY 0x13 /* verify */
|
||||
#define CMD_RBD 0x14 /* recover buffered data */
|
||||
#define CMD_RESERVE_UNIT 0x16 /* reserve unit */
|
||||
#define CMD_RELEASE_UNIT 0x17 /* release unit */
|
||||
/* CMD_COPY 0x18 copy (common to all scsi devs) */
|
||||
#define CMD_ERASE 0x19 /* erase */
|
||||
#define CMD_LOAD_UNLOAD 0x1b /* load/unload */
|
||||
#define CMD_PAMR 0x1e /* prevent/allow medium removal */
|
||||
|
||||
/*
|
||||
* Structure of READ, WRITE, READ REVERSE, RECOVER BUFFERED DATA
|
||||
* commands (i.e., the cdb).
|
||||
* Also used for VERIFY commands.
|
||||
*/
|
||||
struct scsi_cdb_rw {
|
||||
u_char cdb_cmd, /* 0x08 or 0x0a or 0x0f or 0x13 or 0x14 */
|
||||
cdb_lun_bf, /* LUN + reserved + bytecmp + fixed */
|
||||
cdb_lenh, /* transfer length (MSB) */
|
||||
cdb_lenm, /* transfer length */
|
||||
cdb_lenl, /* transfer length (LSB) */
|
||||
cdb_ctrl; /* control byte */
|
||||
};
|
||||
#define SCSI_RW_BYTECMP 0x02 /* byte compare flag if verify */
|
||||
#define SCSI_RW_FIXEDBLK 0x01 /* fixed block size for read/write */
|
||||
|
||||
/*
|
||||
* Structure of a TRACK SELECT command.
|
||||
*/
|
||||
struct scsi_cdb_ts {
|
||||
u_char cdb_cmd, /* 0x0b */
|
||||
cdb_lun_xxx, /* logical unit number + reserved */
|
||||
cdb_xxx1, /* reserved */
|
||||
cdb_xxx2, /* reserved */
|
||||
cdb_track, /* track value */
|
||||
cdb_ctrl; /* control byte */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure of a WRITE FILEMARKS command.
|
||||
*/
|
||||
struct scsi_cdb_wfm {
|
||||
u_char cdb_cmd, /* 0x0b */
|
||||
cdb_lun_xxx, /* logical unit number + reserved */
|
||||
cdb_nfh, /* number of filemarks (MSB) */
|
||||
cdb_nfm, /* number of filemarks */
|
||||
cdb_nfl, /* number of filemarks (LSB) */
|
||||
cdb_ctrl; /* control byte */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure of a SPACE command.
|
||||
*/
|
||||
struct scsi_cdb_space {
|
||||
u_char cdb_cmd, /* 0x0b */
|
||||
cdb_lun_code, /* LUN + reserved + 2-bit code */
|
||||
cdb_counth, /* count (MSB) */
|
||||
cdb_countm, /* count */
|
||||
cdb_countl, /* count (LSB) */
|
||||
cdb_ctrl; /* control byte */
|
||||
};
|
||||
#define SCSI_CMD_SPACE_BLOCKS 0 /* skip blocks */
|
||||
#define SCSI_CMD_SPACE_FMS 1 /* skip file marks */
|
||||
#define SCSI_CMD_SPACE_SFMS 2 /* skip sequential file marks */
|
||||
#define SCSI_CMD_SPACE_PEOD 3 /* skip to physical end of data */
|
||||
|
||||
/*
|
||||
* Structure of an ERASE command.
|
||||
*/
|
||||
struct scsi_cdb_erase {
|
||||
u_char cdb_cmd, /* 0x0b */
|
||||
cdb_lun_long, /* LUN + reserved + long-erase flag */
|
||||
cdb_xxx1, /* reserved */
|
||||
cdb_xxx2, /* reserved */
|
||||
cdb_xxx3, /* reserved */
|
||||
cdb_ctrl; /* control byte */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure of a LOAD/UNLOAD command.
|
||||
*/
|
||||
struct scsi_cdb_lu {
|
||||
u_char cdb_cmd, /* 0x1b */
|
||||
cdb_lun_immed, /* LUN + reserved + immediate flag */
|
||||
cdb_xxx1, /* reserved */
|
||||
cdb_xxx2, /* reserved */
|
||||
cdb_rl, /* reserved + retension flag + load flag */
|
||||
cdb_ctrl; /* control byte */
|
||||
};
|
||||
#define SCSI_LU_RL_RETEN 0x02 /* retension */
|
||||
#define SCSI_LU_RL_LOAD 0x01 /* load */
|
||||
#define SCSI_LU_RL_UNLOAD 0x00 /* unload (pseudo flag) */
|
50
sys/net/bpf_compat.h
Normal file
50
sys/net/bpf_compat.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)bpf_compat.h 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
/* from: $Header: /cvsroot/src/sys/net/Attic/bpf_compat.h,v 1.1.1.1 1998/03/01 02:10:05 fvdl Exp $ (LBL) */
|
||||
|
||||
/*
|
||||
* Some hacks for compatibility across SunOS and 4.4BSD. We emulate malloc
|
||||
* and free with mbuf clusters. We store a pointer to the mbuf in the first
|
||||
* word of the mbuf and return 8 bytes passed the start of data (for double
|
||||
* word alignment). We cannot just use offsets because clusters are not at
|
||||
* a fixed offset from the associated mbuf. Sorry for this kludge.
|
||||
*/
|
||||
#define malloc(size, type, canwait) bpf_alloc(size, canwait)
|
||||
#define free(cp, type) m_free(*(struct mbuf **)(cp - 8))
|
||||
#define M_WAITOK M_WAIT
|
||||
|
||||
/* This mapping works for our purposes. */
|
||||
#define ERESTART EINTR
|
3
sys/netiso/xebec/TRACE
Normal file
3
sys/netiso/xebec/TRACE
Normal file
@ -0,0 +1,3 @@
|
||||
IFTRACE(D_DRIVER)
|
||||
tptrace(DRIVERTRACE, a->a_newstate, p->tp_state, e->ev_number, a->a_action, 0);
|
||||
ENDTRACE
|
186
sys/sys/fbio.h
Normal file
186
sys/sys/fbio.h
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software developed by the Computer Systems
|
||||
* Engineering group at Lawrence Berkeley Laboratory under DARPA
|
||||
* contract BG 91-66 and contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)fbio.h 8.2 (Berkeley) 10/30/93
|
||||
*
|
||||
* from: $Header: /cvsroot/src/sys/sys/Attic/fbio.h,v 1.1.1.1 1998/03/01 02:11:03 fvdl Exp $ (LBL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Frame buffer ioctls (from Sprite, trimmed to essentials for X11).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Frame buffer type codes.
|
||||
*/
|
||||
#define FBTYPE_SUN1BW 0 /* multibus mono */
|
||||
#define FBTYPE_SUN1COLOR 1 /* multibus color */
|
||||
#define FBTYPE_SUN2BW 2 /* memory mono */
|
||||
#define FBTYPE_SUN2COLOR 3 /* color w/rasterop chips */
|
||||
#define FBTYPE_SUN2GP 4 /* GP1/GP2 */
|
||||
#define FBTYPE_SUN5COLOR 5 /* RoadRunner accelerator */
|
||||
#define FBTYPE_SUN3COLOR 6 /* memory color */
|
||||
#define FBTYPE_MEMCOLOR 7 /* memory 24-bit */
|
||||
#define FBTYPE_SUN4COLOR 8 /* memory color w/overlay */
|
||||
|
||||
#define FBTYPE_NOTSUN1 9 /* reserved for customer */
|
||||
#define FBTYPE_NOTSUN2 10 /* reserved for customer */
|
||||
#define FBTYPE_NOTSUN3 11 /* reserved for customer */
|
||||
|
||||
#define FBTYPE_SUNFAST_COLOR 12 /* accelerated 8bit */
|
||||
#define FBTYPE_SUNROP_COLOR 13 /* MEMCOLOR with rop h/w */
|
||||
#define FBTYPE_SUNFB_VIDEO 14 /* Simple video mixing */
|
||||
#define FBTYPE_RESERVED5 15 /* reserved, do not use */
|
||||
#define FBTYPE_RESERVED4 16 /* reserved, do not use */
|
||||
#define FBTYPE_RESERVED3 17 /* reserved, do not use */
|
||||
#define FBTYPE_RESERVED2 18 /* reserved, do not use */
|
||||
#define FBTYPE_RESERVED1 19 /* reserved, do not use */
|
||||
|
||||
#define FBTYPE_LASTPLUSONE 20 /* max number of fbs (change as add) */
|
||||
|
||||
/*
|
||||
* Frame buffer descriptor as returned by FBIOGTYPE.
|
||||
*/
|
||||
struct fbtype {
|
||||
int fb_type; /* as defined above */
|
||||
int fb_height; /* in pixels */
|
||||
int fb_width; /* in pixels */
|
||||
int fb_depth; /* bits per pixel */
|
||||
int fb_cmsize; /* size of color map (entries) */
|
||||
int fb_size; /* total size in bytes */
|
||||
};
|
||||
#define FBIOGTYPE _IOR('F', 0, struct fbtype)
|
||||
|
||||
#ifdef notdef
|
||||
/*
|
||||
* General purpose structure for passing info in and out of frame buffers
|
||||
* (used for gp1) -- unsupported.
|
||||
*/
|
||||
struct fbinfo {
|
||||
int fb_physaddr; /* physical frame buffer address */
|
||||
int fb_hwwidth; /* fb board width */
|
||||
int fb_hwheight; /* fb board height */
|
||||
int fb_addrdelta; /* phys addr diff between boards */
|
||||
u_char *fb_ropaddr; /* fb virtual addr */
|
||||
int fb_unit; /* minor devnum of fb */
|
||||
};
|
||||
#define FBIOGINFO _IOR('F', 2, struct fbinfo)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Color map I/O.
|
||||
*/
|
||||
struct fbcmap {
|
||||
int index; /* first element (0 origin) */
|
||||
int count; /* number of elements */
|
||||
u_char *red; /* red color map elements */
|
||||
u_char *green; /* green color map elements */
|
||||
u_char *blue; /* blue color map elements */
|
||||
};
|
||||
#define FBIOPUTCMAP _IOW('F', 3, struct fbcmap)
|
||||
#define FBIOGETCMAP _IOW('F', 4, struct fbcmap)
|
||||
|
||||
/*
|
||||
* Set/get attributes.
|
||||
*/
|
||||
#define FB_ATTR_NDEVSPECIFIC 8 /* no. of device specific values */
|
||||
#define FB_ATTR_NEMUTYPES 4 /* no. of emulation types */
|
||||
|
||||
struct fbsattr {
|
||||
int flags; /* flags; see below */
|
||||
int emu_type; /* emulation type (-1 if unused) */
|
||||
int dev_specific[FB_ATTR_NDEVSPECIFIC]; /* catchall */
|
||||
};
|
||||
#define FB_ATTR_AUTOINIT 1 /* emulation auto init flag */
|
||||
#define FB_ATTR_DEVSPECIFIC 2 /* dev. specific stuff valid flag */
|
||||
|
||||
struct fbgattr {
|
||||
int real_type; /* real device type */
|
||||
int owner; /* PID of owner, 0 if myself */
|
||||
struct fbtype fbtype; /* fbtype info for real device */
|
||||
struct fbsattr sattr; /* see above */
|
||||
int emu_types[FB_ATTR_NEMUTYPES]; /* possible emulations */
|
||||
/* (-1 if unused) */
|
||||
};
|
||||
/* FBIOSATTR _IOW('F', 5, struct fbsattr) -- unsupported */
|
||||
#define FBIOGATTR _IOR('F', 6, struct fbgattr)
|
||||
|
||||
/*
|
||||
* Video control.
|
||||
*/
|
||||
#define FBVIDEO_OFF 0
|
||||
#define FBVIDEO_ON 1
|
||||
|
||||
#define FBIOSVIDEO _IOW('F', 7, int)
|
||||
#define FBIOGVIDEO _IOR('F', 8, int)
|
||||
|
||||
/*
|
||||
* Hardware cursor control (for, e.g., CG6). A rather complex and icky
|
||||
* interface that smells like VMS, but there it is....
|
||||
*/
|
||||
struct fbcurpos {
|
||||
short x;
|
||||
short y;
|
||||
};
|
||||
|
||||
struct fbcursor {
|
||||
short set; /* flags; see below */
|
||||
short enable; /* nonzero => cursor on, 0 => cursor off */
|
||||
struct fbcurpos pos; /* position on display */
|
||||
struct fbcurpos hot; /* hot-spot within cursor */
|
||||
struct fbcmap cmap; /* cursor color map */
|
||||
struct fbcurpos size; /* number of valid bits in image & mask */
|
||||
caddr_t image; /* cursor image bits */
|
||||
caddr_t mask; /* cursor mask bits */
|
||||
};
|
||||
#define FB_CUR_SETCUR 0x01 /* set on/off (i.e., obey fbcursor.enable) */
|
||||
#define FB_CUR_SETPOS 0x02 /* set position */
|
||||
#define FB_CUR_SETHOT 0x04 /* set hot-spot */
|
||||
#define FB_CUR_SETCMAP 0x08 /* set cursor color map */
|
||||
#define FB_CUR_SETSHAPE 0x10 /* set size & bits */
|
||||
#define FB_CUR_SETALL (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT | \
|
||||
FB_CUR_SETCMAP | FB_CUR_SETSHAPE)
|
||||
|
||||
/* controls for cursor attributes & shape (including position) */
|
||||
#define FBIOSCURSOR _IOW('F', 24, struct fbcursor)
|
||||
#define FBIOGCURSOR _IOWR('F', 25, struct fbcursor)
|
||||
|
||||
/* controls for cursor position only */
|
||||
#define FBIOSCURPOS _IOW('F', 26, struct fbcurpos)
|
||||
#define FBIOGCURPOS _IOW('F', 27, struct fbcurpos)
|
||||
|
||||
/* get maximum cursor size */
|
||||
#define FBIOGCURMAX _IOR('F', 28, struct fbcurpos)
|
79
sys/ufs/ufs/lockf.h
Normal file
79
sys/ufs/ufs/lockf.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Scooter Morris at Genentech Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)lockf.h 8.1 (Berkeley) 6/11/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* The lockf structure is a kernel structure which contains the information
|
||||
* associated with a byte range lock. The lockf structures are linked into
|
||||
* the inode structure. Locks are sorted by the starting byte of the lock for
|
||||
* efficiency.
|
||||
*/
|
||||
struct lockf {
|
||||
short lf_flags; /* Lock semantics: F_POSIX, F_FLOCK, F_WAIT */
|
||||
short lf_type; /* Lock type: F_RDLCK, F_WRLCK */
|
||||
off_t lf_start; /* The byte # of the start of the lock */
|
||||
off_t lf_end; /* The byte # of the end of the lock (-1=EOF)*/
|
||||
caddr_t lf_id; /* The id of the resource holding the lock */
|
||||
struct inode *lf_inode; /* Back pointer to the inode */
|
||||
struct lockf *lf_next; /* A pointer to the next lock on this inode */
|
||||
struct lockf *lf_block; /* The list of blocked locks */
|
||||
};
|
||||
|
||||
/* Maximum length of sleep chains to traverse to try and detect deadlock. */
|
||||
#define MAXDEPTH 50
|
||||
|
||||
__BEGIN_DECLS
|
||||
void lf_addblock __P((struct lockf *, struct lockf *));
|
||||
int lf_clearlock __P((struct lockf *));
|
||||
int lf_findoverlap __P((struct lockf *,
|
||||
struct lockf *, int, struct lockf ***, struct lockf **));
|
||||
struct lockf *
|
||||
lf_getblock __P((struct lockf *));
|
||||
int lf_getlock __P((struct lockf *, struct flock *));
|
||||
int lf_setlock __P((struct lockf *));
|
||||
void lf_split __P((struct lockf *, struct lockf *));
|
||||
void lf_wakelock __P((struct lockf *));
|
||||
__END_DECLS
|
||||
|
||||
#ifdef LOCKF_DEBUG
|
||||
extern int lockf_debug;
|
||||
|
||||
__BEGIN_DECLS
|
||||
void lf_print __P((char *, struct lockf *));
|
||||
void lf_printlist __P((char *, struct lockf *));
|
||||
__END_DECLS
|
||||
#endif
|
364
sys/ufs/ufs/ufs_disksubr.c
Normal file
364
sys/ufs/ufs/ufs_disksubr.c
Normal file
@ -0,0 +1,364 @@
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
/*
|
||||
* Seek sort for disks. We depend on the driver which calls us using b_resid
|
||||
* as the current cylinder number.
|
||||
*
|
||||
* The argument ap structure holds a b_actf activity chain pointer on which we
|
||||
* keep two queues, sorted in ascending cylinder order. The first queue holds
|
||||
* those requests which are positioned after the current cylinder (in the first
|
||||
* request); the second holds requests which came in after their cylinder number
|
||||
* was passed. Thus we implement a one way scan, retracting after reaching the
|
||||
* end of the drive to the first request on the second queue, at which time it
|
||||
* becomes the first queue.
|
||||
*
|
||||
* A one-way scan is natural because of the way UNIX read-ahead blocks are
|
||||
* allocated.
|
||||
*/
|
||||
|
||||
/*
|
||||
* For portability with historic industry practice, the
|
||||
* cylinder number has to be maintained in the `b_resid'
|
||||
* field.
|
||||
*/
|
||||
#define b_cylinder b_resid
|
||||
|
||||
void
|
||||
disksort(ap, bp)
|
||||
register struct buf *ap, *bp;
|
||||
{
|
||||
register struct buf *bq;
|
||||
|
||||
/* If the queue is empty, then it's easy. */
|
||||
if (ap->b_actf == NULL) {
|
||||
bp->b_actf = NULL;
|
||||
ap->b_actf = bp;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we lie after the first (currently active) request, then we
|
||||
* must locate the second request list and add ourselves to it.
|
||||
*/
|
||||
bq = ap->b_actf;
|
||||
if (bp->b_cylinder < bq->b_cylinder) {
|
||||
while (bq->b_actf) {
|
||||
/*
|
||||
* Check for an ``inversion'' in the normally ascending
|
||||
* cylinder numbers, indicating the start of the second
|
||||
* request list.
|
||||
*/
|
||||
if (bq->b_actf->b_cylinder < bq->b_cylinder) {
|
||||
/*
|
||||
* Search the second request list for the first
|
||||
* request at a larger cylinder number. We go
|
||||
* before that; if there is no such request, we
|
||||
* go at end.
|
||||
*/
|
||||
do {
|
||||
if (bp->b_cylinder <
|
||||
bq->b_actf->b_cylinder)
|
||||
goto insert;
|
||||
if (bp->b_cylinder ==
|
||||
bq->b_actf->b_cylinder &&
|
||||
bp->b_blkno < bq->b_actf->b_blkno)
|
||||
goto insert;
|
||||
bq = bq->b_actf;
|
||||
} while (bq->b_actf);
|
||||
goto insert; /* after last */
|
||||
}
|
||||
bq = bq->b_actf;
|
||||
}
|
||||
/*
|
||||
* No inversions... we will go after the last, and
|
||||
* be the first request in the second request list.
|
||||
*/
|
||||
goto insert;
|
||||
}
|
||||
/*
|
||||
* Request is at/after the current request...
|
||||
* sort in the first request list.
|
||||
*/
|
||||
while (bq->b_actf) {
|
||||
/*
|
||||
* We want to go after the current request if there is an
|
||||
* inversion after it (i.e. it is the end of the first
|
||||
* request list), or if the next request is a larger cylinder
|
||||
* than our request.
|
||||
*/
|
||||
if (bq->b_actf->b_cylinder < bq->b_cylinder ||
|
||||
bp->b_cylinder < bq->b_actf->b_cylinder ||
|
||||
(bp->b_cylinder == bq->b_actf->b_cylinder &&
|
||||
bp->b_blkno < bq->b_actf->b_blkno))
|
||||
goto insert;
|
||||
bq = bq->b_actf;
|
||||
}
|
||||
/*
|
||||
* Neither a second list nor a larger request... we go at the end of
|
||||
* the first list, which is the same as the end of the whole schebang.
|
||||
*/
|
||||
insert: bp->b_actf = bq->b_actf;
|
||||
bq->b_actf = bp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to read a disk label from a device using the indicated stategy
|
||||
* routine. The label must be partly set up before this: secpercyl and
|
||||
* anything required in the strategy routine (e.g., sector size) must be
|
||||
* filled in before calling us. Returns NULL on success and an error
|
||||
* string on failure.
|
||||
*/
|
||||
char *
|
||||
readdisklabel(dev, strat, lp)
|
||||
dev_t dev;
|
||||
int (*strat)();
|
||||
register struct disklabel *lp;
|
||||
{
|
||||
register struct buf *bp;
|
||||
struct disklabel *dlp;
|
||||
char *msg = NULL;
|
||||
|
||||
if (lp->d_secperunit == 0)
|
||||
lp->d_secperunit = 0x1fffffff;
|
||||
lp->d_npartitions = 1;
|
||||
if (lp->d_partitions[0].p_size == 0)
|
||||
lp->d_partitions[0].p_size = 0x1fffffff;
|
||||
lp->d_partitions[0].p_offset = 0;
|
||||
|
||||
bp = geteblk((int)lp->d_secsize);
|
||||
bp->b_dev = dev;
|
||||
bp->b_blkno = LABELSECTOR;
|
||||
bp->b_bcount = lp->d_secsize;
|
||||
bp->b_flags = B_BUSY | B_READ;
|
||||
bp->b_cylinder = LABELSECTOR / lp->d_secpercyl;
|
||||
(*strat)(bp);
|
||||
if (biowait(bp))
|
||||
msg = "I/O error";
|
||||
else for (dlp = (struct disklabel *)bp->b_data;
|
||||
dlp <= (struct disklabel *)((char *)bp->b_data +
|
||||
DEV_BSIZE - sizeof(*dlp));
|
||||
dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
|
||||
if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
|
||||
if (msg == NULL)
|
||||
msg = "no disk label";
|
||||
} else if (dlp->d_npartitions > MAXPARTITIONS ||
|
||||
dkcksum(dlp) != 0)
|
||||
msg = "disk label corrupted";
|
||||
else {
|
||||
*lp = *dlp;
|
||||
msg = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bp->b_flags = B_INVAL | B_AGE;
|
||||
brelse(bp);
|
||||
return (msg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check new disk label for sensibility before setting it.
|
||||
*/
|
||||
int
|
||||
setdisklabel(olp, nlp, openmask)
|
||||
register struct disklabel *olp, *nlp;
|
||||
u_long openmask;
|
||||
{
|
||||
register i;
|
||||
register struct partition *opp, *npp;
|
||||
|
||||
if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
|
||||
dkcksum(nlp) != 0)
|
||||
return (EINVAL);
|
||||
while ((i = ffs((long)openmask)) != 0) {
|
||||
i--;
|
||||
openmask &= ~(1 << i);
|
||||
if (nlp->d_npartitions <= i)
|
||||
return (EBUSY);
|
||||
opp = &olp->d_partitions[i];
|
||||
npp = &nlp->d_partitions[i];
|
||||
if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
|
||||
return (EBUSY);
|
||||
/*
|
||||
* Copy internally-set partition information
|
||||
* if new label doesn't include it. XXX
|
||||
*/
|
||||
if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
|
||||
npp->p_fstype = opp->p_fstype;
|
||||
npp->p_fsize = opp->p_fsize;
|
||||
npp->p_frag = opp->p_frag;
|
||||
npp->p_cpg = opp->p_cpg;
|
||||
}
|
||||
}
|
||||
nlp->d_checksum = 0;
|
||||
nlp->d_checksum = dkcksum(nlp);
|
||||
*olp = *nlp;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* encoding of disk minor numbers, should be elsewhere... */
|
||||
#define dkunit(dev) (minor(dev) >> 3)
|
||||
#define dkpart(dev) (minor(dev) & 07)
|
||||
#define dkminor(unit, part) (((unit) << 3) | (part))
|
||||
|
||||
/*
|
||||
* Write disk label back to device after modification.
|
||||
*/
|
||||
int
|
||||
writedisklabel(dev, strat, lp)
|
||||
dev_t dev;
|
||||
int (*strat)();
|
||||
register struct disklabel *lp;
|
||||
{
|
||||
struct buf *bp;
|
||||
struct disklabel *dlp;
|
||||
int labelpart;
|
||||
int error = 0;
|
||||
|
||||
labelpart = dkpart(dev);
|
||||
if (lp->d_partitions[labelpart].p_offset != 0) {
|
||||
if (lp->d_partitions[0].p_offset != 0)
|
||||
return (EXDEV); /* not quite right */
|
||||
labelpart = 0;
|
||||
}
|
||||
bp = geteblk((int)lp->d_secsize);
|
||||
bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart));
|
||||
bp->b_blkno = LABELSECTOR;
|
||||
bp->b_bcount = lp->d_secsize;
|
||||
bp->b_flags = B_READ;
|
||||
(*strat)(bp);
|
||||
if (error = biowait(bp))
|
||||
goto done;
|
||||
for (dlp = (struct disklabel *)bp->b_data;
|
||||
dlp <= (struct disklabel *)
|
||||
((char *)bp->b_data + lp->d_secsize - sizeof(*dlp));
|
||||
dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
|
||||
if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
|
||||
dkcksum(dlp) == 0) {
|
||||
*dlp = *lp;
|
||||
bp->b_flags = B_WRITE;
|
||||
(*strat)(bp);
|
||||
error = biowait(bp);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
error = ESRCH;
|
||||
done:
|
||||
brelse(bp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute checksum for disk label.
|
||||
*/
|
||||
dkcksum(lp)
|
||||
register struct disklabel *lp;
|
||||
{
|
||||
register u_short *start, *end;
|
||||
register u_short sum = 0;
|
||||
|
||||
start = (u_short *)lp;
|
||||
end = (u_short *)&lp->d_partitions[lp->d_npartitions];
|
||||
while (start < end)
|
||||
sum ^= *start++;
|
||||
return (sum);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disk error is the preface to plaintive error messages
|
||||
* about failing disk transfers. It prints messages of the form
|
||||
|
||||
hp0g: hard error reading fsbn 12345 of 12344-12347 (hp0 bn %d cn %d tn %d sn %d)
|
||||
|
||||
* if the offset of the error in the transfer and a disk label
|
||||
* are both available. blkdone should be -1 if the position of the error
|
||||
* is unknown; the disklabel pointer may be null from drivers that have not
|
||||
* been converted to use them. The message is printed with printf
|
||||
* if pri is LOG_PRINTF, otherwise it uses log at the specified priority.
|
||||
* The message should be completed (with at least a newline) with printf
|
||||
* or addlog, respectively. There is no trailing space.
|
||||
*/
|
||||
void
|
||||
diskerr(bp, dname, what, pri, blkdone, lp)
|
||||
register struct buf *bp;
|
||||
char *dname, *what;
|
||||
int pri, blkdone;
|
||||
register struct disklabel *lp;
|
||||
{
|
||||
int unit = dkunit(bp->b_dev), part = dkpart(bp->b_dev);
|
||||
register void (*pr) __P((const char *, ...));
|
||||
char partname = 'a' + part;
|
||||
int sn;
|
||||
|
||||
if (pri != LOG_PRINTF) {
|
||||
log(pri, "");
|
||||
pr = addlog;
|
||||
} else
|
||||
pr = printf;
|
||||
(*pr)("%s%d%c: %s %sing fsbn ", dname, unit, partname, what,
|
||||
bp->b_flags & B_READ ? "read" : "writ");
|
||||
sn = bp->b_blkno;
|
||||
if (bp->b_bcount <= DEV_BSIZE)
|
||||
(*pr)("%d", sn);
|
||||
else {
|
||||
if (blkdone >= 0) {
|
||||
sn += blkdone;
|
||||
(*pr)("%d of ", sn);
|
||||
}
|
||||
(*pr)("%d-%d", bp->b_blkno,
|
||||
bp->b_blkno + (bp->b_bcount - 1) / DEV_BSIZE);
|
||||
}
|
||||
if (lp && (blkdone >= 0 || bp->b_bcount <= lp->d_secsize)) {
|
||||
#ifdef tahoe
|
||||
sn *= DEV_BSIZE / lp->d_secsize; /* XXX */
|
||||
#endif
|
||||
sn += lp->d_partitions[part].p_offset;
|
||||
(*pr)(" (%s%d bn %d; cn %d", dname, unit, sn,
|
||||
sn / lp->d_secpercyl);
|
||||
sn %= lp->d_secpercyl;
|
||||
(*pr)(" tn %d sn %d)", sn / lp->d_nsectors, sn % lp->d_nsectors);
|
||||
}
|
||||
}
|
707
sys/ufs/ufs/ufs_lockf.c
Normal file
707
sys/ufs/ufs/ufs_lockf.c
Normal file
@ -0,0 +1,707 @@
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Scooter Morris at Genentech Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ufs_lockf.c 8.3 (Berkeley) 1/6/94
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
||||
#include <ufs/ufs/lockf.h>
|
||||
#include <ufs/ufs/quota.h>
|
||||
#include <ufs/ufs/inode.h>
|
||||
#include <ufs/ufs/ufs_extern.h>
|
||||
|
||||
/*
|
||||
* This variable controls the maximum number of processes that will
|
||||
* be checked in doing deadlock detection.
|
||||
*/
|
||||
int maxlockdepth = MAXDEPTH;
|
||||
|
||||
#ifdef LOCKF_DEBUG
|
||||
int lockf_debug = 0;
|
||||
#endif
|
||||
|
||||
#define NOLOCKF (struct lockf *)0
|
||||
#define SELF 0x1
|
||||
#define OTHERS 0x2
|
||||
|
||||
/*
|
||||
* Set a byte-range lock.
|
||||
*/
|
||||
int
|
||||
lf_setlock(lock)
|
||||
register struct lockf *lock;
|
||||
{
|
||||
register struct lockf *block;
|
||||
struct inode *ip = lock->lf_inode;
|
||||
struct lockf **prev, *overlap, *ltmp;
|
||||
static char lockstr[] = "lockf";
|
||||
int ovcase, priority, needtolink, error;
|
||||
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 1)
|
||||
lf_print("lf_setlock", lock);
|
||||
#endif /* LOCKF_DEBUG */
|
||||
|
||||
/*
|
||||
* Set the priority
|
||||
*/
|
||||
priority = PLOCK;
|
||||
if (lock->lf_type == F_WRLCK)
|
||||
priority += 4;
|
||||
priority |= PCATCH;
|
||||
/*
|
||||
* Scan lock list for this file looking for locks that would block us.
|
||||
*/
|
||||
while (block = lf_getblock(lock)) {
|
||||
/*
|
||||
* Free the structure and return if nonblocking.
|
||||
*/
|
||||
if ((lock->lf_flags & F_WAIT) == 0) {
|
||||
FREE(lock, M_LOCKF);
|
||||
return (EAGAIN);
|
||||
}
|
||||
/*
|
||||
* We are blocked. Since flock style locks cover
|
||||
* the whole file, there is no chance for deadlock.
|
||||
* For byte-range locks we must check for deadlock.
|
||||
*
|
||||
* Deadlock detection is done by looking through the
|
||||
* wait channels to see if there are any cycles that
|
||||
* involve us. MAXDEPTH is set just to make sure we
|
||||
* do not go off into neverland.
|
||||
*/
|
||||
if ((lock->lf_flags & F_POSIX) &&
|
||||
(block->lf_flags & F_POSIX)) {
|
||||
register struct proc *wproc;
|
||||
register struct lockf *waitblock;
|
||||
int i = 0;
|
||||
|
||||
/* The block is waiting on something */
|
||||
wproc = (struct proc *)block->lf_id;
|
||||
while (wproc->p_wchan &&
|
||||
(wproc->p_wmesg == lockstr) &&
|
||||
(i++ < maxlockdepth)) {
|
||||
waitblock = (struct lockf *)wproc->p_wchan;
|
||||
/* Get the owner of the blocking lock */
|
||||
waitblock = waitblock->lf_next;
|
||||
if ((waitblock->lf_flags & F_POSIX) == 0)
|
||||
break;
|
||||
wproc = (struct proc *)waitblock->lf_id;
|
||||
if (wproc == (struct proc *)lock->lf_id) {
|
||||
free(lock, M_LOCKF);
|
||||
return (EDEADLK);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* For flock type locks, we must first remove
|
||||
* any shared locks that we hold before we sleep
|
||||
* waiting for an exclusive lock.
|
||||
*/
|
||||
if ((lock->lf_flags & F_FLOCK) &&
|
||||
lock->lf_type == F_WRLCK) {
|
||||
lock->lf_type = F_UNLCK;
|
||||
(void) lf_clearlock(lock);
|
||||
lock->lf_type = F_WRLCK;
|
||||
}
|
||||
/*
|
||||
* Add our lock to the blocked list and sleep until we're free.
|
||||
* Remember who blocked us (for deadlock detection).
|
||||
*/
|
||||
lock->lf_next = block;
|
||||
lf_addblock(block, lock);
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 1) {
|
||||
lf_print("lf_setlock: blocking on", block);
|
||||
lf_printlist("lf_setlock", block);
|
||||
}
|
||||
#endif /* LOCKF_DEBUG */
|
||||
if (error = tsleep((caddr_t)lock, priority, lockstr, 0)) {
|
||||
/*
|
||||
* Delete ourselves from the waiting to lock list.
|
||||
*/
|
||||
for (block = lock->lf_next;
|
||||
block != NOLOCKF;
|
||||
block = block->lf_block) {
|
||||
if (block->lf_block != lock)
|
||||
continue;
|
||||
block->lf_block = block->lf_block->lf_block;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If we did not find ourselves on the list, but
|
||||
* are still linked onto a lock list, then something
|
||||
* is very wrong.
|
||||
*/
|
||||
if (block == NOLOCKF && lock->lf_next != NOLOCKF)
|
||||
panic("lf_setlock: lost lock");
|
||||
free(lock, M_LOCKF);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* No blocks!! Add the lock. Note that we will
|
||||
* downgrade or upgrade any overlapping locks this
|
||||
* process already owns.
|
||||
*
|
||||
* Skip over locks owned by other processes.
|
||||
* Handle any locks that overlap and are owned by ourselves.
|
||||
*/
|
||||
prev = &ip->i_lockf;
|
||||
block = ip->i_lockf;
|
||||
needtolink = 1;
|
||||
for (;;) {
|
||||
if (ovcase = lf_findoverlap(block, lock, SELF, &prev, &overlap))
|
||||
block = overlap->lf_next;
|
||||
/*
|
||||
* Six cases:
|
||||
* 0) no overlap
|
||||
* 1) overlap == lock
|
||||
* 2) overlap contains lock
|
||||
* 3) lock contains overlap
|
||||
* 4) overlap starts before lock
|
||||
* 5) overlap ends after lock
|
||||
*/
|
||||
switch (ovcase) {
|
||||
case 0: /* no overlap */
|
||||
if (needtolink) {
|
||||
*prev = lock;
|
||||
lock->lf_next = overlap;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: /* overlap == lock */
|
||||
/*
|
||||
* If downgrading lock, others may be
|
||||
* able to acquire it.
|
||||
*/
|
||||
if (lock->lf_type == F_RDLCK &&
|
||||
overlap->lf_type == F_WRLCK)
|
||||
lf_wakelock(overlap);
|
||||
overlap->lf_type = lock->lf_type;
|
||||
FREE(lock, M_LOCKF);
|
||||
lock = overlap; /* for debug output below */
|
||||
break;
|
||||
|
||||
case 2: /* overlap contains lock */
|
||||
/*
|
||||
* Check for common starting point and different types.
|
||||
*/
|
||||
if (overlap->lf_type == lock->lf_type) {
|
||||
free(lock, M_LOCKF);
|
||||
lock = overlap; /* for debug output below */
|
||||
break;
|
||||
}
|
||||
if (overlap->lf_start == lock->lf_start) {
|
||||
*prev = lock;
|
||||
lock->lf_next = overlap;
|
||||
overlap->lf_start = lock->lf_end + 1;
|
||||
} else
|
||||
lf_split(overlap, lock);
|
||||
lf_wakelock(overlap);
|
||||
break;
|
||||
|
||||
case 3: /* lock contains overlap */
|
||||
/*
|
||||
* If downgrading lock, others may be able to
|
||||
* acquire it, otherwise take the list.
|
||||
*/
|
||||
if (lock->lf_type == F_RDLCK &&
|
||||
overlap->lf_type == F_WRLCK) {
|
||||
lf_wakelock(overlap);
|
||||
} else {
|
||||
ltmp = lock->lf_block;
|
||||
lock->lf_block = overlap->lf_block;
|
||||
lf_addblock(lock, ltmp);
|
||||
}
|
||||
/*
|
||||
* Add the new lock if necessary and delete the overlap.
|
||||
*/
|
||||
if (needtolink) {
|
||||
*prev = lock;
|
||||
lock->lf_next = overlap->lf_next;
|
||||
prev = &lock->lf_next;
|
||||
needtolink = 0;
|
||||
} else
|
||||
*prev = overlap->lf_next;
|
||||
free(overlap, M_LOCKF);
|
||||
continue;
|
||||
|
||||
case 4: /* overlap starts before lock */
|
||||
/*
|
||||
* Add lock after overlap on the list.
|
||||
*/
|
||||
lock->lf_next = overlap->lf_next;
|
||||
overlap->lf_next = lock;
|
||||
overlap->lf_end = lock->lf_start - 1;
|
||||
prev = &lock->lf_next;
|
||||
lf_wakelock(overlap);
|
||||
needtolink = 0;
|
||||
continue;
|
||||
|
||||
case 5: /* overlap ends after lock */
|
||||
/*
|
||||
* Add the new lock before overlap.
|
||||
*/
|
||||
if (needtolink) {
|
||||
*prev = lock;
|
||||
lock->lf_next = overlap;
|
||||
}
|
||||
overlap->lf_start = lock->lf_end + 1;
|
||||
lf_wakelock(overlap);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 1) {
|
||||
lf_print("lf_setlock: got the lock", lock);
|
||||
lf_printlist("lf_setlock", lock);
|
||||
}
|
||||
#endif /* LOCKF_DEBUG */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a byte-range lock on an inode.
|
||||
*
|
||||
* Generally, find the lock (or an overlap to that lock)
|
||||
* and remove it (or shrink it), then wakeup anyone we can.
|
||||
*/
|
||||
int
|
||||
lf_clearlock(unlock)
|
||||
register struct lockf *unlock;
|
||||
{
|
||||
struct inode *ip = unlock->lf_inode;
|
||||
register struct lockf *lf = ip->i_lockf;
|
||||
struct lockf *overlap, **prev;
|
||||
int ovcase;
|
||||
|
||||
if (lf == NOLOCKF)
|
||||
return (0);
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (unlock->lf_type != F_UNLCK)
|
||||
panic("lf_clearlock: bad type");
|
||||
if (lockf_debug & 1)
|
||||
lf_print("lf_clearlock", unlock);
|
||||
#endif /* LOCKF_DEBUG */
|
||||
prev = &ip->i_lockf;
|
||||
while (ovcase = lf_findoverlap(lf, unlock, SELF, &prev, &overlap)) {
|
||||
/*
|
||||
* Wakeup the list of locks to be retried.
|
||||
*/
|
||||
lf_wakelock(overlap);
|
||||
|
||||
switch (ovcase) {
|
||||
|
||||
case 1: /* overlap == lock */
|
||||
*prev = overlap->lf_next;
|
||||
FREE(overlap, M_LOCKF);
|
||||
break;
|
||||
|
||||
case 2: /* overlap contains lock: split it */
|
||||
if (overlap->lf_start == unlock->lf_start) {
|
||||
overlap->lf_start = unlock->lf_end + 1;
|
||||
break;
|
||||
}
|
||||
lf_split(overlap, unlock);
|
||||
overlap->lf_next = unlock->lf_next;
|
||||
break;
|
||||
|
||||
case 3: /* lock contains overlap */
|
||||
*prev = overlap->lf_next;
|
||||
lf = overlap->lf_next;
|
||||
free(overlap, M_LOCKF);
|
||||
continue;
|
||||
|
||||
case 4: /* overlap starts before lock */
|
||||
overlap->lf_end = unlock->lf_start - 1;
|
||||
prev = &overlap->lf_next;
|
||||
lf = overlap->lf_next;
|
||||
continue;
|
||||
|
||||
case 5: /* overlap ends after lock */
|
||||
overlap->lf_start = unlock->lf_end + 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 1)
|
||||
lf_printlist("lf_clearlock", unlock);
|
||||
#endif /* LOCKF_DEBUG */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether there is a blocking lock,
|
||||
* and if so return its process identifier.
|
||||
*/
|
||||
int
|
||||
lf_getlock(lock, fl)
|
||||
register struct lockf *lock;
|
||||
register struct flock *fl;
|
||||
{
|
||||
register struct lockf *block;
|
||||
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 1)
|
||||
lf_print("lf_getlock", lock);
|
||||
#endif /* LOCKF_DEBUG */
|
||||
|
||||
if (block = lf_getblock(lock)) {
|
||||
fl->l_type = block->lf_type;
|
||||
fl->l_whence = SEEK_SET;
|
||||
fl->l_start = block->lf_start;
|
||||
if (block->lf_end == -1)
|
||||
fl->l_len = 0;
|
||||
else
|
||||
fl->l_len = block->lf_end - block->lf_start + 1;
|
||||
if (block->lf_flags & F_POSIX)
|
||||
fl->l_pid = ((struct proc *)(block->lf_id))->p_pid;
|
||||
else
|
||||
fl->l_pid = -1;
|
||||
} else {
|
||||
fl->l_type = F_UNLCK;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk the list of locks for an inode and
|
||||
* return the first blocking lock.
|
||||
*/
|
||||
struct lockf *
|
||||
lf_getblock(lock)
|
||||
register struct lockf *lock;
|
||||
{
|
||||
struct lockf **prev, *overlap, *lf = lock->lf_inode->i_lockf;
|
||||
int ovcase;
|
||||
|
||||
prev = &lock->lf_inode->i_lockf;
|
||||
while (ovcase = lf_findoverlap(lf, lock, OTHERS, &prev, &overlap)) {
|
||||
/*
|
||||
* We've found an overlap, see if it blocks us
|
||||
*/
|
||||
if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK))
|
||||
return (overlap);
|
||||
/*
|
||||
* Nope, point to the next one on the list and
|
||||
* see if it blocks us
|
||||
*/
|
||||
lf = overlap->lf_next;
|
||||
}
|
||||
return (NOLOCKF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk the list of locks for an inode to
|
||||
* find an overlapping lock (if any).
|
||||
*
|
||||
* NOTE: this returns only the FIRST overlapping lock. There
|
||||
* may be more than one.
|
||||
*/
|
||||
int
|
||||
lf_findoverlap(lf, lock, type, prev, overlap)
|
||||
register struct lockf *lf;
|
||||
struct lockf *lock;
|
||||
int type;
|
||||
struct lockf ***prev;
|
||||
struct lockf **overlap;
|
||||
{
|
||||
off_t start, end;
|
||||
|
||||
*overlap = lf;
|
||||
if (lf == NOLOCKF)
|
||||
return (0);
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 2)
|
||||
lf_print("lf_findoverlap: looking for overlap in", lock);
|
||||
#endif /* LOCKF_DEBUG */
|
||||
start = lock->lf_start;
|
||||
end = lock->lf_end;
|
||||
while (lf != NOLOCKF) {
|
||||
if (((type & SELF) && lf->lf_id != lock->lf_id) ||
|
||||
((type & OTHERS) && lf->lf_id == lock->lf_id)) {
|
||||
*prev = &lf->lf_next;
|
||||
*overlap = lf = lf->lf_next;
|
||||
continue;
|
||||
}
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 2)
|
||||
lf_print("\tchecking", lf);
|
||||
#endif /* LOCKF_DEBUG */
|
||||
/*
|
||||
* OK, check for overlap
|
||||
*
|
||||
* Six cases:
|
||||
* 0) no overlap
|
||||
* 1) overlap == lock
|
||||
* 2) overlap contains lock
|
||||
* 3) lock contains overlap
|
||||
* 4) overlap starts before lock
|
||||
* 5) overlap ends after lock
|
||||
*/
|
||||
if ((lf->lf_end != -1 && start > lf->lf_end) ||
|
||||
(end != -1 && lf->lf_start > end)) {
|
||||
/* Case 0 */
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 2)
|
||||
printf("no overlap\n");
|
||||
#endif /* LOCKF_DEBUG */
|
||||
if ((type & SELF) && end != -1 && lf->lf_start > end)
|
||||
return (0);
|
||||
*prev = &lf->lf_next;
|
||||
*overlap = lf = lf->lf_next;
|
||||
continue;
|
||||
}
|
||||
if ((lf->lf_start == start) && (lf->lf_end == end)) {
|
||||
/* Case 1 */
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 2)
|
||||
printf("overlap == lock\n");
|
||||
#endif /* LOCKF_DEBUG */
|
||||
return (1);
|
||||
}
|
||||
if ((lf->lf_start <= start) &&
|
||||
(end != -1) &&
|
||||
((lf->lf_end >= end) || (lf->lf_end == -1))) {
|
||||
/* Case 2 */
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 2)
|
||||
printf("overlap contains lock\n");
|
||||
#endif /* LOCKF_DEBUG */
|
||||
return (2);
|
||||
}
|
||||
if (start <= lf->lf_start &&
|
||||
(end == -1 ||
|
||||
(lf->lf_end != -1 && end >= lf->lf_end))) {
|
||||
/* Case 3 */
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 2)
|
||||
printf("lock contains overlap\n");
|
||||
#endif /* LOCKF_DEBUG */
|
||||
return (3);
|
||||
}
|
||||
if ((lf->lf_start < start) &&
|
||||
((lf->lf_end >= start) || (lf->lf_end == -1))) {
|
||||
/* Case 4 */
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 2)
|
||||
printf("overlap starts before lock\n");
|
||||
#endif /* LOCKF_DEBUG */
|
||||
return (4);
|
||||
}
|
||||
if ((lf->lf_start > start) &&
|
||||
(end != -1) &&
|
||||
((lf->lf_end > end) || (lf->lf_end == -1))) {
|
||||
/* Case 5 */
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 2)
|
||||
printf("overlap ends after lock\n");
|
||||
#endif /* LOCKF_DEBUG */
|
||||
return (5);
|
||||
}
|
||||
panic("lf_findoverlap: default");
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a lock to the end of the blocked list.
|
||||
*/
|
||||
void
|
||||
lf_addblock(lock, blocked)
|
||||
struct lockf *lock;
|
||||
struct lockf *blocked;
|
||||
{
|
||||
register struct lockf *lf;
|
||||
|
||||
if (blocked == NOLOCKF)
|
||||
return;
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 2) {
|
||||
lf_print("addblock: adding", blocked);
|
||||
lf_print("to blocked list of", lock);
|
||||
}
|
||||
#endif /* LOCKF_DEBUG */
|
||||
if ((lf = lock->lf_block) == NOLOCKF) {
|
||||
lock->lf_block = blocked;
|
||||
return;
|
||||
}
|
||||
while (lf->lf_block != NOLOCKF)
|
||||
lf = lf->lf_block;
|
||||
lf->lf_block = blocked;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Split a lock and a contained region into
|
||||
* two or three locks as necessary.
|
||||
*/
|
||||
void
|
||||
lf_split(lock1, lock2)
|
||||
register struct lockf *lock1;
|
||||
register struct lockf *lock2;
|
||||
{
|
||||
register struct lockf *splitlock;
|
||||
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 2) {
|
||||
lf_print("lf_split", lock1);
|
||||
lf_print("splitting from", lock2);
|
||||
}
|
||||
#endif /* LOCKF_DEBUG */
|
||||
/*
|
||||
* Check to see if spliting into only two pieces.
|
||||
*/
|
||||
if (lock1->lf_start == lock2->lf_start) {
|
||||
lock1->lf_start = lock2->lf_end + 1;
|
||||
lock2->lf_next = lock1;
|
||||
return;
|
||||
}
|
||||
if (lock1->lf_end == lock2->lf_end) {
|
||||
lock1->lf_end = lock2->lf_start - 1;
|
||||
lock2->lf_next = lock1->lf_next;
|
||||
lock1->lf_next = lock2;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Make a new lock consisting of the last part of
|
||||
* the encompassing lock
|
||||
*/
|
||||
MALLOC(splitlock, struct lockf *, sizeof *splitlock, M_LOCKF, M_WAITOK);
|
||||
bcopy((caddr_t)lock1, (caddr_t)splitlock, sizeof *splitlock);
|
||||
splitlock->lf_start = lock2->lf_end + 1;
|
||||
splitlock->lf_block = NOLOCKF;
|
||||
lock1->lf_end = lock2->lf_start - 1;
|
||||
/*
|
||||
* OK, now link it in
|
||||
*/
|
||||
splitlock->lf_next = lock1->lf_next;
|
||||
lock2->lf_next = splitlock;
|
||||
lock1->lf_next = lock2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wakeup a blocklist
|
||||
*/
|
||||
void
|
||||
lf_wakelock(listhead)
|
||||
struct lockf *listhead;
|
||||
{
|
||||
register struct lockf *blocklist, *wakelock;
|
||||
|
||||
blocklist = listhead->lf_block;
|
||||
listhead->lf_block = NOLOCKF;
|
||||
while (blocklist != NOLOCKF) {
|
||||
wakelock = blocklist;
|
||||
blocklist = blocklist->lf_block;
|
||||
wakelock->lf_block = NOLOCKF;
|
||||
wakelock->lf_next = NOLOCKF;
|
||||
#ifdef LOCKF_DEBUG
|
||||
if (lockf_debug & 2)
|
||||
lf_print("lf_wakelock: awakening", wakelock);
|
||||
#endif /* LOCKF_DEBUG */
|
||||
wakeup((caddr_t)wakelock);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LOCKF_DEBUG
|
||||
/*
|
||||
* Print out a lock.
|
||||
*/
|
||||
void
|
||||
lf_print(tag, lock)
|
||||
char *tag;
|
||||
register struct lockf *lock;
|
||||
{
|
||||
|
||||
printf("%s: lock 0x%lx for ", tag, lock);
|
||||
if (lock->lf_flags & F_POSIX)
|
||||
printf("proc %d", ((struct proc *)(lock->lf_id))->p_pid);
|
||||
else
|
||||
printf("id 0x%x", lock->lf_id);
|
||||
printf(" in ino %d on dev <%d, %d>, %s, start %d, end %d",
|
||||
lock->lf_inode->i_number,
|
||||
major(lock->lf_inode->i_dev),
|
||||
minor(lock->lf_inode->i_dev),
|
||||
lock->lf_type == F_RDLCK ? "shared" :
|
||||
lock->lf_type == F_WRLCK ? "exclusive" :
|
||||
lock->lf_type == F_UNLCK ? "unlock" :
|
||||
"unknown", lock->lf_start, lock->lf_end);
|
||||
if (lock->lf_block)
|
||||
printf(" block 0x%x\n", lock->lf_block);
|
||||
else
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
lf_printlist(tag, lock)
|
||||
char *tag;
|
||||
struct lockf *lock;
|
||||
{
|
||||
register struct lockf *lf;
|
||||
|
||||
printf("%s: Lock list for ino %d on dev <%d, %d>:\n",
|
||||
tag, lock->lf_inode->i_number,
|
||||
major(lock->lf_inode->i_dev),
|
||||
minor(lock->lf_inode->i_dev));
|
||||
for (lf = lock->lf_inode->i_lockf; lf; lf = lf->lf_next) {
|
||||
printf("\tlock 0x%lx for ", lf);
|
||||
if (lf->lf_flags & F_POSIX)
|
||||
printf("proc %d", ((struct proc *)(lf->lf_id))->p_pid);
|
||||
else
|
||||
printf("id 0x%x", lf->lf_id);
|
||||
printf(", %s, start %d, end %d",
|
||||
lf->lf_type == F_RDLCK ? "shared" :
|
||||
lf->lf_type == F_WRLCK ? "exclusive" :
|
||||
lf->lf_type == F_UNLCK ? "unlock" :
|
||||
"unknown", lf->lf_start, lf->lf_end);
|
||||
if (lf->lf_block)
|
||||
printf(" block 0x%x\n", lf->lf_block);
|
||||
else
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
#endif /* LOCKF_DEBUG */
|
Loading…
Reference in New Issue
Block a user