Import 4.4BSD-Lite for reference

This commit is contained in:
fvdl 1998-03-01 02:09:33 +00:00
parent 77eeaedfe8
commit b50e39fa45
20 changed files with 5371 additions and 0 deletions

72
sys/conf/systags.sh Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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 */