1. Change driver signatures to full signature for slice support.

2. Add "pt" (processor type) driver.
3. Add "worm" (Write Once) driver for Jordan.
This commit is contained in:
Peter Dufault 1995-03-04 20:51:10 +00:00
parent 920052bded
commit f29b7a5d14
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=6890
14 changed files with 834 additions and 198 deletions

View File

@ -14,7 +14,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
*
* $Id: cd.c,v 1.33 1995/01/08 13:38:28 dufault Exp $
* $Id: cd.c,v 1.34 1995/03/01 22:24:39 dufault Exp $
*/
#define SPLCD splbio
@ -89,10 +89,12 @@ struct scsi_data {
static int cdunit(dev_t dev) { return CDUNIT(dev); }
static dev_t cdsetunit(dev_t dev, int unit) { return CDSETUNIT(dev, unit); }
errval cd_open(dev_t dev, int flags, struct scsi_link *sc_link);
errval cd_open(dev_t dev, int flags, int fmt, struct proc *p,
struct scsi_link *sc_link);
errval cd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag,
struct scsi_link *sc_link);
errval cd_close(dev_t dev, struct scsi_link *sc_link);
struct proc *p, struct scsi_link *sc_link);
errval cd_close(dev_t dev, int flag, int fmt, struct proc *p,
struct scsi_link *sc_link);
void cd_strategy(struct buf *bp, struct scsi_link *sc_link);
SCSI_DEVICE_ENTRIES(cd)
@ -108,6 +110,7 @@ struct scsi_device cd_switch =
{0, 0},
0, /* Link flags */
cdattach,
"CD-ROM",
cdopen,
sizeof(struct scsi_data),
T_READONLY,
@ -138,7 +141,6 @@ static struct kern_devconf kdc_cd_template = {
&kdc_scbus0, /* parent - XXX should be host adapter*/
0, /* parentdata */
DC_UNKNOWN, /* not supported */
"SCSI CD-ROM drive"
};
static inline void
@ -150,6 +152,7 @@ cd_registerdev(int unit)
if(!kdc) return;
*kdc = kdc_cd_template;
kdc->kdc_unit = unit;
kdc->kdc_description = cd_switch.desc;
/* XXX should set parentdata */
dev_attach(kdc);
if(dk_ndrive < DK_NDRIVE) {
@ -209,7 +212,8 @@ cdattach(struct scsi_link *sc_link)
* open the device. Make sure the partition info is a up-to-date as can be.
*/
errval
cd_open(dev_t dev, int flags, struct scsi_link *sc_link)
cd_open(dev_t dev, int flags, int fmt, struct proc *p,
struct scsi_link *sc_link)
{
errval errcode = 0;
u_int32 unit, part;
@ -226,7 +230,7 @@ cd_open(dev_t dev, int flags, struct scsi_link *sc_link)
return (ENXIO);
SC_DEBUG(sc_link, SDEV_DB1,
("cdopen: dev=0x%x (unit %d,partition %d)\n",
("cd_open: dev=0x%x (unit %d,partition %d)\n",
dev, unit, part));
/*
* If it's been invalidated, and not everybody has closed it then
@ -240,7 +244,7 @@ cd_open(dev_t dev, int flags, struct scsi_link *sc_link)
* Check that it is still responding and ok.
* if the media has been changed this will result in a
* "unit attention" error which the error code will
* disregard because the SDEV_MEDIA_LOADED flag is not yet set
* disregard because the SDEV_OPEN flag is not yet set
*/
scsi_test_unit_ready(sc_link, SCSI_SILENT);
@ -316,7 +320,8 @@ cd_open(dev_t dev, int flags, struct scsi_link *sc_link)
* occurence of an open device
*/
errval
cd_close(dev_t dev, struct scsi_link *sc_link)
cd_close(dev_t dev, int flag, int fmt, struct proc *p,
struct scsi_link *sc_link)
{
u_int8 unit, part;
struct scsi_data *cd;
@ -369,12 +374,6 @@ cd_strategy(struct buf *bp, struct scsi_link *sc_link)
bp->b_error = EROFS;
goto bad;
}
/*
* If it's a null transfer, return immediatly
*/
if (bp->b_bcount == 0) {
goto done;
}
/*
* Decide which unit and partition we are talking about
*/
@ -539,7 +538,8 @@ cdstart(unit)
* Knows about the internals of this device
*/
errval
cd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct scsi_link *sc_link)
cd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p,
struct scsi_link *sc_link)
{
errval error = 0;
u_int8 unit, part;
@ -869,7 +869,7 @@ cd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct scsi_link *sc_link)
break;
default:
if(part == RAW_PART || SCSI_SUPER(dev))
error = scsi_do_ioctl(dev, cmd, addr, flag, sc_link);
error = scsi_do_ioctl(dev, cmd, addr, flag, p, sc_link);
else
error = ENOTTY;
break;

View File

@ -2,7 +2,7 @@
* Written by grefen@?????
* Based on scsi drivers by Julian Elischer (julian@tfs.com)
*
* $Id: ch.c,v 1.13 1995/01/19 21:02:54 ats Exp $
* $Id: ch.c,v 1.14 1995/03/01 22:24:40 dufault Exp $
*/
#include <sys/types.h>
@ -46,16 +46,17 @@ struct scsi_data {
u_long op_matrix; /* possible opertaions */
u_int16 lsterr; /* details of lasterror */
u_char stor; /* posible Storage locations */
u_int32 initialized;
};
static int chunit(dev_t dev) { return CHUNIT(dev); }
static dev_t chsetunit(dev_t dev, int unit) { return CHSETUNIT(dev, unit); }
errval ch_open(dev_t dev, int flags, struct scsi_link *sc_link);
errval ch_open(dev_t dev, int flags, int fmt, struct proc *p,
struct scsi_link *sc_link);
errval ch_ioctl(dev_t dev, int cmd, caddr_t addr, int flag,
struct scsi_link *sc_link);
errval ch_close(dev_t dev, struct scsi_link *sc_link);
struct proc *p, struct scsi_link *sc_link);
errval ch_close(dev_t dev, int flag, int fmt, struct proc *p,
struct scsi_link *sc_link);
SCSI_DEVICE_ENTRIES(ch)
@ -70,6 +71,7 @@ struct scsi_device ch_switch =
{0, 0},
0, /* Link flags */
chattach,
"Medium-Changer",
chopen,
sizeof(struct scsi_data),
T_CHANGER,
@ -82,7 +84,6 @@ struct scsi_device ch_switch =
};
#define CH_OPEN 0x01
#define CH_KNOWN 0x02
static int
ch_externalize(struct proc *p, struct kern_devconf *kdc, void *userp,
@ -99,7 +100,6 @@ static struct kern_devconf kdc_ch_template = {
&kdc_scbus0, /* parent */
0, /* parentdata */
DC_UNKNOWN, /* not supported */
"SCSI media changer"
};
static inline void
@ -111,6 +111,7 @@ ch_registerdev(int unit)
if(!kdc) return;
*kdc = kdc_ch_template;
kdc->kdc_unit = unit;
kdc->kdc_description = ch_switch.desc;
dev_attach(kdc);
}
@ -121,7 +122,7 @@ ch_registerdev(int unit)
errval
chattach(struct scsi_link *sc_link)
{
u_int32 unit, i, stat;
u_int32 unit, i;
unsigned char *tbl;
struct scsi_data *ch = sc_link->sd;
@ -134,14 +135,11 @@ chattach(struct scsi_link *sc_link)
* request must specify this.
*/
if ((ch_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK /*| SCSI_SILENT */ ))) {
printf("scsi changer :- offline\n");
stat = CH_OPEN;
printf("offline\n");
} else {
printf("scsi changer, %d slot(s) %d drive(s) %d arm(s) %d i/e-slot(s)\n",
printf("%d slot(s) %d drive(s) %d arm(s) %d i/e-slot(s)\n",
ch->slots, ch->drives, ch->chms, ch->imexs);
stat = CH_KNOWN;
}
ch->initialized = 1;
ch_registerdev(unit);
return 0;
@ -151,7 +149,8 @@ chattach(struct scsi_link *sc_link)
* open the device.
*/
errval
ch_open(dev_t dev, int flags, struct scsi_link *sc_link)
ch_open(dev_t dev, int flags, int fmt, struct proc *p,
struct scsi_link *sc_link)
{
errval errcode = 0;
u_int32 unit, mode;
@ -168,12 +167,6 @@ ch_open(dev_t dev, int flags, struct scsi_link *sc_link)
printf("ch%d: already open\n", unit);
return EBUSY;
}
/*
* Make sure the device has been initialised
*/
if (!cd->initialized)
return (ENXIO);
/*
* Catch any unit attention errors.
*/
@ -205,7 +198,8 @@ ch_open(dev_t dev, int flags, struct scsi_link *sc_link)
* occurence of an open device
*/
errval
ch_close(dev_t dev, struct scsi_link *sc_link)
ch_close(dev_t dev, int flag, int fmt, struct proc *p,
struct scsi_link *sc_link)
{
sc_link->sd->flags = 0;
sc_link->flags &= ~SDEV_OPEN;
@ -218,7 +212,7 @@ ch_close(dev_t dev, struct scsi_link *sc_link)
*/
errval
ch_ioctl(dev_t dev, int cmd, caddr_t arg, int mode,
struct scsi_link *sc_link)
struct proc *p, struct scsi_link *sc_link)
{
/* struct ch_cmd_buf *args; */
union scsi_cmd *scsi_cmd;
@ -274,7 +268,7 @@ struct scsi_link *sc_link)
}
}
default:
return scsi_do_ioctl(dev, cmd, arg, mode, sc_link);
return scsi_do_ioctl(dev, cmd, arg, mode, p, sc_link);
}
return (ret ? ESUCCESS : EIO);
}

214
sys/scsi/pt.c Normal file
View File

@ -0,0 +1,214 @@
/*
* pt: Processor Type driver.
*
* Copyright (C) 1995, HD Associates, Inc.
* PO Box 276
* Pepperell, MA 01463
* 508 433 5266
* dufault@hda.com
*
* This code is contributed to the University of California at 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.
*
* $Id:$
*/
/*
* XXX dufault@hda.com: We need the "kern devconf" stuff, but I'm not
* going to add it until it is done in a simple way that provides
* base behavior in scsi_driver.c
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
struct scsi_data {
struct buf *buf_queue; /* the queue of pending IO operations */
};
void ptstart(u_int32 unit);
void pt_strategy(struct buf *bp, struct scsi_link *sc_link);
SCSI_DEVICE_ENTRIES(pt)
struct scsi_device pt_switch =
{
NULL,
ptstart, /* we have a queue, and this is how we service it */
NULL,
NULL,
"pt",
0,
{0, 0},
SDEV_ONCE_ONLY, /* Only one open allowed */
0,
"Processor",
ptopen,
sizeof(struct scsi_data),
T_PROCESSOR,
0,
0,
0,
0,
0,
pt_strategy,
};
/*
* ptstart looks to see if there is a buf waiting for the device
* and that the device is not already busy. If both are true,
* It dequeues the buf and creates a scsi command to perform the
* transfer required. The transfer request will call scsi_done
* on completion, which will in turn call this routine again
* so that the next queued transfer is performed.
* The bufs are queued by the strategy routine (ptstrategy)
*
* This routine is also called after other non-queued requests
* have been made of the scsi driver, to ensure that the queue
* continues to be drained.
* ptstart() is called at splbio
*/
void
ptstart(unit)
u_int32 unit;
{
struct scsi_link *sc_link = SCSI_LINK(&pt_switch, unit);
struct scsi_data *pt = sc_link->sd;
register struct buf *bp = 0;
struct
{
#define PROCESSOR_SEND 0x0A
#define PROCESSOR_RECEIVE 0x08
u_char op_code;
u_char byte2;
u_char len[3];
u_char control;
} cmd;
u_int32 flags;
SC_DEBUG(sc_link, SDEV_DB2, ("ptstart "));
/*
* See if there is a buf to do and we are not already
* doing one
*/
while (sc_link->opennings != 0) {
/* if a special awaits, let it proceed first */
if (sc_link->flags & SDEV_WAITING) {
sc_link->flags &= ~SDEV_WAITING;
wakeup((caddr_t)sc_link);
return;
}
if ((bp = pt->buf_queue) == NULL) {
return; /* no work to bother with */
}
pt->buf_queue = bp->b_actf;
/*
* Fill out the scsi command
*/
bzero(&cmd, sizeof(cmd));
if ((bp->b_flags & B_READ) == B_WRITE) {
cmd.op_code = PROCESSOR_SEND;
flags = SCSI_DATA_OUT;
} else {
cmd.op_code = PROCESSOR_RECEIVE;
flags = SCSI_DATA_IN;
}
scsi_uto3b(bp->b_bcount, cmd.len);
/*
* go ask the adapter to do all this for us
*/
if (scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &cmd,
sizeof(cmd),
(u_char *) bp->b_un.b_addr,
bp->b_bcount,
0, /* can't retry a read on a tape really */
100000,
bp,
flags | SCSI_NOSLEEP) == SUCCESSFULLY_QUEUED) {
} else {
badnews:
printf("pt%d: oops not queued\n", unit);
bp->b_flags |= B_ERROR;
bp->b_error = EIO;
biodone(bp);
}
} /* go back and see if we can cram more work in.. */
}
void
pt_strategy(struct buf *bp, struct scsi_link *sc_link)
{
struct buf **dp;
unsigned char unit;
u_int32 opri;
struct scsi_data *pt;
unit = STUNIT((bp->b_dev));
pt = sc_link->sd;
opri = splbio();
/*
* Use a bounce buffer if necessary
*/
#ifdef BOUNCE_BUFFERS
if (sc_link->flags & SDEV_BOUNCE)
vm_bounce_alloc(bp);
#endif
/*
* Place it in the queue of activities for this tape
* at the end (a bit silly because we only have one user..
* (but it could fork() ))
*/
dp = &(pt->buf_queue);
while (*dp) {
dp = &((*dp)->b_actf);
}
*dp = bp;
bp->b_actf = NULL;
/*
* Tell the device to get going on the transfer if it's
* not doing anything, otherwise just wait for completion
* (All a bit silly if we're only allowing 1 open but..)
*/
ptstart(unit);
splx(opri);
return;
}

View File

@ -8,7 +8,7 @@
* file.
*
* Written by Julian Elischer (julian@dialix.oz.au)
* $Id: scsi_base.c,v 1.19 1995/01/31 11:41:44 dufault Exp $
* $Id: scsi_base.c,v 1.20 1995/02/15 07:44:07 davidg Exp $
*/
#define SPLSD splbio
@ -108,12 +108,16 @@ free_xs(xs, sc_link, flags)
}
}
/* XXX dufault: Replace "sd_size" with "scsi_read_capacity"
* when bde is done with sd.c
*/
/*
* Find out from the device what its capacity is.
*/
u_int32
scsi_size(sc_link, flags)
scsi_read_capacity(sc_link, blk_size, flags)
struct scsi_link *sc_link;
u_int32 *blk_size;
u_int32 flags;
{
struct scsi_read_cap_data rdcap;
@ -145,10 +149,9 @@ scsi_size(sc_link, flags)
printf("could not get size\n");
return (0);
} else {
size = rdcap.addr_0 + 1;
size += rdcap.addr_1 << 8;
size += rdcap.addr_2 << 16;
size += rdcap.addr_3 << 24;
size = scsi_4btou(&rdcap.addr_3) + 1;
if (blk_size)
*blk_size = scsi_4btou(&rdcap.length_3);
}
return (size);
}
@ -932,9 +935,6 @@ scsi_uto3b(val, bytes)
*bytes = val & 0xff;
}
/*
* The reverse of scsi_uto3b
*/
u_int32
scsi_3btou(bytes)
u_char *bytes;
@ -946,9 +946,6 @@ scsi_3btou(bytes)
return rc;
}
/*
* scsi_3btoi: scsi_3btou for twos complement signed integers:
*/
int32
scsi_3btoi(bytes)
u_char *bytes;
@ -961,6 +958,48 @@ scsi_3btoi(bytes)
return (int32) rc;
}
void
scsi_uto2b(val, bytes)
u_int32 val;
u_char *bytes;
{
*bytes++ = (val & 0xff00) >> 8;
*bytes = val & 0xff;
}
u_int32
scsi_2btou(bytes)
u_char *bytes;
{
u_int32 rc;
rc = (*bytes++ << 8);
rc += *bytes;
return rc;
}
void
scsi_uto4b(val, bytes)
u_int32 val;
u_char *bytes;
{
*bytes++ = (val & 0xff000000) >> 24;
*bytes++ = (val & 0xff0000) >> 16;
*bytes++ = (val & 0xff00) >> 8;
*bytes = val & 0xff;
}
u_int32
scsi_4btou(bytes)
u_char *bytes;
{
u_int32 rc;
rc = (*bytes++ << 24);
rc += (*bytes++ << 16);
rc += (*bytes++ << 8);
rc += *bytes;
return rc;
}
/*
* Print out the scsi_link structure's address info.
*/

View File

@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: scsi_driver.c,v 1.1 1995/03/01 22:24:41 dufault Exp $
* $Id: scsi_driver.c,v 1.2 1995/03/03 21:38:43 dufault Exp $
*
*/
#include <sys/types.h>
@ -68,13 +68,16 @@ int scsi_device_attach(struct scsi_link *sc_link)
SC_DEBUG(sc_link, SDEV_DB2,
("%s%dattach: ", device->name, sc_link->dev_unit));
sc_print_addr(sc_link);
printf("%s ", device->desc);
dev = scsi_dev_lookup(device->open);
sc_link->dev = (device->setunit ?
(*device->setunit)(dev, sc_link->dev_unit) :
makedev(major(dev), sc_link->dev_unit) );
errcode = (*(device->attach))(sc_link);
errcode = (device->attach) ? (*(device->attach))(sc_link) : 0;
if (errcode == 0)
sc_link->flags |= device->link_flags;
@ -82,8 +85,9 @@ int scsi_device_attach(struct scsi_link *sc_link)
return errcode;
}
errval
scsi_open(dev_t dev, int flags, struct scsi_device *device)
int
scsi_open(dev_t dev, int flags, int fmt, struct proc *p,
struct scsi_device *device)
{
errval errcode;
u_int32 unit;
@ -102,7 +106,7 @@ scsi_open(dev_t dev, int flags, struct scsi_device *device)
return ENXIO;
errcode = (device->dev_open) ?
(*device->dev_open)(dev, flags, sc_link) : 0;
(*device->dev_open)(dev, flags, fmt, p, sc_link) : 0;
if (sc_link->flags & SDEV_ONCE_ONLY) {
/*
@ -125,8 +129,9 @@ scsi_open(dev_t dev, int flags, struct scsi_device *device)
* close the device.. only called if we are the LAST
* occurence of an open device
*/
errval
scsi_close(dev_t dev, struct scsi_device *device)
int
scsi_close(dev_t dev, int flags, int fmt, struct proc *p,
struct scsi_device *device)
{
errval errcode;
struct scsi_link *scsi_link = SCSI_LINK(device, GETUNIT(device, dev));
@ -134,7 +139,7 @@ scsi_close(dev_t dev, struct scsi_device *device)
SC_DEBUG(scsi_link, SDEV_DB1, ("%sclose: Closing device\n", device->name));
errcode = (device->dev_close) ?
(*device->dev_close)(dev, scsi_link) : 0;
(*device->dev_close)(dev, flags, fmt, p, scsi_link) : 0;
if (scsi_link->flags & SDEV_ONCE_ONLY)
scsi_link->flags &= ~SDEV_OPEN;
@ -142,16 +147,16 @@ scsi_close(dev_t dev, struct scsi_device *device)
return errcode;
}
errval
scsi_ioctl(dev_t dev, u_int32 cmd, caddr_t arg, int mode,
int
scsi_ioctl(dev_t dev, u_int32 cmd, caddr_t arg, int mode, struct proc *p,
struct scsi_device *device)
{
errval errcode;
struct scsi_link *scsi_link = SCSI_LINK(device, GETUNIT(device, dev));
errcode = (device->dev_ioctl) ?
(*device->dev_ioctl)(dev, cmd, arg, mode, scsi_link)
: scsi_do_ioctl(dev, cmd, arg, mode, scsi_link);
(*device->dev_ioctl)(dev, cmd, arg, mode, p, scsi_link)
: scsi_do_ioctl(dev, cmd, arg, mode, p, scsi_link);
return errcode;
}
@ -172,7 +177,12 @@ scsi_strategy(struct buf *bp, struct scsi_device *device)
SC_DEBUG(sc_link, SDEV_DB1, ("%s%ld: %d bytes @ blk%d\n",
device->name, unit, bp->b_bcount, bp->b_blkno));
if (device->dev_strategy)
if (bp->b_bcount == 0)
{
bp->b_resid = 0;
biodone(bp);
}
else if (device->dev_strategy)
{
(*sc_link->adapter->scsi_minphys)(bp);
(*device->dev_strategy)(bp, sc_link);

View File

@ -35,22 +35,27 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: scsi_ioctl.c,v 1.10 1995/01/19 12:41:36 dufault Exp $
* $Id: scsi_driver.h,v 1.1 1995/03/01 22:24:42 dufault Exp $
*
*/
#ifndef _SCSI__DRIVER_H_
#define _SCSI__DRIVER_H_
#include <sys/conf.h>
struct kern_devconf;
struct scsi_link;
struct scsi_device;
struct buf;
struct proc;
int scsi_goaway __P((struct kern_devconf *, int));
int scsi_device_attach __P((struct scsi_link *));
errval scsi_open __P((dev_t, int, struct scsi_device *));
errval scsi_close __P((dev_t, struct scsi_device *));
errval scsi_ioctl __P((dev_t, u_int32, caddr_t, int, struct scsi_device *));
int scsi_goaway __P((struct kern_devconf *, int));
int scsi_device_attach __P((struct scsi_link *));
int scsi_open __P((dev_t, int, int, struct proc *, struct scsi_device *));
int scsi_close __P((dev_t, int, int, struct proc *, struct scsi_device *));
int scsi_ioctl __P((dev_t, u_int32, caddr_t, int, struct proc *,
struct scsi_device *));
void scsi_strategy __P((struct buf *, struct scsi_device *));
void scsi_minphys __P((struct buf *, struct scsi_device *));

View File

@ -38,7 +38,7 @@
* SUCH DAMAGE.
*End copyright
*
* $Id: scsi_ioctl.c,v 1.10 1995/01/19 12:41:36 dufault Exp $
* $Id: scsi_ioctl.c,v 1.11 1995/03/01 22:24:42 dufault Exp $
*
*
*/
@ -243,7 +243,7 @@ void scsiminphys(struct buf *bp)
* in the context of the calling process
*/
errval scsi_do_ioctl(dev_t dev, int cmd, caddr_t addr, int f,
struct scsi_link *sc_link)
struct proc *p, struct scsi_link *sc_link)
{
errval ret = 0;

View File

@ -16,7 +16,7 @@
*
* New configuration setup: dufault@hda.com
*
* $Id: scsiconf.c,v 1.19 1995/02/14 06:18:06 phk Exp $
* $Id: scsiconf.c,v 1.20 1995/03/01 22:24:43 dufault Exp $
*/
#include <sys/types.h>
@ -309,15 +309,15 @@ errval scsi_probe_bus(int bus, int targ, int lun);
/* XXX dufault@hda.com
* This scsi_device doesn't have the scsi_data_size.
* This is used during probe and used to be "probe_switch".
* This is used during probe.
*/
struct scsi_device inval_switch =
struct scsi_device probe_switch =
{
NULL,
NULL,
NULL,
NULL,
"??",
"probe",
0,
{0, 0},
NULL,
@ -470,7 +470,7 @@ scsi_init(void)
/* Feel free to take this out when everyone is sure this config
* code works well:
*/
#define CONFIGD() printf(" config'd at ")
#define CONFIGD() printf(" is configured at ")
/* scsi_bus_conf: Figure out which bus this is. If it is wired in config
* use that. Otherwise use the next free one.
@ -519,7 +519,6 @@ scsi_assign_unit(struct scsi_link *sc_link)
{
int i;
int found;
printf("%s", sc_link->device->name);
found = 0;
for (i = 0; scsi_dinit[i].name; i++) {
if ((strcmp(sc_link->device->name, scsi_dinit[i].name) == 0) &&
@ -529,9 +528,12 @@ scsi_assign_unit(struct scsi_link *sc_link)
(sc_link->lun == 0 && scsi_dinit[i].lun == SCCONF_UNSPEC)
) &&
sc_link->scsibus == scsi_dinit[i].cunit) {
CONFIGD();
sc_link->dev_unit = scsi_dinit[i].unit;
found = 1;
#ifdef CONFIGD
printf("%s is configured at %d\n",
sc_link->device->name, sc_link->dev_unit);
#endif
break;
}
}
@ -539,8 +541,6 @@ scsi_assign_unit(struct scsi_link *sc_link)
if (!found)
sc_link->dev_unit = sc_link->device->free_unit++;
printf("%d: ", sc_link->dev_unit);
return sc_link->dev_unit;
}
@ -669,6 +669,7 @@ scsi_probe_bus(int bus, int targ, int lun)
struct scsidevs *bestmatch = NULL;
struct scsi_link *sc_link = NULL;
boolean maybe_more;
int type;
if ((bus < 0 ) || ( bus >= scbusses->nelem)) {
return ENXIO;
@ -717,11 +718,11 @@ scsi_probe_bus(int bus, int targ, int lun)
}
*sc_link = *sc_link_proto; /* struct copy */
sc_link->opennings = 1;
sc_link->device = &inval_switch;
sc_link->device = &probe_switch;
sc_link->target = targ;
sc_link->lun = lun;
sc_link->quirks = 0;
bestmatch = scsi_probedev(sc_link, &maybe_more);
bestmatch = scsi_probedev(sc_link, &maybe_more, &type);
#ifdef NEW_SCSICONF
if (bestmatch) {
sc_link->quirks = bestmatch->quirks;
@ -732,7 +733,7 @@ scsi_probe_bus(int bus, int targ, int lun)
}
#endif
if (bestmatch) { /* FOUND */
sc_link->device = scsi_device_lookup(bestmatch->type);
sc_link->device = scsi_device_lookup(type);
(void)scsi_assign_unit(sc_link);
@ -777,9 +778,10 @@ scsi_link_get(bus, targ, lun)
* entry.
*/
struct scsidevs *
scsi_probedev(sc_link, maybe_more)
scsi_probedev(sc_link, maybe_more, type_p)
boolean *maybe_more;
struct scsi_link *sc_link;
int *type_p;
{
u_int8 unit = sc_link->adapter_unit;
u_int8 target = sc_link->target;
@ -916,35 +918,20 @@ scsi_probedev(sc_link, maybe_more)
manu[8] = 0;
model[16] = 0;
version[4] = 0;
printf("%s%d targ %d lun %d: type %ld(%s) %s SCSI%d\n"
,scsi_adapter->name
,unit
,target
,lu
sc_print_addr(sc_link);
printf("type %ld(%s) %s SCSI%d\n"
,type
,dtype
,remov ? "removable" : "fixed"
,inqbuf->version & SID_ANSII
);
printf("%s%d targ %d lun %d: <%s%s%s>\n"
,scsi_adapter->name
,unit
,target
,lu
,manu
,model
,version
);
sc_print_addr(sc_link);
printf("<%s%s%s>\n", manu, model, version );
if (qtype[0]) {
printf("%s%d targ %d lun %d: qualifier %ld(%s)\n"
,scsi_adapter->name
,unit
,target
,lu
,qualifier
,qtype
);
sc_print_addr(sc_link);
printf("qualifier %ld(%s)\n" ,qualifier ,qtype);
}
/*
* Try make as good a match as possible with
* available sub drivers
@ -954,6 +941,15 @@ scsi_probedev(sc_link, maybe_more)
if ((bestmatch) && (bestmatch->flags & SC_MORE_LUS)) {
*maybe_more = 1;
}
/* If the device is unknown then we should be trying to look up a
* type driver based on the inquiry type.
*/
if (bestmatch == &unknowndev)
*type_p = type;
else
*type_p = bestmatch->type;
return bestmatch;
}
@ -1102,9 +1098,6 @@ scsi_selectdev(qualifier, type, remov, manu, model, rev)
}
#endif /* NEW_SCSICONF */
if (bestmatch == (struct scsidevs *) 0) {
/* XXX At this point we should default to a base type driver.
*/
printf("No explicit driver match. Attaching as unknown.\n");
bestmatch = &unknowndev;
}
return (bestmatch);

View File

@ -14,7 +14,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
*
* $Id: scsiconf.h,v 1.17 1995/02/14 06:17:23 phk Exp $
* $Id: scsiconf.h,v 1.18 1995/03/01 22:24:44 dufault Exp $
*/
#ifndef SCSI_SCSICONF_H
#define SCSI_SCSICONF_H 1
@ -148,6 +148,9 @@ struct scsi_data;
struct scsi_link; /* scsi_link refers to scsi_device and vice-versa */
struct scsi_xfer;
struct proc;
/*
* These entry points are called by the low-end drivers to get services from
* whatever high-end drivers they are attached to. Each device type has one
@ -172,17 +175,20 @@ struct scsi_device
/* 36*/ int32 link_flags; /* Flags OR'd into sc_link at attach time */
/* 40*/ errval (*attach)(struct scsi_link *sc_link);
/* 44*/ int (*open)(dev_t dev, int flags);
/* 48*/ int sizeof_scsi_data;
/* 52*/ int type; /* Type of device this supports */
/* 56*/ int (*getunit)(dev_t dev);
/* 60*/ dev_t (*setunit)(dev_t dev, int unit);
/* 44*/ char *desc; /* Description of device */
/* 48*/ int (*open)(dev_t dev, int flags, int fmt, struct proc *p);
/* 52*/ int sizeof_scsi_data;
/* 56*/ int type; /* Type of device this supports */
/* 60*/ int (*getunit)(dev_t dev);
/* 64*/ dev_t (*setunit)(dev_t dev, int unit);
/* 64*/ errval (*dev_open)(dev_t dev, int flags, struct scsi_link *sc_link);
/* 68*/ errval (*dev_ioctl)(dev_t dev, int cmd, caddr_t arg, int mode,
/* 68*/ int (*dev_open)(dev_t dev, int flags, int fmt, struct proc *p,
struct scsi_link *sc_link);
/* 72*/ errval (*dev_close)(dev_t dev, struct scsi_link *sc_link);
/* 76*/ void (*dev_strategy)(struct buf *bp, struct scsi_link *sc_link);
/* 72*/ int (*dev_ioctl)(dev_t dev, int cmd, caddr_t arg, int mode,
struct proc *p, struct scsi_link *sc_link);
/* 76*/ int (*dev_close)(dev_t dev, int flag, int fmt, struct proc *p,
struct scsi_link *sc_link);
/* 80*/ void (*dev_strategy)(struct buf *bp, struct scsi_link *sc_link);
/* Not initialized after this */
@ -212,17 +218,17 @@ void NAME##init(void) \
{ \
scsi_device_register(&NAME##_switch); \
} \
errval NAME##open(dev_t dev, int flags) \
int NAME##open(dev_t dev, int flags, int fmt, struct proc *p) \
{ \
return scsi_open(dev, flags, &NAME##_switch); \
return scsi_open(dev, flags, fmt, p, &NAME##_switch); \
} \
errval NAME##ioctl(dev_t dev, int cmd, caddr_t addr, int flag) \
int NAME##ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p) \
{ \
return scsi_ioctl(dev, cmd, addr, flag, &NAME##_switch); \
return scsi_ioctl(dev, cmd, addr, flag, p, &NAME##_switch); \
} \
errval NAME##close(dev_t dev) \
int NAME##close(dev_t dev, int flag, int fmt, struct proc *p) \
{ \
return scsi_close(dev, &NAME##_switch); \
return scsi_close(dev, flag, fmt, p, &NAME##_switch); \
} \
void NAME##minphys(struct buf *bp) \
{ \
@ -439,7 +445,8 @@ char * scsi_type_name(int type);
void scsi_attachdevs __P((struct scsi_link *sc_link_proto));
struct scsi_xfer *get_xs( struct scsi_link *sc_link, u_int32 flags);
void free_xs(struct scsi_xfer *xs, struct scsi_link *sc_link,u_int32 flags);
u_int32 scsi_size( struct scsi_link *sc_link,u_int32 flags);
u_int32 scsi_read_capacity __P(( struct scsi_link *sc_link,
u_int32 *blk_size, u_int32 flags));
errval scsi_test_unit_ready( struct scsi_link *sc_link, u_int32 flags);
errval scsi_change_def( struct scsi_link *sc_link, u_int32 flags);
errval scsi_inquire( struct scsi_link *sc_link,
@ -453,11 +460,12 @@ errval scsi_scsi_cmd( struct scsi_link *sc_link, struct scsi_generic *scsi_cmd,
u_int32 datalen, u_int32 retries,
u_int32 timeout, struct buf *bp,
u_int32 flags);
errval scsi_do_ioctl __P((dev_t dev,
int cmd, caddr_t addr, int f, struct scsi_link *sc_link));
int scsi_do_ioctl __P((dev_t dev, int cmd, caddr_t addr, int mode,
struct proc *p, struct scsi_link *sc_link));
struct scsi_link *scsi_link_get __P((int bus, int targ, int lun));
dev_t scsi_dev_lookup __P((int (*opener)(dev_t dev, int flags)));
dev_t scsi_dev_lookup __P((int (*opener)(dev_t dev, int flags, int fmt,
struct proc *p)));
int scsi_opened_ok __P((dev_t dev, int flag, int type, struct scsi_link *sc_link));
@ -469,6 +477,10 @@ void show_mem(unsigned char * , u_int32);
void scsi_uto3b __P((u_int32 val, u_char *bytes));
u_int32 scsi_3btou __P((u_char *bytes));
int32 scsi_3btoi __P((u_char *bytes));
void scsi_uto4b __P((u_int32 val, u_char *bytes));
u_int32 scsi_4btou __P((u_char *bytes));
void scsi_uto2b __P((u_int32 val, u_char *bytes));
u_int32 scsi_2btou __P((u_char *bytes));
extern void sc_print_addr(struct scsi_link *);
@ -561,10 +573,6 @@ extern struct kern_devconf kdc_scbus0; /* XXX should go away */
#define CDUNIT(DEV) SH3_UNIT(DEV)
#define CDSETUNIT(DEV, U) SH3SETUNIT((DEV), (U))
#define SDUNITSHIFT 3
#define SDUNIT(DEV) SH3_UNIT(DEV)
#define SDSETUNIT(DEV, U) SH3SETUNIT((DEV), (U))
#define CHUNIT(DEV) SH4_UNIT(DEV)
#define CHSETUNIT(DEV, U) SH4SETUNIT((DEV), (U))

View File

@ -14,7 +14,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992
*
* $Id: sd.c,v 1.50 1995/01/31 11:41:46 dufault Exp $
* $Id: sd.c,v 1.51 1995/03/01 22:24:45 dufault Exp $
*/
#define SPLSD splbio
@ -48,6 +48,10 @@ u_int32 sdstrats, sdqueues;
#define SD_RETRIES 4
#define MAXTRANSFER 8 /* 1 page at a time */
#define SDUNITSHIFT 3
#define SDUNIT(DEV) SH3_UNIT(DEV)
#define SDSETUNIT(DEV, U) SH3SETUNIT((DEV), (U))
#define MAKESDDEV(maj, unit, part) (makedev(maj,((unit<<SDUNITSHIFT)+part)))
#define PARTITION(z) (minor(z) & 0x07)
@ -92,10 +96,12 @@ struct scsi_data {
static int sdunit(dev_t dev) { return SDUNIT(dev); }
static dev_t sdsetunit(dev_t dev, int unit) { return SDSETUNIT(dev, unit); }
errval sd_open(dev_t dev, int flags, struct scsi_link *sc_link);
errval sd_open(dev_t dev, int flags, int fmt, struct proc *p,
struct scsi_link *sc_link);
errval sd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag,
struct scsi_link *sc_link);
errval sd_close(dev_t dev, struct scsi_link *sc_link);
struct proc *p, struct scsi_link *sc_link);
errval sd_close(dev_t dev, int flag, int fmt, struct proc *p,
struct scsi_link *sc_link);
void sd_strategy(struct buf *bp, struct scsi_link *sc_link);
SCSI_DEVICE_ENTRIES(sd)
@ -111,6 +117,7 @@ struct scsi_device sd_switch =
{0, 0},
0, /* Link flags */
sdattach,
"Direct-Access",
sdopen,
sizeof(struct scsi_data),
T_DIRECT,
@ -139,7 +146,6 @@ static struct kern_devconf kdc_sd_template = {
&kdc_scbus0, /* XXX parent */
0, /* parentdata */
DC_UNKNOWN, /* not supported */
"SCSI disk"
};
static inline void
@ -151,6 +157,7 @@ sd_registerdev(int unit)
if(!kdc) return;
*kdc = kdc_sd_template;
kdc->kdc_unit = unit;
kdc->kdc_description = sd_switch.desc;
dev_attach(kdc);
if(dk_ndrive < DK_NDRIVE) {
sprintf(dk_names[dk_ndrive], "sd%d", unit);
@ -218,7 +225,8 @@ sdattach(struct scsi_link *sc_link)
* open the device. Make sure the partition info is a up-to-date as can be.
*/
errval
sd_open(dev_t dev, int flags, struct scsi_link *sc_link)
sd_open(dev_t dev, int flags, int fmt, struct proc *p,
struct scsi_link *sc_link)
{
errval errcode = 0;
u_int32 unit, part;
@ -340,7 +348,8 @@ sd_open(dev_t dev, int flags, struct scsi_link *sc_link)
* device. Convenient now but usually a pain.
*/
errval
sd_close(dev_t dev, struct scsi_link *sc_link)
sd_close(dev_t dev, int flag, int fmt, struct proc *p,
struct scsi_link *sc_link)
{
unsigned char unit, part;
struct scsi_data *sd;
@ -586,7 +595,7 @@ sdstart(u_int32 unit)
*/
errval
sd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag,
struct scsi_link *sc_link)
struct proc *p, struct scsi_link *sc_link)
{
/* struct sd_cmd_buf *args; */
errval error = 0;
@ -693,7 +702,7 @@ struct scsi_link *sc_link)
default:
if (part == RAWPART || SCSI_SUPER(dev) )
error = scsi_do_ioctl(dev, cmd, addr, flag, sc_link);
error = scsi_do_ioctl(dev, cmd, addr, flag, p, sc_link);
else
error = ENOTTY;
break;
@ -954,10 +963,7 @@ sdsize(dev_t dev)
if ((sd->flags & SDINIT) == 0)
return -1;
if (sd == 0 || (sd->flags & SDHAVELABEL) == 0) {
/* XXX: By rights sdopen should be called like:
* sdopen(MAKESDDEV(major(dev), unit, RAWPART), FREAD, S_IFBLK, 0);
*/
val = sdopen(MAKESDDEV(major(dev), unit, RAWPART), FREAD);
val = sdopen(MAKESDDEV(major(dev), unit, RAWPART), FREAD, S_IFBLK, 0);
if (val != 0)
return -1;
}

View File

@ -12,7 +12,7 @@
* on the understanding that TFS is not responsible for the correct
* functioning of this software in any circumstances.
*
* $Id: st.c,v 1.27 1995/02/25 19:11:11 jkh Exp $
* $Id: st.c,v 1.28 1995/03/01 22:24:46 dufault Exp $
*/
/*
@ -218,10 +218,12 @@ struct scsi_data {
static int stunit(dev_t dev) { return STUNIT(dev); }
static dev_t stsetunit(dev_t dev, int unit) { return STSETUNIT(dev, unit); }
errval st_open(dev_t dev, int flags, struct scsi_link *sc_link);
errval st_open(dev_t dev, int flags, int fmt, struct proc *p,
struct scsi_link *sc_link);
errval st_ioctl(dev_t dev, int cmd, caddr_t addr, int flag,
struct scsi_link *sc_link);
errval st_close(dev_t dev, struct scsi_link *sc_link);
struct proc *p, struct scsi_link *sc_link);
errval st_close(dev_t dev, int flag, int fmt, struct proc *p,
struct scsi_link *sc_link);
void st_strategy(struct buf *bp, struct scsi_link *sc_link);
SCSI_DEVICE_ENTRIES(st)
@ -237,6 +239,7 @@ struct scsi_device st_switch =
{0, 0},
0, /* Link flags */
stattach,
"Sequential-Access",
stopen,
sizeof(struct scsi_data),
T_SEQUENTIAL,
@ -287,7 +290,6 @@ static struct kern_devconf kdc_st_template = {
&kdc_scbus0, /* XXX parent */
0, /* parentdata */
DC_UNKNOWN, /* not supported */
"SCSI tape drive"
};
static inline void
@ -299,6 +301,7 @@ st_registerdev(int unit)
if(!kdc) return;
*kdc = kdc_st_template;
kdc->kdc_unit = unit;
kdc->kdc_description = st_switch.desc;
dev_attach(kdc);
}
@ -495,7 +498,8 @@ st_loadquirks(sc_link)
* open the device.
*/
errval
st_open(dev_t dev, int flags, struct scsi_link *sc_link)
st_open(dev_t dev, int flags, int fmt, struct proc *p,
struct scsi_link *sc_link)
{
u_int32 unit, mode, dsty;
errval errno = 0;
@ -580,7 +584,8 @@ st_open(dev_t dev, int flags, struct scsi_link *sc_link)
* occurence of an open device
*/
errval
st_close(dev_t dev, struct scsi_link *sc_link)
st_close(dev_t dev, int flag, int fmt, struct proc *p,
struct scsi_link *sc_link)
{
unsigned char unit, mode;
struct scsi_data *st;
@ -1104,7 +1109,7 @@ ststart(unit)
*/
errval
st_ioctl(dev_t dev, int cmd, caddr_t arg, int flag,
struct scsi_link *sc_link)
struct proc *p, struct scsi_link *sc_link)
{
errval errcode = 0;
unsigned char unit;
@ -1227,7 +1232,7 @@ struct scsi_link *sc_link)
break;
default:
if(IS_CTLMODE(dev))
errcode = scsi_do_ioctl(dev, cmd, arg, flag, sc_link);
errcode = scsi_do_ioctl(dev, cmd, arg, flag, p, sc_link);
else
errcode = ENOTTY;
break;

View File

@ -44,7 +44,7 @@
* SUCH DAMAGE.
*End copyright
*
* $Id:$
* $Id: su.c,v 1.3 1995/01/08 15:56:10 dufault Exp $
*
* Tabstops 4
*/
@ -58,39 +58,49 @@
#include <sys/buf.h>
#include <sys/systm.h>
/* bnxio, cnxio: non existent device entries (with ugly casts to quiet gcc).
/* XXX: These are taken from, and perhaps belong in, conf.c
*/
#define nxopen (d_open_t *)enxio
#define nxclose (d_close_t *)enxio
#define nxread (d_rdwr_t *)enxio
#define nxwrite nxread
#define nxstrategy (d_strategy_t *)enxio
#define nxioctl (d_ioctl_t *)enxio
#define nxdump (d_dump_t *)enxio
#define nxstop (d_stop_t *)enxio
#define nxreset (d_reset_t *)enxio
#define nxselect (d_select_t *)enxio
#define nxmmap (d_mmap_t *)enxio
#define nxdevtotty (d_ttycv_t *)nullop
#define zerosize (d_psize_t *)0
/* bnxio, cnxio: non existent device entries
*/
static struct bdevsw bnxio = {
(int (*) __P((dev_t dev, int oflags, int devtype,
struct proc *p))) enxio,
(int (*) __P((dev_t dev, int fflag, int devtype,
struct proc *p))) enxio,
(d_strategy_t *) enxio,
(int (*) __P((dev_t dev, int cmd, caddr_t data,
int fflag, struct proc *p))) enxio,
(int (*) ()) enxio,
(int (*) __P((dev_t dev))) 0,
(int ) 0
nxopen,
nxclose,
nxstrategy,
nxioctl,
nxdump,
zerosize,
0
};
static struct cdevsw cnxio = {
(int (*) __P((dev_t dev, int oflags, int devtype,
struct proc *p))) enxio,
(int (*) __P((dev_t dev, int fflag, int devtype,
struct proc *))) enxio,
(int (*) __P((dev_t dev, struct uio *uio, int ioflag))) enxio,
(int (*) __P((dev_t dev, struct uio *uio, int ioflag))) enxio,
(int (*) __P((dev_t dev, int cmd, caddr_t data,
int fflag, struct proc *p))) enxio,
(int (*) __P((struct tty *tp, int rw))) nullop,
(int (*) __P((int uban))) enxio,
(struct tty *) 0,
(int (*) __P((dev_t dev, int which, struct proc *p))) enxio,
(int (*) __P(())) enxio,
(d_strategy_t *) enxio
nxopen,
nxclose,
nxread,
nxwrite,
nxioctl,
nxstop,
nxreset,
nxdevtotty,
nxselect,
nxmmap,
nxstrategy
};
/* getsws: Look up the base dev switch for a given new style
/* getsws: Look up the base dev switch for a given "by minor number" style
* device.
*/
static int

View File

@ -2,7 +2,10 @@
* Driver for a device we can't identify.
* by Julian Elischer (julian@tfs.com)
*
* $Id: uk.c,v 1.6 1995/01/08 13:38:38 dufault Exp $
* $Id: uk.c,v 1.7 1995/03/01 22:24:47 dufault Exp $
*
* If you find that you are adding any code to this file look closely
* at putting it in "scsi_driver.c" instead.
*/
#include <sys/param.h>
@ -21,7 +24,8 @@ struct scsi_device uk_switch =
0,
{0, 0},
SDEV_ONCE_ONLY, /* Only one open allowed */
ukattach,
0,
"Unknown",
ukopen,
0,
T_UNKNOWN,
@ -32,15 +36,3 @@ struct scsi_device uk_switch =
0,
0,
};
/*
* The routine called by the low level scsi routine when it discovers
* a device suitable for this driver.
*/
errval
ukattach(struct scsi_link *sc_link)
{
printf("unknown device\n");
return 0;
}

360
sys/scsi/worm.c Normal file
View File

@ -0,0 +1,360 @@
/*
* worm: Write Once device driver
*
* Copyright (C) 1995, HD Associates, Inc.
* PO Box 276
* Pepperell, MA 01463
* 508 433 5266
* dufault@hda.com
*
* This code is contributed to the University of California at 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.
*
* $Id:$
*/
/* XXX This is PRELIMINARY.
*
* We need the "kern devconf" stuff, but I'm not
* going to add it until it is done in a simple way that provides
* base behavior in scsi_driver.c
*
* Until Bruce finishes the slice stuff there will be no partitions.
* When it is finished I hope to hoist the partition code up into
* "scsi_driver" and use common code for all devices.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
#include <scsi/scsi_disk.h>
struct scsi_data {
struct buf *buf_queue; /* the queue of pending IO operations */
u_int32 n_blks; /* Number of blocks (0 for bogus) */
u_int32 blk_size; /* Size of each blocks */
};
void wormstart(u_int32 unit);
errval worm_open(dev_t dev, int flags, int fmt, struct proc *p,
struct scsi_link *sc_link);
errval worm_ioctl(dev_t dev, int cmd, caddr_t addr, int flag,
struct proc *p, struct scsi_link *sc_link);
errval worm_close(dev_t dev, int flag, int fmt, struct proc *p,
struct scsi_link *sc_link);
void worm_strategy(struct buf *bp, struct scsi_link *sc_link);
SCSI_DEVICE_ENTRIES(worm)
struct scsi_device worm_switch =
{
NULL,
wormstart, /* we have a queue, and this is how we service it */
NULL,
NULL,
"worm",
0,
{0, 0},
SDEV_ONCE_ONLY, /* Only one open allowed */
wormattach,
"Write-Once",
wormopen,
sizeof(struct scsi_data),
T_WORM,
0,
0,
worm_open,
0,
worm_close,
worm_strategy,
};
static int worm_size(struct scsi_link *sc_link)
{
int ret;
struct scsi_data *worm = sc_link->sd;
worm->n_blks = scsi_read_capacity(sc_link, &worm->blk_size,
SCSI_NOSLEEP | SCSI_NOMASK);
if (worm->n_blks)
{
sc_link->flags |= SDEV_MEDIA_LOADED;
ret = 1;
}
else
{
sc_link->flags &= ~SDEV_MEDIA_LOADED;
ret = 0;
}
return ret;
}
errval
wormattach(struct scsi_link *sc_link)
{
struct scsi_data *worm = sc_link->sd;
printf("- UNTESTED ");
if (worm_size(sc_link) == 0)
printf("- can't get capacity.\n");
else
printf("with %ld %ld byte blocks.\n", worm->n_blks, worm->blk_size);
return 0;
}
/*
* wormstart looks to see if there is a buf waiting for the device
* and that the device is not already busy. If both are true,
* It dequeues the buf and creates a scsi command to perform the
* transfer required. The transfer request will call scsi_done
* on completion, which will in turn call this routine again
* so that the next queued transfer is performed.
* The bufs are queued by the strategy routine (wormstrategy)
*
* This routine is also called after other non-queued requests
* have been made of the scsi driver, to ensure that the queue
* continues to be drained.
* wormstart() is called at splbio
*
* XXX It looks like we need a "scsistart" to hoist common code up
* into. In particular, the removable media checking should be
* handled in one place.
*/
void
wormstart(unit)
u_int32 unit;
{
struct scsi_link *sc_link = SCSI_LINK(&worm_switch, unit);
struct scsi_data *worm = sc_link->sd;
register struct buf *bp = 0;
struct
{
u_char op_code;
u_char byte2;
u_char lba3; /* I don't want to worry about packing */
u_char lba2;
u_char lba1;
u_char lba0;
u_char reserved;
u_char tl1;
u_char tl0;
u_char ctl;
} cmd;
u_int32 flags;
u_int32 lba; /* Logical block address */
u_int32 tl; /* Transfer length */
SC_DEBUG(sc_link, SDEV_DB2, ("wormstart "));
/*
* We should reject all queued entries if SDEV_MEDIA_LOADED is not true.
*/
if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
goto badnews; /* no I/O.. media changed or something */
}
/*
* See if there is a buf to do and we are not already
* doing one
*/
while (sc_link->opennings != 0) {
/* if a special awaits, let it proceed first */
if (sc_link->flags & SDEV_WAITING) {
sc_link->flags &= ~SDEV_WAITING;
wakeup((caddr_t)sc_link);
return;
}
if ((bp = worm->buf_queue) == NULL) {
return; /* no work to bother with */
}
worm->buf_queue = bp->b_actf;
/*
* Fill out the scsi command
*/
bzero(&cmd, sizeof(cmd));
if ((bp->b_flags & B_READ) == B_WRITE) {
cmd.op_code = WRITE_BIG;
flags = SCSI_DATA_OUT;
} else {
cmd.op_code = READ_BIG;
flags = SCSI_DATA_IN;
}
lba = bp->b_blkno / (worm->blk_size / DEV_BSIZE);
tl = bp->b_bcount / worm->blk_size;
scsi_uto4b(lba, &cmd.lba3);
scsi_uto2b(tl, &cmd.tl1);
/*
* go ask the adapter to do all this for us
*/
if (scsi_scsi_cmd(sc_link,
(struct scsi_generic *) &cmd,
sizeof(cmd),
(u_char *) bp->b_un.b_addr,
bp->b_bcount,
0, /* can't retry a read on a tape really */
100000,
bp,
flags | SCSI_NOSLEEP) == SUCCESSFULLY_QUEUED) {
} else {
badnews:
printf("worm%d: oops not queued\n", unit);
bp->b_flags |= B_ERROR;
bp->b_error = EIO;
biodone(bp);
}
} /* go back and see if we can cram more work in.. */
}
void
worm_strategy(struct buf *bp, struct scsi_link *sc_link)
{
struct buf **dp;
unsigned char unit;
u_int32 opri;
struct scsi_data *worm;
unit = STUNIT((bp->b_dev));
worm = sc_link->sd;
/* XXX: Can't we move this check up to "scsi_strategy"?
*/
if (!(sc_link->flags & SDEV_MEDIA_LOADED) ||
bp->b_blkno > worm->n_blks ||
bp->b_bcount & (worm->blk_size - 1)) {
bp->b_error = EIO;
bp->b_flags |= B_ERROR;
biodone(bp);
return;
}
opri = splbio();
/*
* Use a bounce buffer if necessary
* XXX: How can we move this up?
*/
#ifdef BOUNCE_BUFFERS
if (sc_link->flags & SDEV_BOUNCE)
vm_bounce_alloc(bp);
#endif
/*
* Place it in the queue of activities for this device
* at the end.
*/
dp = &(worm->buf_queue);
while (*dp) {
dp = &((*dp)->b_actf);
}
*dp = bp;
bp->b_actf = NULL;
wormstart(unit);
splx(opri);
return;
}
/*
* Open the device. XXX: I'm completely guessing at this sequence.
*/
int
worm_open(dev_t dev, int flags, int fmt, struct proc *p,
struct scsi_link *sc_link)
{
struct scsi_data *worm = sc_link->sd;
if (sc_link->flags & SDEV_OPEN)
return EBUSY;
/*
* Check that it is still responding and ok.
* if the media has been changed this will result in a
* "unit attention" error which the error code will
* disregard because the SDEV_OPEN flag is not yet set
*
* XXX This should REALLY be hoisted up. As soon as Bruce
* finishes that slice stuff. (Add a different flag,
* and then do a "scsi_test_unit_ready" with the "ignore
* unit attention" thing set. Then all this replicated
* test unit ready code can be pulled up.
*/
scsi_test_unit_ready(sc_link, SCSI_SILENT);
/*
* Next time actually take notice of error returns
*/
sc_link->flags |= SDEV_OPEN; /* unit attn errors are now errors */
if (scsi_test_unit_ready(sc_link, SCSI_SILENT) != 0) {
SC_DEBUG(sc_link, SDEV_DB3, ("not ready\n"));
sc_link->flags &= ~SDEV_OPEN;
return ENXIO;
}
scsi_start_unit(sc_link, SCSI_SILENT);
scsi_prevent(sc_link, PR_PREVENT, SCSI_SILENT);
if (worm_size(sc_link) == 0) {
scsi_stop_unit(sc_link, 0, SCSI_SILENT);
scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
sc_link->flags &= ~SDEV_OPEN;
return ENXIO;
}
return 0;
}
int
worm_close(dev_t dev, int flag, int fmt, struct proc *p,
struct scsi_link *sc_link)
{
scsi_stop_unit(sc_link, 0, SCSI_SILENT);
scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
sc_link->flags &= ~SDEV_OPEN;
return 0;
}