summaryrefslogtreecommitdiffstats
path: root/sys/scsi
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>1998-09-15 10:40:55 +0000
committergibbs <gibbs@FreeBSD.org>1998-09-15 10:40:55 +0000
commit79200df6729d1afbc24596e05c0bee54a2544616 (patch)
tree454f8a346e1e8ffbde91ed6c5a172835b1d7d78c /sys/scsi
parent4035fc4bcc3a3a3a921bfaa090dd3f7f02b9737a (diff)
downloadFreeBSD-src-79200df6729d1afbc24596e05c0bee54a2544616.zip
FreeBSD-src-79200df6729d1afbc24596e05c0bee54a2544616.tar.gz
Obsoleted by CAM.
Diffstat (limited to 'sys/scsi')
-rw-r--r--sys/scsi/README203
-rw-r--r--sys/scsi/cd.c1419
-rw-r--r--sys/scsi/ch.c750
-rw-r--r--sys/scsi/od.c966
-rw-r--r--sys/scsi/pt.c326
-rw-r--r--sys/scsi/scsi_all.h351
-rw-r--r--sys/scsi/scsi_base.c1370
-rw-r--r--sys/scsi/scsi_cd.h216
-rw-r--r--sys/scsi/scsi_changer.h400
-rw-r--r--sys/scsi/scsi_debug.h59
-rw-r--r--sys/scsi/scsi_disk.h221
-rw-r--r--sys/scsi/scsi_driver.c245
-rw-r--r--sys/scsi/scsi_driver.h64
-rw-r--r--sys/scsi/scsi_generic.h63
-rw-r--r--sys/scsi/scsi_ioctl.c406
-rw-r--r--sys/scsi/scsi_message.h37
-rw-r--r--sys/scsi/scsi_sense.c309
-rw-r--r--sys/scsi/scsi_tape.h247
-rw-r--r--sys/scsi/scsi_worm.h128
-rw-r--r--sys/scsi/scsiconf.c1573
-rw-r--r--sys/scsi/scsiconf.h618
-rw-r--r--sys/scsi/sctarg.c319
-rw-r--r--sys/scsi/sd.c1065
-rw-r--r--sys/scsi/ssc.c162
-rw-r--r--sys/scsi/st.c2005
-rw-r--r--sys/scsi/su.c361
-rw-r--r--sys/scsi/uk.c96
-rw-r--r--sys/scsi/worm.c1811
28 files changed, 0 insertions, 15790 deletions
diff --git a/sys/scsi/README b/sys/scsi/README
deleted file mode 100644
index b9a626a..0000000
--- a/sys/scsi/README
+++ /dev/null
@@ -1,203 +0,0 @@
-WARNING: This file was not fully updated by dufault@hda.com when
-changing the configuration. See the end for new notes.
-
-This release consists of the following files
-(relative to the base of the source tree )
-
-share/man/man4/scsi.4 <-useful general info
-share/man/man4/uk.4
-share/man/man4/su.4
-share/man/man4/ch.4
-share/man/man4/cd.4
-share/man/man4/sd.4
-share/man/man4/st.4 <--READ THIS IF YOU USE TAPES!
-sbin/scsi/procargs.c
-sbin/scsi/scsi.c
-sbin/scsi/scsi.1
-sbin/scsi/Makefile
-sbin/st/Makefile
-sbin/st/st.1
-sbin/st/st.c
-sys/sys/chio.h
-sys/sys/cdio.h
-sys/sys/mtio.h
-sys/sys/scsiio.h
-sys/i386/conf/EXAMPLE
-sys/i386/isa/ultra14f.c <-runs 14f and 34f
-sys/i386/isa/ultra_all.c.beta <-beta version, runs 14f,24f and 34f
-sys/i386/isa/bt742a.c
-sys/i386/isa/aha1742.c
-sys/i386/isa/aha1542.c
-sys/scsi/syspatches
-sys/scsi/syspatches/conf.c
-sys/scsi/syspatches/user_scsi.diffs
-sys/scsi/syspatches/MAKEDEV.diff
-sys/scsi/syspatches/isa.c.patch
-sys/scsi/syspatches/README
-sys/scsi/uk.c
-sys/scsi/su.c
-sys/scsi/st.c
-sys/scsi/sd.c
-sys/scsi/ch.c
-sys/scsi/cd.c
-sys/scsi/scsi_ioctl.c
-sys/scsi/scsi_base.c
-sys/scsi/scsiconf.c
-sys/scsi/scsi_tape.h
-sys/scsi/scsi_disk.h
-sys/scsi/scsi_changer.h
-sys/scsi/scsi_cd.h
-sys/scsi/scsi_all.h
-sys/scsi/scsi_debug.h
-sys/scsi/scsiconf.h
-sys/scsi/README <--this file
-
-notice sys/scsi/sg.c and sys/sys/sgio.h have been removed
-
-
-----------------------------------------------------------------
-This scsi system is designed to allow the re-use of top end drivers
-such as disk and tape drivers, with different scsi adapters.
-
-As of writing this document, There are top end drivers working for:
-----------------------------------------------------------------
-generic scsi disk
-generic scsi tape
-cd-rom (plays music under the xcplayer (?) program)
-AEG Character recognition devices *
-Calera Character recognition devices *
-Generic scsi-II scanners *
-Exabyte tape changer device.
-GENERIC SCSI DEVICES (user generated scsi commands)
-----------------------------------------------------------------
-
-
-There are also working bottom end drivers for:
-----------------------------------------------------------------
-adaptec 1542 (and 1742 in 1542 mode)
-bustec 742a (apparently works for VESA version (445S?))(and 747?)
-adaptec 174x (note NOT 27xx)
-Ultrastore 14f (works for 34f (VESA version))
-Ultrastore 24f RSN (Beta version included here)
-----------------------------------------------------------------
-
-
-################## Using the scsi system ##################
-------------minor numbers---------------
-This scsi system does not allocate minor numbers to devices depending
-on their SCSI IDs is any way. A devices minor number is dependant
-on the order in which it was found.
-e.g. the first tape found will become st0 (minor number 0)
- the second found will become st1 (minor number 16)
- the third will become st2 (minor 32)
- etc.
-
-These devices could be on the same scsi bus or different scsi busses.
-That would not change their minor numbers.
-
-THE EXCEPTION TO THIS IS IN THE GENERIC SCSI DRIVER. in which case
-the following mapping applies:
-
-BB TTT LLL B= scsi bus number, T = target number, L = LUN.
-
-It is possible to run two different TYPES of scsi adapters at the
-same time and have st0 on one and st1 on another. (for example)
-
-There is a scheme supported in which scsi devices can be 'wired in' even
-if they are not present or powered on at probe time. (see scsiconf.c)
-In addition, the scsi(1) command allows the operator ask for a
-reprobe at any time. Newly found devices will be configured in. Any
-device that does not map to a known device type is attached to the
-'unknown' (uk) driver.
-
-
---------------making devices------------
-A changed version of /dev/MAKEDEV is supplied that
-can be used to make devices sd[01234] and st[01234]
-
-e.g.
-cd /dev
-sh MAKEDEV sd0 sd1 sd2 st0 st1 cd0
-
-see st(1) and st(4) for info on tape devices.
-
---------------file layout-------------------
-Originally I had all scsi definitions in one file: scsi.h
-I have since moved definitions of commands so that all
-definitions needed for a particular type of device are
-found together in the include file of that name.
-This approximatly follows the layout of their definition
-in the SCSI-2 spec.
-As such they are:
-
-scsi_all.h general commands for all devices --- CHAPTER 7
-scsi-disk.h commands relevant to disk --- CHAPTER 8
-scsi-tape.h commands for scsi tapes --- CHAPTER 9
-scsi-cd.h commands for cd-roms (and audio) --- CHAPTER 13
-scsi-changer.h commands medium changer devices --- CHAPTER 16
-
----------ioctl definitions-------------
-User accessable structures (e.g. ioctl definitions) have been
-placed in sys/cdio, sys/sgio and sys/chio (based after sys/mtio for
-the ioctls for mag tapes (including st).
-General scsi ioctls are found in sys/scsiio.h.
-
------------cd-rom-----------------
-The cd rom driver ha been tested by a number of people and
-grefen@convex.com has completed the audio play
-functions.
-(xcdplayer was available from the 'from_ref' directory on agate)
-
-At this time it is possible audio play is broken on cdroms and I will
-be unable to fix it until I get one to test.
-***IMPORTANT***
-Cdrom audio is only suported at all for cdroms that use SCSI2 audio
-definitions.
-
--------------media changer---------------
-Once again courtesy of grefen@convex.com (in germany)
-I have not tested this but he assures me it's ready for testing.
-If anyone has an exabyte tape changer or similar,
-contact the author for information regarding the control interface
-and program.
-
-WARNING: This has not been tested for a LONG TIME!
-
-
----------recent changes-----------
-Removed all bitfields from machine independent sections to make
-it possible for them to be used on big-endian architectures.
-
-Removed scsi specific timeouts in favour of system timeout handling.
-
-Many structures (getting more all the time) now dynamically allocated.
-
-Addition of code in the tape driver to recognise models of drive that
-have particular problems so they can be handled specially.
-
-many bug-fixes and cleanups.
-
----------even more recent changes:--------
-
-rewrote almost the entire thing..
-
-
-
-------Mon Oct 11 22:20:25 WST 1993------
-
-Code is now all KNF (or close to it).
-
-A new structure has been introduced..
-Called scsi_link, one of these exists for every bus/target/lun
-that has a driver attached to it.
-It has links to the adapter and to the driver, as well as status
-information of global interest. (e.g. if the device is in use).
-The use of this new structure has allowed the compaction of a
-lot of duplicated code into a single copy (now in scsi_base.c)
-and makes more simple the USER level scsi implimentation.
-
-------Tue Feb 28 07:43:17 EST 1995-----
-dufault@hda.com: Redid configuration to support wired devices.
-All driver entries now get bounced directly into the routines in
-"scsi_driver" via a set of functions generated by the SCSI_ENTRIES macro
-in scsi_conf.h. This lets us put the common code in a single place.
diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c
deleted file mode 100644
index 750746f..0000000
--- a/sys/scsi/cd.c
+++ /dev/null
@@ -1,1419 +0,0 @@
-/*
- * Written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- *
- * $Id: cd.c,v 1.98 1998/08/17 19:09:36 bde Exp $
- */
-
-#include "opt_bounce.h"
-#include "opt_devfs.h"
-#include "opt_scsi.h"
-
-#define SPLCD splbio
-#define ESUCCESS 0
-#include <sys/param.h>
-#include <sys/dkbad.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/buf.h>
-#include <sys/cdio.h>
-#include <sys/disklabel.h>
-#include <sys/diskslice.h>
-#include <sys/dkstat.h>
-#include <sys/kernel.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-
-#include <scsi/scsi_all.h>
-#include <scsi/scsi_cd.h>
-#include <scsi/scsi_disk.h> /* rw_big and start_stop come from there */
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-#include "ioconf.h"
-
-static errval cd_get_parms __P((int, int));
-static u_int32_t cd_size __P((int unit, int flags));
-static d_strategy_t cdstrategy1;
-static errval cd_get_mode __P((u_int32_t, struct cd_mode_data *, u_int32_t));
-static errval cd_set_mode __P((u_int32_t unit, struct cd_mode_data *));
-static errval cd_read_toc __P((u_int32_t, u_int32_t, u_int32_t, struct cd_toc_entry *,
- u_int32_t));
-
-static errval cd_pause __P((u_int32_t, u_int32_t));
-static errval cd_reset __P((u_int32_t));
-static errval cd_play_msf __P((u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t));
-static errval cd_play __P((u_int32_t, u_int32_t, u_int32_t));
-#ifdef notyet
-static errval cd_play_big __P((u_int32_t unit, u_int32_t blk, u_int32_t len));
-#endif
-static errval cd_play_tracks __P((u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t));
-static errval cd_read_subchannel __P((u_int32_t, u_int32_t, u_int32_t, int, struct cd_sub_channel_info *, u_int32_t));
-
-static d_open_t cdopen;
-static d_read_t cdread;
-static d_close_t cdclose;
-static d_ioctl_t cdioctl;
-static d_strategy_t cdstrategy;
-
-#define CDEV_MAJOR 15
-#define BDEV_MAJOR 6
-static struct cdevsw cd_cdevsw = {
- cdopen, cdclose, cdread, nowrite,
- cdioctl, nostop, nullreset, nodevtotty,
- seltrue, nommap, cdstrategy, "cd",
- NULL, -1, nodump, nopsize,
- D_DISK, 0, -1 };
-
-static int32_t cdstrats, cdqueues;
-
-#define CDUNIT(dev) dkunit(dev)
-
-/* XXX introduce a dkmodunit() macro for this. */
-#define CDSETUNIT(DEV, U) \
- makedev(major(DEV), dkmakeminor((U), dkslice(DEV), dkpart(DEV)))
-
-#define CDOUTSTANDING 2
-#define CDRETRIES 1
-#define LEADOUT 0xaa /* leadout toc entry */
-
-#define PARTITION(dev) dkpart(dev)
-
-static void cdstart(u_int32_t unit, u_int32_t flags);
-
-struct scsi_data {
- u_int32_t flags;
-#define CDINIT 0x04 /* device has been init'd */
- struct cd_parms {
- u_int32_t blksize;
- u_long disksize; /* total number sectors */
- } params;
- struct diskslices *dk_slices; /* virtual drives */
- struct buf_queue_head buf_queue;
- int dkunit;
-#ifdef DEVFS
- void *b_devfs_token;
- void *c_devfs_token;
- void *ctl_devfs_token;
-#endif
-};
-
-static int cdunit(dev_t dev) { return CDUNIT(dev); }
-static dev_t cdsetunit(dev_t dev, int unit) { return CDSETUNIT(dev, unit); }
-
-static errval cd_open(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-static errval cd_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag,
- struct proc *p, struct scsi_link *sc_link);
-static errval cd_close(dev_t dev, int flag, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-static void cd_strategy(struct buf *bp, struct scsi_link *sc_link);
-
-SCSI_DEVICE_ENTRIES(cd)
-
-static struct scsi_device cd_switch =
-{
- NULL, /* use default error handler */
- cdstart, /* we have a queue, which is started by this */
- NULL, /* we do not have an async handler */
- NULL, /* use default 'done' routine */
- "cd", /* we are to be refered to by this name */
- 0, /* no device specific flags */
- {0, 0},
- 0, /* Link flags */
- cdattach,
- "CD-ROM",
- cdopen,
- sizeof(struct scsi_data),
- T_READONLY,
- cdunit,
- cdsetunit,
- cd_open,
- cd_ioctl,
- cd_close,
- cd_strategy,
-};
-
-#define CD_STOP 0
-#define CD_START 1
-#define CD_EJECT -2
-
-static __inline void
-cd_registerdev(int unit)
-{
- if(dk_ndrive < DK_NDRIVE) {
- sprintf(dk_names[dk_ndrive], "cd%d", unit);
- dk_wpms[dk_ndrive] = (150*1024/2);
- SCSI_DATA(&cd_switch, unit)->dkunit = dk_ndrive++;
- } else {
- SCSI_DATA(&cd_switch, unit)->dkunit = -1;
- }
-}
-
-/*
- * The routine called by the low level scsi routine when it discovers
- * A device suitable for this driver
- */
-static int
-cdattach(struct scsi_link *sc_link)
-{
- u_int32_t unit;
- struct cd_parms *dp;
- struct scsi_data *cd = sc_link->sd;
-#ifdef DEVFS
- int mynor;
-#endif
-
- unit = sc_link->dev_unit;
- dp = &(cd->params);
-
- bufq_init(&cd->buf_queue);
- if (sc_link->opennings > CDOUTSTANDING)
- sc_link->opennings = CDOUTSTANDING;
- /*
- * Use the subdriver to request information regarding
- * the drive. We cannot use interrupts yet, so the
- * request must specify this.
- *
- * XXX dufault@hda.com:
- * Need to handle this better in the case of no record. Rather than
- * a state driven sense handler I think we should make it so that
- * the command can get the sense back so that it can selectively log
- * errors.
- */
- if (sc_link->quirks & CD_Q_NO_TOUCH) {
- dp->disksize = 0;
- } else {
- cd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
- }
- if (dp->disksize) {
- printf("cd present [%lu x %lu byte records]",
- cd->params.disksize, (u_long)cd->params.blksize);
- } else {
- printf("can't get the size");
- }
-
- cd->flags |= CDINIT;
- cd_registerdev(unit);
-#ifdef DEVFS
- mynor = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART);
- cd->b_devfs_token = devfs_add_devswf(&cd_cdevsw, mynor, DV_BLK,
- UID_ROOT, GID_OPERATOR, 0640,
- "cd%d", unit);
- cd->c_devfs_token = devfs_add_devswf(&cd_cdevsw, mynor, DV_CHR,
- UID_ROOT, GID_OPERATOR, 0640,
- "rcd%d", unit);
- mynor = dkmakeminor(unit, 0, 0); /* XXX */
- cd->ctl_devfs_token = devfs_add_devswf(&cd_cdevsw,
- mynor | SCSI_CONTROL_MASK,
- DV_CHR,
- UID_ROOT, GID_WHEEL, 0600,
- "rcd%d.ctl", unit);
-#endif
-
- return 0;
-}
-
-/*
- * open the device. Make sure the partition info is a up-to-date as can be.
- */
-static errval
-cd_open(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link)
-{
- errval errcode = 0;
- u_int32_t unit;
- struct disklabel label;
- struct scsi_data *cd;
- int n;
-
- unit = CDUNIT(dev);
-
- cd = sc_link->sd;
- /*
- * Make sure the device has been initialised
- */
- if ((cd == NULL) || (!(cd->flags & CDINIT)))
- return (ENXIO);
-
- SC_DEBUG(sc_link, SDEV_DB1,
- ("cd_open: dev=0x%lx (unit %lu,partition %d)\n",
- (u_long)dev, (u_long)unit, PARTITION(dev)));
- /*
- * 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.
- * Makes sure that we know it if the media has been changed..
- */
- scsi_test_unit_ready(sc_link, SCSI_SILENT);
-
- /*
- * If it's been invalidated, then forget the label.
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED) && cd->dk_slices != NULL) {
- /*
- * If somebody still has it open, then forbid re-entry.
- */
- if (dsisopen(cd->dk_slices)) {
- SC_DEBUG(sc_link, SDEV_DB2,
- ("unit attn, but openparts?\n"));
- return (ENXIO);
- }
-
- dsgone(&cd->dk_slices);
- }
-
- /*
- * Start the drive, and take notice of error returns.
- * Some (arguably broken) drives go crazy on this attempt, we can
- * handle it.
- */
- if ((sc_link->quirks & CD_Q_NO_START) == 0) {
- scsi_start_unit(sc_link, CD_START);
- SC_DEBUG(sc_link, SDEV_DB3, ("'start' attempted "));
- }
- sc_link->flags |= SDEV_OPEN; /* unit attn errors are now errors */
-
- /*
- * Some drives take a long time to become ready after a disk swap
- * and report 'Not Ready' rather than 'Unit in the Process of Getting
- * Ready' while doing so; attempts to mount during this period will
- * return ENXIO. Give them some time to come up.
- */
- for (n = 0; scsi_test_unit_ready(sc_link, SCSI_SILENT) && n != 12; n++)
- tsleep(cd, PRIBIO | PCATCH, "cdrdy", hz);
-
- /* If still not ready, give up */
- if (scsi_test_unit_ready(sc_link, SCSI_SILENT) != 0) {
- SC_DEBUG(sc_link, SDEV_DB3, ("not ready\n"));
- errcode = ENXIO;
- goto bad;
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("Device present\n"));
- scsi_prevent(sc_link, PR_PREVENT, SCSI_SILENT);
- /*
- * Load the physical device parameters
- */
- if (cd_get_parms(unit, 0)) {
- errcode = ENXIO;
- goto bad;
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
-
- /*
- * Build prototype label for whole disk.
- * Should put manufacturer and model in d_typename and d_packname.
- * Should take information about different data tracks from the
- * TOC and put it in the partition table.
- */
- bzero(&label, sizeof label);
- label.d_type = DTYPE_SCSI;
- strncpy(label.d_typename, "scsi cd_rom", sizeof(label.d_typename));
- label.d_secsize = cd->params.blksize;
- label.d_secperunit = cd->params.disksize;
- label.d_flags = D_REMOVABLE;
- /*
- * Make partition 'a' cover the whole disk. This is a temporary
- * compatibility hack. The 'a' partition should not exist, so
- * the slice code won't create it. The slice code will make
- * partition (RAW_PART + 'a') cover the whole disk and fill in
- * some more defaults.
- */
- label.d_partitions[0].p_size = label.d_secperunit;
- label.d_partitions[0].p_fstype = FS_OTHER;
-
- /* Initialize slice tables. */
- errcode = dsopen("cd", dev, fmt, DSO_NOLABELS | DSO_ONESLICE,
- &cd->dk_slices, &label, cdstrategy1,
- (ds_setgeom_t *)NULL, &cd_cdevsw);
- if (errcode != 0)
- goto bad;
- SC_DEBUG(sc_link, SDEV_DB3, ("Slice tables initialized "));
-
- SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));
- sc_link->flags |= SDEV_MEDIA_LOADED;
- return 0;
-
- bad:
- /*
- * if we would have been the only open
- * then leave things back as they were
- */
- if (!dsisopen(cd->dk_slices)) {
- sc_link->flags &= ~SDEV_OPEN;
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
- }
- return (errcode);
-}
-
-/*
- * close the device.. only called if we are the LAST
- * occurence of an open device
- */
-static errval
-cd_close(dev_t dev, int flag, int fmt, struct proc *p,
- struct scsi_link *sc_link)
-{
- struct scsi_data *cd;
-
- cd = sc_link->sd;
- SC_DEBUG(sc_link, SDEV_DB2, ("cd%d: closing part %d\n",
- CDUNIT(dev), PARTITION(dev)));
- dsclose(dev, fmt, cd->dk_slices);
- if (!dsisopen(cd->dk_slices)) {
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
- sc_link->flags &= ~SDEV_OPEN;
- }
- return (0);
-}
-
-
-static int
-cdread(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(cdstrategy, NULL, dev, 1, minphys, uio));
-}
-
-/*
- * Actually translate the requested transfer into one the physical driver can
- * understand. The transfer is described by a buf and will include only one
- * physical transfer.
- */
-static void
-cd_strategy(struct buf *bp, struct scsi_link *sc_link)
-{
- u_int32_t opri;
- u_int32_t unit = CDUNIT((bp->b_dev));
- struct scsi_data *cd = sc_link->sd;
-
- cdstrats++;
- /*
- * If the device has been made invalid, error out
- * maybe the media changed
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- bp->b_error = EIO;
- goto bad;
- }
- /*
- * can't ever write to a CD
- */
- if ((bp->b_flags & B_READ) == 0) {
- bp->b_error = EROFS;
- goto bad;
- }
-
- /*
- * Do bounds checking, adjust transfer, and set b_pblkno.
- */
- if (dscheck(bp, cd->dk_slices) <= 0)
- goto done;
-
- opri = SPLCD();
-
- /*
- * 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 disk activities for this disk
- */
- bufq_insert_tail(&cd->buf_queue, bp);
-
- /*
- * Tell the device to get going on the transfer if it's
- * not doing anything, otherwise just wait for completion
- */
- cdstart(unit, 0);
-
- splx(opri);
- return;
- bad:
- bp->b_flags |= B_ERROR;
- done:
-
- /*
- * Correctly set the buf to indicate a completed xfer
- */
- bp->b_resid = bp->b_bcount;
- biodone(bp);
- return;
-}
-
-static void
-cdstrategy1(struct buf *bp)
-{
- /*
- * XXX - do something to make cdstrategy() but not this block while
- * we're doing dsinit() and dsioctl().
- */
- cdstrategy(bp);
-}
-
-/*
- * cdstart 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 deques the buf and creates a scsi command to perform the
- * transfer in the buf. 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 (cdstrategy)
- *
- * 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.
- *
- * must be called at the correct (highish) spl level
- * cdstart() is called at SPLCD from cdstrategy and scsi_done
- */
-static void
-cdstart(unit, flags)
- u_int32_t unit;
- u_int32_t flags;
-{
- register struct buf *bp = 0;
- struct scsi_rw_big cmd;
- u_int32_t blkno, nblk;
- struct scsi_link *sc_link = SCSI_LINK(&cd_switch, unit);
- struct scsi_data *cd = sc_link->sd;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("cdstart%lu ", (u_long)unit));
- /*
- * See if there is a buf to do and we are not already
- * doing one
- */
- if (!sc_link->opennings) {
- return; /* no room for us, unit already underway */
- }
- if (sc_link->flags & SDEV_WAITING) { /* is room, but a special waits */
- return; /* give the special that's waiting a chance to run */
- }
-
- bp = bufq_first(&cd->buf_queue);
- if (bp == NULL) { /* yes, an assign */
- return;
- }
- bufq_remove(&cd->buf_queue, bp);
-
- /*
- * Should reject all queued entries if SDEV_MEDIA_LOADED is not true.
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- goto bad; /* no I/O.. media changed or something */
- }
- /*
- * We have a buf, now we should make a command
- */
- blkno = bp->b_pblkno;
- nblk = bp->b_bcount / cd->params.blksize;
-
- /*
- * Fill out the scsi command
- */
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = READ_BIG;
- cmd.addr_3 = (blkno & 0xff000000UL) >> 24;
- cmd.addr_2 = (blkno & 0xff0000) >> 16;
- cmd.addr_1 = (blkno & 0xff00) >> 8;
- cmd.addr_0 = blkno & 0xff;
- cmd.length2 = (nblk & 0xff00) >> 8;
- cmd.length1 = (nblk & 0xff);
-
- /*
- * Call the routine that chats with the adapter.
- * Note: we cannot sleep as we may be an interrupt
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- (u_char *) bp->b_data,
- bp->b_bcount,
- CDRETRIES,
- 30000,
- bp,
- flags | ((bp->b_flags & B_READ) ?
- SCSI_DATA_IN : SCSI_DATA_OUT))
- != SUCCESSFULLY_QUEUED) {
- bad:
- printf("cd%lu: oops not queued\n", (u_long)unit);
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- biodone(bp);
- return;
- }
- cdqueues++;
- if(cd->dkunit >= 0) {
- dk_xfer[cd->dkunit]++;
- dk_seek[cd->dkunit]++; /* don't know */
- dk_wds[cd->dkunit] += bp->b_bcount >> 6;
- }
-}
-
-/*
- * Perform special action on behalf of the user.
- * Knows about the internals of this device
- */
-static errval
-cd_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p,
- struct scsi_link *sc_link)
-{
- errval error;
- u_int32_t unit;
- register struct scsi_data *cd;
-
- /*
- * Find the device that the user is talking about
- */
- cd = sc_link->sd;
- SC_DEBUG(sc_link, SDEV_DB2, ("cdioctl 0x%lx ", cmd));
-
- /*
- * If the device is not valid.. abandon ship
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED))
- return (EIO);
-
- if (cmd == DIOCSBAD)
- return (EINVAL); /* XXX */
-#if 0
- /* Wait until we have exclusive access to the device. */
- /* XXX this is how sd does it. How did we work without this? */
- error = scsi_device_lock(sc_link);
- if (error)
- return error;
-#endif
- error = dsioctl("cd", dev, cmd, addr, flag, &cd->dk_slices,
- cdstrategy1, (ds_setgeom_t *)NULL);
- scsi_device_unlock(sc_link);
- if (error != ENOIOCTL)
- return (error);
- if (PARTITION(dev) != RAW_PART)
- return (ENOTTY);
- error = 0;
- unit = CDUNIT(dev);
- switch (cmd) {
- case CDIOCPLAYTRACKS:
- {
- struct ioc_play_track *args
- = (struct ioc_play_track *) addr;
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.flags &= ~CD_PA_SOTC;
- data.page.audio.flags |= CD_PA_IMMED;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- if (sc_link->quirks & CD_Q_BCD_TRACKS) {
- args->start_track = bin2bcd(args->start_track);
- args->end_track = bin2bcd(args->end_track);
- }
- return (cd_play_tracks(unit
- ,args->start_track
- ,args->start_index
- ,args->end_track
- ,args->end_index
- ));
- }
- break;
- case CDIOCPLAYMSF:
- {
- struct ioc_play_msf *args
- = (struct ioc_play_msf *) addr;
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.flags &= ~CD_PA_SOTC;
- data.page.audio.flags |= CD_PA_IMMED;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- return (cd_play_msf(unit
- ,args->start_m
- ,args->start_s
- ,args->start_f
- ,args->end_m
- ,args->end_s
- ,args->end_f
- ));
- }
- break;
- case CDIOCPLAYBLOCKS:
- {
- struct ioc_play_blocks *args
- = (struct ioc_play_blocks *) addr;
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.flags &= ~CD_PA_SOTC;
- data.page.audio.flags |= CD_PA_IMMED;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- return (cd_play(unit, args->blk, args->len));
-
- }
- break;
- case CDIOCREADSUBCHANNEL:
- {
- struct ioc_read_subchannel *args
- = (struct ioc_read_subchannel *) addr;
- struct cd_sub_channel_info data;
- u_int32_t len = args->data_len;
- if (len > sizeof(data) ||
- len < sizeof(struct cd_sub_channel_header)) {
- error = EINVAL;
- break;
- }
- if (sc_link->quirks & CD_Q_BCD_TRACKS)
- args->track = bin2bcd(args->track);
- error = cd_read_subchannel(unit, args->address_format,
- args->data_format, args->track, &data, len);
- if (error)
- break;
- if (sc_link->quirks & CD_Q_BCD_TRACKS)
- data.what.track_info.track_number =
- bcd2bin(data.what.track_info.track_number);
- len = min(len, ((data.header.data_len[0] << 8) +
- data.header.data_len[1] +
- sizeof(struct cd_sub_channel_header)));
- if (copyout(&data, args->data, len) != 0) {
- error = EFAULT;
- }
- }
- break;
- case CDIOREADTOCHEADER:
- {
- struct ioc_toc_header th;
- error = cd_read_toc(unit, 0, 0,
- (struct cd_toc_entry *)&th, sizeof th);
- if (error)
- break;
- if (sc_link->quirks & CD_Q_BCD_TRACKS) {
- /* we are going to have to convert the BCD
- * encoding on the cd to what is expected
- */
- th.starting_track = bcd2bin(th.starting_track);
- th.ending_track = bcd2bin(th.ending_track);
- }
- NTOHS(th.len);
- bcopy(&th, addr, sizeof th);
- }
- break;
- case CDIOREADTOCENTRYS:
- {
- struct {
- struct ioc_toc_header header;
- struct cd_toc_entry entries[100];
- } data;
- struct {
- struct ioc_toc_header header;
- struct cd_toc_entry entry;
- } lead;
- struct ioc_read_toc_entry *te =
- (struct ioc_read_toc_entry *) addr;
- struct ioc_toc_header *th;
- u_int32_t len, readlen, idx, num;
- u_int32_t starting_track = te->starting_track;
-
- if ( te->data_len < sizeof(struct cd_toc_entry)
- || (te->data_len % sizeof(struct cd_toc_entry)) != 0
- || te->address_format != CD_MSF_FORMAT
- && te->address_format != CD_LBA_FORMAT
- ) {
- error = EINVAL;
- break;
- }
-
- th = &data.header;
- error = cd_read_toc(unit, 0, 0,
- (struct cd_toc_entry *)th, sizeof (*th));
- if (error)
- break;
-
- if (sc_link->quirks & CD_Q_BCD_TRACKS) {
- /* we are going to have to convert the BCD
- * encoding on the cd to what is expected
- */
- th->starting_track =
- bcd2bin(th->starting_track);
- th->ending_track = bcd2bin(th->ending_track);
- }
-
- if (starting_track == 0)
- starting_track = th->starting_track;
- else if (starting_track == LEADOUT)
- starting_track = th->ending_track + 1;
- else if (starting_track < th->starting_track ||
- starting_track > th->ending_track + 1) {
- error = EINVAL;
- break;
- }
-
- /* calculate reading length without leadout entry */
- readlen = (th->ending_track - starting_track + 1) *
- sizeof(struct cd_toc_entry);
-
- /* and with leadout entry */
- len = readlen + sizeof(struct cd_toc_entry);
- if (te->data_len < len) {
- len = te->data_len;
- if (readlen > len)
- readlen = len;
- }
- if (len > sizeof(data.entries)) {
- error = EINVAL;
- break;
- }
- num = len / sizeof(struct cd_toc_entry);
-
- if (readlen > 0) {
- error = cd_read_toc(unit, te->address_format,
- starting_track,
- (struct cd_toc_entry *)&data,
- readlen + sizeof (*th));
- if (error)
- break;
- }
-
- /* make leadout entry if needed */
- idx = starting_track + num - 1;
- if (sc_link->quirks & CD_Q_BCD_TRACKS)
- th->ending_track = bcd2bin(th->ending_track);
- if (idx == th->ending_track + 1) {
- error = cd_read_toc(unit, te->address_format,
- LEADOUT,
- (struct cd_toc_entry *)&lead,
- sizeof(lead));
- if (error)
- break;
- data.entries[idx - starting_track] = lead.entry;
- }
-
- if (sc_link->quirks & CD_Q_BCD_TRACKS) {
- for (idx = 0; idx < num - 1; idx++) {
- data.entries[idx].track =
- bcd2bin(data.entries[idx].track);
- }
- }
-
- error = copyout(data.entries, te->data, len);
- }
- break;
- case CDIOREADTOCENTRY:
- {
- struct {
- struct ioc_toc_header header;
- struct cd_toc_entry entry;
- } data;
- struct ioc_read_toc_single_entry *te =
- (struct ioc_read_toc_single_entry *) addr;
- struct ioc_toc_header *th;
- u_int32_t track;
-
- if (te->address_format != CD_MSF_FORMAT
- && te->address_format != CD_LBA_FORMAT) {
- error = EINVAL;
- break;
- }
-
- th = &data.header;
- error = cd_read_toc(unit, 0, 0,
- (struct cd_toc_entry *)th, sizeof (*th));
- if (error)
- break;
-
- if (sc_link->quirks & CD_Q_BCD_TRACKS) {
- /* we are going to have to convert the BCD
- * encoding on the cd to what is expected
- */
- th->starting_track =
- bcd2bin(th->starting_track);
- th->ending_track = bcd2bin(th->ending_track);
- }
-
- track = te->track;
- if (track == 0)
- track = th->starting_track;
- else if (track == LEADOUT)
- /* OK */;
- else if (track < th->starting_track ||
- track > th->ending_track + 1) {
- error = EINVAL;
- break;
- }
-
- error = cd_read_toc(unit, te->address_format,
- track,
- (struct cd_toc_entry *)&data,
- sizeof data);
- if (error)
- break;
-
- if (sc_link->quirks & CD_Q_BCD_TRACKS)
- data.entry.track = bcd2bin(data.entry.track);
-
- bcopy(&data.entry, &te->entry,
- sizeof(struct cd_toc_entry));
- }
- break;
- case CDIOCSETPATCH:
- {
- struct ioc_patch *arg = (struct ioc_patch *) addr;
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
- data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
- data.page.audio.port[2].channels = arg->patch[2];
- data.page.audio.port[3].channels = arg->patch[3];
- error = cd_set_mode(unit, &data);
- if (error)
- break; /* eh? */
- }
- break;
- case CDIOCGETVOL:
- {
- struct ioc_vol *arg = (struct ioc_vol *) addr;
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
- arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
- arg->vol[2] = data.page.audio.port[2].volume;
- arg->vol[3] = data.page.audio.port[3].volume;
- }
- break;
- case CDIOCSETVOL:
- {
- struct ioc_vol *arg = (struct ioc_vol *) addr;
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.port[LEFT_PORT].channels = CHANNEL_0;
- data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
- data.page.audio.port[RIGHT_PORT].channels = CHANNEL_1;
- data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
- data.page.audio.port[2].volume = arg->vol[2];
- data.page.audio.port[3].volume = arg->vol[3];
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- }
- break;
- case CDIOCSETMONO:
- {
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL | RIGHT_CHANNEL;
- data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL | RIGHT_CHANNEL;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- }
- break;
- case CDIOCSETSTEREO:
- {
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
- data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- }
- break;
- case CDIOCSETMUTE:
- {
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.port[LEFT_PORT].channels = 0;
- data.page.audio.port[RIGHT_PORT].channels = 0;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- }
- break;
- case CDIOCSETLEFT:
- {
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
- data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- }
- break;
- case CDIOCSETRIGHT:
- {
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
- data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- }
- break;
- case CDIOCRESUME:
- error = cd_pause(unit, 1);
- break;
- case CDIOCPAUSE:
- error = cd_pause(unit, 0);
- break;
- case CDIOCSTART:
- error = scsi_start_unit(sc_link, 0);
- break;
- case CDIOCSTOP:
- error = scsi_stop_unit(sc_link, 0, 0);
- break;
- case CDIOCEJECT:
- error = scsi_stop_unit(sc_link, 1, 0);
- break;
- case CDIOCALLOW:
- error = scsi_prevent(sc_link, PR_ALLOW, 0);
- break;
- case CDIOCPREVENT:
- error = scsi_prevent(sc_link, PR_PREVENT, 0);
- break;
- case CDIOCSETDEBUG:
- sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
- break;
- case CDIOCCLRDEBUG:
- sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
- break;
- case CDIOCRESET:
- return (cd_reset(unit));
- break;
- default:
- error = scsi_do_ioctl(dev, cmd, addr, flag, p, sc_link);
- break;
- }
- return (error);
-}
-
-/*
- * Find out from the device what its capacity is
- */
-static u_int32_t
-cd_size(unit, flags)
- int unit;
- int flags;
-{
- struct scsi_read_cd_cap_data rdcap;
- struct scsi_read_cd_capacity scsi_cmd;
- u_int32_t size;
- u_int32_t blksize;
- struct scsi_link *sc_link = SCSI_LINK(&cd_switch, unit);
- struct scsi_data *cd = sc_link->sd;
-
- /*
- * make up a scsi command and ask the scsi driver to do
- * it for you.
- */
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = READ_CD_CAPACITY;
-
- /*
- * If the command works, interpret the result as a 4 byte
- * number of blocks and a blocksize
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) & rdcap,
- sizeof(rdcap),
- CDRETRIES,
- 20000, /* might be a disk-changer */
- NULL,
- SCSI_DATA_IN | flags) != 0) {
- return (0);
- } else {
- size = rdcap.addr_0 + 1;
- size += rdcap.addr_1 << 8;
- size += rdcap.addr_2 << 16;
- size += rdcap.addr_3 << 24;
- blksize = rdcap.length_0;
- blksize += rdcap.length_1 << 8;
- blksize += rdcap.length_2 << 16;
- blksize += rdcap.length_3 << 24;
- }
- if (blksize < 512)
- blksize = 2048; /* some drives lie ! */
- if (size < 100)
- size = 400000; /* ditto */
- SC_DEBUG(sc_link, SDEV_DB3, ("cd%d: %lu %lu byte blocks\n",
- unit, (u_long)size, (u_long)blksize));
- cd->params.disksize = size;
- cd->params.blksize = blksize;
- return (size);
-}
-
-/*
- * Get the requested page into the buffer given
- */
-static errval
-cd_get_mode(unit, data, page)
- u_int32_t unit;
- struct cd_mode_data *data;
- u_int32_t page;
-{
- struct scsi_mode_sense scsi_cmd;
- errval retval;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- bzero(data, sizeof(*data));
- scsi_cmd.op_code = MODE_SENSE;
- scsi_cmd.page = page;
- scsi_cmd.length = sizeof(*data) & 0xff;
- retval = scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) data,
- sizeof(*data),
- CDRETRIES,
- 20000, /* should be immed */
- NULL,
- SCSI_DATA_IN);
- return (retval);
-}
-
-/*
- * Get the requested page into the buffer given
- */
-static errval
-cd_set_mode(unit, data)
- u_int32_t unit;
- struct cd_mode_data *data;
-{
- struct scsi_mode_select scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SELECT;
- scsi_cmd.byte2 |= SMS_PF;
- scsi_cmd.length = sizeof(*data) & 0xff;
- data->header.data_length = 0;
- /*
- * SONY drives do not allow a mode select with a medium_type
- * value that has just been returned by a mode sense; use a
- * medium_type of 0 (Default) instead.
- */
- data->header.medium_type = 0;
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) data,
- sizeof(*data),
- CDRETRIES,
- 20000, /* should be immed */
- NULL,
- SCSI_DATA_OUT));
-}
-
-/*
- * Get scsi driver to send a "start playing" command
- */
-static errval
-cd_play(unit, blk, len)
- u_int32_t unit, blk, len;
-{
- struct scsi_play scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = PLAY;
- scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff;
- scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff;
- scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff;
- scsi_cmd.blk_addr[3] = blk & 0xff;
- scsi_cmd.xfer_len[0] = (len >> 8) & 0xff;
- scsi_cmd.xfer_len[1] = len & 0xff;
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- CDRETRIES,
- 200000, /* should be immed */
- NULL,
- 0));
-}
-
-#ifdef notyet
-/*
- * Get scsi driver to send a "start playing" command
- */
-static errval
-cd_play_big(unit, blk, len)
- u_int32_t unit, blk, len;
-{
- struct scsi_play_big scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = PLAY_BIG;
- scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff;
- scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff;
- scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff;
- scsi_cmd.blk_addr[3] = blk & 0xff;
- scsi_cmd.xfer_len[0] = (len >> 24) & 0xff;
- scsi_cmd.xfer_len[1] = (len >> 16) & 0xff;
- scsi_cmd.xfer_len[2] = (len >> 8) & 0xff;
- scsi_cmd.xfer_len[3] = len & 0xff;
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- CDRETRIES,
- 20000, /* should be immed */
- NULL,
- 0));
-}
-#endif
-
-/*
- * Get scsi driver to send a "start playing" command
- */
-static errval
-cd_play_tracks(unit, strack, sindex, etrack, eindex)
- u_int32_t unit, strack, sindex, etrack, eindex;
-{
- struct scsi_play_track scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = PLAY_TRACK;
- scsi_cmd.start_track = strack;
- scsi_cmd.start_index = sindex;
- scsi_cmd.end_track = etrack;
- scsi_cmd.end_index = eindex;
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- CDRETRIES,
- 20000, /* should be immed */
- NULL,
- 0));
-}
-
-/*
- * Get scsi driver to send a "play msf" command
- */
-static errval
-cd_play_msf(unit, startm, starts, startf, endm, ends, endf)
- u_int32_t unit, startm, starts, startf, endm, ends, endf;
-{
- struct scsi_play_msf scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = PLAY_MSF;
- scsi_cmd.start_m = startm;
- scsi_cmd.start_s = starts;
- scsi_cmd.start_f = startf;
- scsi_cmd.end_m = endm;
- scsi_cmd.end_s = ends;
- scsi_cmd.end_f = endf;
-
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- CDRETRIES,
- 2000,
- NULL,
- 0));
-}
-
-/*
- * Get scsi driver to send a "start up" command
- */
-static errval
-cd_pause(unit, go)
- u_int32_t unit, go;
-{
- struct scsi_pause scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = PAUSE;
- scsi_cmd.resume = go;
-
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- CDRETRIES,
- 2000,
- NULL,
- 0));
-}
-
-/*
- * Get scsi driver to send a "RESET" command
- */
-static errval
-cd_reset(unit)
- u_int32_t unit;
-{
- return scsi_reset_target(SCSI_LINK(&cd_switch, unit));
-}
-
-/*
- * Read subchannel
- */
-static errval
-cd_read_subchannel(unit, mode, format, track, data, len)
- u_int32_t unit, mode, format;
- int track;
- struct cd_sub_channel_info *data;
- u_int32_t len;
-{
- struct scsi_read_subchannel scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
-
- scsi_cmd.op_code = READ_SUBCHANNEL;
- if (mode == CD_MSF_FORMAT)
- scsi_cmd.byte2 |= CD_MSF;
- scsi_cmd.byte3 = SRS_SUBQ;
- scsi_cmd.subchan_format = format;
- scsi_cmd.track = track;
- scsi_cmd.data_len[0] = (len) >> 8;
- scsi_cmd.data_len[1] = (len) & 0xff;
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(struct scsi_read_subchannel),
- (u_char *) data,
- len,
- CDRETRIES,
- 5000,
- NULL,
- SCSI_DATA_IN));
-}
-
-/*
- * Read table of contents
- */
-static errval
-cd_read_toc(unit, mode, start, data, len)
- u_int32_t unit, mode, start;
- struct cd_toc_entry *data;
- u_int32_t len;
-{
- struct scsi_read_toc scsi_cmd;
- u_int32_t ntoc;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- /*if(len!=sizeof(struct ioc_toc_header))
- * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
- * else */
- ntoc = len;
-
- scsi_cmd.op_code = READ_TOC;
- if (mode == CD_MSF_FORMAT)
- scsi_cmd.byte2 |= CD_MSF;
- scsi_cmd.from_track = start;
- scsi_cmd.data_len[0] = (ntoc) >> 8;
- scsi_cmd.data_len[1] = (ntoc) & 0xff;
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(struct scsi_read_toc),
- (u_char *) data,
- len,
- CDRETRIES,
- 5000,
- NULL,
- SCSI_DATA_IN));
-}
-
-#define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
-
-/*
- * Get the scsi driver to send a full inquiry to the device and use the
- * results to fill out the disk parameter structure.
- */
-static errval
-cd_get_parms(unit, flags)
- int unit;
- int flags;
-{
- struct scsi_link *sc_link = SCSI_LINK(&cd_switch, unit);
-
- /*
- * First check if we have it all loaded
- */
- if (sc_link->flags & SDEV_MEDIA_LOADED)
- return (0);
- /*
- * give a number of sectors so that sec * trks * cyls
- * is <= disk_size
- */
- if (cd_size(unit, flags)) {
- sc_link->flags |= SDEV_MEDIA_LOADED;
- return (0);
- } else {
- return (ENXIO);
- }
-}
-
-static cd_devsw_installed = 0;
-
-static void cd_drvinit(void *unused)
-{
-
- if( ! cd_devsw_installed ) {
- cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &cd_cdevsw);
- cd_devsw_installed = 1;
- }
-}
-
-SYSINIT(cddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,cd_drvinit,NULL)
-
-
diff --git a/sys/scsi/ch.c b/sys/scsi/ch.c
deleted file mode 100644
index 9b970fb..0000000
--- a/sys/scsi/ch.c
+++ /dev/null
@@ -1,750 +0,0 @@
-/*
- * Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
- * All rights reserved.
- *
- * Partially based on an autochanger driver written by Stefan Grefen
- * and on an autochanger driver written by the Systems Programming Group
- * at 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 acknowledgements:
- * This product includes software developed by Jason R. Thorpe
- * for And Communications, http://www.and.com/
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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: ch.c,v 1.47 1998/06/17 14:13:13 bde Exp $
- */
-
-#include "opt_devfs.h"
-#include "opt_bounce.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/chio.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-#ifdef BOUNCE_BUFFERS
-#include <sys/buf.h>
-#endif
-
-#include <scsi/scsi_changer.h>
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_driver.h>
-
-#include "ioconf.h"
-
-#define CHRETRIES 2
-#define CHUNIT(x) (minor((x)))
-#define CHSETUNIT(x, y) makedev(major(x), y)
-
-struct ch_softc {
- /*
- * Human-readable external name. FreeBSD doesn't have a
- * generic hook for this, so we make it look NetBSD-like. See
- * comment in chattach().
- */
- struct {
- char dv_xname[16];
- } sc_dev;
-
- /*
- * Pointer back to the scsi_link. See comment in chattach().
- */
- struct scsi_link *sc_link;
-
- int sc_picker; /* current picker */
-
- /*
- * The following information is obtained from the
- * element address assignment page.
- */
- int sc_firsts[4]; /* firsts, indexed by CHET_* */
- int sc_counts[4]; /* counts, indexed by CHET_* */
-
- /*
- * The following mask defines the legal combinations
- * of elements for the MOVE MEDIUM command.
- */
- u_int8_t sc_movemask[4];
-
- /*
- * As above, but for EXCHANGE MEDIUM.
- */
- u_int8_t sc_exchangemask[4];
-
- int flags; /* misc. info */
-#ifdef DEVFS
- void *c_devfs_token;
- void *ctl_devfs_token;
-#endif
-};
-
-/* sc_flags */
-#define CHF_ROTATE 0x01 /* picker can rotate */
-
-static d_open_t chopen;
-static d_close_t chclose;
-static d_ioctl_t chioctl;
-
-#define CDEV_MAJOR 17
-static struct cdevsw ch_cdevsw =
- { chopen, chclose, noread, nowrite, /*17*/
- chioctl, nostop, nullreset, nodevtotty,/* ch */
- seltrue, nommap, nostrat, "ch", NULL, -1 };
-
-/*
- * SCSI glue.
- */
-
-/*
- * Under FreeBSD, this macro sets up a bunch of trampoline
- * functions that indirect through the SCSI subsystem.
- */
-SCSI_DEVICE_ENTRIES(ch)
-
-static int chunit __P((dev_t));
-static dev_t chsetunit __P((dev_t, int));
-
-/* So, like, why not "int"? */
-static errval ch_devopen __P((dev_t, int, int, struct proc *,
- struct scsi_link *));
-static errval ch_devioctl __P((dev_t, u_long, caddr_t, int, struct proc *,
- struct scsi_link *));
-static errval ch_devclose __P((dev_t, int, int, struct proc *,
- struct scsi_link *));
-
-static struct scsi_device ch_switch = {
- NULL, /* (*err_handler) */
- NULL, /* (*start) */
- NULL, /* (*async) */
- NULL, /* (*done) */
- "ch", /* name */
- 0, /* flags */
- { 0, 0 }, /* spare[2] */
- 0, /* link_flags */
- chattach, /* (*attach) */
- "Medium-Changer", /* desc */
- chopen, /* (*open) */
- sizeof(struct ch_softc), /* sizeof_scsi_data */
- T_CHANGER, /* type */
- chunit, /* (*getunit) */
- chsetunit, /* (*setunit) */
- ch_devopen, /* (*dev_open) */
- ch_devioctl, /* (*dev_ioctl) */
- ch_devclose, /* (*dev_close) */
-};
-
-static int ch_move __P((struct ch_softc *, struct changer_move *));
-static int ch_exchange __P((struct ch_softc *, struct changer_exchange *));
-static int ch_position __P((struct ch_softc *, struct changer_position *));
-static int ch_usergetelemstatus __P((struct ch_softc *, int, u_int8_t *));
-static int ch_getelemstatus __P((struct ch_softc *, int, int, caddr_t, size_t));
-static int ch_get_params __P((struct ch_softc *, int));
-
-static errval
-chattach(link)
- struct scsi_link *link;
-{
- struct ch_softc *sc = (struct ch_softc *)(link->sd);
- u_int32_t unit = link->dev_unit;
-
- /*
- * FreeBSD doesn't have any common way of carrying
- * around a device's external name (i.e. <name><unit>),
- * so emulate the structure used by NetBSD to keep the
- * diffs lower.
- */
- bzero(sc->sc_dev.dv_xname, sizeof(sc->sc_dev.dv_xname));
- sprintf(sc->sc_dev.dv_xname, "%s%d", ch_switch.name, unit);
-
- /*
- * FreeBSD gets "softc" info for a device from the
- * scsi_link argument passed to indirect entry point functions.
- * NetBSD get scsi_link info from softcs that are
- * obtained from indexes passed to direct entry point functions.
- * We emulate the NetBSD behavior here to keep the diffs
- * lower.
- */
- sc->sc_link = link;
-
- /*
- * Get information about the device. Note we can't use
- * interrupts yet.
- */
- if (ch_get_params(sc, SCSI_NOSLEEP|SCSI_NOMASK))
- printf("offline");
- else {
- printf("%d slot%s, %d drive%s, %d picker%s",
- sc->sc_counts[CHET_ST], (sc->sc_counts[CHET_ST] > 1) ?
- "s" : "",
- sc->sc_counts[CHET_DT], (sc->sc_counts[CHET_DT] > 1) ?
- "s" : "",
- sc->sc_counts[CHET_MT], (sc->sc_counts[CHET_MT] > 1) ?
- "s" : "");
- if (sc->sc_counts[CHET_IE])
- printf(", %d portal%s", sc->sc_counts[CHET_IE],
- (sc->sc_counts[CHET_IE] > 1) ? "s" : "");
- if (bootverbose) {
- printf("\n"); /* This will probably look ugly ... bummer. */
- printf("%s: move mask: 0x%x 0x%x 0x%x 0x%x\n",
- sc->sc_dev.dv_xname,
- sc->sc_movemask[CHET_MT], sc->sc_movemask[CHET_ST],
- sc->sc_movemask[CHET_IE], sc->sc_movemask[CHET_DT]);
- printf("%s: exchange mask: 0x%x 0x%x 0x%x 0x%x\n",
- sc->sc_dev.dv_xname,
- sc->sc_exchangemask[CHET_MT], sc->sc_exchangemask[CHET_ST],
- sc->sc_exchangemask[CHET_IE], sc->sc_exchangemask[CHET_DT]);
- }
- }
-
- /* Default the current picker. */
- sc->sc_picker = sc->sc_firsts[CHET_MT];
-
-#ifdef DEVFS
- sc->c_devfs_token = devfs_add_devswf(&ch_cdevsw, unit << 4, DV_CHR,
- UID_ROOT, GID_OPERATOR, 0600,
- "ch%d", unit);
- sc->ctl_devfs_token = devfs_add_devswf(&ch_cdevsw,
- (unit << 4) | SCSI_CONTROL_MASK,
- DV_CHR,
- UID_ROOT, GID_OPERATOR, 0600,
- "ch%d.ctl", unit);
-#endif
- return (0);
-}
-
-static errval
-ch_devopen(dev, flags, fmt, p, link)
- dev_t dev;
- int flags, fmt;
- struct proc *p;
- struct scsi_link *link;
-{
- struct ch_softc *sc = (struct ch_softc *)(link->sd);
- errval error = 0;
- int unit;
-
- unit = CHUNIT(dev);
-
- /*
- * Only allow one open at a time.
- */
- if (link->flags & SDEV_OPEN)
- return (EBUSY);
-
- link->flags |= SDEV_OPEN;
-
- /*
- * Absorb any unit attention errors. Ignore "not ready"
- * since this might occur if e.g. a tape isn't actually
- * loaded in the drive.
- */
- (void)scsi_test_unit_ready(link, SCSI_SILENT);
-
- /*
- * Make sure our parameters are up to date.
- */
- if (error = ch_get_params(sc, 0))
- goto bad;
-
- return (0);
-
- bad:
- link->flags &= ~SDEV_OPEN;
- return (error);
-}
-
-static errval
-ch_devclose(dev, flags, fmt, p, link)
- dev_t dev;
- int flags, fmt;
- struct proc *p;
- struct scsi_link *link;
-{
-
- link->flags &= ~SDEV_OPEN;
- return (0);
-}
-
-static errval
-ch_devioctl(dev, cmd, data, flags, p, link)
- dev_t dev;
- u_long cmd;
- caddr_t data;
- int flags;
- struct proc *p;
- struct scsi_link *link;
-{
- struct ch_softc *sc = (struct ch_softc *)(link->sd);
- caddr_t elemdata;
- int error = 0;
-
- switch (cmd) {
- case CHIOMOVE:
- error = ch_move(sc, (struct changer_move *)data);
- break;
-
- case CHIOEXCHANGE:
- error = ch_exchange(sc, (struct changer_exchange *)data);
- break;
-
- case CHIOPOSITION:
- error = ch_position(sc, (struct changer_position *)data);
- break;
-
- case CHIOGPICKER:
- *(int *)data = sc->sc_picker - sc->sc_firsts[CHET_MT];
- break;
-
- case CHIOSPICKER: {
- int new_picker = *(int *)data;
-
- if (new_picker > (sc->sc_counts[CHET_MT] - 1))
- return (EINVAL);
- sc->sc_picker = sc->sc_firsts[CHET_MT] + new_picker;
- break; }
-
- case CHIOGPARAMS: {
- struct changer_params *cp = (struct changer_params *)data;
-
- cp->cp_curpicker = sc->sc_picker - sc->sc_firsts[CHET_MT];
- cp->cp_npickers = sc->sc_counts[CHET_MT];
- cp->cp_nslots = sc->sc_counts[CHET_ST];
- cp->cp_nportals = sc->sc_counts[CHET_IE];
- cp->cp_ndrives = sc->sc_counts[CHET_DT];
- break; }
-
- case CHIOGSTATUS: {
- struct changer_element_status *ces =
- (struct changer_element_status *)data;
-
- error = ch_usergetelemstatus(sc, ces->ces_type, ces->ces_data);
- break; }
-
- /* Implement prevent/allow? */
-
- default:
- error = scsi_do_ioctl(dev, cmd, data, flags, p, link);
- break;
- }
-
- return (error);
-}
-
-static int
-ch_move(sc, cm)
- struct ch_softc *sc;
- struct changer_move *cm;
-{
- struct scsi_move_medium cmd;
- u_int16_t fromelem, toelem;
-
- /*
- * Check arguments.
- */
- if ((cm->cm_fromtype > CHET_DT) || (cm->cm_totype > CHET_DT))
- return (EINVAL);
- if ((cm->cm_fromunit > (sc->sc_counts[cm->cm_fromtype] - 1)) ||
- (cm->cm_tounit > (sc->sc_counts[cm->cm_totype] - 1)))
- return (ENODEV);
-
- /*
- * Check the request against the changer's capabilities.
- */
- if ((sc->sc_movemask[cm->cm_fromtype] & (1 << cm->cm_totype)) == 0)
- return (EINVAL);
-
- /*
- * Calculate the source and destination elements.
- */
- fromelem = sc->sc_firsts[cm->cm_fromtype] + cm->cm_fromunit;
- toelem = sc->sc_firsts[cm->cm_totype] + cm->cm_tounit;
-
- /*
- * Build the SCSI command.
- */
- bzero(&cmd, sizeof(cmd));
- cmd.opcode = MOVE_MEDIUM;
- scsi_uto2b(sc->sc_picker, cmd.tea);
- scsi_uto2b(fromelem, cmd.src);
- scsi_uto2b(toelem, cmd.dst);
- if (cm->cm_flags & CM_INVERT)
- cmd.flags |= MOVE_MEDIUM_INVERT;
-
- /*
- * Send command to changer.
- */
- return (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
- sizeof(cmd), NULL, 0, CHRETRIES, 100000, NULL, 0));
-}
-
-static int
-ch_exchange(sc, ce)
- struct ch_softc *sc;
- struct changer_exchange *ce;
-{
- struct scsi_exchange_medium cmd;
- u_int16_t src, dst1, dst2;
-
- /*
- * Check arguments.
- */
- if ((ce->ce_srctype > CHET_DT) || (ce->ce_fdsttype > CHET_DT) ||
- (ce->ce_sdsttype > CHET_DT))
- return (EINVAL);
- if ((ce->ce_srcunit > (sc->sc_counts[ce->ce_srctype] - 1)) ||
- (ce->ce_fdstunit > (sc->sc_counts[ce->ce_fdsttype] - 1)) ||
- (ce->ce_sdstunit > (sc->sc_counts[ce->ce_sdsttype] - 1)))
- return (ENODEV);
-
- /*
- * Check the request against the changer's capabilities.
- */
- if (((sc->sc_exchangemask[ce->ce_srctype] &
- (1 << ce->ce_fdsttype)) == 0) ||
- ((sc->sc_exchangemask[ce->ce_fdsttype] &
- (1 << ce->ce_sdsttype)) == 0))
- return (EINVAL);
-
- /*
- * Calculate the source and destination elements.
- */
- src = sc->sc_firsts[ce->ce_srctype] + ce->ce_srcunit;
- dst1 = sc->sc_firsts[ce->ce_fdsttype] + ce->ce_fdstunit;
- dst2 = sc->sc_firsts[ce->ce_sdsttype] + ce->ce_sdstunit;
-
- /*
- * Build the SCSI command.
- */
- bzero(&cmd, sizeof(cmd));
- cmd.opcode = EXCHANGE_MEDIUM;
- scsi_uto2b(sc->sc_picker, cmd.tea);
- scsi_uto2b(src, cmd.src);
- scsi_uto2b(dst1, cmd.fdst);
- scsi_uto2b(dst2, cmd.sdst);
- if (ce->ce_flags & CE_INVERT1)
- cmd.flags |= EXCHANGE_MEDIUM_INV1;
- if (ce->ce_flags & CE_INVERT2)
- cmd.flags |= EXCHANGE_MEDIUM_INV2;
-
- /*
- * Send command to changer.
- */
- return (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
- sizeof(cmd), NULL, 0, CHRETRIES, 100000, NULL, 0));
-}
-
-static int
-ch_position(sc, cp)
- struct ch_softc *sc;
- struct changer_position *cp;
-{
- struct scsi_position_to_element cmd;
- u_int16_t dst;
-
- /*
- * Check arguments.
- */
- if (cp->cp_type > CHET_DT)
- return (EINVAL);
- if (cp->cp_unit > (sc->sc_counts[cp->cp_type] - 1))
- return (ENODEV);
-
- /*
- * Calculate the destination element.
- */
- dst = sc->sc_firsts[cp->cp_type] + cp->cp_unit;
-
- /*
- * Build the SCSI command.
- */
- bzero(&cmd, sizeof(cmd));
- cmd.opcode = POSITION_TO_ELEMENT;
- scsi_uto2b(sc->sc_picker, cmd.tea);
- scsi_uto2b(dst, cmd.dst);
- if (cp->cp_flags & CP_INVERT)
- cmd.flags |= POSITION_TO_ELEMENT_INVERT;
-
- /*
- * Send command to changer.
- */
- return (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
- sizeof(cmd), NULL, 0, CHRETRIES, 100000, NULL, 0));
-}
-
-/*
- * Perform a READ ELEMENT STATUS on behalf of the user, and return to
- * the user only the data the user is interested in (i.e. an array of
- * flags bytes).
- */
-static int
-ch_usergetelemstatus(sc, chet, uptr)
- struct ch_softc *sc;
- int chet;
- u_int8_t *uptr;
-{
- struct read_element_status_header *st_hdr;
- struct read_element_status_page_header *pg_hdr;
- struct read_element_status_descriptor *desc;
- caddr_t data = NULL;
-#ifdef BOUNCE_BUFFERS
- int datasize = 0;
-#endif
- size_t size, desclen;
- int avail, i, error = 0;
- u_int8_t *user_data = NULL;
-
- /*
- * If there are no elements of the requested type in the changer,
- * the request is invalid.
- */
- if (sc->sc_counts[chet] == 0)
- return (EINVAL);
-
- /*
- * Request one descriptor for the given element type. This
- * is used to determine the size of the descriptor so that
- * we can allocate enough storage for all of them. We assume
- * that the first one can fit into 1k.
- */
-#ifdef BOUNCE_BUFFERS
- data = (caddr_t)vm_bounce_kva_alloc(btoc(1024));
- if (!data)
- return (ENOMEM);
- datasize = 1024;
-#else
- data = (caddr_t)malloc(1024, M_DEVBUF, M_WAITOK);
-#endif
- if (error = ch_getelemstatus(sc, sc->sc_firsts[chet], 1, data, 1024))
- goto done;
-
- st_hdr = (struct read_element_status_header *)data;
- pg_hdr = (struct read_element_status_page_header *)((char *)st_hdr +
- sizeof(struct read_element_status_header));
- desclen = scsi_2btou(pg_hdr->edl);
-
- size = sizeof(struct read_element_status_header) +
- sizeof(struct read_element_status_page_header) +
- (desclen * sc->sc_counts[chet]);
-
- /*
- * Reallocate storage for descriptors and get them from the
- * device.
- */
-#ifdef BOUNCE_BUFFERS
- vm_bounce_kva_alloc_free((vm_offset_t)data, btoc(datasize));
- data = (caddr_t)vm_bounce_kva_alloc(btoc(size));
- if (!data) {
- error = ENOMEM;
- goto done;
- }
- datasize = size;
-#else
- free(data, M_DEVBUF);
- data = (caddr_t)malloc(size, M_DEVBUF, M_WAITOK);
-#endif
- if (error = ch_getelemstatus(sc, sc->sc_firsts[chet],
- sc->sc_counts[chet], data, size))
- goto done;
-
- /*
- * Fill in the user status array.
- */
- st_hdr = (struct read_element_status_header *)data;
- avail = scsi_2btou(st_hdr->count);
- if (avail != sc->sc_counts[chet])
- printf("%s: warning, READ ELEMENT STATUS avail != count\n",
- sc->sc_dev.dv_xname);
-
- user_data = (u_int8_t *)malloc(avail, M_DEVBUF, M_WAITOK);
-
- desc = (struct read_element_status_descriptor *)((char *)data +
- sizeof(struct read_element_status_header) +
- sizeof(struct read_element_status_page_header));
- for (i = 0; i < avail; ++i) {
- user_data[i] = desc->flags1;
- desc = (struct read_element_status_descriptor *)
- ((char *)desc + desclen);
- }
-
- /* Copy flags array out to userspace. */
- error = copyout(user_data, uptr, avail);
-
- done:
-#ifdef BOUNCE_BUFFERS
- if (data != NULL)
- vm_bounce_kva_alloc_free((vm_offset_t)data, btoc(datasize));
-#else
- if (data != NULL)
- free(data, M_DEVBUF);
-#endif
- if (user_data != NULL)
- free(user_data, M_DEVBUF);
- return (error);
-}
-
-static int
-ch_getelemstatus(sc, first, count, data, datalen)
- struct ch_softc *sc;
- int first, count;
- caddr_t data;
- size_t datalen;
-{
- struct scsi_read_element_status cmd;
-
- /*
- * Build SCSI command.
- */
- bzero(&cmd, sizeof(cmd));
- cmd.opcode = READ_ELEMENT_STATUS;
- scsi_uto2b(first, cmd.sea);
- scsi_uto2b(count, cmd.count);
- scsi_uto3b(datalen, cmd.len);
-
- /*
- * Send command to changer.
- */
- return (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
- sizeof(cmd), (u_char *)data, datalen, CHRETRIES, 100000, NULL, SCSI_DATA_IN));
-}
-
-
-/*
- * Ask the device about itself and fill in the parameters in our
- * softc.
- */
-static int
-ch_get_params(sc, scsiflags)
- struct ch_softc *sc;
- int scsiflags;
-{
- struct scsi_mode_sense cmd;
- struct scsi_mode_sense_data {
- struct scsi_mode_header header;
- union {
- struct page_element_address_assignment ea;
- struct page_transport_geometry_parameters tg;
- struct page_device_capabilities cap;
- } pages;
- } sense_data;
- int error, from;
- u_int8_t *moves, *exchanges;
-
- /*
- * Grab info from the element address assignment page.
- */
- bzero(&cmd, sizeof(cmd));
- bzero(&sense_data, sizeof(sense_data));
- cmd.op_code = MODE_SENSE;
- cmd.byte2 |= 0x08; /* disable block descriptors */
- cmd.page = 0x1d;
- cmd.length = (sizeof(sense_data) & 0xff);
- error = scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
- sizeof(cmd), (u_char *)&sense_data, sizeof(sense_data), CHRETRIES,
- 6000, NULL, scsiflags | SCSI_DATA_IN);
- if (error) {
- printf("%s: could not sense element address page\n",
- sc->sc_dev.dv_xname);
- return (error);
- }
-
- sc->sc_firsts[CHET_MT] = scsi_2btou(sense_data.pages.ea.mtea);
- sc->sc_counts[CHET_MT] = scsi_2btou(sense_data.pages.ea.nmte);
- sc->sc_firsts[CHET_ST] = scsi_2btou(sense_data.pages.ea.fsea);
- sc->sc_counts[CHET_ST] = scsi_2btou(sense_data.pages.ea.nse);
- sc->sc_firsts[CHET_IE] = scsi_2btou(sense_data.pages.ea.fieea);
- sc->sc_counts[CHET_IE] = scsi_2btou(sense_data.pages.ea.niee);
- sc->sc_firsts[CHET_DT] = scsi_2btou(sense_data.pages.ea.fdtea);
- sc->sc_counts[CHET_DT] = scsi_2btou(sense_data.pages.ea.ndte);
-
- /* XXX ask for page trasport geom */
-
- /*
- * Grab info from the capabilities page.
- */
- bzero(&cmd, sizeof(cmd));
- bzero(&sense_data, sizeof(sense_data));
- cmd.op_code = MODE_SENSE;
- cmd.byte2 |= 0x08; /* disable block descriptors */
- cmd.page = 0x1f;
- cmd.length = (sizeof(sense_data) & 0xff);
- error = scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
- sizeof(cmd), (u_char *)&sense_data, sizeof(sense_data), CHRETRIES,
- 6000, NULL, scsiflags | SCSI_DATA_IN);
- if (error) {
- printf("%s: could not sense capabilities page\n",
- sc->sc_dev.dv_xname);
- return (error);
- }
-
- bzero(sc->sc_movemask, sizeof(sc->sc_movemask));
- bzero(sc->sc_exchangemask, sizeof(sc->sc_exchangemask));
- moves = &sense_data.pages.cap.move_from_mt;
- exchanges = &sense_data.pages.cap.exchange_with_mt;
- for (from = CHET_MT; from <= CHET_DT; ++from) {
- sc->sc_movemask[from] = moves[from];
- sc->sc_exchangemask[from] = exchanges[from];
- }
-
- sc->sc_link->flags |= SDEV_MEDIA_LOADED;
- return (0);
-}
-
-static int
-chunit(dev)
- dev_t dev;
-{
-
- return (CHUNIT(dev));
-}
-
-static dev_t
-chsetunit(dev, unit)
- dev_t dev;
- int unit;
-{
-
- return (CHSETUNIT(dev, unit));
-}
-
-
-static ch_devsw_installed = 0;
-
-static void
-ch_drvinit(void *unused)
-{
- dev_t dev;
-
- if( ! ch_devsw_installed ) {
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev,&ch_cdevsw, NULL);
- ch_devsw_installed = 1;
- }
-}
-
-SYSINIT(chdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ch_drvinit,NULL)
diff --git a/sys/scsi/od.c b/sys/scsi/od.c
deleted file mode 100644
index 5943b50..0000000
--- a/sys/scsi/od.c
+++ /dev/null
@@ -1,966 +0,0 @@
-/*
- * Copyright (c) 1995,1996 Shunsuke Akiyama. 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 Shunsuke Akiyama.
- * 4. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY Shunsuke Akiyama 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 Shunsuke Akiyama 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: od.c,v 1.45 1998/07/30 15:16:05 bde Exp $
- */
-
-/*
- * Compile option defines:
- */
-
-/*
- * If drive returns sense key as 0x02 with vendor specific additional
- * sense code (ASC) and additional sense code qualifier (ASCQ), or
- * illegal ASC and ASCQ. This cause an error (NOT READY) and retrying.
- * To suppress this, uncomment following.
- * Or put "options OD_BOGUS_NOT_READY" entry into your kernel
- * configuration file.
- *
-#define OD_BOGUS_NOT_READY
- */
-
-/*
- * For an automatic spindown, try this. Again, preferrably as an
- * option in your config file.
- * WARNING! Use at your own risk. Joerg's ancient SONY SMO drive
- * groks it fine, while Shunsuke's Fujitsu chokes on it and times
- * out.
-#define OD_AUTO_TURNOFF
- */
-
-#include "opt_bounce.h"
-#include "opt_devfs.h"
-#include "opt_scsi.h"
-#include "opt_od.h"
-
-#define SPLOD splbio
-#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/dkbad.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/buf.h>
-#include <sys/cdio.h>
-#include <sys/dkstat.h>
-#include <sys/disklabel.h>
-#include <sys/diskslice.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-#include <scsi/scsi_disk.h>
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-#include "ioconf.h"
-
-static u_int32_t odstrats, odqueues;
-
-#define SECSIZE 512 /* default sector size */
-#define ODOUTSTANDING 4
-#define OD_RETRIES 4
-
-#define PARTITION(dev) dkpart(dev)
-#define ODUNIT(dev) dkunit(dev)
-
-/* XXX introduce a dkmodunit() macro for this. */
-#define ODSETUNIT(DEV, U) \
- makedev(major(DEV), dkmakeminor((U), dkslice(DEV), dkpart(DEV)))
-
-struct scsi_data {
- u_int32_t flags;
-#define ODINIT 0x04 /* device has been init'd */
- struct disk_parms {
- u_char heads; /* Number of heads */
- u_int16_t cyls; /* Number of cylinders (fictitious) */
- u_int16_t sectors; /* Number of sectors/track */
- u_int16_t secsiz; /* Number of bytes/sector */
- u_int32_t disksize; /* total number sectors */
- u_int16_t rpm; /* medium rotation rate */
- } params;
- struct diskslices *dk_slices; /* virtual drives */
- struct buf_queue_head buf_queue;
- int dkunit; /* disk stats unit number */
-#ifdef DEVFS
- /* Eventually move all these to common disk struct. */
- void *b_devfs_token;
- void *c_devfs_token;
- void *ctl_devfs_token;
-#endif
-};
-
-static errval od_get_parms __P((int unit, int flags));
-#ifdef notyet
-static errval od_reassign_blocks __P((int unit, int block));
-#endif
-static u_int32_t od_size __P((int unit, int flags));
-static int od_sense_handler __P((struct scsi_xfer *));
-static void odstart __P((u_int32_t, u_int32_t));
-static void odstrategy1 __P((struct buf *));
-
-static dev_t odsetunit(dev_t dev, int unit) { return ODSETUNIT(dev, unit); }
-static int odunit(dev_t dev) { return ODUNIT(dev); }
-
-static errval od_open __P((dev_t dev, int mode, int fmt, struct proc *p,
- struct scsi_link *sc_link));
-static errval od_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag,
- struct proc *p, struct scsi_link *sc_link);
-static errval od_close __P((dev_t dev, int fflag, int fmt, struct proc *p,
- struct scsi_link *sc_link));
-static void od_strategy(struct buf *bp, struct scsi_link *sc_link);
-
-static d_open_t odopen;
-static d_read_t odread;
-static d_write_t odwrite;
-static d_close_t odclose;
-static d_ioctl_t odioctl;
-static d_strategy_t odstrategy;
-
-#define CDEV_MAJOR 70
-#define BDEV_MAJOR 20
-static struct cdevsw od_cdevsw = {
- odopen, odclose, odread, odwrite,
- odioctl, nostop, nullreset, nodevtotty,
- seltrue, nommap, odstrategy, "od",
- NULL, -1, nodump, nopsize,
- D_DISK, 0, -1 };
-
-/*
- * Actually include the interface routines
- */
-SCSI_DEVICE_ENTRIES(od)
-
-static struct scsi_device od_switch =
-{
- od_sense_handler,
- odstart, /* have a queue, served by this */
- NULL, /* have no async handler */
- NULL, /* Use default 'done' routine */
- "od",
- 0,
- {0, 0},
- 0, /* Link flags */
- odattach,
- "Optical",
- odopen,
- sizeof(struct scsi_data),
- T_OPTICAL,
- odunit,
- odsetunit,
- od_open,
- od_ioctl,
- od_close,
- od_strategy,
-};
-
-static __inline void
-od_registerdev(int unit)
-{
- if(dk_ndrive < DK_NDRIVE) {
- sprintf(dk_names[dk_ndrive], "od%d", unit);
- dk_wpms[dk_ndrive] = (4*1024*1024/2); /* 4MB/sec */
- SCSI_DATA(&od_switch, unit)->dkunit = dk_ndrive++;
- } else {
- SCSI_DATA(&od_switch, unit)->dkunit = -1;
- }
-}
-
-
-/*
- * The routine called by the low level scsi routine when it discovers
- * a device suitable for this driver.
- */
-static errval
-odattach(struct scsi_link *sc_link)
-{
- u_int32_t unit;
- struct disk_parms *dp;
-#ifdef DEVFS
- int mynor;
-#endif
-
- struct scsi_data *od = sc_link->sd;
-
- unit = sc_link->dev_unit;
-
- dp = &(od->params);
-
- if (sc_link->opennings > ODOUTSTANDING)
- sc_link->opennings = ODOUTSTANDING;
-
- bufq_init(&od->buf_queue);
- /*
- * Use the subdriver to request information regarding
- * the drive. We cannot use interrupts yet, so the
- * request must specify this.
- */
- scsi_start_unit(sc_link, SCSI_NOSLEEP | SCSI_NOMASK
- | SCSI_ERR_OK | SCSI_SILENT);
- od_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
- /*
- * if we don't have actual parameters, assume 512 bytes/sec
- * (could happen on removable media - MOD)
- * -- this avoids the division below from falling over
- */
- if(dp->secsiz == 0) dp->secsiz = SECSIZE;
- if (dp->disksize != 0) {
- printf("%luMB (%lu %u byte sectors)",
- (u_long)(dp->disksize / ((1024L * 1024L) / dp->secsiz)),
- (u_long)dp->disksize, dp->secsiz);
- } else {
- printf("od not present");
- }
-
-#ifndef SCSI_REPORT_GEOMETRY
- if ( (sc_link->flags & SDEV_BOOTVERBOSE) )
-#endif
- {
- sc_print_addr(sc_link);
- printf("with approximate %d cyls, %d heads, and %d sectors/track",
- dp->cyls, dp->heads, dp->sectors);
- }
-#ifdef OD_AUTO_TURNOFF
- scsi_stop_unit(sc_link, 0, SCSI_ERR_OK | SCSI_SILENT);
-#endif /* OD_AUTO_TURNOFF */
-
- od->flags |= ODINIT;
- od_registerdev(unit);
-
-#ifdef DEVFS
- mynor = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART);
- od->b_devfs_token = devfs_add_devswf(&od_cdevsw, mynor, DV_BLK,
- UID_ROOT, GID_OPERATOR, 0640,
- "od%d", unit);
- od->c_devfs_token = devfs_add_devswf(&od_cdevsw, mynor, DV_CHR,
- UID_ROOT, GID_OPERATOR, 0640,
- "rod%d", unit);
- mynor = dkmakeminor(unit, 0, 0); /* XXX */
- od->ctl_devfs_token = devfs_add_devswf(&od_cdevsw,
- mynor | SCSI_CONTROL_MASK,
- DV_CHR,
- UID_ROOT, GID_WHEEL, 0600,
- "rod%d.ctl", unit);
-#endif
-
- return 0;
-}
-
-/*
- * open the device. Make sure the partition info is a up-to-date as can be.
- */
-static errval
-od_open(dev, mode, fmt, p, sc_link)
- dev_t dev;
- int mode;
- int fmt;
- struct proc *p;
- struct scsi_link *sc_link;
-{
- errval errcode = 0;
- u_int32_t unit;
- struct disklabel label;
- struct scsi_data *od;
-
- unit = ODUNIT(dev);
- od = sc_link->sd;
-
- /*
- * Make sure the disk has been initialized
- * At some point in the future, get the scsi driver
- * to look for a new device if we are not initted
- */
- if ((!od) || (!(od->flags & ODINIT))) {
- return ENXIO;
- }
-
- SC_DEBUG(sc_link, SDEV_DB1,
- ("od_open: dev=0x%lx (unit %lu, partition %d)\n",
- (u_long)dev, (u_long)unit, PARTITION(dev)));
-
- /*
- * Try to start the drive, and try to clear "Unit Attention"
- * condition, when media had been changed before.
- * This operation also clears the SDEV_MEDIA_LOADED flag in its
- * error handling routine.
- */
- scsi_start_unit(sc_link, SCSI_SILENT);
- scsi_prevent(sc_link, PR_PREVENT, SCSI_ERR_OK | SCSI_SILENT);
-
- /*
- * Make sure the drive is ready.
- */
- scsi_test_unit_ready(sc_link, 0);
-
- SC_DEBUG(sc_link, SDEV_DB3, ("'start' attempted "));
-
- sc_link->flags |= SDEV_OPEN; /* unit attn becomes an err now */
- /*
- * If it's been invalidated, then forget the label.
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- /*
- * If somebody still has it open, then forbid re-entry.
- */
- if (dsisopen(od->dk_slices)) {
- errcode = ENXIO;
- goto bad;
- }
-
- if (od->dk_slices != NULL)
- dsgone(&od->dk_slices);
- }
-
- /*
- * This time actually take notice of error returns
- */
- if (scsi_test_unit_ready(sc_link, SCSI_SILENT) != 0) {
- SC_DEBUG(sc_link, SDEV_DB3, ("not ready\n"));
- errcode = ENXIO;
- goto bad;
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("device present\n"));
-
- /*
- * Load the physical device parameters
- */
- errcode = od_get_parms(unit, 0); /* sets SDEV_MEDIA_LOADED */
- if (errcode) {
- goto bad;
- }
- switch (od->params.secsiz) {
- case SECSIZE :
- case 1024 :
- case 2048 :
- break;
- default :
- printf("od%lu: Can't deal with %u bytes logical blocks\n",
- (u_long)unit, od->params.secsiz);
- Debugger("od");
- errcode = ENXIO;
- goto bad;
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("params loaded "));
-
- /* Build label for whole disk. */
- bzero(&label, sizeof label);
- label.d_type = DTYPE_SCSI;
- label.d_secsize = od->params.secsiz;
- label.d_nsectors = od->params.sectors;
- label.d_ntracks = od->params.heads;
- label.d_ncylinders = od->params.cyls;
- label.d_secpercyl = od->params.heads * od->params.sectors;
- label.d_rpm = od->params.rpm; /* maybe wrong */
- if (label.d_secpercyl == 0)
- label.d_secpercyl = 64*32;
- /* XXX as long as it's not 0
- * - readdisklabel divides by it (?)
- */
- label.d_secperunit = od->params.disksize;
-
- /* Initialize slice tables. */
- errcode = dsopen("od", dev, fmt, 0, &od->dk_slices, &label, odstrategy1,
- (ds_setgeom_t *)NULL, &od_cdevsw);
- if (errcode != 0)
- goto bad;
- SC_DEBUG(sc_link, SDEV_DB3, ("Slice tables initialized "));
-
- SC_DEBUG(sc_link, SDEV_DB3, ("open %lu %lu\n",
- (u_long)odstrats, (u_long)odqueues));
-
- return 0;
-
-bad:
- if (!dsisopen(od->dk_slices)) {
- scsi_prevent(sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT);
-#ifdef OD_AUTO_TURNOFF
- scsi_stop_unit(sc_link, 0, SCSI_ERR_OK | SCSI_SILENT);
-#endif /* OD_AUTO_TURNOFF */
- sc_link->flags &= ~SDEV_OPEN;
- }
- return errcode;
-}
-
-/*
- * close the device.. only called if we are the LAST occurence of an open
- * device. Convenient now but usually a pain.
- */
-static errval
-od_close(dev, fflag, fmt, p, sc_link)
- dev_t dev;
- int fflag;
- int fmt;
- struct proc *p;
- struct scsi_link *sc_link;
-{
- struct scsi_data *od;
-
- od = sc_link->sd;
- dsclose(dev, fmt, od->dk_slices);
- if (!dsisopen(od->dk_slices)) {
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT | SCSI_ERR_OK);
-#ifdef OD_AUTO_TURNOFF
- scsi_stop_unit(sc_link, 0, SCSI_ERR_OK | SCSI_SILENT);
-#endif /* OD_AUTO_TURNOFF */
- sc_link->flags &= ~SDEV_OPEN;
- }
- return 0;
-}
-
-static int
-odread(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(odstrategy, NULL, dev, 1, minphys, uio));
-}
-
-static int
-odwrite(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(odstrategy, NULL, dev, 0, minphys, uio));
-}
-
-/*
- * Actually translate the requested transfer into one the physical driver
- * can understand. The transfer is described by a buf and will include
- * only one physical transfer.
- */
-static void
-od_strategy(struct buf *bp, struct scsi_link *sc_link)
-{
- u_int32_t opri;
- struct scsi_data *od;
- u_int32_t unit;
-
- odstrats++;
- unit = ODUNIT((bp->b_dev));
- od = sc_link->sd;
-
- /*
- * If the device has been made invalid, error out
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- bp->b_error = EIO;
- goto bad;
- }
-
- /*
- * Do bounds checking, adjust transfer, and set b_pblkno.
- */
- if (dscheck(bp, od->dk_slices) <= 0)
- goto done; /* XXX check b_resid */
-
- opri = SPLOD();
-
- /*
- * 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 disk activities for this disk
- */
- bufq_insert_tail(&od->buf_queue, bp);
-
- /*
- * Tell the device to get going on the transfer if it's
- * not doing anything, otherwise just wait for completion
- */
- odstart(unit, 0);
-
- splx(opri);
- return /*0*/;
-bad:
- bp->b_flags |= B_ERROR;
-done:
-
- /*
- * Correctly set the buf to indicate a completed xfer
- */
- bp->b_resid = bp->b_bcount;
- biodone(bp);
- return /*0*/;
-}
-
-static void
-odstrategy1(struct buf *bp)
-{
- /*
- * XXX - do something to make odstrategy() but not this block while
- * we're doing dsinit() and dsioctl().
- */
- odstrategy(bp);
-}
-
-/*
- * odstart 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 in the buf. 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 (odstrategy)
- *
- * 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.
- *
- * must be called at the correct (highish) spl level
- * odstart() is called at SPLOD from odstrategy and scsi_done
- */
-static void
-odstart(u_int32_t unit, u_int32_t flags)
-{
- register struct scsi_link *sc_link = SCSI_LINK(&od_switch, unit);
- register struct scsi_data *od = sc_link->sd;
- struct buf *bp = 0;
- struct scsi_rw_big cmd;
- u_int32_t blkno, nblk;
- u_int32_t secsize;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("odstart "));
- /*
- * Check if the device has room for another command
- */
- while (sc_link->opennings) {
-
- /*
- * there is excess capacity, but a special waits
- * It'll need the adapter as soon as we clear out of the
- * way and let it run (user level wait).
- */
- if (sc_link->flags & SDEV_WAITING) {
- return;
- }
- /*
- * See if there is a buf with work for us to do..
- */
- bp = bufq_first(&od->buf_queue);
- if (bp == NULL) { /* yes, an assign */
- return;
- }
- bufq_remove(&od->buf_queue, bp);
-
- /*
- * If the device has become invalid, abort all the
- * reads and writes until all files have been closed and
- * re-openned
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- goto bad;
- }
- /*
- * We have a buf, now we know we are going to go through
- * With this thing..
- */
- secsize = od->params.secsiz;
- blkno = bp->b_pblkno;
- if (bp->b_bcount & (secsize - 1))
- {
- goto bad;
- }
- nblk = bp->b_bcount / secsize;
-
- /*
- * Fill out the scsi command
- */
- cmd.op_code = (bp->b_flags & B_READ)
- ? READ_BIG : WRITE_BIG;
- scsi_uto4b(blkno, &cmd.addr_3);
- scsi_uto2b(nblk, &cmd.length2);
- cmd.byte2 = cmd.reserved = cmd.control = 0;
- /*
- * Call the routine that chats with the adapter.
- * Note: we cannot sleep as we may be an interrupt
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- (u_char *) bp->b_data,
- bp->b_bcount,
- OD_RETRIES,
- 100000,
- bp,
- flags | ((bp->b_flags & B_READ) ?
- SCSI_DATA_IN : SCSI_DATA_OUT))
- == SUCCESSFULLY_QUEUED) {
- odqueues++;
- if(od->dkunit >= 0) {
- dk_xfer[od->dkunit]++;
- dk_seek[od->dkunit]++; /* don't know */
- dk_wds[od->dkunit] += bp->b_bcount >> 6;
- }
- } else {
-bad:
- printf("od%lu: oops not queued\n", (u_long)unit);
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- biodone(bp);
- }
- }
-}
-
-/*
- * Perform special action on behalf of the user
- * Knows about the internals of this device
- */
-static errval
-od_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p,
- struct scsi_link *sc_link)
-{
- /* struct od_cmd_buf *args; */
- errval error;
- struct scsi_data *od;
-
- /*
- * Find the device that the user is talking about
- */
- od = sc_link->sd;
- SC_DEBUG(sc_link, SDEV_DB1, ("odioctl (0x%lx)", cmd));
-
- /*
- * If the device is not valid.. abandon ship
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED))
- return EIO;
-
- switch (cmd) {
- case DIOCSBAD:
- error = EINVAL;
- break;
- case CDIOCEJECT:
- error = scsi_stop_unit(sc_link, 1, 0);
- sc_link->flags &= ~SDEV_MEDIA_LOADED;
- break;
- case CDIOCALLOW:
- error = scsi_prevent(sc_link, PR_ALLOW, 0);
- break;
- case CDIOCPREVENT:
- error = scsi_prevent(sc_link, PR_PREVENT, 0);
- break;
- default:
- error = dsioctl("od", dev, cmd, addr, flag, &od->dk_slices,
- odstrategy1, (ds_setgeom_t *)NULL);
- if (error == ENOIOCTL) {
- if (PARTITION(dev) != RAW_PART) {
- error = ENOTTY;
- } else {
- error = scsi_do_ioctl(dev, cmd, addr,
- flag, p, sc_link);
- }
- }
- break;
- }
- return error;
-}
-
-/*
- * Find out from the device what its capacity is
- */
-static u_int32_t
-od_size(unit, flags)
- int unit, flags;
-{
- struct scsi_read_cap_data rdcap;
- struct scsi_read_capacity rdcap_cmd;
- struct scsi_link *sc_link = SCSI_LINK(&od_switch, unit);
- struct scsi_data *od = sc_link->sd;
- struct scsi_mode_sense mdsense_cmd;
- struct scsi_mode_sense_data {
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- union disk_pages pages;
- } scsi_sense;
-
- /*
- * make up a scsi command and ask the scsi driver to do
- * it for you.
- */
- bzero(&rdcap_cmd, sizeof(rdcap_cmd));
- rdcap_cmd.op_code = READ_CAPACITY;
-
- /*
- * If the command works, interpret the result as a 4 byte
- * number of blocks
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &rdcap_cmd,
- sizeof(rdcap_cmd),
- (u_char *) & rdcap,
- sizeof(rdcap),
- OD_RETRIES,
- 10000,
- NULL,
- flags | SCSI_DATA_IN) != 0) {
- return 0;
- } else {
- od->params.disksize = scsi_4btou(&rdcap.addr_3) + 1;
- od->params.secsiz = scsi_4btou(&rdcap.length_3);
- }
-
- /*
- * do a "mode sense page 4" (rigid disk drive geometry)
- */
- bzero(&mdsense_cmd, sizeof(mdsense_cmd));
- mdsense_cmd.op_code = MODE_SENSE;
- mdsense_cmd.page = 4;
- mdsense_cmd.length = 0x20;
- /*
- * If the command worked, use the results to fill out
- * the parameter structure
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &mdsense_cmd,
- sizeof(mdsense_cmd),
- (u_char *) & scsi_sense,
- sizeof(scsi_sense),
- OD_RETRIES,
- 10000,
- NULL,
- flags | SCSI_SILENT | SCSI_DATA_IN) != 0) {
-
- /* default to a fictitious geometry */
- od->params.heads = 64;
- } else {
- SC_DEBUG(sc_link, SDEV_DB3,
- ("%lu cyls, %d heads, %lu rpm\n",
- (u_long)scsi_3btou(&scsi_sense.pages.rigid_geometry.ncyl_2),
- scsi_sense.pages.rigid_geometry.nheads,
- (u_long)scsi_2btou(
- &scsi_sense.pages.rigid_geometry.medium_rot_rate_1)));
-
- od->params.heads = scsi_sense.pages.rigid_geometry.nheads;
- if (od->params.heads == 0)
- od->params.heads = 64; /* fictitious */
- od->params.rpm =
- scsi_2btou(&scsi_sense.pages.rigid_geometry.medium_rot_rate_1);
- }
-
- /*
- * do a "mode sense page 3" (format device)
- */
- bzero(&mdsense_cmd, sizeof(mdsense_cmd));
- mdsense_cmd.op_code = MODE_SENSE;
- mdsense_cmd.page = 3;
- mdsense_cmd.length = 0x20;
- /*
- * If the command worked, use the results to fill out
- * the parameter structure
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &mdsense_cmd,
- sizeof(mdsense_cmd),
- (u_char *) & scsi_sense,
- sizeof(scsi_sense),
- OD_RETRIES,
- 10000,
- NULL,
- flags | SCSI_SILENT | SCSI_DATA_IN) != 0) {
-
- /* default to a fictitious geometry */
- od->params.sectors = 32;
- } else {
- SC_DEBUG(sc_link, SDEV_DB3,
- ("%d secs\n",
- scsi_2btou(&scsi_sense.pages.disk_format.ph_sec_t_1)));
-
- od->params.sectors =
- scsi_2btou(&scsi_sense.pages.disk_format.ph_sec_t_1);
- if (od->params.sectors == 0)
- od->params.sectors = 32; /* fictitious */
- }
-
- return od->params.disksize;
-}
-
-#ifdef notyet
-/*
- * Tell the device to map out a defective block
- */
-static errval
-od_reassign_blocks(unit, block)
- int unit, block;
-{
- struct scsi_reassign_blocks scsi_cmd;
- struct scsi_reassign_blocks_data rbdata;
- struct scsi_link *sc_link = SCSI_LINK(&od_switch, unit);
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- bzero(&rbdata, sizeof(rbdata));
- scsi_cmd.op_code = REASSIGN_BLOCKS;
-
- rbdata.length_msb = 0;
- rbdata.length_lsb = sizeof(rbdata.defect_descriptor[0]);
- scsi_uto4b(block, &rbdata.defect_descriptor[0].dlbaddr_3);
-
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) & rbdata,
- sizeof(rbdata),
- OD_RETRIES,
- 20000,
- NULL,
- SCSI_DATA_OUT);
-}
-#endif
-
-/*
- * Get the scsi driver to send a full inquiry to the
- * device and use the results to fill out the disk
- * parameter structure.
- */
-static errval
-od_get_parms(unit, flags)
- int unit, flags;
-{
- struct scsi_link *sc_link = SCSI_LINK(&od_switch, unit);
- struct scsi_data *od = sc_link->sd;
- struct disk_parms *disk_parms = &od->params;
- u_int32_t sectors;
- errval retval;
-
- /*
- * First check if we have it all loaded
- */
- if (sc_link->flags & SDEV_MEDIA_LOADED)
- return 0;
-
- /*
- * Use fictitious geometry, this depends on the size of medium.
- */
- sectors = od_size(unit, flags);
- /* od_size() sets secsiz, disksize, sectors, and heads */
-
- /* fictitious number of cylinders, so that C*H*S <= total */
- if (disk_parms->sectors != 0 && disk_parms->heads != 0) {
- disk_parms->cyls =
- sectors / (disk_parms->sectors * disk_parms->heads);
- } else {
- disk_parms->cyls = 0;
- }
-
- if (sectors != 0) {
- sc_link->flags |= SDEV_MEDIA_LOADED;
- retval = 0;
- } else {
- retval = ENXIO;
- }
- return retval;
-}
-
-/*
- * sense handler: Called to determine what to do when the
- * device returns a CHECK CONDITION.
- */
-
-static int
-od_sense_handler(struct scsi_xfer *xs)
-{
- struct scsi_sense_data *sense;
- struct scsi_sense_extended *ext;
- int asc, ascq;
-
- sense = &(xs->sense);
- ext = (struct scsi_sense_extended *)&(sense->ext.extended);
-
- /* I don't know what the heck to do with a deferred error,
- * so I'll just kick it back to the caller.
- */
- if ((sense->error_code & SSD_ERRCODE) == 0x71)
- return SCSIRET_CONTINUE;
-
-#ifdef OD_BOGUS_NOT_READY
- if (((sense->error_code & SSD_ERRCODE) == 0x70) &&
- ((sense->ext.extended.flags & SSD_KEY) == 0x02))
- /* No point in retrying Not Ready */
- return SCSIRET_CONTINUE;
-#endif
-
- if (((sense->error_code & SSD_ERRCODE) == 0x70) &&
- ((sense->ext.extended.flags & SSD_KEY) == 0x04))
- /* No point in retrying Hardware Failure */
- return SCSIRET_CONTINUE;
-
- if (((sense->error_code & SSD_ERRCODE) == 0x70) &&
- ((sense->ext.extended.flags & SSD_KEY) == 0x05))
- /* No point in retrying Illegal Requests */
- return SCSIRET_CONTINUE;
-
- asc = (ext->extra_len >= 5) ? ext->add_sense_code : 0;
- ascq = (ext->extra_len >= 6) ? ext->add_sense_code_qual : 0;
-
- if (asc == 0x11 || asc == 0x30 || asc == 0x31 || asc == 0x53
- || asc == 0x5a) {
- /* Unrecovered errors */
- return SCSIRET_CONTINUE;
- }
- if (asc == 0x21 && ascq == 0) {
- /* Logical block address out of range */
- return SCSIRET_CONTINUE;
- }
- if (asc == 0x27 && ascq == 0) {
- /* Write protected */
- return SCSIRET_CONTINUE;
- }
- if (asc == 0x28 && ascq == 0) {
- /* Not ready to ready transition */
- /* (medium may have changed) */
- return SCSIRET_CONTINUE;
- }
- if (asc == 0x3a && ascq == 0) {
- /* Medium not present */
- return SCSIRET_CONTINUE;
- }
-
- /* Retry all disk errors.
- */
- scsi_sense_print(xs);
- if (xs->retries)
- printf(", retries:%d\n", xs->retries);
- else
- printf(", FAILURE\n");
-
- return SCSIRET_DO_RETRY;
-}
-
-static od_devsw_installed = 0;
-
-static void od_drvinit(void *unused)
-{
-
- if( ! od_devsw_installed ) {
- cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &od_cdevsw);
- od_devsw_installed = 1;
- }
-}
-
-SYSINIT(oddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,od_drvinit,NULL)
diff --git a/sys/scsi/pt.c b/sys/scsi/pt.c
deleted file mode 100644
index c2a2a18..0000000
--- a/sys/scsi/pt.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * 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: pt.c,v 1.29 1998/07/04 22:30:24 julian Exp $
- */
-
-#include "opt_bounce.h"
-#include "opt_devfs.h"
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-#include "ioconf.h"
-
-struct scsi_data {
- struct buf_queue_head buf_queue;
-#ifdef DEVFS
- void *devfs_data_tok;
- void *devfs_ctl_tok;
-#endif
-};
-
-static d_open_t ptopen;
-static d_read_t ptread;
-static d_write_t ptwrite;
-static d_close_t ptclose;
-static d_ioctl_t ptioctl;
-static d_strategy_t ptstrategy;
-
-#define CDEV_MAJOR 61
-static struct cdevsw pt_cdevsw =
- { ptopen, ptclose, ptread, ptwrite, /*61*/
- ptioctl, nostop, nullreset, nodevtotty,/* pt */
- seltrue, nommap, ptstrategy, "pt", NULL, -1 };
-
-SCSI_DEVICE_ENTRIES(pt)
-
-static void ptstart(u_int32_t unit, u_int32_t flags);
-static void pt_strategy(struct buf *bp, struct scsi_link *sc_link);
-static int pt_sense(struct scsi_xfer *scsi_xfer);
-
-static struct scsi_device pt_switch =
-{
- pt_sense,
- 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 */
- ptattach,
- "Processor",
- ptopen,
- sizeof(struct scsi_data),
- T_PROCESSOR,
- 0,
- 0,
- 0,
- 0,
- 0,
- pt_strategy,
-};
-
-static errval
-ptattach(struct scsi_link *sc_link)
-{
- struct scsi_data *pt = sc_link->sd;
-
- bufq_init(&pt->buf_queue);
-
-#ifdef DEVFS
- pt->devfs_data_tok = devfs_add_devswf(&pt_cdevsw,
- sc_link->dev_unit,
- DV_CHR,
- UID_ROOT, GID_WHEEL, 0600,
- "pt%d", sc_link->dev_unit);
- pt->devfs_ctl_tok = devfs_add_devswf(&pt_cdevsw,
- sc_link->dev_unit | SCSI_CONTROL_MASK,
- DV_CHR,
- UID_ROOT, GID_WHEEL, 0600,
- "pt%d.ctl", sc_link->dev_unit);
-#endif
- return 0;
-}
-
-/*
- * 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
- */
-static void
-ptstart(unit, flags)
- u_int32_t unit;
- u_int32_t flags;
-{
- 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;
-
-
- 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;
- }
-
- bp = bufq_first(&pt->buf_queue);
- if (bp == NULL) { /* yes, an assign */
- return;
- }
- bufq_remove(&pt->buf_queue, bp);
-
- /*
- * 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_data,
- bp->b_bcount,
- 0,
- 10000,
- bp,
- flags) == SUCCESSFULLY_QUEUED) {
- } else {
- printf("pt%lu: oops not queued\n", (u_long)unit);
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- biodone(bp);
- }
- } /* go back and see if we can cram more work in.. */
-}
-
-static int
-ptread( dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(ptstrategy, NULL, dev, 1, minphys, uio));
-}
-
-static int
-ptwrite ( dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(ptstrategy, NULL, dev, 0, minphys, uio));
-}
-
-static void
-pt_strategy(struct buf *bp, struct scsi_link *sc_link)
-{
- unsigned char unit;
- u_int32_t opri;
- struct scsi_data *pt;
-
- unit = minor((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() ))
- */
- bufq_insert_tail(&pt->buf_queue, bp);
-
- /*
- * 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, 0);
-
- splx(opri);
- return;
-}
-
-/*
- * sense handler: Called to determine what to do when the
- * device returns a CHECK CONDITION.
- *
- * For the processor type devices we try to handle the "info" field.
- */
-
-static int
-pt_sense(struct scsi_xfer *xs)
-{
- struct scsi_sense_data *sense = &(xs->sense);
- struct buf *bp;
-
- long resid;
-
- if ((sense->error_code & SSD_ERRCODE_VALID) == 0 ||
- (sense->ext.extended.flags & SSD_ILI) == 0) {
- return SCSIRET_CONTINUE; /* let the default handler handle it */
- }
-
- resid = ntohl(*((int32_t *) sense->ext.extended.info));
-
- bp = xs->bp;
-
- if (resid < 0) {
- /* It synthesized data in order to fill our request.
- * Move resid back to cover this.
- */
- xs->resid = -resid;
- xs->flags |= SCSI_RESID_VALID;
- return 0;
- }
- else {
- /* It wanted to send more data. We can't really do anything
- * about this.
- */
- return SCSIRET_CONTINUE;
- }
-}
-
-static pt_devsw_installed = 0;
-
-static void
-pt_drvinit(void *unused)
-{
- dev_t dev;
-
- if ( ! pt_devsw_installed ) {
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev,&pt_cdevsw, NULL);
- pt_devsw_installed = 1;
- }
-}
-
-SYSINIT(ptdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,pt_drvinit,NULL)
-
-
diff --git a/sys/scsi/scsi_all.h b/sys/scsi/scsi_all.h
deleted file mode 100644
index f12ac72..0000000
--- a/sys/scsi/scsi_all.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Largely written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- *
- * $Id: scsi_all.h,v 1.15 1997/02/22 09:44:27 peter Exp $
- */
-
-/*
- * SCSI general interface description
- */
-
-#ifndef _SCSI_SCSI_ALL_H
-#define _SCSI_SCSI_ALL_H 1
-/*
- * SCSI command format
- */
-
-/*
- * Define dome bits that are in ALL (or a lot of) scsi commands
- */
-#define SCSI_CTL_LINK 0x01
-#define SCSI_CTL_FLAG 0x02
-#define SCSI_CTL_VENDOR 0xC0
-#define SCSI_CMD_LUN 0xA0 /* these two should not be needed */
-#define SCSI_CMD_LUN_SHIFT 5 /* LUN in the cmd is no longer SCSI */
-
-
-struct scsi_generic
-{
- u_char opcode;
- u_char bytes[11];
-};
-
-struct scsi_test_unit_ready
-{
- u_char op_code;
- u_char byte2;
- u_char unused[3];
- u_char control;
-};
-
-struct scsi_send_diag
-{
- u_char op_code;
- u_char byte2;
-#define SSD_UOL 0x01
-#define SSD_DOL 0x02
-#define SSD_SELFTEST 0x04
-#define SSD_PF 0x10
- u_char unused[1];
- u_char paramlen[2];
- u_char control;
-};
-
-struct scsi_sense
-{
- u_char op_code;
- u_char byte2;
- u_char unused[2];
- u_char length;
- u_char control;
-};
-
-struct scsi_inquiry
-{
- u_char op_code;
- u_char byte2;
- u_char unused[2];
- u_char length;
- u_char control;
-};
-
-struct scsi_mode_sense
-{
- u_char op_code;
- u_char byte2;
-#define SMS_DBD 0x08
- u_char page;
-#define SMS_PAGE_CODE 0x3F
-#define SMS_PAGE_CTRL 0xC0
-#define SMS_PAGE_CTRL_CURRENT 0x00
-#define SMS_PAGE_CTRL_CHANGEABLE 0x40
-#define SMS_PAGE_CTRL_DEFAULT 0x80
-#define SMS_PAGE_CTRL_SAVED 0xC0
- u_char unused;
- u_char length;
- u_char control;
-};
-
-struct scsi_mode_sense_big
-{
- u_char op_code;
- u_char byte2; /* same bits as small version */
- u_char page; /* same bits as small version */
- u_char unused[4];
- u_char length[2];
- u_char control;
-};
-
-struct scsi_mode_select
-{
- u_char op_code;
- u_char byte2;
-#define SMS_SP 0x01
-#define SMS_PF 0x10
- u_char unused[2];
- u_char length;
- u_char control;
-};
-
-struct scsi_mode_select_big
-{
- u_char op_code;
- u_char byte2; /* same bits as small version */
- u_char unused[5];
- u_char length[2];
- u_char control;
-};
-
-struct scsi_reserve
-{
- u_char op_code;
- u_char byte2;
- u_char unused[2];
- u_char length;
- u_char control;
-};
-
-struct scsi_release
-{
- u_char op_code;
- u_char byte2;
- u_char unused[2];
- u_char length;
- u_char control;
-};
-
-struct scsi_prevent
-{
- u_char op_code;
- u_char byte2;
- u_char unused[2];
- u_char how;
- u_char control;
-};
-#define PR_PREVENT 0x01
-#define PR_ALLOW 0x00
-
-struct scsi_changedef
-{
- u_char op_code;
- u_char byte2;
- u_char unused1;
- u_char how;
- u_char unused[4];
- u_char datalen;
- u_char control;
-};
-#define SC_SCSI_1 0x01
-#define SC_SCSI_2 0x03
-
-/*
- * Opcodes
- */
-
-#define TEST_UNIT_READY 0x00
-#define REQUEST_SENSE 0x03
-#define INQUIRY 0x12
-#define MODE_SELECT 0x15
-#define MODE_SENSE 0x1a
-#define START_STOP 0x1b
-#define RESERVE 0x16
-#define RELEASE 0x17
-#define PREVENT_ALLOW 0x1e
-#define POSITION_TO_ELEMENT 0x2b
-#define CHANGE_DEFINITION 0x40
-#define MODE_SENSE_BIG 0x54
-#define MODE_SELECT_BIG 0x55
-#define MOVE_MEDIUM 0xa5
-#define READ_ELEMENT_STATUS 0xb8
-
-
-/*
- * sense data format
- */
-#define T_DIRECT 0
-#define T_SEQUENTIAL 1
-#define T_PRINTER 2
-#define T_PROCESSOR 3
-#define T_WORM 4
-#define T_READONLY 5
-#define T_SCANNER 6
-#define T_OPTICAL 7
-#define T_CHANGER 8
-#define T_COMM 9
-#define T_ASC0 10
-#define T_ASC1 11
-#define T_TARGET 12
-#define T_UNKNOWN 13
-#define T_NTYPES 14
-
-#define T_NODEVICE 0x1F
-
-#define T_REMOV 1
-#define T_FIXED 0
-
-struct scsi_inquiry_data
-{
- u_char device;
-#define SID_TYPE 0x1F
-#define SID_QUAL 0xE0
-#define SID_QUAL_LU_OK 0x00
-#define SID_QUAL_LU_OFFLINE 0x20
-#define SID_QUAL_RSVD 0x40
-#define SID_QUAL_BAD_LU 0x60
- u_char dev_qual2;
-#define SID_QUAL2 0x7F
-#define SID_REMOVABLE 0x80
- u_char version;
-#define SID_ANSII 0x07
-#define SID_ECMA 0x38
-#define SID_ISO 0xC0
- u_char response_format;
- u_char additional_length;
- u_char unused[2];
- u_char flags;
-#define SID_SftRe 0x01
-#define SID_CmdQue 0x02
-#define SID_Linked 0x08
-#define SID_Sync 0x10
-#define SID_WBus16 0x20
-#define SID_WBus32 0x40
-#define SID_RelAdr 0x80
- char vendor[8];
- char product[16];
- char revision[4];
- u_char extra[8];
-};
-
-
-struct scsi_sense_data
-{
-/* 1*/ u_char error_code; /* same bits as new version */
- union
- {
- struct
- {
-/* 2*/ u_char blockhi;
-/* 3*/ u_char blockmed;
-/* 4*/ u_char blocklow;
- } unextended;
- struct
- {
-/* 2*/ u_char segment;
-/* 3*/ u_char flags; /* same bits as new version */
-/* 7*/ u_char info[4];
-/* 8*/ u_char extra_len;
- /* allocate enough room to hold new stuff
- ( by increasing 16 to 24 below) */
-/*32*/ u_char extra_bytes[24];
- } extended;
- }ext;
-}; /* total of 32 bytes */
-
-struct scsi_sense_extended
-{
-/* 2*/ u_char segment;
-/* 3*/ u_char flags;
-#define SSD_KEY 0x0F
-#define SSD_ILI 0x20
-#define SSD_EOM 0x40
-#define SSD_FILEMARK 0x80
-/* 7*/ u_char info[4];
-/* 8*/ u_char extra_len;
-/*12*/ u_char cmd_spec_info[4];
-/*13*/ u_char add_sense_code;
-/*14*/ u_char add_sense_code_qual;
-/*15*/ u_char fru;
-/*16*/ u_char sense_key_spec_1;
-#define SSD_SCS_VALID 0x80
-/*17*/ u_char sense_key_spec_2;
-/*18*/ u_char sense_key_spec_3;
-/*32*/ u_char extra_bytes[14];
-};
-
-struct scsi_sense_data_new
-{
-/* 1*/ u_char error_code;
-#define SSD_ERRCODE 0x7F
-#define SSD_ERRCODE_VALID 0x80
- union
- {
- struct /* this is deprecated, the standard says "DON'T"*/
- {
-/* 2*/ u_char blockhi;
-/* 3*/ u_char blockmed;
-/* 4*/ u_char blocklow;
- } unextended;
-
- struct scsi_sense_extended extended;
- } ext;
-}; /* total of 32 bytes */
-
-struct blk_desc
-{
- u_char density;
- u_char nblocks[3];
- u_char reserved;
- u_char blklen[3];
-};
-
-struct scsi_mode_header
-{
- u_char data_length; /* Sense data length */
- u_char medium_type;
- u_char dev_spec;
- u_char blk_desc_len;
-};
-
-struct scsi_mode_header_big
-{
- u_char data_length[2]; /* Sense data length */
- u_char medium_type;
- u_char dev_spec;
- u_char unused[2];
- u_char blk_desc_len[2];
-};
-
-
-/*
- * Status Byte
- */
-#define SCSI_OK 0x00
-#define SCSI_CHECK 0x02
-#define SCSI_BUSY 0x08
-#define SCSI_INTERM 0x10
-#define SCSI_RSVD 0x18
-#define SCSI_QUEUE_FULL 0x28
-#endif /*_SCSI_SCSI_ALL_H*/
diff --git a/sys/scsi/scsi_base.c b/sys/scsi/scsi_base.c
deleted file mode 100644
index 67d01b8..0000000
--- a/sys/scsi/scsi_base.c
+++ /dev/null
@@ -1,1370 +0,0 @@
-/*
- * Written By Julian ELischer
- * Copyright julian Elischer 1993.
- * Permission is granted to use or redistribute this file in any way as long
- * as this notice remains. Julian Elischer does not guarantee that this file
- * is totally correct for any given task and users of this file must
- * accept responsibility for any damage that occurs from the application of this
- * file.
- *
- * Written by Julian Elischer (julian@dialix.oz.au)
- * $Id: scsi_base.c,v 1.57 1998/07/11 07:45:57 bde Exp $
- */
-
-#include "opt_bounce.h"
-#include "opt_scsi.h"
-
-#define SPLSD splbio
-#define ESUCCESS 0
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/malloc.h>
-#include <sys/proc.h>
-
-#include <machine/clock.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-
-#include <scsi/scsi_disk.h>
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-
-static errval sc_err1(struct scsi_xfer *);
-static errval scsi_interpret_sense(struct scsi_xfer *);
-static struct scsi_xfer *get_xs( struct scsi_link *sc_link, u_int32_t flags);
-static void free_xs(struct scsi_xfer *xs, struct scsi_link *sc_link,
- u_int32_t flags);
-#ifdef SCSIDEBUG
-static void show_mem(unsigned char *address, u_int32_t num);
-static void show_scsi_xs (struct scsi_xfer *);
-#endif
-
-#ifdef notyet
-static int scsi_sense_qualifiers (struct scsi_xfer *, int *, int *);
-#endif
-
-static struct scsi_xfer *next_free_xs;
-
-/*
- * Get a scsi transfer structure for the caller. Charge the structure
- * to the device that is referenced by the sc_link structure. If the
- * sc_link structure has no 'credits' then the device already has the
- * maximum number or outstanding operations under way. In this stage,
- * wait on the structure so that when one is freed, we are awoken again
- * If the SCSI_NOSLEEP flag is set, then do not wait, but rather, return
- * a NULL pointer, signifying that no slots were available
- * Note in the link structure, that we are waiting on it.
- */
-
-static struct scsi_xfer *
-get_xs(sc_link, flags)
- struct scsi_link *sc_link; /* who to charge the xs to */
- u_int32_t flags; /* if this call can sleep */
-{
- struct scsi_xfer *xs;
- u_int32_t s;
-
- SC_DEBUG(sc_link, SDEV_DB3, ("get_xs\n"));
- s = splbio();
- while (!sc_link->opennings) {
- SC_DEBUG(sc_link, SDEV_DB3, ("sleeping\n"));
- if (flags & SCSI_NOSLEEP) {
- splx(s);
- return 0;
- }
- sc_link->flags |= SDEV_WAITING;
- tsleep((caddr_t)sc_link, PRIBIO, "scsiget", 0);
- }
- sc_link->active++;
- sc_link->opennings--;
- if ( (xs = next_free_xs) ) {
- next_free_xs = xs->next;
- splx(s);
- } else {
- splx(s);
- SC_DEBUG(sc_link, SDEV_DB3, ("making\n"));
- xs = malloc(sizeof(*xs), M_TEMP,
- ((flags & SCSI_NOSLEEP) ? M_NOWAIT : M_WAITOK));
- if (xs == NULL) {
- sc_print_addr(sc_link);
- printf("cannot allocate scsi xs\n");
- return (NULL);
- }
- callout_handle_init(&xs->timeout_ch);
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("returning\n"));
- xs->sc_link = sc_link;
- return (xs);
-}
-
-/*
- * Given a scsi_xfer struct, and a device (referenced through sc_link)
- * return the struct to the free pool and credit the device with it
- * If another process is waiting for an xs, do a wakeup, let it proceed
- */
-static void
-free_xs(xs, sc_link, flags)
- struct scsi_xfer *xs;
- struct scsi_link *sc_link; /* who to credit for returning it */
- u_int32_t flags;
-{
- xs->next = next_free_xs;
- next_free_xs = xs;
-
- SC_DEBUG(sc_link, SDEV_DB3, ("free_xs\n"));
- /* if was 0 and someone waits, wake them up */
- sc_link->active--;
- if ((!sc_link->opennings++) && (sc_link->flags & SDEV_WAITING)) {
- sc_link->flags &= ~SDEV_WAITING;
- wakeup((caddr_t)sc_link); /* remember, it wakes them ALL up */
- } else {
- if (sc_link->device->start) {
- SC_DEBUG(sc_link, SDEV_DB2, ("calling private start()\n"));
- (*(sc_link->device->start)) (sc_link->dev_unit, 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_t
-scsi_read_capacity(sc_link, blk_size, flags)
- struct scsi_link *sc_link;
- u_int32_t *blk_size;
- u_int32_t flags;
-{
- struct scsi_read_cap_data rdcap;
- struct scsi_read_capacity scsi_cmd;
- u_int32_t size;
-
- /*
- * make up a scsi command and ask the scsi driver to do
- * it for you.
- */
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = READ_CAPACITY;
-
- /*
- * If the command works, interpret the result as a 4 byte
- * number of blocks
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) & rdcap,
- sizeof(rdcap),
- 4,
- 5000000, /* WORMs tend to take a HUGE amount of time */
- NULL,
- flags | SCSI_DATA_IN) != 0) {
-
- sc_print_addr(sc_link);
- printf("could not get size\n");
- return (0);
- } else {
- size = scsi_4btou(&rdcap.addr_3) + 1;
- if (blk_size)
- *blk_size = scsi_4btou(&rdcap.length_3);
- }
- return (size);
-}
-
-errval
-scsi_reset_target(sc_link)
- struct scsi_link *sc_link;
-{
- return (scsi_scsi_cmd(sc_link,
- 0,
- 0,
- 0,
- 0,
- 1,
- 2000,
- NULL,
- SCSI_RESET));
-}
-
-errval
-scsi_target_mode(sc_link, on_off)
- struct scsi_link *sc_link;
- int on_off;
-{
- struct scsi_generic scsi_cmd;
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.opcode = SCSI_OP_TARGET;
- scsi_cmd.bytes[0] = (on_off) ? 1 : 0;
-
- return (scsi_scsi_cmd(sc_link,
- &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 1,
- 2000,
- NULL,
- SCSI_ESCAPE));
-}
-
-/*
- * Get scsi driver to send a "are you ready?" command
- */
-errval
-scsi_test_unit_ready(sc_link, flags)
- struct scsi_link *sc_link;
- u_int32_t flags;
-{
- struct scsi_test_unit_ready scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = TEST_UNIT_READY;
-
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 2,
- 100000,
- NULL,
- flags));
-}
-
-#ifdef SCSI_2_DEF
-/*
- * Do a scsi operation, asking a device to run as SCSI-II if it can.
- */
-errval
-scsi_change_def(sc_link, flags)
- struct scsi_link *sc_link;
- u_int32_t flags;
-{
- struct scsi_changedef scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = CHANGE_DEFINITION;
- scsi_cmd.how = SC_SCSI_2;
-
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 2,
- 100000,
- NULL,
- flags));
-}
-#endif /* SCSI_2_DEF */
-
-/*
- * Do a scsi operation asking a device what it is
- * Use the scsi_cmd routine in the switch table.
- */
-errval
-scsi_inquire(sc_link, inqbuf, flags)
- struct scsi_link *sc_link;
- struct scsi_inquiry_data *inqbuf;
- u_int32_t flags;
-{
- struct scsi_inquiry scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = INQUIRY;
- scsi_cmd.length = sizeof(struct scsi_inquiry_data);
-
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) inqbuf,
- sizeof(struct scsi_inquiry_data),
- 2,
- 100000,
- NULL,
- SCSI_DATA_IN | flags));
-}
-
-/*
- * Prevent or allow the user to remove the media
- */
-errval
-scsi_prevent(sc_link, type, flags)
- struct scsi_link *sc_link;
- u_int32_t type, flags;
-{
- struct scsi_prevent scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = PREVENT_ALLOW;
- scsi_cmd.how = type;
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 2,
- 5000,
- NULL,
- flags));
-}
-
-/*
- * Get scsi driver to send a "start up" command
- */
-errval
-scsi_start_unit(sc_link, flags)
- struct scsi_link *sc_link;
- u_int32_t flags;
-{
- struct scsi_start_stop scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = START_STOP;
- scsi_cmd.how = SSS_START;
-
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 2,
- 30000,
- NULL,
- flags));
-}
-
-/*
- * Get scsi driver to send a "stop" command
- */
-errval
-scsi_stop_unit(sc_link, eject, flags)
- struct scsi_link *sc_link;
- u_int32_t eject;
- u_int32_t flags;
-{
- struct scsi_start_stop scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = START_STOP;
- if (eject) {
- scsi_cmd.how = SSS_LOEJ;
- }
-
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 2,
- 10000,
- NULL,
- flags));
-}
-
-/*
- * This routine is called by the scsi interrupt when the transfer is complete.
- */
-void
-scsi_done(xs)
- struct scsi_xfer *xs;
-{
- struct scsi_link *sc_link = xs->sc_link;
- struct buf *bp = xs->bp;
- errval retval;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("scsi_done\n"));
-#ifdef SCSIDEBUG
- if (sc_link->flags & SDEV_DB1)
- {
- show_scsi_cmd(xs);
- }
-#endif /*SCSIDEBUG */
- /*
- * If it's a user level request, bypass all usual completion processing,
- * let the user work it out.. We take reponsibility for freeing the
- * xs when the user returns. (and restarting the device's queue).
- */
- if (xs->flags & SCSI_USER) {
- SC_DEBUG(sc_link, SDEV_DB3, ("calling user done()\n"));
- scsi_user_done(xs); /* to take a copy of the sense etc. */
- SC_DEBUG(sc_link, SDEV_DB3, ("returned from user done()\n "));
-
- free_xs(xs, sc_link, SCSI_NOSLEEP); /* restarts queue too */
- SC_DEBUG(sc_link, SDEV_DB3, ("returning to adapter\n"));
- return;
- }
- /*
- * If the device has its own done routine, call it first.
- * If it returns a legit error value, return that, otherwise
- * it wants us to continue with normal processing.
- */
-
- if (sc_link->device->done) {
- SC_DEBUG(sc_link, SDEV_DB2, ("calling private done()\n"));
- retval = (*sc_link->device->done) (xs);
- if (retval == -1) {
- free_xs(xs, sc_link, SCSI_NOSLEEP); /*XXX */
- return; /* it did it all, finish up */
- }
- /* XXX: This isn't used anywhere. Do you have plans for it,
- * Julian? (dufault@hda.com).
- * This allows a private 'done' handler to
- * resubmit the command if it wants to retry,
- * In this case the xs must NOT be freed. (julian)
- */
- if (retval == -2) {
- return; /* it did it all, finish up */
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("continuing with generic done()\n"));
- }
- if ((bp = xs->bp) == NULL) {
- /*
- * if it's a normal upper level request, then ask
- * the upper level code to handle error checking
- * rather than doing it here at interrupt time
- */
- wakeup((caddr_t)xs);
- return;
- }
- /*
- * Go and handle errors now.
- * If it returns SCSIRET_DO_RETRY then we should RETRY
- */
- if ((retval = sc_err1(xs)) == SCSIRET_DO_RETRY) {
- if ((*(sc_link->adapter->scsi_cmd)) (xs)
- == SUCCESSFULLY_QUEUED) { /* don't wake the job, ok? */
- return;
- }
- xs->flags |= ITSDONE;
- }
-
- free_xs(xs, sc_link, SCSI_NOSLEEP); /* does a start if needed */
- biodone(bp);
-}
-
-/*
- * ask the scsi driver to perform a command for us.
- * tell it where to read/write the data, and how
- * long the data is supposed to be. If we have a buf
- * to associate with the transfer, we need that too.
- */
-errval
-scsi_scsi_cmd(sc_link, scsi_cmd, cmdlen, data_addr, datalen,
- retries, timeout, bp, flags)
- struct scsi_link *sc_link;
- struct scsi_generic *scsi_cmd;
- u_int32_t cmdlen;
- u_char *data_addr;
- u_int32_t datalen;
- u_int32_t retries;
- u_int32_t timeout;
- struct buf *bp;
- u_int32_t flags;
-{
- struct scsi_xfer *xs;
- errval retval;
- u_int32_t s;
- struct proc *p = curproc;
- int iskstack = 0; /* 0 = "ok", 1 = copied from kernel stack */
-
- /*
- * Illegal command lengths will wedge host adapter software.
- * Reject zero length commands and assert all defined commands
- * are the correct length.
- */
- if ((flags & (SCSI_RESET | SCSI_ESCAPE)) == 0)
- {
- if (cmdlen == 0) {
- retval = EFAULT;
- goto bad_with_biodone;
- } else {
- static u_int8_t sizes[] = {6, 10, 10, 0, 0, 12, 0, 0 };
- u_int8_t size = sizes[((scsi_cmd->opcode) >> 5)];
- if (size && (size != cmdlen)) {
- retval = EIO;
- goto bad_with_biodone;
- }
- }
- }
-
- SC_DEBUG(sc_link, SDEV_DB2, ("scsi_cmd\n"));
-
- xs = get_xs(sc_link, flags);
- if (!xs) {
- retval = ENOMEM;
- goto bad_with_biodone;
- }
- /*
- * Fill out the scsi_xfer structure. We don't know whose context
- * the cmd is in, so copy it.
- */
- bcopy(scsi_cmd, &(xs->cmdstore), cmdlen);
- xs->flags = INUSE | flags;
- xs->sc_link = sc_link;
- xs->retries = retries;
- xs->timeout = timeout;
- xs->cmd = &xs->cmdstore;
- xs->cmdlen = cmdlen;
- xs->data = data_addr;
- xs->datalen = datalen;
- xs->resid = 0;
- xs->bp = bp;
-/*XXX*/ /*use constant not magic number */
- if (datalen && (caddr_t) data_addr < (caddr_t) KERNBASE) {
- /* XXX: should panic */
- printf("scsi_scsi_cmd(): data target is user space!\n");
-#ifdef SCSIDEBUG
- show_scsi_cmd(xs);
-#endif /* SCSIDEBUG */
- retval = EFAULT;
- goto bad;
- }
- /* XXX theoretically.. in !BOUNCE_BUFFERS, we can still get to all
- * process's kstack's, *BUT* we can swap a process. We really don't
- * need to take a fault in that situation. Besides, the permanent
- * KVM space will go away and only the current process will be
- * reachable once the kthreading is finished.
- */
- if (datalen && p != NULL &&
- (caddr_t)data_addr > (caddr_t)p->p_addr &&
- (caddr_t)data_addr < (caddr_t)p->p_addr + UPAGES * PAGE_SIZE)
- iskstack = 1;
- /* if we are doing a scsi command to/from per-proc kstack, copy it.. */
- if (iskstack) {
- if (bp) {
- printf("Data buffered space not in kernel context\n");
-#ifdef SCSIDEBUG
- show_scsi_cmd(xs);
-#endif /* SCSIDEBUG */
- retval = EFAULT;
- goto bad;
- }
-#ifdef BOUNCE_BUFFERS
- xs->data = (caddr_t) vm_bounce_kva_alloc(btoc(datalen));
-#else
- xs->data = malloc(datalen, M_TEMP, M_WAITOK);
-#endif
- /* I think waiting is ok *//*XXX */
- switch ((int)(flags & (SCSI_DATA_IN | SCSI_DATA_OUT))) {
- case 0:
- printf("No direction flags, assuming both\n");
-#ifdef SCSIDEBUG
- show_scsi_cmd(xs);
-#endif /* SCSIDEBUG */
- case SCSI_DATA_IN | SCSI_DATA_OUT: /* weird */
- case SCSI_DATA_OUT:
- bcopy(data_addr, xs->data, datalen);
- break;
- case SCSI_DATA_IN:
- bzero(xs->data, datalen);
- }
- }
-retry:
- xs->error = XS_NOERROR;
-#ifdef PARANOID
- if (datalen && ((caddr_t) xs->data < (caddr_t) KERNBASE)) {
- printf("It's still wrong!\n");
- }
-#endif /*PARANOID*/
-#ifdef SCSIDEBUG
- if (sc_link->flags & SDEV_DB3) show_scsi_xs(xs);
-#endif /* SCSIDEBUG */
- /*
- * Do the transfer. If we are polling we will return:
- * COMPLETE, Was poll, and scsi_done has been called
- * TRY_AGAIN_LATER, Adapter short resources, try again
- *
- * if under full steam (interrupts) it will return:
- * SUCCESSFULLY_QUEUED, will do a wakeup when complete
- * TRY_AGAIN_LATER, (as for polling)
- * After the wakeup, we must still check if it succeeded
- *
- * If we have a bp however, all the error proccessing
- * and the buffer code both expect us to return straight
- * to them, so as soon as the command is queued, return
- */
-
- retval = (*(sc_link->adapter->scsi_cmd)) (xs);
-
- switch (retval) {
- case SUCCESSFULLY_QUEUED:
- if (bp) {
- return 0; /* will sleep (or not) elsewhere */
- }
- s = splbio();
- while (!(xs->flags & ITSDONE)) {
- tsleep((caddr_t)xs, PRIBIO + 1, "scsicmd", 0);
- }
- splx(s);
- /* fall through to check success of completed command */
- case COMPLETE: /* Polling command completed ok */
-/*XXX*/ case HAD_ERROR: /* Polling command completed with error */
- SC_DEBUG(sc_link, SDEV_DB3, ("back in cmd()\n"));
- if ((retval = sc_err1(xs)) == SCSIRET_DO_RETRY)
- goto retry;
- break;
-
- case TRY_AGAIN_LATER: /* adapter resource shortage */
- SC_DEBUG(sc_link, SDEV_DB3, ("will try again \n"));
- /* should sleep 1 sec here */
- if (xs->retries--) {
- xs->flags &= ~ITSDONE;
- goto retry;
- }
- default:
- retval = EIO;
- }
- /*
- * If we had to copy the data out of the user's context,
- * then do the other half (copy it back or whatever)
- * and free the memory buffer
- */
- if (iskstack) {
- switch ((int)(flags & (SCSI_DATA_IN | SCSI_DATA_OUT))) {
- case 0:
- case SCSI_DATA_IN | SCSI_DATA_OUT: /* weird */
- case SCSI_DATA_IN:
- bcopy(xs->data, data_addr, datalen);
- break;
- }
-bad_with_alloc:
-#ifdef BOUNCE_BUFFERS
- vm_bounce_kva_alloc_free((vm_offset_t) xs->data,
- btoc(datalen));
-#else
- free(xs->data, M_TEMP);
-#endif
- }
- /*
- * we have finished with the xfer stuct, free it and
- * check if anyone else needs to be started up.
- */
-bad:
- s = splbio();
- free_xs(xs, sc_link, flags); /* includes the 'start' op */
- splx(s);
-bad_with_biodone:
- if (bp && retval) {
- bp->b_error = retval;
- bp->b_flags |= B_ERROR;
- biodone(bp);
- }
- return (retval);
-}
-
-static errval
-sc_done(struct scsi_xfer *xs, int code)
-{
- /*
- * If it has a buf, we might be working with
- * a request from the buffer cache or some other
- * piece of code that requires us to process
- * errors at interrupt time. We have probably
- * been called by scsi_done()
- */
- struct buf *bp;
-
- if (code == SCSIRET_DO_RETRY) {
- if (xs->retries--) {
- xs->error = XS_NOERROR;
- xs->flags &= ~ITSDONE;
- return SCSIRET_DO_RETRY;
- }
- code = EIO; /* Too many retries */
- }
-
- /*
- * an EOF condition results in a VALID resid..
- */
- if(xs->flags & SCSI_EOF) {
- xs->resid = xs->datalen;
- xs->flags |= SCSI_RESID_VALID;
- }
-
- bp = xs->bp;
- if (code != ESUCCESS) {
- if (bp) {
- bp->b_error = 0;
- bp->b_flags |= B_ERROR;
- bp->b_error = code;
- bp->b_resid = bp->b_bcount;
- SC_DEBUG(xs->sc_link, SDEV_DB3,
- ("scsi_interpret_sense (bp) returned %d\n", code));
- } else {
- SC_DEBUG(xs->sc_link, SDEV_DB3,
- ("scsi_interpret_sense (no bp) returned %d\n", code));
- }
- }
- else {
- if (bp) {
-
- bp->b_error = 0;
-
- /* XXX: We really shouldn't need this SCSI_RESID_VALID flag.
- * If we initialize it to 0 and only touch it if we have
- * a value then we can leave out the test.
- */
-
- if (xs->flags & SCSI_RESID_VALID) {
- bp->b_resid = xs->resid;
- bp->b_flags |= B_ERROR;
- } else {
- bp->b_resid = 0;
- }
- }
- }
-
- return code;
-}
-
-/*
- * submit a scsi command, given the command.. used for retries
- * and callable from timeout()
- */
-#ifdef NOTYET
-errval scsi_submit(xs)
- struct scsi_xfer *xs;
-{
- struct scsi_link *sc_link = xs->sc_link;
- int retval;
-
- retval = (*(sc_link->adapter->scsi_cmd)) (xs);
-
- return retval;
-}
-
-/*
- * Retry a scsi command, given the command, and a delay.
- */
-errval scsi_retry(xs,delay)
- struct scsi_xfer *xs;
- int delay;
-{
- if(delay)
- {
- timeout(((void())*)scsi_submit,xs,hz*delay);
- return(0);
- }
- else
- {
- return(scsi_submit(xs));
- }
-}
-#endif
-
-/*
- * handle checking for errors..
- * called at interrupt time from scsi_done() and
- * at user time from scsi_scsi_cmd(), depending on whether
- * there was a bp (basically, if there is a bp, there may be no
- * associated process at the time. (it could be an async operation))
- * lower level routines shouldn't know about xs->bp.. we are the lowest.
- */
-static errval
-sc_err1(xs)
- struct scsi_xfer *xs;
-{
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("sc_err1,err = 0x%lx \n",
- (u_long)xs->error));
-
- switch ((int)xs->error) {
- case XS_SENSE:
- return sc_done(xs, scsi_interpret_sense(xs));
-
- case XS_NOERROR:
- return sc_done(xs, ESUCCESS);
-
- case XS_BUSY:
- /* should somehow arange for a 1 sec delay here (how?)[jre]
- * tsleep(&localvar, priority, "foo", hz);
- * that's how! [unknown]
- * no, we could be at interrupt context.. use
- * timeout(scsi_resubmit,xs,hz); [jre] (not implimenteed yet)
- */
- DELAY(1000);
- case XS_TIMEOUT:
- return sc_done(xs, SCSIRET_DO_RETRY);
-
- /* fall through */
- case XS_SELTIMEOUT:
- case XS_DRIVER_STUFFUP:
- return sc_done(xs, EIO);
-
- default:
- sc_print_addr(xs->sc_link);
- printf("unknown error category from scsi driver\n");
- return sc_done(xs, EIO);
- }
-}
-
-#ifdef notyet
-static int
-scsi_sense_qualifiers(xs, asc, ascq)
- struct scsi_xfer *xs;
- int *asc;
- int *ascq;
-{
- struct scsi_sense_data_new *sense;
- struct scsi_sense_extended *ext;
-
- sense = (struct scsi_sense_data_new *)&(xs->sense);
-
- ext = &(sense->ext.extended);
-
- if (ext->extra_len < 5)
- return 0;
-
- *asc = (ext->extra_len >= 5) ? ext->add_sense_code : 0;
- *ascq = (ext->extra_len >= 6) ? ext->add_sense_code_qual : 0;
-
- return 1;
-}
-
-#endif
-
-/*
- * scsi_sense_print will decode the sense data into human
- * readable form. Sense handlers can use this to generate
- * a report. This NOW DOES send the closing "\n".
- */
-void scsi_sense_print(xs)
- struct scsi_xfer *xs;
-{
- struct scsi_sense_data_new *sense;
- struct scsi_sense_extended *ext;
- u_int32_t key;
- u_int32_t info;
- int asc, ascq;
-
- /* This sense key text now matches what is in the SCSI spec
- * (Yes, even the capitals)
- * so that it is easier to look through the spec to find the
- * appropriate place.
- */
- static char *sense_key_text[] =
- {
- "NO SENSE", "RECOVERED ERROR",
- "NOT READY", "MEDIUM ERROR",
- "HARDWARE FAILURE", "ILLEGAL REQUEST",
- "UNIT ATTENTION", "DATA PROTECT",
- "BLANK CHECK", "Vendor Specific",
- "COPY ABORTED", "ABORTED COMMAND",
- "EQUAL", "VOLUME OVERFLOW",
- "MISCOMPARE", "RESERVED"
- };
-
- sc_print_start(xs->sc_link);
-
- sense = (struct scsi_sense_data_new *)&(xs->sense);
- ext = &(sense->ext.extended);
-
- key = ext->flags & SSD_KEY;
-
- switch (sense->error_code & SSD_ERRCODE) {
- case 0x71: /* deferred error */
- printf("Deferred Error: ");
-
- /* DROP THROUGH */
-
- case 0x70:
-
- printf("%s", sense_key_text[key]);
- info = (ext->info[0] << 24) | (ext->info[1] << 16)
- | (ext->info[2] << 8) | ext->info[3];
-
- if (sense->error_code & SSD_ERRCODE_VALID) {
-
- switch ((int)key) {
- case 0x2: /* NOT READY */
- case 0x5: /* ILLEGAL REQUEST */
- case 0x6: /* UNIT ATTENTION */
- case 0x7: /* DATA PROTECT */
- break;
- case 0x8: /* BLANK CHECK */
- printf(" req sz: %lu (decimal)", (u_long)info);
- break;
- default:
- if (info) {
- if (sense->ext.extended.flags & SSD_ILI) {
- printf(
- " ILI (length mismatch): %ld",
- (u_long)info);
- }
- else {
- printf(" info:%#lx",
- (u_long)info);
- }
- }
- }
- }
- else if (info)
- printf(" info?:%#lx", (u_long)info);
-
- if (ext->extra_len >= 4) {
- if (bcmp(ext->cmd_spec_info, "\0\0\0\0", 4)) {
- printf(" csi:%x,%x,%x,%x",
- ext->cmd_spec_info[0],
- ext->cmd_spec_info[1],
- ext->cmd_spec_info[2],
- ext->cmd_spec_info[3]);
- }
- }
-
- asc = (ext->extra_len >= 5) ? ext->add_sense_code : 0;
- ascq = (ext->extra_len >= 6) ? ext->add_sense_code_qual : 0;
-
- if (asc || ascq)
- {
- char *desc = scsi_sense_desc(asc, ascq);
- printf(" asc:%x,%x", asc, ascq);
-
- if (strlen(desc) > 40)
- sc_print_addr(xs->sc_link);;
-
- printf(" %s", desc);
- }
-
- if (ext->extra_len >= 7 && ext->fru) {
- printf(" field replaceable unit: %x", ext->fru);
- }
-
- if (ext->extra_len >= 10 &&
- (ext->sense_key_spec_1 & SSD_SCS_VALID)) {
- printf(" sks:%x,%x", ext->sense_key_spec_1,
- (ext->sense_key_spec_2 |
- ext->sense_key_spec_3));
- }
- break;
-
- /*
- * Not code 70, just report it
- */
- default:
- printf("error code %d",
- sense->error_code & SSD_ERRCODE);
- if (sense->error_code & SSD_ERRCODE_VALID) {
- printf(" at block no. %ld (decimal)",
- (((unsigned long)sense->ext.unextended.blockhi) << 16) +
- (((unsigned long)sense->ext.unextended.blockmed) << 8) +
- ((unsigned long)sense->ext.unextended.blocklow));
- }
- }
-
- printf("\n");
- sc_print_finish();
-}
-
-/*
- * Look at the returned sense and act on the error, determining
- * the unix error number to pass back. (0 = report no error)
- *
- * THIS IS THE DEFAULT SENSE HANDLER
- */
-static errval
-scsi_interpret_sense(xs)
- struct scsi_xfer *xs;
-{
- struct scsi_sense_data_new *sense;
- struct scsi_sense_extended *ext;
- struct scsi_link *sc_link = xs->sc_link;
- u_int32_t key;
- u_int32_t silent;
- errval errcode;
- int error_code, asc, ascq;
-
- /*
- * If the flags say errs are ok, then always return ok.
- * XXX: What if it is a deferred error?
- */
- if (xs->flags & SCSI_ERR_OK)
- return (ESUCCESS);
-
- sense = (struct scsi_sense_data_new *)&(xs->sense);
- ext = &(sense->ext.extended);
-#ifdef SCSIDEBUG
- if (sc_link->flags & SDEV_DB1) {
-
- u_int32_t count = 0;
- printf("code%x valid%x ",
- sense->error_code & SSD_ERRCODE,
- sense->error_code & SSD_ERRCODE_VALID ? 1 : 0);
- printf("seg%x key%x ili%x eom%x fmark%x\n",
- ext->segment,
- ext->flags & SSD_KEY,
- ext->flags & SSD_ILI ? 1 : 0,
- ext->flags & SSD_EOM ? 1 : 0,
- ext->flags & SSD_FILEMARK ? 1 : 0);
- printf("info: %x %x %x %x followed by %d extra bytes\n",
- ext->info[0],
- ext->info[1],
- ext->info[2],
- ext->info[3],
- ext->extra_len);
- printf("extra: ");
- while (count < ext->extra_len) {
- printf("%x ", ext->extra_bytes[count++]);
- }
- printf("\n");
- }
- #endif /*SCSIDEBUG */
- /*
- * If the device has its own sense handler, call it first.
- * If it returns a legit errno value, return that, otherwise
- * it should return either DO_RETRY or CONTINUE to either
- * request a retry or continue with default sense handling.
- */
- if (sc_link->device->err_handler) {
- SC_DEBUG(sc_link, SDEV_DB2,
- ("calling private err_handler()\n"));
- errcode = (*sc_link->device->err_handler) (xs);
-
- SC_DEBUG(sc_link, SDEV_DB2,
- ("private err_handler() returned %d\n",errcode));
- if (errcode >= 0) {
- SC_DEBUG(sc_link, SDEV_DB2,
- ("SCSI_EOF = %d\n",(xs->flags & SCSI_EOF)?1:0));
- SC_DEBUG(sc_link, SDEV_DB2,
- ("SCSI_RESID_VALID = %d\n",
- (xs->flags & SCSI_RESID_VALID)?1:0));
-
- if(xs->flags & SCSI_EOF) {
- xs->resid = xs->datalen;
- xs->flags |= SCSI_RESID_VALID;
- }
- return errcode; /* valid errno value */
- }
-
- switch(errcode) {
- case SCSIRET_DO_RETRY: /* Requested a retry */
- return errcode;
-
- case SCSIRET_CONTINUE: /* Continue with default sense processing */
- break;
-
- default:
- sc_print_addr(xs->sc_link);
- printf("unknown return code %d from sense handler.\n",
- errcode);
-
- return errcode;
- }
- }
-
- /* otherwise use the default */
- silent = xs->flags & SCSI_SILENT;
- key = ext->flags & SSD_KEY;
- error_code = sense->error_code & SSD_ERRCODE;
- asc = (ext->extra_len >= 5) ? ext->add_sense_code : 0;
- ascq = (ext->extra_len >= 6) ? ext->add_sense_code_qual : 0;
-
- /*
- * Retry while the device is returning a ``Logical unit
- * is in the process of becoming ready.'' (until it either
- * eventually yields an error, or finally succeeds).
- */
- if (error_code == 0x70 /* current error */ &&
- (int)key == 0x2 /* not ready */ &&
- asc == 4 && ascq == 1 /* logical unit i i t p o b r */)
- return (SCSIRET_DO_RETRY);
-
- if (!silent) {
- scsi_sense_print(xs);
- }
-
- switch (error_code) {
- case 0x71: /* deferred error */
- /* Print even if silent (not silent was already done)
- */
- if (silent) {
- scsi_sense_print(xs);
- }
-
- /* XXX:
- * This error doesn't relate to the command associated
- * with this request sense. A deferred error is an error
- * for a command that has already returned GOOD status (see 7.2.14.2).
- *
- * By my reading of that section, it looks like the current command
- * has been cancelled, we should now clean things up (hopefully
- * recovering any lost data) and then
- * retry the current command. There are two easy choices, both
- * wrong:
- * 1. Drop through (like we had been doing), thus treating this as
- * if the error were for the current command and return and stop
- * the current command.
- * 2. Issue a retry (like I made it do) thus hopefully recovering
- * the current transfer, and ignoring the fact that we've dropped
- * a command.
- *
- * These should probably be handled in a device specific
- * sense handler or punted back up to a user mode daemon
- */
- return SCSIRET_DO_RETRY;
-
- /*
- * If it's code 70, use the extended stuff and interpret the key
- */
- case 0x70:
-
- switch ((int)key) {
- case 0x0: /* NO SENSE */
- case 0x1: /* RECOVERED ERROR */
- case 0xc: /* EQUAL */
- if(xs->flags & SCSI_EOF) {
- xs->resid = xs->datalen;
- xs->flags |= SCSI_RESID_VALID;
- }
- return (ESUCCESS);
- case 0x2: /* NOT READY */
- sc_link->flags &= ~SDEV_MEDIA_LOADED;
- return (EBUSY);
- case 0x5: /* ILLEGAL REQUEST */
- return (EINVAL);
- case 0x6: /* UNIT ATTENTION */
- sc_link->flags &= ~SDEV_MEDIA_LOADED;
- if (sc_link->flags & SDEV_OPEN) {
- return (EIO);
- } else {
- return 0;
- }
- case 0x7: /* DATA PROTECT */
- return (EACCES);
- case 0xd: /* VOLUME OVERFLOW */
- return (ENOSPC);
- case 0x8: /* BLANK CHECK */
- xs->flags |= SCSI_EOF; /* force EOF on tape read */
- return (ESUCCESS);
- default:
- return (EIO);
- }
- /*
- * Not code 70, return EIO
- */
- default:
- return (EIO);
- }
-}
-
-/*
- * Utility routines often used in SCSI stuff
- */
-
-/*
- * convert a physical address to 3 bytes,
- * MSB at the lowest address,
- * LSB at the highest.
- */
-void
-scsi_uto3b(val, bytes)
- u_int32_t val;
- u_char *bytes;
-{
- *bytes++ = (val & 0xff0000) >> 16;
- *bytes++ = (val & 0xff00) >> 8;
- *bytes = val & 0xff;
-}
-
-u_int32_t
-scsi_3btou(bytes)
- u_char *bytes;
-{
- u_int32_t rc;
- rc = (*bytes++ << 16);
- rc += (*bytes++ << 8);
- rc += *bytes;
- return rc;
-}
-
-int32_t
-scsi_3btoi(bytes)
- u_char *bytes;
-{
- u_int32_t rc = scsi_3btou(bytes);
-
- if (rc & 0x00800000)
- rc |= 0xff000000;
-
- return (int32_t) rc;
-}
-
-void
-scsi_uto2b(val, bytes)
- u_int32_t val;
- u_char *bytes;
-{
- *bytes++ = (val & 0xff00) >> 8;
- *bytes = val & 0xff;
-}
-
-u_int32_t
-scsi_2btou(bytes)
- u_char *bytes;
-{
- u_int32_t rc;
- rc = (*bytes++ << 8);
- rc += *bytes;
- return rc;
-}
-
-void
-scsi_uto4b(val, bytes)
- u_int32_t val;
- u_char *bytes;
-{
- *bytes++ = (val & 0xff000000) >> 24;
- *bytes++ = (val & 0xff0000) >> 16;
- *bytes++ = (val & 0xff00) >> 8;
- *bytes = val & 0xff;
-}
-
-u_int32_t
-scsi_4btou(bytes)
- u_char *bytes;
-{
- u_int32_t rc;
- rc = (*bytes++ << 24);
- rc += (*bytes++ << 16);
- rc += (*bytes++ << 8);
- rc += *bytes;
- return rc;
-}
-
-static int sc_printing;
-
-void
-sc_print_init()
-{
- sc_printing++;
-}
-
-void
-sc_print_start(sc_link)
- struct scsi_link *sc_link;
-{
- sc_print_addr(sc_link);
- sc_printing++;
-}
-void
-sc_print_finish()
-{
- sc_printing--;
-}
-
-static void
-id_put(int id, char *after)
-{
- switch(id)
- {
- case SCCONF_UNSPEC:
- break;
-
- case SCCONF_ANY:
- printf("?");
- break;
-
- default:
- printf("%d", id);
- break;
- }
-
- printf("%s", after);
-}
-
-/*
- * sc_print_addr: Print out the scsi_link structure's address info.
- * This should handle any circumstance, even the transitory ones
- * during system configuration.
- */
-
-void
-sc_print_addr(sc_link)
- struct scsi_link *sc_link;
-{
- if (sc_printing)
- printf("\n");
-
- if (sc_link->device == 0) {
- printf("nodevice at ");
- }
- else if (strcmp(sc_link->device->name, "probe") != 0) {
- printf("%s", sc_link->device->name);
- id_put(sc_link->dev_unit, ": ");
- return;
- }
-
- printf("scbus");
- id_put(sc_link->scsibus, " ");
-
- printf("target ");
- id_put(sc_link->target, " ");
- printf("lun ");
- id_put(sc_link->lun, ": ");
-}
-
-#ifdef SCSIDEBUG
-/*
- * Given a scsi_xfer, dump the request, in all its glory
- */
-static void
-show_scsi_xs(xs)
- struct scsi_xfer *xs;
-{
- printf("xs(%p): ", (void *)xs);
- printf("flg(0x%lx)", (u_long)xs->flags);
- printf("sc_link(%p)", (void *)xs->sc_link);
- printf("retr(0x%x)", xs->retries);
- printf("timo(0x%lx)", (long)xs->timeout);
- printf("cmd(%p)", (void *)xs->cmd);
- printf("len(0x%lx)", (long)xs->cmdlen);
- printf("data(%p)", (void *)xs->data);
- printf("len(0x%lx)", (long)xs->datalen);
- printf("res(0x%lx)", (long)xs->resid);
- printf("err(0x%lx)", (long)xs->error);
- printf("bp(%p)", (void *)xs->bp);
- show_scsi_cmd(xs);
-}
-
-void
-show_scsi_cmd(struct scsi_xfer *xs)
-{
- u_char *b = (u_char *) xs->cmd;
- int i = 0;
-
- sc_print_addr(xs->sc_link);
- printf("command: ");
-
- if (!(xs->flags & SCSI_RESET)) {
- while (i < xs->cmdlen) {
- if (i)
- printf(",");
- printf("%x", b[i++]);
- }
- printf("-[%ld bytes]\n", (long)xs->datalen);
- if (xs->datalen)
- show_mem(xs->data, min(64, xs->datalen));
- } else {
- printf("-RESET-\n");
- }
-}
-
-static void
-show_mem(address, num)
- unsigned char *address;
- u_int32_t num;
-{
- u_int32_t y;
- printf("------------------------------");
- for (y = 0; y < num; y += 1) {
- if (!(y % 16))
- printf("\n%03ld: ", (long)y);
- printf("%02x ", *address++);
- }
- printf("\n------------------------------\n");
-}
-#endif /*SCSIDEBUG */
diff --git a/sys/scsi/scsi_cd.h b/sys/scsi/scsi_cd.h
deleted file mode 100644
index 26e366b..0000000
--- a/sys/scsi/scsi_cd.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- *
- * $Id: scsi_cd.h,v 1.10 1997/02/22 09:44:28 peter Exp $
- */
-#ifndef _SCSI_SCSI_CD_H
-#define _SCSI_SCSI_CD_H 1
-
-/*
- * Define two bits always in the same place in byte 2 (flag byte)
- */
-#define CD_RELADDR 0x01
-#define CD_MSF 0x02
-
-/*
- * SCSI command format
- */
-
-struct scsi_pause
-{
- u_char op_code;
- u_char byte2;
- u_char unused[6];
- u_char resume;
- u_char control;
-};
-#define PA_PAUSE 1
-#define PA_RESUME 0
-
-struct scsi_play_msf
-{
- u_char op_code;
- u_char byte2;
- u_char unused;
- u_char start_m;
- u_char start_s;
- u_char start_f;
- u_char end_m;
- u_char end_s;
- u_char end_f;
- u_char control;
-};
-
-struct scsi_play_track
-{
- u_char op_code;
- u_char byte2;
- u_char unused[2];
- u_char start_track;
- u_char start_index;
- u_char unused1;
- u_char end_track;
- u_char end_index;
- u_char control;
-};
-
-struct scsi_play
-{
- u_char op_code;
- u_char byte2;
- u_char blk_addr[4];
- u_char unused;
- u_char xfer_len[2];
- u_char control;
-};
-
-struct scsi_play_big
-{
- u_char op_code;
- u_char byte2; /* same as above */
- u_char blk_addr[4];
- u_char xfer_len[4];
- u_char unused;
- u_char control;
-};
-
-struct scsi_play_rel_big
-{
- u_char op_code;
- u_char byte2; /* same as above */
- u_char blk_addr[4];
- u_char xfer_len[4];
- u_char track;
- u_char control;
-};
-
-struct scsi_read_header
-{
- u_char op_code;
- u_char byte2;
- u_char blk_addr[4];
- u_char unused;
- u_char data_len[2];
- u_char control;
-};
-
-struct scsi_read_subchannel
-{
- u_char op_code;
- u_char byte2;
- u_char byte3;
-#define SRS_SUBQ 0x40
- u_char subchan_format;
- u_char unused[2];
- u_char track;
- u_char data_len[2];
- u_char control;
-};
-
-struct scsi_read_toc
-{
- u_char op_code;
- u_char byte2;
- u_char unused[4];
- u_char from_track;
- u_char data_len[2];
- u_char control;
-};
-
-struct scsi_read_cd_capacity
-{
- u_char op_code;
- u_char byte2;
- u_char addr_3; /* Most Significant */
- u_char addr_2;
- u_char addr_1;
- u_char addr_0; /* Least Significant */
- u_char unused[3];
- u_char control;
-};
-
-/*
- * Opcodes
- */
-
-#define READ_CD_CAPACITY 0x25 /* slightly different from disk */
-#define READ_SUBCHANNEL 0x42 /* cdrom read Subchannel */
-#define READ_TOC 0x43 /* cdrom read TOC */
-#define READ_HEADER 0x44 /* cdrom read header */
-#define PLAY 0x45 /* cdrom play 'play audio' mode */
-#define PLAY_MSF 0x47 /* cdrom play Min,Sec,Frames mode */
-#define PLAY_TRACK 0x48 /* cdrom play track/index mode */
-#define PLAY_TRACK_REL 0x49 /* cdrom play track/index mode */
-#define PAUSE 0x4b /* cdrom pause in 'play audio' mode */
-#define PLAY_BIG 0xa5 /* cdrom pause in 'play audio' mode */
-#define PLAY_TRACK_REL_BIG 0xa9 /* cdrom play track/index mode */
-
-
-
-struct scsi_read_cd_cap_data
-{
- u_char addr_3; /* Most significant */
- u_char addr_2;
- u_char addr_1;
- u_char addr_0; /* Least significant */
- u_char length_3; /* Most significant */
- u_char length_2;
- u_char length_1;
- u_char length_0; /* Least significant */
-};
-
-union cd_pages
-{
- struct audio_page
- {
- u_char page_code;
-#define CD_PAGE_CODE 0x3F
-#define AUDIO_PAGE 0x0e
-#define CD_PAGE_PS 0x80
- u_char param_len;
- u_char flags;
-#define CD_PA_SOTC 0x02
-#define CD_PA_IMMED 0x04
- u_char unused[2];
- u_char format_lba;
-#define CD_PA_FORMAT_LBA 0x0F
-#define CD_PA_APR_VALID 0x80
- u_char lb_per_sec[2];
- struct port_control
- {
- u_char channels;
-#define CHANNEL 0x0F
-#define CHANNEL_0 1
-#define CHANNEL_1 2
-#define CHANNEL_2 4
-#define CHANNEL_3 8
-#define LEFT_CHANNEL CHANNEL_0
-#define RIGHT_CHANNEL CHANNEL_1
- u_char volume;
- } port[4];
-#define LEFT_PORT 0
-#define RIGHT_PORT 1
- }audio;
-};
-
-struct cd_mode_data
-{
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- union cd_pages page;
-};
-#endif /*_SCSI_SCSI_CD_H*/
-
diff --git a/sys/scsi/scsi_changer.h b/sys/scsi/scsi_changer.h
deleted file mode 100644
index be24baf..0000000
--- a/sys/scsi/scsi_changer.h
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
- * All rights reserved.
- *
- * Partially based on an autochanger driver written by Stefan Grefen
- * and on an autochanger driver written by the Systems Programming Group
- * at 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 acknowledgements:
- * This product includes software developed by Jason R. Thorpe
- * for And Communications, http://www.and.com/
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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: scsi_changer.h,v 1.9 1997/02/22 09:44:29 peter Exp $
- */
-
-/*
- * SCSI changer interface description
- */
-
-/*
- * Partially derived from software written by Stefan Grefen
- * (grefen@goofy.zdv.uni-mainz.de soon grefen@convex.com)
- * based on the SCSI System by written Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- */
-
-#ifndef _SCSI_SCSI_CHANGER_H
-#define _SCSI_SCSI_CHANGER_H 1
-
-/*
- * SCSI command format
- */
-
-/*
- * Exchange the medium in the source element with the medium
- * located at the destination element.
- */
-struct scsi_exchange_medium {
- u_int8_t opcode;
-#define EXCHANGE_MEDIUM 0xa6
- u_int8_t byte2;
- u_int8_t tea[2]; /* transport element address */
- u_int8_t src[2]; /* source address */
- u_int8_t fdst[2]; /* first destination address */
- u_int8_t sdst[2]; /* second destination address */
- u_int8_t flags;
-#define EXCHANGE_MEDIUM_INV1 0x01
-#define EXCHANGE_MEDIUM_INV2 0x02
- u_int8_t control;
-};
-
-/*
- * Cause the medium changer to check all elements for medium and any
- * other status relevant to the element.
- */
-struct scsi_initialize_elememt_status {
- u_int8_t opcode;
-#define INITIALIZE_ELEMENT_STATUS 0x07
- u_int8_t byte2;
- u_int8_t reserved[3];
- u_int8_t control;
-};
-
-/*
- * Request the changer to move a unit of media from the source element
- * to the destination element.
- */
-struct scsi_move_medium {
- u_int8_t opcode;
-#define MOVE_MEDIUM 0xa5
- u_int8_t byte2;
- u_int8_t tea[2]; /* transport element address */
- u_int8_t src[2]; /* source element address */
- u_int8_t dst[2]; /* destination element address */
- u_int8_t reserved[2];
- u_int8_t flags;
-#define MOVE_MEDIUM_INVERT 0x01
- u_int8_t control;
-};
-
-/*
- * Position the specified transport element (picker) in front of
- * the destination element specified.
- */
-struct scsi_position_to_element {
- u_int8_t opcode;
-#define POSITION_TO_ELEMENT 0x2b
- u_int8_t byte2;
- u_int8_t tea[2]; /* transport element address */
- u_int8_t dst[2]; /* destination element address */
- u_int8_t reserved[2];
- u_int8_t flags;
-#define POSITION_TO_ELEMENT_INVERT 0x01
- u_int8_t control;
-};
-
-/*
- * Request that the changer report the status of its internal elements.
- */
-struct scsi_read_element_status {
- u_int8_t opcode;
-#define READ_ELEMENT_STATUS 0xb8
- u_int8_t byte2;
-#define READ_ELEMENT_STATUS_VOLTAG 0x10 /* report volume tag info */
- /* ...next 4 bits are an element type code... */
- u_int8_t sea[2]; /* starting element address */
- u_int8_t count[2]; /* number of elements */
- u_int8_t reserved0;
- u_int8_t len[3]; /* length of data buffer */
- u_int8_t reserved1;
- u_int8_t control;
-};
-
-struct scsi_request_volume_element_address {
- u_int8_t opcode;
-#define REQUEST_VOLUME_ELEMENT_ADDRESS 0xb5
- u_int8_t byte2;
-#define REQUEST_VOLUME_ELEMENT_ADDRESS_VOLTAG 0x10
- /* ...next 4 bits are an element type code... */
- u_int8_t eaddr[2]; /* element address */
- u_int8_t count[2]; /* number of elements */
- u_int8_t reserved0;
- u_int8_t len[3]; /* length of data buffer */
- u_int8_t reserved1;
- u_int8_t control;
-};
-
-/* XXX scsi_release */
-
-/*
- * Data returned by READ ELEMENT STATUS consists of an 8-byte header
- * followed by one or more read_element_status_pages.
- */
-struct read_element_status_header {
- u_int8_t fear[2]; /* first element address reported */
- u_int8_t count[2]; /* number of elements available */
- u_int8_t reserved;
- u_int8_t nbytes[3]; /* byte count of all pages */
-};
-
-struct read_element_status_page_header {
- u_int8_t type; /* element type code; see type codes below */
- u_int8_t flags;
-#define READ_ELEMENT_STATUS_AVOLTAG 0x40
-#define READ_ELEMENT_STATUS_PVOLTAG 0x80
- u_int8_t edl[2]; /* element descriptor length */
- u_int8_t reserved;
- u_int8_t nbytes[3]; /* byte count of all descriptors */
-};
-
-struct read_element_status_descriptor {
- u_int8_t eaddr[2]; /* element address */
- u_int8_t flags1;
-
-#define READ_ELEMENT_STATUS_FULL 0x01
-#define READ_ELEMENT_STATUS_IMPEXP 0x02
-#define READ_ELEMENT_STATUS_EXCEPT 0x04
-#define READ_ELEMENT_STATUS_ACCESS 0x08
-#define READ_ELEMENT_STATUS_EXENAB 0x10
-#define READ_ELEMENT_STATUS_INENAB 0x20
-
-#define READ_ELEMENT_STATUS_MT_MASK1 0x05
-#define READ_ELEMENT_STATUS_ST_MASK1 0x0c
-#define READ_ELEMENT_STATUS_IE_MASK1 0x3f
-#define READ_ELEMENT_STATUS_DT_MASK1 0x0c
-
- u_int8_t reserved0;
- u_int8_t sense_code;
- u_int8_t sense_qual;
-
- /*
- * dt_scsi_flags and dt_scsi_addr are valid only on data transport
- * elements. These bytes are undefined for all other element types.
- */
- u_int8_t dt_scsi_flags;
-
-#define READ_ELEMENT_STATUS_DT_LUNMASK 0x07
-#define READ_ELEMENT_STATUS_DT_LUVALID 0x10
-#define READ_ELEMENT_STATUS_DT_IDVALID 0x20
-#define READ_ELEMENT_STATUS_DT_NOTBUS 0x80
-
- u_int8_t dt_scsi_addr;
-
- u_int8_t reserved1;
-
- u_int8_t flags2;
-#define READ_ELEMENT_STATUS_INVERT 0x40
-#define READ_ELEMENT_STATUS_SVALID 0x80
- u_int8_t ssea[2]; /* source storage element address */
-
- /*
- * bytes 12-47: Primary volume tag information.
- * (field omitted if PVOLTAG = 0)
- *
- * bytes 48-83: Alternate volume tag information.
- * (field omitted if AVOLTAG = 0)
- *
- * bytes 84-87: Reserved (moved up if either of the above fields
- * are omitted)
- *
- * bytes 88-end: Vendor-specific: (moved up if either of the
- * above fields are missing)
- */
-};
-
-/* XXX add data returned by REQUEST VOLUME ELEMENT ADDRESS */
-
-/* Element type codes */
-#define ELEMENT_TYPE_MASK 0x0f /* Note: these aren't bits */
-#define ELEMENT_TYPE_ALL 0x00
-#define ELEMENT_TYPE_MT 0x01
-#define ELEMENT_TYPE_ST 0x02
-#define ELEMENT_TYPE_IE 0x03
-#define ELEMENT_TYPE_DT 0x04
-
-/*
- * XXX The following definitions should be common to all SCSI device types.
- */
-#define PGCODE_MASK 0x3f /* valid page number bits in pg_code */
-#define PGCODE_PS 0x80 /* indicates page is savable */
-
-/*
- * Device capabilities page.
- *
- * This page defines characteristics of the elemenet types in the
- * medium changer device.
- *
- * Note in the definitions below, the following abbreviations are
- * used:
- * MT Medium transport element (picker)
- * ST Storage transport element (slot)
- * IE Import/export element (portal)
- * DT Data tranfer element (tape/disk drive)
- */
-struct page_device_capabilities {
- u_int8_t pg_code; /* page code (0x1f) */
- u_int8_t pg_length; /* page length (0x12) */
-
- /*
- * The STOR_xx bits indicate that an element of a given
- * type may provide independent storage for a unit of
- * media. The top four bits of this value are reserved.
- */
- u_int8_t stor;
-#define STOR_MT 0x01
-#define STOR_ST 0x02
-#define STOR_IE 0x04
-#define STOR_DT 0x08
-
- u_int8_t reserved0;
-
- /*
- * The MOVE_TO_yy bits indicate the changer supports
- * moving a unit of medium from an element of a given type to an
- * element of type yy. This is used to determine if a given
- * MOVE MEDIUM command is legal. The top four bits of each
- * of these values are reserved.
- */
- u_int8_t move_from_mt;
- u_int8_t move_from_st;
- u_int8_t move_from_ie;
- u_int8_t move_from_dt;
-#define MOVE_TO_MT 0x01
-#define MOVE_TO_ST 0x02
-#define MOVE_TO_IE 0x04
-#define MOVE_TO_DT 0x08
-
- u_int8_t reserved1[2];
-
- /*
- * Similar to above, but for EXCHANGE MEDIUM.
- */
- u_int8_t exchange_with_mt;
- u_int8_t exchange_with_st;
- u_int8_t exchange_with_ie;
- u_int8_t exchange_with_dt;
-#define EXCHANGE_WITH_MT 0x01
-#define EXCHANGE_WITH_ST 0x02
-#define EXCHANGE_WITH_IE 0x04
-#define EXCHANGE_WITH_DT 0x08
-};
-
-/*
- * Medium changer elemement address assignment page.
- *
- * Some of these fields can be a little confusing, so an explanation
- * is in order.
- *
- * Each component within a a medium changer apparatus is called an
- * "element".
- *
- * The "medium transport element address" is the address of the first
- * picker (robotic arm). "Number of medium transport elements" tells
- * us how many pickers exist in the changer.
- *
- * The "first storage element address" is the address of the first
- * slot in the tape or disk magazine. "Number of storage elements" tells
- * us how many slots exist in the changer.
- *
- * The "first import/export element address" is the address of the first
- * medium portal accessible both by the medium changer and an outside
- * human operator. This is where the changer might deposit tapes destined
- * for some vault. The "number of import/export elements" tells us
- * not many of these portals exist in the changer. NOTE: this number may
- * be 0.
- *
- * The "first data transfer element address" is the address of the first
- * tape or disk drive in the changer. "Number of data transfer elements"
- * tells us how many drives exist in the changer.
- */
-struct page_element_address_assignment {
- u_int8_t pg_code; /* page code (0x1d) */
- u_int8_t pg_length; /* page length (0x12) */
-
- /* Medium transport element address */
- u_int8_t mtea[2];
-
- /* Number of medium transport elements */
- u_int8_t nmte[2];
-
- /* First storage element address */
- u_int8_t fsea[2];
-
- /* Number of storage elements */
- u_int8_t nse[2];
-
- /* First import/export element address */
- u_int8_t fieea[2];
-
- /* Number of import/export elements */
- u_int8_t niee[2];
-
- /* First data transfer element address */
- u_int8_t fdtea[2];
-
- /* Number of data trafer elements */
- u_int8_t ndte[2];
-
- u_int8_t reserved[2];
-};
-
-/*
- * Transport geometry parameters page.
- *
- * Defines whether each medium transport element is a member of a set of
- * elements that share a common robotics subsystem and whether the element
- * is capable of media rotation. One transport geometry descriptor is
- * transferred for each medium transport element, beginning with the first
- * medium transport element (other than the default transport element address
- * of 0).
- */
-struct page_transport_geometry_parameters {
- u_int8_t pg_code; /* page code (0x1e) */
- u_int8_t pg_length; /* page length; variable */
-
- /* Transport geometry descriptor(s) are here. */
-
- u_int8_t misc;
-#define CAN_ROTATE 0x01
-
- /* Member number in transport element set. */
- u_int8_t member;
-};
-
-#endif /* _SCSI_SCSI_CHANGER_H */
diff --git a/sys/scsi/scsi_debug.h b/sys/scsi/scsi_debug.h
deleted file mode 100644
index a362f5d..0000000
--- a/sys/scsi/scsi_debug.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Use
- * options SCSIDEBUG
- *
- * in the kernel config file to get these macros into effect.
- */
-
-/*
- * Written by Julian Elischer (julian@tfs.com)
- *
- * $Id$
- */
-#ifndef _SCSI_SCSI_DEBUG_H
-#define _SCSI_SCSI_DEBUG_H 1
-
-/*
- * These are the new debug bits. (Sat Oct 2 12:46:46 WST 1993)
- * the following DEBUG bits are defined to exist in the flags word of
- * the scsi_link structure.
- */
-#define SDEV_DB1 0x10 /* scsi commands, errors, data */
-#define SDEV_DB2 0x20 /* routine flow tracking */
-#define SDEV_DB3 0x40 /* internal to routine flows */
-#define SDEV_DB4 0x80 /* level 4 debugging for this dev */
-
-/* target and LUN we want to debug */
-#define DEBUGTARG 9 /*9 = dissable*/
-#define DEBUGLUN 0
-#define DEBUGLEVEL (SDEV_DB1|SDEV_DB2)
-
-/*
- * This is the usual debug macro for use with the above bits
- */
-#ifdef SCSIDEBUG
-#define SC_DEBUG(sc_link,Level,Printstuff) \
- if((sc_link)->flags & (Level)) \
- { \
- printf("%s%d(%s%d:%d:%d): ", \
- sc_link->device->name, \
- sc_link->dev_unit, \
- sc_link->adapter->name, \
- sc_link->adapter_unit, \
- sc_link->target, \
- sc_link->lun); \
- printf Printstuff; \
- }
-#define SC_DEBUGN(sc_link,Level,Printstuff) \
- if((sc_link)->flags & (Level)) \
- { \
- printf Printstuff; \
- }
-#else
-#define SC_DEBUG(A,B,C) /* not included */
-#define SC_DEBUGN(A,B,C) /* not included */
-#endif
-
-#endif /*_SCSI_SCSI_DEBUG_H*/
-/* END OF FILE */
-
diff --git a/sys/scsi/scsi_disk.h b/sys/scsi/scsi_disk.h
deleted file mode 100644
index a33e4e7..0000000
--- a/sys/scsi/scsi_disk.h
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * SCSI interface description
- */
-
-/*
- * Some lines of this file come from a file of the name "scsi.h"
- * distributed by OSF as part of mach2.5,
- * so the following disclaimer has been kept.
- *
- * Copyright 1990 by Open Software Foundation,
- * Grenoble, FRANCE
- *
- * All Rights Reserved
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appears in all copies and
- * that both the copyright notice and this permission notice appear in
- * supporting documentation, and that the name of OSF or Open Software
- * Foundation not be used in advertising or publicity pertaining to
- * distribution of the software without specific, written prior
- * permission.
- *
- * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
- * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
- * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * Largely written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- *
- * $Id$
- */
-
-/*
- * SCSI command format
- */
-
-#ifndef _SCSI_SCSI_DISK_H
-#define _SCSI_SCSI_DISK_H 1
-
-struct scsi_reassign_blocks
-{
- u_char op_code;
- u_char byte2;
- u_char unused[3];
- u_char control;
-};
-
-struct scsi_rw
-{
- u_char op_code;
- u_char addr_2; /* Most significant */
-#define SRW_TOPADDR 0x1F /* only 5 bits here */
- u_char addr_1;
- u_char addr_0; /* least significant */
- u_char length;
- u_char control;
-};
-
-struct scsi_rw_big
-{
- u_char op_code;
- u_char byte2;
-#define SRWB_RELADDR 0x01
- u_char addr_3; /* Most significant */
- u_char addr_2;
- u_char addr_1;
- u_char addr_0; /* least significant */
- u_char reserved;
- u_char length2;
- u_char length1;
- u_char control;
-};
-
-struct scsi_read_capacity
-{
- u_char op_code;
- u_char byte2;
- u_char addr_3; /* Most Significant */
- u_char addr_2;
- u_char addr_1;
- u_char addr_0; /* Least Significant */
- u_char unused[3];
- u_char control;
-};
-
-struct scsi_start_stop
-{
- u_char op_code;
- u_char byte2;
- u_char unused[2];
- u_char how;
-#define SSS_START 0x01
-#define SSS_LOEJ 0x02
- u_char control;
-};
-
-
-
-/*
- * Opcodes
- */
-
-#define REASSIGN_BLOCKS 0x07
-#define READ_COMMAND 0x08
-#define WRITE_COMMAND 0x0a
-#define MODE_SELECT 0x15
-#define MODE_SENSE 0x1a
-#define START_STOP 0x1b
-#define PREVENT_ALLOW 0x1e
-#define READ_CAPACITY 0x25
-#define READ_BIG 0x28
-#define WRITE_BIG 0x2a
-
-
-
-struct scsi_read_cap_data
-{
- u_char addr_3; /* Most significant */
- u_char addr_2;
- u_char addr_1;
- u_char addr_0; /* Least significant */
- u_char length_3; /* Most significant */
- u_char length_2;
- u_char length_1;
- u_char length_0; /* Least significant */
-};
-
-struct scsi_reassign_blocks_data
-{
- u_char reserved[2];
- u_char length_msb;
- u_char length_lsb;
- struct
- {
- u_char dlbaddr_3; /* defect logical block address (MSB) */
- u_char dlbaddr_2;
- u_char dlbaddr_1;
- u_char dlbaddr_0; /* defect logical block address (LSB) */
- } defect_descriptor[1];
-};
-
-union disk_pages /* this is the structure copied from osf */
-{
- struct page_disk_format {
- u_char pg_code; /* page code (should be 3) */
-#define DISK_PGCODE 0x3F /* only 6 bits valid */
- u_char pg_length; /* page length (should be 0x16) */
- u_char trk_z_1; /* tracks per zone (MSB) */
- u_char trk_z_0; /* tracks per zone (LSB) */
- u_char alt_sec_1; /* alternate sectors per zone (MSB) */
- u_char alt_sec_0; /* alternate sectors per zone (LSB) */
- u_char alt_trk_z_1; /* alternate tracks per zone (MSB) */
- u_char alt_trk_z_0; /* alternate tracks per zone (LSB) */
- u_char alt_trk_v_1; /* alternate tracks per volume (MSB) */
- u_char alt_trk_v_0; /* alternate tracks per volume (LSB) */
- u_char ph_sec_t_1; /* physical sectors per track (MSB) */
- u_char ph_sec_t_0; /* physical sectors per track (LSB) */
- u_char bytes_s_1; /* bytes per sector (MSB) */
- u_char bytes_s_0; /* bytes per sector (LSB) */
- u_char interleave_1;/* interleave (MSB) */
- u_char interleave_0;/* interleave (LSB) */
- u_char trk_skew_1; /* track skew factor (MSB) */
- u_char trk_skew_0; /* track skew factor (LSB) */
- u_char cyl_skew_1; /* cylinder skew (MSB) */
- u_char cyl_skew_0; /* cylinder skew (LSB) */
- u_char flags; /* various */
-#define DISK_FMT_SURF 0x10
-#define DISK_FMT_RMB 0x20
-#define DISK_FMT_HSEC 0x40
-#define DISK_FMT_SSEC 0x80
- u_char reserved21;
- u_char reserved22;
- u_char reserved23;
- } disk_format;
- struct page_rigid_geometry {
- u_char pg_code; /* page code (should be 4) */
- u_char pg_length; /* page length (should be 0x16) */
- u_char ncyl_2; /* number of cylinders (MSB) */
- u_char ncyl_1; /* number of cylinders */
- u_char ncyl_0; /* number of cylinders (LSB) */
- u_char nheads; /* number of heads */
- u_char st_cyl_wp_2; /* starting cyl., write precomp (MSB) */
- u_char st_cyl_wp_1; /* starting cyl., write precomp */
- u_char st_cyl_wp_0; /* starting cyl., write precomp (LSB) */
- u_char st_cyl_rwc_2;/* starting cyl., red. write cur (MSB)*/
- u_char st_cyl_rwc_1;/* starting cyl., red. write cur */
- u_char st_cyl_rwc_0;/* starting cyl., red. write cur (LSB)*/
- u_char driv_step_1; /* drive step rate (MSB) */
- u_char driv_step_0; /* drive step rate (LSB) */
- u_char land_zone_2; /* landing zone cylinder (MSB) */
- u_char land_zone_1; /* landing zone cylinder */
- u_char land_zone_0; /* landing zone cylinder (LSB) */
- u_char rpl; /* rotational position locking (2 bits) */
- u_char rot_offset; /* rotational offset */
- u_char reserved19;
- u_char medium_rot_rate_1; /* medium rotation rate (RPM) (MSB) */
- u_char medium_rot_rate_0; /* medium rotation rate (RPM) (LSB) */
- u_char reserved22;
- u_char reserved23;
- } rigid_geometry;
-} ;
-#endif /* _SCSI_SCSI_DISK_H*/
diff --git a/sys/scsi/scsi_driver.c b/sys/scsi/scsi_driver.c
deleted file mode 100644
index 69f2278..0000000
--- a/sys/scsi/scsi_driver.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * 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: scsi_driver.c,v 1.26 1997/09/02 20:06:34 bde Exp $
- *
- */
-
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-#define GETUNIT(DEVICE, DEV) \
- ((DEVICE)->getunit) ? (*(DEVICE)->getunit)((DEV)) \
- : (minor((DEV)) & ~SCSI_CONTROL_MASK)
-
-/* scsi_device_attach: Attach a SCSI device. This routine will
- * print out the device address, what it is, then call the type
- * attach function and when that returns print a newline. If the
- * type attach will make LOT's of noise it should print a leading
- * newline and then the address using sc_print_addr. See "sd.c".
- */
-int scsi_device_attach(struct scsi_link *sc_link)
-{
- errval errcode;
- dev_t dev;
- struct scsi_device *device = sc_link->device;
-
- if (bootverbose)
- sc_link->flags |= SDEV_BOOTVERBOSE;
-
- SC_DEBUG(sc_link, SDEV_DB2,
- ("%s%dattach: ", device->name, sc_link->dev_unit));
-
- /* Print _sane_ probe info! */
- printf("%s%d at scbus%d target %d lun %d\n",
- sc_link->device->name, sc_link->dev_unit,
- sc_link->scsibus, sc_link->target, sc_link->lun);
-#ifndef SCSIDEBUG
- scsi_print_info(sc_link);
-#endif
-
- printf("%s%d: %s ", device->name, sc_link->dev_unit, device->desc);
- /*
- * XXX some SCSI adapter drivers print out things while the
- * device-specific attach routine is running. The result is
- * something of a mess. This hack at least keeps it so each
- * line will begin with foodev0:.
- */
- sc_print_init();
-
- 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) ? (*(device->attach))(sc_link) : 0;
-
- printf("\n");
- sc_print_finish();
-
- if (errcode == 0)
- sc_link->flags |= device->link_flags;
-
- return errcode;
-}
-
-int
-scsi_open(dev_t dev, int flags, int fmt, struct proc *p,
-struct scsi_device *device)
-{
- errval errcode;
- u_int32_t unit;
- struct scsi_link *sc_link;
-
- if (device == 0)
- return ENXIO;
-
- unit = GETUNIT(device, dev);
- sc_link = SCSI_LINK(device, unit);
-
- /*
- * Check the unit is legal
- */
- if (sc_link == 0 || (sc_link->sd == 0 && !(sc_link->flags & SDEV_UK)))
- return ENXIO;
-
- /* If it is a "once only" device that is already open return EBUSY.
- */
- if ((sc_link->flags & SDEV_ONCE_ONLY) && (sc_link->flags & SDEV_IS_OPEN))
- return EBUSY;
-
- /* For the control device (user ioctl's only) don't call the open
- * entry.
- */
- if (SCSI_CONTROL(dev) || (device->dev_open == 0))
- {
- scsi_test_unit_ready(sc_link, SCSI_SILENT);
- errcode = 0;
- }
- else
- errcode = (*device->dev_open)(dev, flags, fmt, p, sc_link);
-
- if (!errcode ) sc_link->flags |= SDEV_IS_OPEN;
-
- SC_DEBUG(sc_link, SDEV_DB1, ("%sopen: dev=0x%lx (unit %lu) result %d\n",
- device->name, (u_long)dev, (u_long)unit, errcode));
-
- return errcode;
-}
-
-int
-scsi_close(dev_t dev, int flags, int fmt, struct proc *p,
-struct scsi_device *device)
-{
- errval errcode;
- struct scsi_link *sc_link = SCSI_LINK(device, GETUNIT(device, dev));
-
- SC_DEBUG(sc_link, SDEV_DB1, ("%sclose: Closing device\n", device->name));
-
- if (SCSI_CONTROL(dev) || (device->dev_close == 0))
- errcode = 0;
- else
- errcode = (*device->dev_close)(dev, flags, fmt, p, sc_link);
-
- sc_link->flags &= ~SDEV_IS_OPEN;
-
- return errcode;
-}
-
-int
-scsi_ioctl(dev_t dev, u_int32_t cmd, caddr_t arg, int flags, struct proc *p,
-struct scsi_device *device)
-{
- errval errcode;
- struct scsi_link *sc_link = SCSI_LINK(device, GETUNIT(device, dev));
-
- if (SCSI_CONTROL(dev) || (device->dev_ioctl == 0))
- errcode = scsi_do_ioctl(dev, cmd, arg, flags, p, sc_link);
- else
- errcode = (*device->dev_ioctl)(dev, cmd, arg, flags, p, sc_link);
-
- return errcode;
-}
-
-void
-scsi_minphys(struct buf *bp, struct scsi_device *device)
-{
- struct scsi_link *sc_link = SCSI_LINK(device, GETUNIT(device, bp->b_dev));
- (*sc_link->adapter->scsi_minphys)(bp);
-}
-
-void
-scsi_strategy(struct buf *bp, struct scsi_device *device)
-{
- u_int32_t unit = GETUNIT(device, bp->b_dev);
- struct scsi_link *sc_link = SCSI_LINK(device, unit);
-
- SC_DEBUG(sc_link, SDEV_DB2, ("\n%sstrategy ", device->name));
- SC_DEBUG(sc_link, SDEV_DB1, ("%ld bytes @ blk%ld\n",
- bp->b_bcount, (long)bp->b_blkno));
-
- if (SCSI_CONTROL(bp->b_dev) || (device->dev_strategy == 0))
- {
- bp->b_resid = bp->b_bcount;
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- biodone(bp);
- }
- else
- {
- bp->b_resid = 0;
- bp->b_error = 0;
-
- if (bp->b_bcount == 0)
- biodone(bp);
- else
- {
- (*sc_link->adapter->scsi_minphys)(bp);
- (*device->dev_strategy)(bp, sc_link);
- }
- }
-}
-
-int scsi_device_lock(struct scsi_link *sc_link)
-{
- int error;
- while (sc_link->flags & SDEV_XLOCK) {
- sc_link->flags |= SDEV_WANT;
- error = tsleep(&sc_link->flags, PRIBIO | PCATCH, "sdevlk",0);
- if (error)
- return error;
- }
- sc_link->flags |= SDEV_XLOCK;
- return 0;
-}
-
-void scsi_device_unlock(struct scsi_link *sc_link)
-{
- sc_link->flags &= ~SDEV_XLOCK;
- if (sc_link->flags & SDEV_WANT) {
- sc_link->flags &= ~SDEV_WANT;
- wakeup(&sc_link->flags);
- }
-}
diff --git a/sys/scsi/scsi_driver.h b/sys/scsi/scsi_driver.h
deleted file mode 100644
index 50f4851..0000000
--- a/sys/scsi/scsi_driver.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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: scsi_driver.h,v 1.12 1997/06/25 19:07:42 tegge Exp $
- *
- */
-#ifndef _SCSI__DRIVER_H_
-#define _SCSI__DRIVER_H_
-
-#ifdef KERNEL
-
-struct scsi_link;
-struct scsi_device;
-struct buf;
-struct proc;
-
-int scsi_device_attach __P((struct scsi_link *));
-int scsi_device_lock __P((struct scsi_link *));
-void scsi_device_unlock __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_t, 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 *));
-
-#endif /* KERNEL */
-
-#endif /* _SCSI__DRIVER_H_ */
diff --git a/sys/scsi/scsi_generic.h b/sys/scsi/scsi_generic.h
deleted file mode 100644
index 2cd6f6c..0000000
--- a/sys/scsi/scsi_generic.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Contributed by HD Associates (contact: dufault@hda.com)
- * Copyright (c) 1992, 1993 HD Associates
- *
- * Berkeley style copyright. I've just snarfed it out of stdio.h:
- *
- * 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: @(#)stdio.h 5.17 (Berkeley) 6/3/91
- * $Id$
- */
-
-/* generic SCSI header file. We use the same minor number format
- * as on SGI except that the flag bits aren't available because they
- * are used as the board index.
- *
- * The minor number format is:
- * FF UUU III (FFUU UIII)
- *
- * Where:
- * FF is the board index
- * UUU are the LUN
- * III is the SCSI ID (controller)
- */
-
-#ifndef _SCSI_GENERIC_H_
-#define _SCSI_GENERIC_H_
-
-#define G_SCSI_FLAG(DEV) (((DEV) & 0xC0) >> 6)
-#define G_SCSI_UNIT(DEV) G_SCSI_FLAG(DEV)
-#define G_SCSI_LUN(DEV) (((DEV) & 0x38) >> 3)
-#define G_SCSI_ID(DEV) ((DEV) & 0x7)
-
-#define G_SCSI_MINOR(FLAG, LUN, ID) \
- (((FLAG) << 6) | ((LUN) << 3) | (ID))
-
-#endif /* _SCSI_GENERIC_H_ */
diff --git a/sys/scsi/scsi_ioctl.c b/sys/scsi/scsi_ioctl.c
deleted file mode 100644
index c63de3a..0000000
--- a/sys/scsi/scsi_ioctl.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * Copyright (C) 1992, 1993, 1994, 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.
- *End copyright
- *
- * $Id: scsi_ioctl.c,v 1.31 1998/06/07 17:12:49 dfr Exp $
- *
- *
- */
-
-#include "opt_bounce.h"
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
-
-#define b_screq b_driver1 /* a patch in buf.h */
-#define b_sc_link b_driver2 /* a patch in buf.h */
-
-#include <sys/fcntl.h>
-#include <sys/proc.h>
-#include <sys/uio.h>
-
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <sys/scsiio.h>
-
-static void scsierr(struct buf *, int); /* XXX ??? */
-
-/*
- * We let the user interpret his own sense in the generic scsi world.
- * This routine is called at interrupt time if the SCSI_USER bit was set
- * in the flags passed to scsi_scsi_cmd(). No other completion processing
- * takes place, even if we are running over another device driver.
- * The lower level routines that call us here, will free the xs and restart
- * the device's queue if such exists.
- */
-#ifndef min
-#define min(A,B) ((A<B) ? A : B )
-#endif
-
-void scsi_user_done(xs)
-struct scsi_xfer *xs;
-{
-
- struct buf *bp;
- scsireq_t *screq;
-
- bp = xs->bp;
- if(!bp) { /* ALL user requests must have a buf */
- sc_print_addr(xs->sc_link);
- printf("User command with no buf\n");
- return ;
- }
- screq = bp->b_screq;
- if (!screq) { /* Is it one of ours? (the SCSI_USER bit says it is) */
- sc_print_addr(xs->sc_link);
- printf("User command with no request\n");
- return ;
- }
-
- SC_DEBUG(xs->sc_link,SDEV_DB2,("user-done\n"));
- screq->retsts = 0;
- screq->status = xs->status;
- switch((int)xs->error) {
- case XS_NOERROR:
- SC_DEBUG(xs->sc_link,SDEV_DB3,("no error\n"));
- if (xs->flags & SCSI_RESID_VALID)
- screq->datalen_used = xs->datalen - xs->resid;
- else
- screq->datalen_used = xs->datalen;
- screq->retsts = SCCMD_OK;
- break;
-
- case XS_SENSE:
- SC_DEBUG(xs->sc_link,SDEV_DB3,("have sense\n"));
- screq->senselen_used = min(sizeof(xs->sense),SENSEBUFLEN);
- bcopy(&xs->sense,screq->sense,screq->senselen);
- screq->retsts = SCCMD_SENSE;
- break;
-
- case XS_DRIVER_STUFFUP:
- sc_print_addr(xs->sc_link);
- printf("host adapter code inconsistency\n");
- screq->retsts = SCCMD_UNKNOWN;
- break;
-
- case XS_TIMEOUT:
- SC_DEBUG(xs->sc_link,SDEV_DB3,("timeout\n"));
- screq->retsts = SCCMD_TIMEOUT;
- break;
-
- case XS_BUSY:
- SC_DEBUG(xs->sc_link,SDEV_DB3,("busy\n"));
- screq->retsts = SCCMD_BUSY;
- break;
-
- default:
- sc_print_addr(xs->sc_link);
- printf("unknown error category from host adapter code\n");
- screq->retsts = SCCMD_UNKNOWN;
- break;
- }
- biodone(bp); /* we're waiting on it in scsistrategy() */
- return; /* it'll free the xs and restart any queue */
-}
-
-
-/* Pseudo strategy function
- * Called by scsi_do_ioctl() via physio/physstrat if there is to
- * be data transfered, and directly if there is no data transfer.
- *
- * Can't be used with block devices or raw_read/raw_write directly
- * from the cdevsw/bdevsw tables because they couldn't have added
- * the screq structure. [JRE]
- */
-static void
-scsistrategy(struct buf *bp)
-{
- errval err;
- struct scsi_link *sc_link = bp->b_sc_link;
- scsireq_t *screq;
- u_int32_t flags = 0;
- int s;
-
-
- if(!sc_link) {
- printf("user_strat: No link pointer\n");
- scsierr(bp,EINVAL);
- return;
- }
- SC_DEBUG(sc_link,SDEV_DB2,("user_strategy\n"));
- screq = bp->b_screq;
- if(!screq) {
- sc_print_addr(sc_link);
- printf("No request block\n");
- scsierr(bp,EINVAL);
- return;
- }
-
- /* We're in trouble if physio tried to break up the
- * transfer:
- */
- if (bp->b_bcount != screq->datalen) {
- sc_print_addr(sc_link);
- printf("physio split the request.. cannot proceed\n");
- scsierr(bp, EIO);
- return;
- }
-
- if (screq->timeout == 0) {
- scsierr(bp, EINVAL);
- return;
- }
-
- if (screq->cmdlen > sizeof(struct scsi_generic)) {
- sc_print_addr(sc_link);
- printf("cmdlen too big ");
- scsierr(bp, EFAULT);
- return;
- }
-
-
- if (screq->flags & SCCMD_READ)
- flags |= SCSI_DATA_IN;
-
- if (screq->flags & SCCMD_WRITE)
- flags |= SCSI_DATA_OUT;
-
- if (screq->flags & SCCMD_TARGET)
- flags |= SCSI_TARGET;
-
- if (screq->flags & SCCMD_ESCAPE)
- flags |= SCSI_ESCAPE;
-
-#ifdef BOUNCE_BUFFERS
- if (sc_link->flags & SDEV_BOUNCE)
- vm_bounce_alloc(bp);
-#endif
-
- err = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *)screq->cmd,
- screq->cmdlen,
- (u_char *)bp->b_data,
- screq->datalen,
- 0, /* user must do the retries *//* ignored */
- screq->timeout,
- bp,
- flags | SCSI_USER);
-
-
-
- /*because there is a bp, scsi_scsi_cmd will return immediatly*/
- if (err)
- {
- scsierr(bp, err);
- return;
- }
- SC_DEBUG(sc_link,SDEV_DB3,("about to sleep\n"));
- s = splbio();
- while(!(bp->b_flags & B_DONE))
- {
- tsleep((caddr_t)bp, PRIBIO, "scsistrat", 0);
- }
- splx(s);
- SC_DEBUG(sc_link,SDEV_DB3,("back from sleep\n"));
- return;
-}
-
-/*
- * Something (e.g. another driver) has called us
- * with an sc_link for a target/lun/adapter, and a scsi
- * specific ioctl to perform, better try.
- * If user-level type command, we must still be running
- * in the context of the calling process
- */
-errval scsi_do_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flags,
-struct proc *p, struct scsi_link *sc_link)
-{
- errval ret = 0;
-
- /* If we can't write the device we can't permit much:
- */
-
- if (cmd != SCIOCIDENTIFY && cmd != SCIOCGETDEVINFO&& !(flags & FWRITE))
- return EACCES;
-
- SC_DEBUG(sc_link,SDEV_DB2, ("scsi_do_ioctl(0x%lx)\n", cmd));
- switch(cmd)
- {
- case SCIOCCOMMAND:
- {
- /*
- * You won't believe this, but the arg copied in
- * from the user space, is on the kernel stack
- * for this process, so we can't write
- * to it at interrupt time..
- * we need to copy it in and out!
- * Make a static copy using malloc!
- */
- scsireq_t *screq2 = (scsireq_t *)addr;
- scsireq_t *screq = (scsireq_t *)addr;
- int rwflag = (screq->flags & SCCMD_READ) ? B_READ : B_WRITE;
- struct buf *bp;
- caddr_t d_addr;
- int len;
-
-#if 0 /* XXX dufault@hda.com: This looks too rev dependent. Do it always? */
- if((unsigned int)screq < (unsigned int)KERNBASE)
-#endif
- {
- screq = malloc(sizeof(scsireq_t),M_TEMP,M_WAITOK);
- bcopy(screq2,screq,sizeof(scsireq_t));
- }
- bp = malloc(sizeof (struct buf),M_TEMP,M_WAITOK);
- bzero(bp,sizeof(struct buf));
- d_addr = screq->databuf;
- bp->b_bcount = len = screq->datalen;
- bp->b_screq = screq;
- bp->b_sc_link = sc_link;
- if (len) {
- struct uio auio;
- struct iovec aiov;
- long cnt;
-
- aiov.iov_base = d_addr;
- aiov.iov_len = len;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
-
- auio.uio_resid = len;
- if (auio.uio_resid < 0)
- return (EINVAL);
-
- auio.uio_rw = (rwflag == B_READ) ? UIO_READ : UIO_WRITE;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_procp = curproc;
- cnt = len;
- ret = physio(scsistrategy, bp, dev, rwflag,
- minphys, &auio);
- } else {
- /* if no data, no need to translate it.. */
- bp->b_data = 0;
- bp->b_dev = dev;
- bp->b_flags |= B_BUSY;
-
- scsistrategy(bp);
- ret = bp->b_error;
- }
- free(bp,M_TEMP);
-#if 0 /* XXX dufault@hda.com: This looks too rev dependent. Do it always? */
- if((unsigned int)screq2 < (unsigned int)KERNBASE)
-#endif
- {
- bcopy(screq,screq2,sizeof(scsireq_t));
- free(screq,M_TEMP);
- }
- break;
- }
- case SCIOCDEBUG:
- {
- int level = *((int *)addr);
- SC_DEBUG(sc_link,SDEV_DB3,("debug set to %d\n",level));
- sc_link->flags &= ~SDEV_DBX; /*clear debug bits */
- if(level & 1) sc_link->flags |= SDEV_DB1;
- if(level & 2) sc_link->flags |= SDEV_DB2;
- if(level & 4) sc_link->flags |= SDEV_DB3;
- if(level & 8) sc_link->flags |= SDEV_DB4;
- ret = 0;
- break;
- }
- case SCIOCREPROBE:
- {
- struct scsi_addr *sca = (struct scsi_addr *) addr;
-
- ret = scsi_probe_busses(sca->scbus,sca->target,sca->lun);
- break;
- }
- case SCIOCRECONFIG:
- case SCIOCDECONFIG:
- ret = EINVAL;
- break;
-
- case SCIOCIDENTIFY:
- {
- struct scsi_addr *sca = (struct scsi_addr *) addr;
- sca->scbus = sc_link->scsibus;
- sca->target = sc_link->target;
- sca->lun = sc_link->lun;
- break;
- }
- case SCIOCGETDEVINFO:
- {
- struct scsi_devinfo *scd = (struct scsi_devinfo *)addr;
- struct scsi_link *scl;
- scl = scsi_link_get(scd->addr.scbus, scd->addr.target,
- scd->addr.lun);
- if (scl != 0) {
- scd->dev = scl->dev;
- /* XXX buffers better be big enough... */
- sprintf(scd->devname, "%s%d",
- scl->device->name, scl->dev_unit);
- sprintf(scd->adname, "%s%d:%d",
- scl->adapter->name, scl->adapter_unit,
- scl->adapter_bus);
- ret = 0;
- } else {
- ret = ENXIO;
- }
- break;
- }
-
- default:
- ret = ENOTTY;
- break;
- }
-
- return ret;
-}
-
-void
-scsierr(bp,err)
- struct buf *bp;
- int err;
-{
- bp->b_flags |= B_ERROR;
- bp->b_error = err;
- biodone(bp);
- return;
-}
-
diff --git a/sys/scsi/scsi_message.h b/sys/scsi/scsi_message.h
deleted file mode 100644
index 7163d49..0000000
--- a/sys/scsi/scsi_message.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Messages (1 byte) */ /* I/T (M)andatory or (O)ptional */
-#define MSG_CMDCOMPLETE 0x00 /* M/M */
-#define MSG_EXTENDED 0x01 /* O/O */
-#define MSG_SAVEDATAPOINTER 0x02 /* O/O */
-#define MSG_RESTOREPOINTERS 0x03 /* O/O */
-#define MSG_DISCONNECT 0x04 /* O/O */
-#define MSG_INITIATOR_DET_ERR 0x05 /* M/M */
-#define MSG_ABORT 0x06 /* O/M */
-#define MSG_MESSAGE_REJECT 0x07 /* M/M */
-#define MSG_NOOP 0x08 /* M/M */
-#define MSG_PARITY_ERROR 0x09 /* M/M */
-#define MSG_LINK_CMD_COMPLETE 0x0a /* O/O */
-#define MSG_LINK_CMD_COMPLETEF 0x0b /* O/O */
-#define MSG_BUS_DEV_RESET 0x0c /* O/M */
-#define MSG_ABORT_TAG 0x0d /* O/O */
-#define MSG_CLEAR_QUEUE 0x0e /* O/O */
-#define MSG_INIT_RECOVERY 0x0f /* O/O */
-#define MSG_REL_RECOVERY 0x10 /* O/O */
-#define MSG_TERM_IO_PROC 0x11 /* O/O */
-
-/* Messages (2 byte) */
-#define MSG_SIMPLE_Q_TAG 0x20 /* O/O */
-#define MSG_HEAD_OF_Q_TAG 0x21 /* O/O */
-#define MSG_ORDERED_Q_TAG 0x22 /* O/O */
-#define MSG_IGN_WIDE_RESIDUE 0x23 /* O/O */
-
-/* Identify message */ /* M/M */
-#define MSG_IDENTIFYFLAG 0x80
-#define MSG_IDENTIFY(lun, disc) (((disc) ? 0xc0 : MSG_IDENTIFYFLAG) | (lun))
-#define MSG_ISIDENTIFY(m) ((m) & MSG_IDENTIFYFLAG)
-
-/* Extended messages (opcode and length) */
-#define MSG_EXT_SDTR 0x01
-#define MSG_EXT_SDTR_LEN 0x03
-
-#define MSG_EXT_WDTR 0x03
-#define MSG_EXT_WDTR_LEN 0x02
diff --git a/sys/scsi/scsi_sense.c b/sys/scsi/scsi_sense.c
deleted file mode 100644
index 3dfc0ef..0000000
--- a/sys/scsi/scsi_sense.c
+++ /dev/null
@@ -1,309 +0,0 @@
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-
-#include <scsi/scsiconf.h>
-
-/* XXX There should be a way for a type driver to have its own
- * private senses and add them when it is added.
- */
-
-#if !defined(NO_SCSI_SENSE)
-
-#include "sd.h"
-#include "st.h"
-#define NSPRINT 0
-#include "pt.h"
-#include "worm.h"
-#include "cd.h"
-#define NSCAN 0
-#include "od.h"
-#include "ch.h"
-#define NCOMM 0
-
-static struct
-{
- u_char asc;
- u_char ascq;
- char *desc;
-} tab[] = {
-#if (NCH > 0)
- {0x28, 0x01, "Import or export element accessed" },
- {0x21, 0x01, "Invalid element address" },
- {0x3b, 0x0d, "Medium destination element full" },
- {0x3b, 0x0e, "Medium source element empty" },
-#endif
-#if (NOD > 0)
- {0x58, 0x00, "Generation does not exist" },
- {0x59, 0x00, "Updated block read" },
-#endif
-#if (NSCAN > 0)
- {0x2c, 0x02, "Invalid combination of windows specified" },
- {0x60, 0x00, "Lamp failure" },
- {0x61, 0x02, "Out of focus" },
- {0x3b, 0x0c, "Position past beginning of medium" },
- {0x3b, 0x0b, "Position past end of medium" },
- {0x3b, 0x0a, "Read past beginning of medium" },
- {0x3b, 0x09, "Read past end of medium" },
- {0x62, 0x00, "Scan head positioning error" },
- {0x2c, 0x01, "Too many windows specified" },
- {0x61, 0x01, "Unable to acquire video" },
- {0x61, 0x00, "Video acquisition error" },
-#endif
-#if (NCD > 0)
- {0x00, 0x11, "Audio play operation in progress" },
- {0x00, 0x12, "Audio play operation paused" },
- {0x00, 0x14, "Audio play operation stopped due to error" },
- {0x00, 0x13, "Audio play operation successfully completed" },
- {0x63, 0x00, "End of user area encountered on this track" },
- {0x64, 0x00, "Illegal mode for this track" },
- {0x00, 0x15, "No current audio status to return" },
- {0x18, 0x03, "Recovered data with CIRC" },
- {0x18, 0x04, "Recovered data with L-EC" },
- {0x57, 0x00, "Unable to recover table-of-contents" },
-#endif
-#if (NWORM > 0)||(NOD > 0)
- {0x11, 0x07, "Data resynchronization error" },
-#endif
-#if (NWORM > 0)||(NCD > 0)||(NOD > 0)
- {0x11, 0x06, "Circ unrecovered error" },
- {0x09, 0x02, "Focus servo failure" },
- {0x11, 0x05, "L-EC uncorrectable error" },
- {0x17, 0x04, "Recovered data with retries and/or CIRC applied" },
- {0x09, 0x03, "Spindle servo failure" },
- {0x09, 0x01, "Tracking servo failure" },
-#endif
-#if (NPT > 0)
- {0x54, 0x00, "SCSI to host system interface failure" },
- {0x55, 0x00, "System resource failure" },
-#endif
-#if (NSPRINT > 0)
- {0x3b, 0x07, "Failed to sense bottom-of-form" },
- {0x3b, 0x06, "Failed to sense top-of-form" },
- {0x3b, 0x05, "Paper jam" },
- {0x36, 0x00, "Ribbon, ink, or toner failure" },
- {0x3b, 0x04, "Slew failure" },
- {0x3b, 0x03, "Tape or electronic vertical forms unit not ready" },
-#endif
-#if (NST > 0)
- {0x14, 0x04, "Block sequence error" },
- {0x52, 0x00, "Cartridge fault" },
- {0x14, 0x03, "End-of-data not found" },
- {0x03, 0x02, "Excessive write errors" },
- {0x00, 0x01, "Filemark detected" },
- {0x14, 0x02, "Filemark or setmark not found" },
- {0x11, 0x08, "Incomplete block read" },
- {0x11, 0x09, "No gap found" },
- {0x03, 0x01, "No write current" },
- {0x2d, 0x00, "Overwrite error on update in place" },
- {0x50, 0x02, "Position error related to timing" },
- {0x3b, 0x08, "Reposition error" },
- {0x00, 0x03, "Setmark detected" },
- {0x33, 0x00, "Tape length error" },
- {0x3b, 0x01, "Tape position error at beginning-of-medium" },
- {0x3b, 0x02, "Tape position error at end-of-medium" },
- {0x53, 0x01, "Unload tape failure" },
- {0x50, 0x00, "Write append error" },
- {0x50, 0x01, "Write append position error" },
-#endif
-#if (NST > 0)||(NOD > 0)
- {0x51, 0x00, "Erase failure" },
-#endif
-#if (NST > 0)||(NSCAN > 0)
- {0x00, 0x04, "Beginning-of-partition/medium detected" },
- {0x00, 0x05, "End-of-data detected" },
- {0x00, 0x02, "End-of-partition/medium detected" },
- {0x0c, 0x00, "Write error" },
-#endif
-#if (NST > 0)||(NSPRINT > 0)
- {0x3b, 0x00, "Sequential positioning error" },
-#endif
-#if (NSD > 0)
- {0x41, 0x00, "Data path failure (should use 40 nn)" },
- {0x22, 0x00, "Illegal function (should use 20 00, 24 00, or 26 00)" },
- {0x42, 0x00, "Power-on or self-test failure (should use 40 nn)" },
- {0x40, 0x00, "Ram failure (should use 40 nn)" },
-#endif
-#if (NSD > 0)||(NOD > 0)
- {0x19, 0x00, "Defect list error" },
- {0x19, 0x03, "Defect list error in grown list" },
- {0x19, 0x02, "Defect list error in primary list" },
- {0x19, 0x01, "Defect list not available" },
- {0x1c, 0x00, "Defect list not found" },
- {0x1c, 0x02, "Grown defect list not found" },
- {0x1c, 0x01, "Primary defect list not found" },
- {0x5c, 0x00, "RPL status change" },
- {0x5c, 0x02, "Spindles not synchronized" },
- {0x5c, 0x01, "Spindles synchronized" },
-#endif
-#if (NSD > 0)||(NWORM > 0)||(NOD > 0)
- {0x13, 0x00, "Address mark not found for data field" },
- {0x12, 0x00, "Address mark not found for id field" },
- {0x16, 0x00, "Data synchronization mark error" },
- {0x32, 0x01, "Defect list update failure" },
- {0x10, 0x00, "Id CRC or ECC error" },
- {0x1d, 0x00, "Miscompare during verify operation" },
- {0x32, 0x00, "No defect spare location available" },
- {0x01, 0x00, "No index/sector signal" },
- {0x17, 0x06, "Recovered data without ECC - data auto-reallocated" },
- {0x17, 0x07, "Recovered data without ECC - recommend reassignment" },
- {0x17, 0x08, "Recovered data without ECC - recommend rewrite" },
- {0x1e, 0x00, "Recovered ID with ECC correction" },
- {0x11, 0x04, "Unrecovered read error - auto reallocate failed" },
- {0x11, 0x0b, "Unrecovered read error - recommend reassignment" },
- {0x11, 0x0c, "Unrecovered read error - recommend rewrite the data" },
- {0x0c, 0x02, "Write error - auto reallocation failed" },
- {0x0c, 0x01, "Write error recovered with auto reallocation" },
-#endif
-#if (NSD > 0)||(NWORM > 0)||(NCD > 0)||(NOD > 0)
- {0x18, 0x02, "Recovered data - data auto-reallocated" },
- {0x18, 0x05, "Recovered data - recommend reassignment" },
- {0x18, 0x06, "Recovered data - recommend rewrite" },
- {0x17, 0x05, "Recovered data using previous sector id" },
- {0x18, 0x01, "Recovered data with error correction & retries applied" },
-#endif
-#if (NSD > 0)||(NWORM > 0)||(NCD > 0)||(NOD > 0)||(NCH > 0)
- {0x06, 0x00, "No reference position found" },
- {0x02, 0x00, "No seek complete" },
-#endif
-#if (NSD > 0)||(NSPRINT > 0)||(NOD > 0)
- {0x31, 0x01, "Format command failed" },
-#endif
-#if (NSD > 0)||(NST > 0)
- {0x30, 0x03, "Cleaning cartridge installed" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NOD > 0)
- {0x11, 0x0a, "Miscorrected error" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NWORM > 0)||(NOD > 0)
- {0x31, 0x00, "Medium format corrupted" },
- {0x5a, 0x03, "Operator selected write permit" },
- {0x5a, 0x02, "Operator selected write protect" },
- {0x27, 0x00, "Write protected" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NWORM > 0)||(NSCAN > 0)||(NOD > 0)
- {0x11, 0x02, "Error too long to correct" },
- {0x11, 0x03, "Multiple read errors" },
- {0x11, 0x01, "Read retries exhausted" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NWORM > 0)||(NCD > 0)||(NOD > 0)
- {0x30, 0x02, "Cannot read medium - incompatible format" },
- {0x30, 0x01, "Cannot read medium - unknown format" },
- {0x15, 0x02, "Positioning error detected by read of medium" },
- {0x14, 0x01, "Record not found" },
- {0x18, 0x00, "Recovered data with error correction applied" },
- {0x17, 0x03, "Recovered data with negative head offset" },
- {0x17, 0x02, "Recovered data with positive head offset" },
- {0x09, 0x00, "Track following error" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NWORM > 0)||(NCD > 0)||(NOD > 0)||(NCH > 0)
- {0x30, 0x00, "Incompatible medium installed" },
- {0x21, 0x00, "Logical block address out of range" },
- {0x53, 0x02, "Medium removal prevented" },
- {0x5a, 0x01, "Operator medium removal request" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NWORM > 0)||(NCD > 0)||(NSCAN > 0)||(NOD > 0)
- {0x17, 0x00, "Recovered data with no error correction applied" },
- {0x17, 0x01, "Recovered data with retries" },
- {0x11, 0x00, "Unrecovered read error" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NSPRINT > 0)||(NOD > 0)
- {0x04, 0x04, "Logical unit not ready, format in progress" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NSPRINT > 0)||(NWORM > 0)||(NSCAN > 0)||(NOD > 0)
- {0x03, 0x00, "Peripheral device write fault" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NSPRINT > 0)||(NWORM > 0)||(NCD > 0)||(NSCAN > 0)||(NOD > 0)
- {0x14, 0x00, "Recorded entity not found" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NSPRINT > 0)||(NWORM > 0)||(NCD > 0)||(NSCAN > 0)||(NOD > 0)||(NCH > 0)
- {0x15, 0x01, "Mechanical positioning error" },
- {0x53, 0x00, "Media load or eject failed" },
- {0x3a, 0x00, "Medium not present" },
- {0x07, 0x00, "Multiple peripheral devices selected" },
- {0x15, 0x00, "Random positioning error" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NSPRINT > 0)||(NWORM > 0)||(NCD > 0)||(NSCAN > 0)||(NOD > 0)||(NCH > 0)||(ncomm > 0)
- {0x2a, 0x02, "Log parameters changed" },
- {0x08, 0x00, "Logical unit communication failure" },
- {0x08, 0x02, "Logical unit communication parity error" },
- {0x08, 0x01, "Logical unit communication time-out" },
- {0x2a, 0x01, "Mode parameters changed" },
- {0x2a, 0x00, "Parameters changed" },
- {0x37, 0x00, "Rounded parameter" },
- {0x39, 0x00, "Saving parameters not supported" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NSPRINT > 0)||(NPT > 0)||(NWORM > 0)||(NCD > 0)||(NSCAN > 0)||(NOD > 0)||(ncomm > 0)
- {0x2b, 0x00, "Copy cannot execute since host cannot disconnect" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NSPRINT > 0)||(NPT > 0)||(NWORM > 0)||(NCD > 0)||(NSCAN > 0)||(NOD > 0)||(NCH > 0)
- {0x5b, 0x02, "Log counter at maximum" },
- {0x5b, 0x00, "Log exception" },
- {0x5b, 0x03, "Log list codes exhausted" },
- {0x5a, 0x00, "Operator request or state change input (unspecified)" },
- {0x5b, 0x01, "Threshold condition met" },
-#endif
- {0x3f, 0x02, "Changed operating definition" },
- {0x4a, 0x00, "Command phase error" },
- {0x2c, 0x00, "Command sequence error" },
- {0x2f, 0x00, "Commands cleared by another initiator" },
- {0x4b, 0x00, "Data phase error" },
-/* {0x40, 0xnn, "Diagnostic failure on component nn (80h-ffh)" }, */
- {0x0a, 0x00, "Error log overflow" },
- {0x00, 0x06, "I/O process terminated" },
- {0x48, 0x00, "Initiator detected error message received" },
- {0x3f, 0x03, "Inquiry data has changed" },
- {0x44, 0x00, "Internal target failure" },
- {0x3d, 0x00, "Invalid bits in identify message" },
- {0x20, 0x00, "Invalid command operation code" },
- {0x24, 0x00, "Invalid field in CDB" },
- {0x26, 0x00, "Invalid field in parameter list" },
- {0x49, 0x00, "Invalid message error" },
- {0x05, 0x00, "Logical unit does not respond to selection" },
- {0x4c, 0x00, "Logical unit failed self-configuration" },
- {0x3e, 0x00, "Logical unit has not self-configured yet" },
- {0x04, 0x01, "Logical unit is in process of becoming ready" },
- {0x04, 0x00, "Logical unit not ready, cause not reportable" },
- {0x04, 0x02, "Logical unit not ready, initializing command required" },
- {0x04, 0x03, "Logical unit not ready, manual intervention required" },
- {0x25, 0x00, "Logical unit not supported" },
- {0x43, 0x00, "Message error" },
- {0x3f, 0x01, "Microcode has been changed" },
- {0x00, 0x00, "No additional sense information" },
- {0x28, 0x00, "Not ready to ready transition, medium may have changed" },
- {0x4e, 0x00, "Overlapped commands attempted" },
- {0x1a, 0x00, "Parameter list length error" },
- {0x26, 0x01, "Parameter not supported" },
- {0x26, 0x02, "Parameter value invalid" },
- {0x29, 0x00, "Power on, reset, or bus device reset occurred" },
- {0x47, 0x00, "SCSI parity error" },
- {0x45, 0x00, "Select or reselect failure" },
- {0x1b, 0x00, "Synchronous data transfer error" },
- {0x3f, 0x00, "Target operating conditions have changed" },
- {0x26, 0x03, "Threshold parameters not supported" },
- {0x46, 0x00, "Unsuccessful soft reset" },
-};
-
-char *scsi_sense_desc(int asc, int ascq)
-{
- int i;
-
- if (asc >= 0x80 && asc <= 0xff)
- return "Vendor Specific ASC";
-
- if (ascq >= 0x80 && ascq <= 0xff)
- return "Vendor Specific ASCQ";
-
- for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++)
- if (tab[i].asc == asc && tab[i].ascq == ascq)
- return tab[i].desc;
-
- return "";
-}
-
-#else /* NO_SCSI_SENSE */
-char *scsi_sense_desc(int asc, int ascq)
-{
- return "";
-}
-#endif
diff --git a/sys/scsi/scsi_tape.h b/sys/scsi/scsi_tape.h
deleted file mode 100644
index 5b16574..0000000
--- a/sys/scsi/scsi_tape.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * SCSI tape interface description
- */
-
-/*
- * Written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- */
-
-/*
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- *
- * $Id$
- */
-#ifndef SCSI_SCSI_TAPE_H
-#define SCSI_SCSI_TAPE_H 1
-
-
-
-/*
- * SCSI command formats
- */
-
-
-struct scsi_rw_tape
-{
- u_char op_code;
- u_char byte2;
-#define SRWT_FIXED 0x01
- u_char len[3];
- u_char control;
-};
-
-struct scsi_space
-{
- u_char op_code;
- u_char byte2;
-#define SS_CODE 0x03
- u_char number[3];
- u_char control;
-};
-#define SP_BLKS 0
-#define SP_FILEMARKS 1
-#define SP_SEQ_FILEMARKS 2
-#define SP_EOM 3
-
-struct scsi_write_filemarks
-{
- u_char op_code;
- u_char byte2;
- u_char number[3];
- u_char control;
-};
-
-struct scsi_rewind
-{
- u_char op_code;
- u_char byte2;
-#define SR_IMMED 0x01
- u_char unused[3];
- u_char control;
-};
-
-/*
-** Tape erase - AKL: Andreas Klemm <andreas@knobel.gun.de>
-*/
-struct scsi_erase
-{
- u_char op_code;
- u_char byte2;
-#define SE_LONG 0x01 /*
- ** Archive Viper 2525 doesn't allow short
- ** erase, other tapes possibly don't allow
- ** that, too.
- */
-#define SE_IMMED 0x02
- u_char unused[3];
- u_char control;
-};
-
-struct scsi_load
-{
- u_char op_code;
- u_char byte2;
-#define SL_IMMED 0x01
- u_char unused[2];
- u_char how;
- u_char control;
-};
-#define LD_UNLOAD 0
-#define LD_LOAD 1
-#define LD_RETEN 2
-
-
-struct scsi_blk_limits
-{
- u_char op_code;
- u_char byte2;
- u_char unused[3];
- u_char control;
-};
-
-/*
- * Opcodes
- */
-
-#define REWIND 0x01
-#define READ_BLK_LIMITS 0x05
-#define READ_COMMAND_TAPE 0x08
-#define WRITE_COMMAND_TAPE 0x0a
-#define WRITE_FILEMARKS 0x10
-#define SPACE 0x11
-#define ERASE 0x19
-#define LOAD_UNLOAD 0x1b
-
-
-
-struct scsi_blk_limits_data
-{
- u_char reserved;
- u_char max_length_2; /* Most significant */
- u_char max_length_1;
- u_char max_length_0; /* Least significant */
- u_char min_length_1; /* Most significant */
- u_char min_length_0; /* Least significant */
-};
-
-/* defines for the device specific byte in the mode select/sense header */
-#define SMH_DSP_SPEED 0x0F
-#define SMH_DSP_BUFF_MODE 0x70
-#define SMH_DSP_BUFF_MODE_OFF 0x00
-#define SMH_DSP_BUFF_MODE_ON 0x10
-#define SMH_DSP_BUFF_MODE_MLTI 0x20
-#define SMH_DSP_WRITE_PROT 0x80
-
-/* A special for the CIPHER ST150S(old drive) */
-struct blk_desc_cipher
-{
- u_char density;
- u_char nblocks[3];
- u_char reserved;
- u_char blklen[3];
- u_char other;
-#define ST150_SEC 0x01 /* soft error count */
-#define SR150_AUI 0x02 /* autoload inhibit */
-};
-
-/*
- * This structure defines the various mode pages that tapes know about.
- */
-#define PAGE_HEADERLEN 2
-struct tape_pages
-{
- u_char pg_code; /* page code */
-#define ST_PAGE_CONFIGURATION 0x10
-#define ST_PAGE_MEDIUM_PART 0x11
-#define ST_PAGE_MEDIUM_PART2 0x12
-#define ST_PAGE_MEDIUM_PART3 0x13
-#define ST_PAGE_MEDIUM_PART4 0x14
-#define ST_P_CODE 0x3F /* page code */
-#define ST_P_PS 0x80 /* page savable */
- u_char pg_length; /* page length */
- union
- {
- struct
- {
- u_char active_format; /* active format for density*/
-#define ST_P_CAP 0x40 /* change active Partition */
-#define ST_P_CAF 0x20 /* change active format */
-#define ST_P_AF 0x1F /* active format */
- u_char active_partition; /* */
- u_char write_buffer_full_ratio; /* highwater writing*/
- u_char read_buffer_empty_ratio; /* lowwater reading*/
- u_char write_delay_high; /* # 100mSecs before flush*/
- u_char write_delay_low; /* of buffer to the media */
- u_char flags1; /* various single bit flags */
-#define ST_P_DBR 0x80 /* supports data-buffer recovery */
-#define ST_P_BIS 0x40 /* supports Block_ID */
-#define ST_P_RSmk 0x20 /* Reports setmarks during reads and spaces */
-#define ST_P_AVC 0x10 /* Supports Automatic Velocity Control */
-#define ST_P_SOCF 0x0C /* Stop On Consecutive Filemarks, */
-#define ST_P_RBO 0x02 /* Recoverd Buffered Data order, 1 = LIFO */
-#define ST_P_REW 0x01 /* Report Early Warning (see SEW) */
- u_char gap_size; /*I/B gap, 1=min 0=default */
- u_char flags2; /* various single bit flags */
-#define ST_P_EOD 0xE0 /* What is and EOD....*/
-#define ST_P_EOD_DEF 0x00 /* Drive's default */
-#define ST_P_EOD_FMT 0x20 /* define by format */
-#define ST_P_EOD_SOCF 0x40 /* define by SOCF (above) */
-#define ST_P_EEG 0x10 /* use EOD above */
-#define ST_P_SEW 0x04 /* Synchronise at Early warning.. flush buffers*/
- u_char early_warn_high;/* buf size at early warning */
- u_char early_warn_med; /* after early warning, only */
- u_char early_warn_low; /* buufer this much data */
- u_char data_compress_alg; /* 0 = off, 1 = default */
- u_char reserved; /* The standard says so */
- } configuration;
- struct
- {
-#define ST_MAXPARTS 16 /*for now*/
- u_char max_add_parts; /* that drive allows */
- u_char parts_defined; /* max min(ST_MAXPARTS,max_add_parts) */
- u_char flags;
-#define ST_P_FDP 0x80
-#define ST_P_SDP 0x40
-#define ST_P_IDP 0x20
-#define ST_P_PSUM 0x18 /* units of part defs.. */
-#define ST_P_PSUM_BYTES 0x0 /* units of part defs.. */
-#define ST_P_PSUM_KBYTES 0x08 /* units of part defs.. */
-#define ST_P_PSUM_MBYTES 0x10 /* units of part defs.. */
- u_char medium_format_recog;
-#define ST_P_REC_NONE 0x00
-#define ST_P_REC_FMT 0x01 /* can recognise format of new media */
-#define ST_P_REC_PART 0x02 /* can recognise partitions of new media */
-#define ST_P_REC_FMT_PART 0x03 /* can recognise format and parts */
- u_char reserved1;
- u_char reserved2;
- struct
- {
- u_char high;
- u_char low;
- }part[ST_MAXPARTS];
- } medium_partition;
- struct
- {
- struct
- {
- u_char high;
- u_char low;
- }part[ST_MAXPARTS];
- } medium_partition_extra;
- }pages;
-};
-
-
-#endif /*SCSI_SCSI_TAPE_H*/
diff --git a/sys/scsi/scsi_worm.h b/sys/scsi/scsi_worm.h
deleted file mode 100644
index 6f8fc61..0000000
--- a/sys/scsi/scsi_worm.h
+++ /dev/null
@@ -1,128 +0,0 @@
-#ifndef _SCSI_SCSI_WORM_H
-#define _SCSI_SCSI_WORM_H
-
-#define PAGE_HEADERLEN 2
-
-/*
- * Opcodes
- */
-
-#define REZERO_UNIT 0x01 /* re-init; XXX belongs to scsi_all? */
-#define SYNCHRONIZE_CACHE 0x35 /* flush write buffer, close wr chn */
-#define FIRST_WRITEABLE_ADDR 0xe2 /* return first available LBA */
-#define RESERVE_TRACK 0xe4 /* reserve a track for later write */
-#define READ_TRACK_INFORMATION 0xe5 /* get info for a particular track */
-#define WRITE_TRACK 0xe6 /* open the write channel */
-#define LOAD_UNLOAD 0xe7 /* resembles part of START_STOP */
-#define FIXATION 0xe9 /* write leadin/leadout */
-#define WRITE_SESSION 0xed /* guide to write a new session */
-#define READ_SESSION_INFO 0xee /* read leadin/leadout lengths */
-
-struct scsi_rezero_unit
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[3];
- u_char control;
-};
-
-struct scsi_synchronize_cache
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[7];
- u_char control;
-};
-
-/* struct scsi_first_writeable_address; */
-
-struct scsi_reserve_track
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[3];
- u_char reserve_length_3; /* MSB */
- u_char reserve_length_2;
- u_char reserve_length_1;
- u_char reserve_length_0; /* LSB */
- u_char control;
-};
-
-/* struct scsi_read_track_information; */
-
-struct scsi_write_track
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[3];
- u_char track_number; /* 0 means: use next available */
- u_char mode;
-#define WORM_TRACK_MODE_RAW 0x08
-#define WORM_TRACK_MODE_AUDIO 0x04
-#define WORM_TRACK_MODE_MODE1 0x01 /* also audio with preemphasis */
-#define WORM_TRACK_MODE_MODE2 0x02
- u_char transfer_length_1; /* number of blocks to transfer, MSB */
- u_char transfer_length_0; /* LSB */
- u_char control;
-#define WORM_TRACK_CONTROL_MIX 0x40 /* mixed mode blocks */
-};
-
-struct scsi_load_unload
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[6];
- u_char load;
-#define WORM_LOAD_MEDIUM 0x01
- u_char control;
-};
-
-struct scsi_fixation
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[6];
- u_char action;
-#define WORM_FIXATION_ONP 0x08 /* open next program area (new session) */
-#define WORM_TOC_TYPE_AUDIO 0x00
-#define WORM_TOC_TYPE_CDROM 0x01
-#define WORM_TOC_TYPE_CDROM_1 0x02 /* CD-ROM, first track mode 1 (?) */
-#define WORM_TOC_TYPE_CDROM_2 0x03 /* CD-ROM, first track mode 2 */
-#define WORM_TOC_TYPE_CDI 0x04
- u_char control;
-};
-
-struct scsi_write_session
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[4];
- u_char action; /* see scsi_fixation above */
-#define WORM_LOFP_MODE_MODE1 0x10
-#define WORM_LOFP_MODE_MODE2 0x20
- u_char transfer_length_2; /* number of blocks to transfer, MSB */
- u_char transfer_length_1; /* LSB */
- u_char control;
-};
-
-struct scsi_read_session_info
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[6];
- u_char transfer_length;
- u_char control;
-};
-
-struct scsi_first_writable_address
-{
- u_char op_code;
- u_char byte2;
- u_char track_number;
- u_char mode;
- u_char reserved[4];
- u_char transfer_length;
- u_char control;
-};
-
-#endif /* _SCSI_SCSI_WORM_H */
diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c
deleted file mode 100644
index f805edc..0000000
--- a/sys/scsi/scsiconf.c
+++ /dev/null
@@ -1,1573 +0,0 @@
-/*
- * Written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- *
- * New configuration setup: dufault@hda.com
- *
- * $Id: scsiconf.c,v 1.107 1998/07/28 09:03:37 phk Exp $
- */
-
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/conf.h>
-#ifdef PC98
-#include <sys/device.h>
-#endif
-
-#include <machine/clock.h>
-
-#include "sd.h"
-#include "st.h"
-#include "cd.h"
-#include "ch.h"
-#include "od.h"
-#include "pt.h"
-#include "worm.h"
-
-#include "sctarg.h"
-
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-static struct extend_array *extend_new __P((void));
-static void extend_release __P((struct extend_array *ea, int index));
-static void *extend_set __P((struct extend_array *ea, int index, void *value));
-
-/*
- * XXX SCSI_DEVICE_ENTRIES() generates extern switches but it should
- * generate static switches except for this. Separate macros are
- * probably required for the extern and static parts.
- */
-extern struct scsi_device uk_switch;
-
-/***********************************************************************
- * Extensible arrays: Use a realloc like implementation to permit
- * the arrays to be extend. These are set up to be moved out
- * of this file if needed elsewhere.
- */
-struct extend_array
-{
- int nelem;
- void **ps;
-};
-
-static void make_readable __P((char *to, char *from, size_t n));
-static int match __P((char *pattern, char *name));
-static int scsi_bus_conf __P((struct scsi_link *sc_link_proto));
-
-static void *
-extend_alloc(size_t s)
-{
- void *p = malloc(s, M_DEVBUF, M_NOWAIT);
- if (!p)
- panic("extend_alloc: malloc failed.");
- return p;
-}
-
-static void
-extend_free(void *p) { free(p, M_DEVBUF); }
-
-/* EXTEND_CHUNK: Number of extend slots to allocate whenever we need a new
- * one.
- */
-#ifndef EXTEND_CHUNK
- #define EXTEND_CHUNK 8
-#endif
-
-static struct extend_array *
-extend_new(void)
-{
- struct extend_array *p = extend_alloc(sizeof(*p));
- if (p) {
- p->nelem = 0;
- p->ps = 0;
- }
-
- return p;
-}
-
-static void *
-extend_set(struct extend_array *ea, int index, void *value)
-{
- if (index >= ea->nelem) {
- void **space;
- space = extend_alloc(sizeof(void *) * (index + EXTEND_CHUNK));
- bzero(space, sizeof(void *) * (index + EXTEND_CHUNK));
-
- /* Make sure we have something to copy before we copy it */
- if (ea->nelem) {
- bcopy(ea->ps, space, sizeof(void *) * ea->nelem);
- extend_free(ea->ps);
- }
-
- ea->ps = space;
- ea->nelem = index + EXTEND_CHUNK;
- }
- if (ea->ps[index]) {
- printf("extend_set: entry %d already has storage.\n", index);
- return 0;
- }
- else
- ea->ps[index] = value;
-
- return value;
-}
-
-void *
-extend_get(struct extend_array *ea, int index)
-{
- if (ea == NULL || index >= ea->nelem || index < 0)
- return NULL;
- return ea->ps[index];
-}
-
-static void
-extend_release(struct extend_array *ea, int index)
-{
- void *p = extend_get(ea, index);
- if (p) {
- ea->ps[index] = 0;
- }
-}
-
-/***********************************************************************
- * This extend_array holds an array of "scsibus_data" pointers.
- * One of these is allocated and filled in for each scsi bus.
- * it holds pointers to allow the scsi bus to get to the driver
- * that is running each LUN on the bus
- * it also has a template entry which is the prototype struct
- * supplied by the adapter driver, this is used to initialise
- * the others, before they have the rest of the fields filled in
- */
-
-static struct extend_array *scbusses;
-
-/*
- * The structure of known drivers for autoconfiguration
- */
-struct scsidevs {
- u_int32_t type;
- u_int32_t driver; /* normally the same as type */
- boolean removable;
- char *manufacturer;
- char *model;
- char *version;
- char *devname;
- char flags; /* 1 show my comparisons during boot(debug) */
- u_int16_t quirks;
- void *devmodes;
-};
-
-#define SC_SHOWME 0x01
-#define SC_ONE_LU 0x00
-#define SC_MORE_LUS 0x02
-
-static struct scsidevs unknowndev =
- {
- T_UNKNOWN, T_UNKNOWN, 0, "*", "*", "*",
- "uk", SC_MORE_LUS
- };
-static st_modes mode_tandberg3600 =
- {
- {0, 0, 0}, /* minor 0,1,2,3 */
- {0, ST_Q_FORCE_VAR_MODE, QIC_525}, /* minor 4,5,6,7 */
- {0, 0, QIC_150}, /* minor 8,9,10,11 */
- {0, 0, QIC_120} /* minor 12,13,14,15 */
- };
-static st_modes mode_tandberg4200 =
- {
- {0, 0, 0}, /* minor 0,1,2,3 */
- {0, ST_Q_FORCE_VAR_MODE, 0}, /* minor 4,5,6,7 */
- {0, 0, QIC_150}, /* minor 8,9,10,11 */
- {0, 0, QIC_120} /* minor 12,13,14,15 */
- };
-static st_modes mode_archive2525 =
- {
- {0, ST_Q_SNS_HLP, 0}, /* minor 0,1,2,3 */
- {0, ST_Q_SNS_HLP, QIC_525}, /* minor 4,5,6,7 */
- {0, 0, QIC_150}, /* minor 8,9,10,11 */
- {0, 0, QIC_120} /* minor 12,13,14,15 */
- };
-static st_modes mode_archive150 =
- {
- {0, 0, 0}, /* minor 0,1,2,3 */
- {0, 0, QIC_150}, /* minor 4,5,6,7 */
- {0, 0, QIC_120}, /* minor 8,9,10,11 */
- {0, 0, QIC_24} /* minor 12,13,14,15 */
- };
-static st_modes mode_wangtek5525 =
- {
- {0, 0, 0}, /* minor 0,1,2,3 */
- {0, ST_Q_BLKSIZ, QIC_525}, /* minor 4,5,6,7 */
- {0, 0, QIC_150}, /* minor 8,9,10,11 */
- {0, 0, QIC_120} /* minor 12,13,14,15 */
- };
-static st_modes mode_wangdat1300 =
- {
- {0, 0, 0}, /* minor 0,1,2,3 */
- {512, ST_Q_FORCE_FIXED_MODE, DDS}, /* minor 4,5,6,7 */
- {1024, ST_Q_FORCE_FIXED_MODE, DDS}, /* minor 8,9,10,11 */
- {0, ST_Q_FORCE_VAR_MODE, DDS} /* minor 12,13,14,15 */
- };
-static st_modes mode_unktape =
- {
- {0, 0, 0}, /* minor 0,1,2,3 */
- {512, ST_Q_FORCE_FIXED_MODE, QIC_24}, /* minor 4,5,6,7 */
- {0, ST_Q_FORCE_VAR_MODE, HALFINCH_1600}, /* minor 8,9,10,11 */
- {0, ST_Q_FORCE_VAR_MODE, HALFINCH_6250} /* minor 12,13,14,15 */
- };
-
-static int worm_mode_philips = WORM_Q_PHILIPS;
-static int worm_mode_plasmon = WORM_Q_PLASMON;
-
-/***********************************************************************
- * A list of known devices and their "quirks". Matching is based
- * first on device type, then on the manufacturer, model, and revision
- * strings returned by the device. The returned strings are fixed lengths
- * of 8, 16 and 4 bytes respectively. In the matching pattern, a
- * question mark (?) matches any single character and a trailing
- * asterisk (*) matches remaining characters. For patterns shorter
- * than their respective fields, trailing spaces are implied.
- */
-
-static struct scsidevs knowndevs[] =
-{
-#if NOD > 0
- {
- T_OPTICAL, T_OPTICAL, T_REMOV, "MATSHITA", "PD-1 LF-1*", "*",
- "od", SC_MORE_LUS
- },
- {
- T_DIRECT, T_OPTICAL, T_REMOV, "SONY", "SMO-*", "*",
- "od", SC_MORE_LUS
- },
- {
- T_DIRECT, T_OPTICAL, T_REMOV, "MOST", "RMD-5200-S", "*",
- "od", SC_ONE_LU
- },
- {
- T_DIRECT, T_OPTICAL, T_REMOV, "RICOH", "RO-*", "*",
- "od", SC_ONE_LU
- },
-#endif /* NOD */
-#if NSD > 0
- {
- T_DIRECT, T_DIRECT, T_FIXED, "EMULEX", "MD21*" , "*",
- "sd", SC_MORE_LUS
- },
- {
- T_DIRECT, T_DIRECT, T_FIXED, "IFT", "*" , "*",
- "sd", SC_MORE_LUS
- },
-#endif /* NSD */
-#if NST > 0
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "TANDBERG", " TDC 3600", "*",
- "st", SC_ONE_LU, ST_Q_NEEDS_PAGE_0, mode_tandberg3600
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "TANDBERG", " TDC 42*", "*",
- "st", SC_ONE_LU, ST_Q_SNS_HLP|ST_Q_NO_1024, mode_tandberg4200
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "ARCHIVE", "VIPER 2525*", "-005",
- "st", SC_ONE_LU, 0, mode_archive2525
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "ARCHIVE", "VIPER 150 *", "*",
- "st", SC_ONE_LU, ST_Q_NEEDS_PAGE_0, mode_archive150
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "WANGTEK", "5525ES*", "*",
- "st", SC_ONE_LU, 0, mode_wangtek5525
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "WangDAT", "Model 1300", "*",
- "st", SC_ONE_LU, 0, mode_wangdat1300
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "DEC", "DLT2700", "*",
- "st", SC_MORE_LUS, 0
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "Quantum", "DLT*", "*",
- "st", SC_MORE_LUS, 0
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "SUN", "DLT*", "*",
- "st", SC_MORE_LUS, 0
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "HP", "C1553A*", "*",
- "st", SC_MORE_LUS, 0
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "HP", "C1557A", "*",
- "st", SC_MORE_LUS, 0
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "ARCHIVE", "Python 28849-*", "*",
- "st", SC_MORE_LUS, 0
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "ARCHIVE", "4586XX 28887-*", "*",
- "st", SC_MORE_LUS, 0
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "SONY", "TSL-7000", "*",
- "st", SC_MORE_LUS, 0
- },
-#endif /* NST */
-#if NCH > 0
- /*
- * The <ARCHIVE, Python 28849-XXX, 4.98> is a SCSI changer device
- * with an Archive Python DAT drive built-in. The tape appears
- * at LUN 0 and the changer at LUN 1.
- * This entry should not be needed at all.
- */
- {
- T_CHANGER, T_CHANGER, T_REMOV, "ARCHIVE", "Python 28849-*", "*",
- "ch", SC_MORE_LUS
- },
- {
- T_CHANGER, T_CHANGER, T_REMOV, "ARCHIVE", "4586XX 28887-*", "*",
- "ch", SC_MORE_LUS
- },
- {
- T_CHANGER, T_CHANGER, T_REMOV, "SONY", "TSL-7000", "*",
- "ch", SC_MORE_LUS
- },
-#endif /* NCH */
-#if NCD > 0
-#ifndef UKTEST /* make cdroms unrecognised to test the uk driver */
- /*
- * CDU-8003A aka Apple CDROM-300.
- */
- {
- T_READONLY, T_READONLY, T_REMOV, "SONY", "CD-ROM CDU-8003A", "1.9a",
- "cd", SC_ONE_LU
- },
- {
- T_READONLY, T_READONLY, T_REMOV, "SONY", "CD-ROM CDU-8012", "3.1a",
- "cd", SC_ONE_LU
- },
- {
- T_READONLY, T_READONLY, T_REMOV, "PIONEER", "CD-ROM DRM-6??*" ,"*",
- "cd", SC_MORE_LUS, CD_Q_NO_TOUCH
- },
- {
- T_READONLY, T_READONLY, T_REMOV, "NRC", "MBR-7*" ,"*",
- "cd", SC_MORE_LUS
- },
- {
- T_READONLY, T_READONLY, T_REMOV, "CHINON", "CD-ROM CDS-535","*",
- "cd", SC_ONE_LU, CD_Q_BCD_TRACKS
- },
- /*
- * Note: My drive with v1.0 firmware "forgets" to generate scsi parity
- * when answering probes.. :-( EVIL!! You need to disable scsi parity
- * checking in order to find out that it answers to all 7 LUNS. :-(
- * -Peter
- */
- {
- T_READONLY, T_READONLY, T_REMOV, "NEC", "CD-ROM DRIVE:55","*",
- "cd", SC_ONE_LU
- },
- /*
- * Same with the OEM version of this drive (1.0 firmware).
- * -Paul
- */
- {
- T_READONLY, T_READONLY, T_REMOV, "NEC", "CD-ROM DRIVE:210","*",
- "cd", SC_ONE_LU
- },
- /*
- * Doobe-doo-be doooo
- * -Mary
- */
- {
- T_READONLY, T_READONLY, T_REMOV, "MEDIAVIS", "RENO CD-ROMX2A","*",
- "cd", SC_ONE_LU, CD_Q_NO_START
- },
- {
- T_READONLY, T_READONLY, T_REMOV, "NAKAMICH", "MJ-*" ,"*",
- "cd", SC_MORE_LUS
- },
- /* yet another changer */
- {
- T_READONLY, T_READONLY, T_REMOV, "REGAL", "CDC-4*" ,"*",
- "cd", SC_MORE_LUS
- },
- /* IODATA CD-C68E 6 CD changer */
- {
- T_READONLY, T_READONLY, T_REMOV, "IODATA", "CD-C68E" ,"*",
- "cd", SC_MORE_LUS
- },
-#endif /* !UKTEST */
-#endif /* NCD */
-#if NWORM > 0
- {
- T_READONLY, T_WORM, T_REMOV, "HP", "C4324/C4325", "*",
- "worm", SC_ONE_LU, 0, &worm_mode_philips
- },
- {
- T_READONLY, T_WORM, T_REMOV, "HP", "CD-Writer 6020", "*",
- "worm", SC_ONE_LU, 0, &worm_mode_philips
- },
- {
- /* That's the Philips drive, in case anybody wonders... */
- T_READONLY, T_WORM, T_REMOV, "IMS", "CDD2000*", "*",
- "worm", SC_ONE_LU, 0, &worm_mode_philips
- },
- {
- /* Here's another Philips drive... */
- T_READONLY, T_WORM, T_REMOV, "PHILIPS", "CDD2*", "*",
- "worm", SC_ONE_LU, 0, &worm_mode_philips
- },
- /*
- * The Plasmon's are dual-faced: they appear as T_WORM if the
- * drive is empty, or a CD-R medium is in the drive, and they
- * announce theirselves as T_READONLY if a CD-ROM (or fixated
- * CD-R) is there. We need both entries here, so the worm_mode
- * hook will be properly filled in.
- */
- {
- T_READONLY, T_WORM, T_REMOV, "PLASMON", "RF41*", "*",
- "worm", SC_ONE_LU, 0, &worm_mode_plasmon
- },
- {
- T_WORM, T_WORM, T_REMOV, "PLASMON", "RF41*", "*",
- "worm", SC_ONE_LU, 0, &worm_mode_plasmon
- },
-#endif /* NWORM */
-#if NPT > 0
- /*
- * Some of the Epson scanners erroneously respond to more than
- * one LUN.
- */
- {
- T_PROCESSOR, T_PROCESSOR, T_FIXED, "EPSON SC", "*", "*",
- "pt", SC_ONE_LU
- },
-#endif /* NPT */
-
- /*
- * Wildcard entries. Keep them down here below all device
- * specific entries, so the above ones can override the type
- * driver if necessary.
- */
-#if NOD > 0
- {
- T_OPTICAL, T_OPTICAL, T_REMOV, "*", "*", "*",
- "od", SC_ONE_LU
- },
-#endif /* NOD */
-#if NSD > 0
- {
- T_DIRECT, T_DIRECT, T_FIXED, "HP", "C372*", "*",
- "sd", SC_ONE_LU, SD_Q_NO_TAGS
- },
- {
- T_DIRECT, T_DIRECT, T_REMOV, "iomega", "jaz*", "*",
- "sd", SC_ONE_LU, SD_Q_NO_TAGS
- },
- {
- T_DIRECT, T_DIRECT, T_FIXED, "*", "*", "*",
- "sd", SC_ONE_LU
- },
- {
- T_DIRECT, T_DIRECT, T_REMOV, "*", "*", "*",
- "sd", SC_ONE_LU
- },
-#endif /* NSD */
-#if NST > 0
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "*", "*", "*",
- "st", SC_ONE_LU, 0, mode_unktape
- },
-#endif /* NST */
-#if NCH > 0
- /*
- * Due to the way media changers are working, they are most
- * likely always on a different LUN than the transfer element
- * device. Thus, it should be safe to always probe all LUNs
- * on them.
- */
- {
- T_CHANGER, T_CHANGER, T_REMOV, "*", "*", "*",
- "ch", SC_MORE_LUS
- },
-#endif /* NCH */
-#if NCD > 0 && !defined(UKTEST)
- {
- T_READONLY, T_READONLY, T_REMOV, "*", "*", "*",
- "cd", SC_ONE_LU
- },
-#endif /* NCD */
-#if NWORM > 0
- {
- T_WORM, T_WORM, T_REMOV, "*", "*", "*",
- "worm", SC_ONE_LU
- },
-#endif /* NWORM */
- {
- 0
- }
-};
-
-/*
- * Declarations
- */
-static struct scsidevs *scsi_probedev __P((struct scsi_link *sc_link,
- boolean *maybe_more, int *type_p));
-static struct scsidevs *scsi_selectdev __P((u_int32_t qualifier, u_int32_t type,
- boolean remov, char *manu, char *model,
- char *rev));
-
-/* XXX dufault@hda.com
- * This scsi_device doesn't have the scsi_data_size.
- * This is used during probe.
- */
-static struct scsi_device probe_switch =
-{
- NULL,
- NULL,
- NULL,
- NULL,
- "probe",
-};
-
-static int free_bus; /* First bus not wired down */
-
-static struct scsi_device *device_list;
-static int next_free_type = T_NTYPES;
-
-/* Register new functions at the head of the list. That allows
- * you to replace a standard driver with a new one.
- *
- * You can't register the exact device (the same in memory structure)
- * more than once - the list links are part of the structure. That is
- * prevented.
- *
- * Custom devices should always be registered as type "-1". Then
- * the next available type number will be allocated for it.
- *
- * Be careful not to register a type as 0 unless you really mean to
- * replace the disk driver.
- *
- * This is usually called only by the "device_init" function generated
- * automatically in the SCSI_DEVICE_ENTRIES macro.
- */
-
-void
-scsi_device_register(struct scsi_device *sd)
-{
- /* Not only is it pointless to add the same device more than once
- * but it will also screw up the list.
- */
- struct scsi_device *is_there;
- for (is_there = device_list; is_there; is_there = is_there->next)
- if (is_there == sd)
- return;
-
- if (sd->type == -1)
- sd->type = next_free_type++;
-
- sd->next = device_list;
- device_list = sd;
-
- if (sd->links == 0)
- sd->links = extend_new();
-}
-
-static struct scsi_device *
-scsi_device_lookup(int type)
-{
- struct scsi_device *sd;
-
- for (sd = device_list; sd; sd = sd->next)
- if (sd->type == type)
- return sd;
-
- return &uk_switch;
-}
-
-static struct scsi_device *
-scsi_device_lookup_by_name(char *name)
-{
- struct scsi_device *sd;
-
- for (sd = device_list; sd; sd = sd->next)
- if (strcmp(sd->name, name) == 0)
- return sd;
-
- return &uk_switch;
-}
-
-/* Macro that lets us know something is specified.
- */
-#define IS_SPECIFIED(ARG) (ARG != SCCONF_UNSPEC && ARG != SCCONF_ANY)
-
-/* scsi_init: Do all the one time processing. This initializes the
- * type drivers and initializes the configuration.
- */
-static void
-scsi_init(void)
-{
- static int done = 0;
- if(!done) {
- int i;
-
- done = 1;
-
- scbusses = extend_new();
-
- /* First call all type initialization functions.
- */
- ukinit(); /* We always have the unknown device. */
-
- for (i = 0; scsi_tinit[i]; i++)
- (*scsi_tinit[i])();
-
- /* Lowest free bus for auto-configure is one
- * more than the first one not
- * specified in config:
- */
- for (i = 0; scsi_cinit[i].driver; i++)
- if (IS_SPECIFIED(scsi_cinit[i].scbus) &&
- free_bus <= scsi_cinit[i].scbus)
- free_bus = scsi_cinit[i].scbus + 1;
-
- /* Lowest free unit for each type for auto-configure is one
- * more than the first one not specified in the config file:
- */
- for (i = 0; scsi_dinit[i].name; i++) {
- struct scsi_device_config *sdc = scsi_dinit + i;
- struct scsi_device *sd =
- scsi_device_lookup_by_name(sdc->name);
-
- /* This is a little tricky: We don't want "sd 4" to match as
- * a wired down device, but we do want "sd 4 target 5" or
- * even "sd 4 scbus 1" to match.
- */
- if (IS_SPECIFIED(sdc->unit) &&
- (IS_SPECIFIED(sdc->target) || IS_SPECIFIED(sdc->cunit)) &&
- sd->free_unit <= sdc->unit)
- sd->free_unit = sdc->unit + 1;
- }
- }
-}
-
-/* scsi_bus_conf: Figure out which bus this is. If it is wired in config
- * use that. Otherwise use the next free one.
- */
-static int
-scsi_bus_conf(sc_link_proto)
- struct scsi_link *sc_link_proto;
-{
- int i;
- int bus;
-
- /* Which bus is this? Try to find a match in the "scsi_cinit"
- * table. If it isn't wired down auto-configure it at the
- * next available bus.
- */
-
- bus = SCCONF_UNSPEC;
- for (i = 0; scsi_cinit[i].driver; i++) {
- if (IS_SPECIFIED(scsi_cinit[i].scbus))
- {
- if (!strcmp(sc_link_proto->adapter->name, scsi_cinit[i].driver)
- &&(sc_link_proto->adapter_unit == scsi_cinit[i].unit))
- {
- if (IS_SPECIFIED(scsi_cinit[i].bus)) {
- if (sc_link_proto->adapter_bus==scsi_cinit[i].bus){
- bus = scsi_cinit[i].scbus;
- break;
- }
- }
- else if (sc_link_proto->adapter_bus == 0) {
- /* Backwards compatibility for single bus cards */
- bus = scsi_cinit[i].scbus;
- break;
- }
- else {
- printf("Ambiguous scbus configuration for %s%d "
- "bus %d, cannot wire down. The kernel "
- "config entry for scbus%d should specify "
- "a controller bus.\n"
- "Scbus will be assigned dynamically.\n",
- sc_link_proto->adapter->name,
- sc_link_proto->adapter_unit,
- sc_link_proto->adapter_bus,
- sc_link_proto->adapter_bus );
- break;
- }
- }
- }
- }
-
-
- if (bus == SCCONF_UNSPEC)
- bus = free_bus++;
- else if (bootverbose)
- printf("Choosing drivers for scbus configured at %d\n", bus);
-
- return bus;
-}
-
-/* scsi_assign_unit: Look through the structure generated by config.
- * See if there is a fixed assignment for this unit. If there isn't,
- * assign the next free unit.
- */
-static int
-scsi_assign_unit(struct scsi_link *sc_link)
-{
- int i;
- int found;
-#ifdef PC98
- struct cfdata cf;
- cf.cf_flags = 0;
-#endif
-
- found = 0;
- for (i = 0; scsi_dinit[i].name; i++) {
- if ((strcmp(sc_link->device->name, scsi_dinit[i].name) == 0) &&
- sc_link->target == scsi_dinit[i].target &&
- (
- (sc_link->lun == scsi_dinit[i].lun) ||
- (sc_link->lun == 0 && scsi_dinit[i].lun == SCCONF_UNSPEC)
- ) &&
- sc_link->scsibus == scsi_dinit[i].cunit) {
- sc_link->dev_unit = scsi_dinit[i].unit;
- found = 1;
-#ifdef PC98
- cf.cf_flags = scsi_dinit[i].flags;
-#endif
- if (bootverbose)
- printf("%s is configured at %d\n",
- sc_link->device->name, sc_link->dev_unit);
- break;
- }
- }
-
- if (!found)
- sc_link->dev_unit = sc_link->device->free_unit++;
-
-#ifdef PC98
- if (!found) {
- for (i = 0; scsi_dinit[i].name; i++) {
- if ((strcmp(sc_link->device->name, scsi_dinit[i].name) == 0) &&
- (scsi_dinit[i].target == SCCONF_UNSPEC))
- cf.cf_flags = scsi_dinit[i].flags;
- }
- }
- if (sc_link->adapter->open_target_lu)
- (*(sc_link->adapter->open_target_lu))(sc_link, &cf);
-#endif
-
- return sc_link->dev_unit;
-}
-
-
-#if NSCTARG > 0
-/* The SCSI target configuration is simpler. If an entry is present
- * we just return the bus, target and lun for that unit.
- */
-static void
-scsi_sctarg_lookup(char *name, int unit, int *target, int *lun, int *bus)
-{
- int i;
-
- *bus = SCCONF_UNSPEC;
- *target = SCCONF_UNSPEC;
- *lun = SCCONF_UNSPEC;
-
- for (i = 0; scsi_dinit[i].name; i++) {
- if ((strcmp(name, scsi_dinit[i].name) == 0) &&
- unit == scsi_dinit[i].unit)
- {
- *bus = scsi_dinit[i].cunit;
- *target = scsi_dinit[i].target;
- *lun = scsi_dinit[i].lun;
- }
- }
-}
-#endif /* NSCTARG > 0 */
-
-void
-scsi_configure_start(void)
-{
- scsi_init();
-}
-
-#if NSCTARG > 0
-static errval scsi_attach_sctarg __P((void));
-#endif
-
-void
-scsi_configure_finish(void)
-{
-
-#if NSCTARG > 0
- scsi_attach_sctarg();
-#endif
-
-}
-
-/*
- * scsi_attachdevs is the routine called by the adapter boards
- * to get all their devices configured in.
- */
-void
-scsi_attachdevs(scbus)
- struct scsibus_data *scbus;
-{
- int scsibus;
- struct scsi_link *sc_link_proto = scbus->adapter_link;
-
- if ( (scsibus = scsi_bus_conf(sc_link_proto)) == -1) {
- return;
- }
- /*
- * if the adapter didn't give us this, set a default
- * (compatibility with old adapter drivers)
- */
- if(!(sc_link_proto->opennings)) {
- sc_link_proto->opennings = 1;
- }
- sc_link_proto->scsibus = scsibus;
- /*
- * Allocate our target-lun space.
- */
- scbus->sc_link = (struct scsi_link *(*)[][8])malloc(
- sizeof(struct scsi_link *[scbus->maxtarg + 1][8]),
- M_TEMP, M_NOWAIT);
- if(scbus == 0 || scbus->sc_link == 0
- || extend_set(scbusses, scsibus, scbus) == 0) {
- panic("scsi_attachdevs: malloc");
- }
- bzero(scbus->sc_link, sizeof(struct scsi_link*[scbus->maxtarg + 1][8]));
-#if defined(SCSI_DELAY) && SCSI_DELAY > 2
- printf("%s%d: waiting for scsi devices to settle\n",
- sc_link_proto->adapter->name, sc_link_proto->adapter_unit);
-#else /* SCSI_DELAY > 2 */
-#undef SCSI_DELAY
-#define SCSI_DELAY 2
-#endif /* SCSI_DELAY */
- DELAY(1000000 * SCSI_DELAY);
- scsi_probe_bus(scsibus,-1,-1);
-}
-
-/*
- * Probe the requested scsi bus. It must be already set up.
- * -1 requests all set up scsi busses.
- * targ and lun optionally narrow the search if not -1
- */
-errval
-scsi_probe_busses(int bus, int targ, int lun)
-{
- if (bus == -1) {
- for(bus = 0; bus < scbusses->nelem; bus++) {
- scsi_probe_bus(bus, targ, lun);
- }
- return 0;
- } else {
- return scsi_probe_bus(bus, targ, lun);
- }
-}
-
-/* scsi_alloc_unit: Register a scsi_data pointer for a given
- * unit in a given scsi_device structure.
- *
- * XXX dufault@hda.com: I still don't like the way this reallocs stuff -
- * but at least now it is collected in one place instead of existing
- * in multiple type drivers. I'd like it better if we had it do a
- * second pass after it knew the sizes of everything and set up everything
- * at once.
- */
-static int
-scsi_alloc_unit(struct scsi_link *sc_link)
-{
- u_int32_t unit;
- struct scsi_data *sd;
- struct scsi_device *dsw;
-
- unit = sc_link->dev_unit;
- dsw = sc_link->device;
-
- /*
- * allocate the per unit data area
- */
- if (dsw->sizeof_scsi_data)
- {
- sd = malloc(dsw->sizeof_scsi_data, M_DEVBUF, M_NOWAIT);
- if (!sd) {
- printf("%s%lu: malloc failed for scsi_data\n",
- sc_link->device->name, (u_long)unit);
- return 0;
- }
- bzero(sd, dsw->sizeof_scsi_data);
- }
- else
- sd = 0;
-
- sc_link->sd = sd;
-
- if (extend_set(dsw->links, unit, (void *)sc_link) == 0) {
- printf("%s%lu: Can't store link pointer.\n",
- sc_link->device->name, (u_long)unit);
- free(sd, M_DEVBUF);
- return 0;
- }
-
- return 1;
-}
-
-static void
-scsi_free_unit(struct scsi_link *sc_link)
-{
- if (sc_link->sd)
- {
- free(sc_link->sd, M_DEVBUF);
- sc_link->sd = 0;
- }
- extend_release(sc_link->device->links, sc_link->dev_unit);
-}
-
-#if NSCTARG > 0
-
-/* XXX: It is a bug that the sc_link has this information
- * about the adapter in it. The sc_link should refer to
- * a structure that is host adpater specific. That will also
- * pull all knowledge of an sc_link out of the adapter drivers.
- */
-
-errval
-scsi_set_bus(int bus, struct scsi_link *sc_link)
-{
- struct scsi_link *ad_link;
- struct scsibus_data *scsibus_data;
-
- if (bus < 0 || bus > scbusses->nelem) {
- return ENXIO;
- }
-
- scsibus_data = (struct scsibus_data *)extend_get(scbusses, bus);
-
- if(!scsibus_data) {
- return ENXIO;
- }
-
- ad_link = scsibus_data->adapter_link;
-
- sc_link->adapter_unit = ad_link->adapter_unit;
- sc_link->adapter_targ = ad_link->adapter_targ;
- sc_link->adapter = ad_link->adapter;
- sc_link->device = ad_link->device;
- sc_link->flags = ad_link->flags;
-
- return 0;
-}
-
-/*
- * Allocate and attach as many SCSI target devices as configured.
- * There are two ways that you can configure the target device:
- * 1. In the configuration file. That is handled here.
- * 2. Via the minor number. That takes precedence over the config file.
- */
-static errval
-scsi_attach_sctarg()
-{
- struct scsi_link *sc_link = NULL;
- int dev_unit;
- struct scsi_device *sctarg = scsi_device_lookup(T_TARGET);
-
- if (sctarg == 0) {
- return ENXIO;
- }
-
- for (dev_unit = 0; dev_unit < NSCTARG; dev_unit++) {
-
- int target, lun, bus;
-
- /* If we don't have a link block allocate one.
- */
- if (!sc_link) {
- sc_link = malloc(sizeof(*sc_link), M_TEMP, M_NOWAIT);
- }
-
- scsi_sctarg_lookup(sctarg->name, dev_unit, &target, &lun, &bus);
-
- if (IS_SPECIFIED(bus)) {
- struct scsibus_data *scsibus_data;
-
- if (bus < 0 || bus > scbusses->nelem) {
- printf("%s%d: configured on illegal bus %d.\n",
- sctarg->name, dev_unit, bus);
- continue;
- }
-
- scsibus_data = (struct scsibus_data *)extend_get(scbusses, bus);
-
- if(!scsibus_data) {
- printf("%s%d: no bus %d.\n", sctarg->name, dev_unit, bus);
- continue;
- }
-
- *sc_link = *scsibus_data->adapter_link; /* struct copy */
- sc_link->target = target;
- sc_link->lun = lun;
- }
- else {
- /* This will be configured in the open routine.
- */
- sc_link->scsibus = SCCONF_UNSPEC;
- sc_link->target = SCCONF_UNSPEC;
- sc_link->lun = SCCONF_UNSPEC;
- }
-
- sc_link->quirks = 0;
- sc_link->device = sctarg;
- sc_link->dev_unit = dev_unit;
-
- if (scsi_alloc_unit(sc_link)) {
-
- if (scsi_device_attach(sc_link) == 0) {
- sc_link = NULL; /* it's been used */
- }
- else
- scsi_free_unit(sc_link);
- }
- }
-
- if (sc_link) {
- free(sc_link, M_TEMP);
- }
-
- return 0;
-}
-#endif /* NSCTARG > 0 */
-
-/*
- * Allocate a scsibus_data structure
- * The target/lun area is dynamically allocated in scsi_attachdevs after
- * the controller driver has a chance to update the maxtarg field.
- */
-struct scsibus_data*
-scsi_alloc_bus()
-{
- struct scsibus_data *scbus;
- /*
- * Prepare the scsibus_data area for the upperlevel
- * scsi code.
- */
- scbus = malloc(sizeof(struct scsibus_data), M_TEMP, M_NOWAIT);
- if(!scbus) {
- printf("scsi_alloc_bus: - cannot malloc!\n");
- return NULL;
- }
- bzero(scbus, sizeof(struct scsibus_data));
- /* Setup the defaults */
- scbus->maxtarg = 7;
- scbus->maxlun = 7;
- return scbus;
-}
-
-/*
- * Probe the requested scsi bus. It must be already set up.
- * targ and lun optionally narrow the search if not -1
- */
-errval
-scsi_probe_bus(int bus, int targ, int lun)
-{
- struct scsibus_data *scsibus_data ;
- int maxtarg,mintarg,maxlun,minlun;
- struct scsi_link *sc_link_proto;
- u_int8_t scsi_addr ;
- struct scsidevs *bestmatch = NULL;
- struct scsi_link *sc_link = NULL;
- boolean maybe_more;
- int type;
-
- if ((bus < 0 ) || ( bus >= scbusses->nelem)) {
- return ENXIO;
- }
- scsibus_data = (struct scsibus_data *)extend_get(scbusses, bus);
- if(!scsibus_data) return ENXIO;
- sc_link_proto = scsibus_data->adapter_link;
- scsi_addr = sc_link_proto->adapter_targ;
- if(targ == -1){
- maxtarg = scsibus_data->maxtarg;
- mintarg = 0;
- } else {
- if((targ < 0 ) || (targ > scsibus_data->maxtarg)) return EINVAL;
- maxtarg = mintarg = targ;
- }
-
- if(lun == -1){
- maxlun = scsibus_data->maxlun;
- minlun = 0;
- } else {
- if((lun < 0 ) || (lun > scsibus_data->maxlun)) return EINVAL;
- maxlun = minlun = lun;
- }
-
- printf("scbus%d at %s%d bus %d\n",
- sc_link_proto->scsibus, sc_link_proto->adapter->name,
- sc_link_proto->adapter_unit, sc_link_proto->adapter_bus);
-
- for ( targ = mintarg;targ <= maxtarg; targ++) {
- maybe_more = 0; /* by default only check 1 lun */
- if (targ == scsi_addr) {
- continue;
- }
- for ( lun = minlun; lun <= maxlun ;lun++) {
- /*
- * The spot appears to already have something
- * linked in, skip past it. Must be doing a 'reprobe'
- */
- if((*scsibus_data->sc_link)[targ][lun])
- {/* don't do this one, but check other luns */
- maybe_more = 1;
- continue;
- }
- /*
- * If we presently don't have a link block
- * then allocate one to use while probing
- */
- if (!sc_link) {
- sc_link = malloc(sizeof(*sc_link), M_TEMP, M_NOWAIT);
- }
- *sc_link = *sc_link_proto; /* struct copy */
- sc_link->device = &probe_switch;
- sc_link->target = targ;
- sc_link->lun = lun;
- sc_link->quirks = 0;
- bestmatch = scsi_probedev(sc_link, &maybe_more, &type);
- if (bestmatch) {
- sc_link->quirks = bestmatch->quirks;
- sc_link->devmodes = bestmatch->devmodes;
- } else {
- sc_link->quirks = 0;
- sc_link->devmodes = NULL;
- }
- if (bestmatch) { /* FOUND */
- sc_link->device = scsi_device_lookup(type);
-
- (void)scsi_assign_unit(sc_link);
-
- if (scsi_alloc_unit(sc_link)) {
-
- if (scsi_device_attach(sc_link) == 0) {
- (*scsibus_data->sc_link)[targ][lun] = sc_link;
- sc_link = NULL; /* it's been used */
- }
- else
- scsi_free_unit(sc_link);
- }
- }
-
- if (!(maybe_more)) { /* nothing suggests we'll find more */
- break; /* nothing here, skip to next targ */
- }
- /* otherwise something says we should look further */
- }
- }
- if (sc_link) {
- free(sc_link, M_TEMP);
- }
- return 0;
-}
-
-/* Return the scsi_link for this device, if any.
- */
-struct scsi_link *
-scsi_link_get(bus, targ, lun)
- int bus;
- int targ;
- int lun;
-{
- struct scsibus_data *scsibus_data =
- (struct scsibus_data *)extend_get(scbusses, bus);
- return (scsibus_data) ? (*scsibus_data->sc_link)[targ][lun] : 0;
-}
-
-/* make_readable: Make the inquiry data readable. Anything less than a ' '
- * is made a '?' and trailing spaces are removed.
- */
-static void
-make_readable(to, from, n)
- char *to;
- char *from;
- size_t n;
-{
- int i;
-
- for (i = 0; from[i] && i < n - 1; i++) {
- if (from[i] < ' ')
- to[i]='?';
- else
- to[i] = from[i];
- }
-
- while (i && to[i - 1] == ' ')
- i--;
-
- to[i] = 0;
-}
-
-#ifndef SCSIDEBUG
-void scsi_print_info(sc_link)
- struct scsi_link *sc_link;
-{
- int dtype = 0;
- char *desc;
- char *qtype;
- struct scsi_inquiry_data *inqbuf;
- u_int32_t len, qualifier, type;
- boolean remov;
- char manu[8 + 1];
- char model[16 + 1];
- char version[4 + 1];
-
- inqbuf = &sc_link->inqbuf;
-
- type = inqbuf->device & SID_TYPE;
- qualifier = inqbuf->device & SID_QUAL;
- remov = inqbuf->dev_qual2 & SID_REMOVABLE;
-
- switch ((int)qualifier) {
- case SID_QUAL_LU_OK:
- qtype = "";
- break;
-
- case SID_QUAL_LU_OFFLINE:
- qtype = "Supported device currently not connected";
- break;
-
- default:
- dtype = 1;
- qtype = "Vendor specific peripheral qualifier";
- break;
- }
-
- if ((inqbuf->version & SID_ANSII) > 0) {
- if ((len = inqbuf->additional_length
- + ((char *) inqbuf->unused
- - (char *) inqbuf))
- > (sizeof(struct scsi_inquiry_data) - 1))
- len = sizeof(struct scsi_inquiry_data) - 1;
- desc = inqbuf->vendor;
- desc[len - (desc - (char *) inqbuf)] = 0;
- make_readable(manu, inqbuf->vendor, sizeof(manu));
- make_readable(model, inqbuf->product, sizeof(model));
- make_readable(version, inqbuf->revision, sizeof(version));
- } else {
- /*
- * If not advanced enough, use default values
- */
- desc = "early protocol device";
- make_readable(manu, "unknown", sizeof(manu));
- make_readable(model, "unknown", sizeof(model));
- make_readable(version, "????", sizeof(version));
- }
-
- printf("%s%d: ", sc_link->device->name,
- sc_link->dev_unit);
- printf("<%s %s %s> ", manu, model, version );
- printf("type %lu %sSCSI %d",
- (u_long)type, remov ? "removable " : "fixed ",
- inqbuf->version & SID_ANSII);
- if (qtype[0]) {
- sc_print_addr(sc_link);
- printf(" qualifier %lu: %s", (u_long)qualifier, qtype);
- }
-
- printf("\n");
-}
-#endif
-
-/*
- * given a target and lu, ask the device what
- * it is, and find the correct driver table
- * entry.
- */
-static struct scsidevs *
-scsi_probedev(sc_link, maybe_more, type_p)
- boolean *maybe_more;
- struct scsi_link *sc_link;
- int *type_p;
-{
-#ifdef SCSIDEBUG
- u_int8_t target = sc_link->target;
- u_int8_t lu = sc_link->lun;
-#endif
- struct scsidevs *bestmatch = (struct scsidevs *) 0;
- int dtype = 0;
- char *desc;
- char *qtype;
- struct scsi_inquiry_data *inqbuf;
- u_int32_t len, qualifier, type;
- boolean remov;
- char manu[8 + 1];
- char model[16 + 1];
- char version[4 + 1];
-
- inqbuf = &sc_link->inqbuf;
-
- bzero(inqbuf, sizeof(*inqbuf));
- /*
- * Ask the device what it is
- */
-#ifdef SCSIDEBUG
- if ((target == DEBUGTARG) && (lu == DEBUGLUN))
- sc_link->flags |= (DEBUGLEVEL);
- else
- sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2 | SDEV_DB3 | SDEV_DB4);
-#endif /* SCSIDEBUG */
- /* catch unit attn */
- scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
-#ifdef DOUBTFULL
- switch (scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT)) {
- case 0: /* said it WAS ready */
- case EBUSY: /* replied 'NOT READY' but WAS present, continue */
- case ENXIO:
- break;
- case EIO: /* device timed out */
- case EINVAL: /* Lun not supported */
- default:
- return (struct scsidevs *) 0;
-
- }
-#endif /*DOUBTFULL*/
-#ifdef SCSI_2_DEF
- /* some devices need to be told to go to SCSI2 */
- /* However some just explode if you tell them this.. leave it out */
- scsi_change_def(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
-#endif /*SCSI_2_DEF */
-
- /* Now go ask the device all about itself */
- if (scsi_inquire(sc_link, inqbuf, SCSI_NOSLEEP | SCSI_NOMASK) != 0) {
- return (struct scsidevs *) 0;
- }
-
- /*
- * note what BASIC type of device it is
- */
- type = inqbuf->device & SID_TYPE;
- qualifier = inqbuf->device & SID_QUAL;
- remov = inqbuf->dev_qual2 & SID_REMOVABLE;
-
- /*
- * Any device qualifier that has the top bit set (qualifier&4 != 0)
- * is vendor specific and will match in the default of this switch.
- */
-
- switch ((int)qualifier) {
- case SID_QUAL_LU_OK:
- qtype = "";
- break;
-
- case SID_QUAL_LU_OFFLINE:
- qtype = "Supported device currently not connected";
- break;
-
- case SID_QUAL_RSVD: /* Peripheral qualifier reserved in SCSI-2 spec */
- *maybe_more = 1;
- return (struct scsidevs *) 0;
-
- case SID_QUAL_BAD_LU: /* Target can not support a device on this unit */
- /*
- * Check for a non-existent unit. If the device is returning
- * this much, then we must set the flag that has
- * the searchers keep looking on other luns.
- */
- *maybe_more = 1;
- return (struct scsidevs *) 0;
-
- default:
- dtype = 1;
- qtype = "Vendor specific peripheral qualifier";
- *maybe_more = 1;
- break;
- }
-
- if (dtype == 0) {
- if (type == T_NODEVICE) {
- *maybe_more = 1;
- return (struct scsidevs *) 0;
- }
- dtype = 1;
- }
- /*
- * Then if it's advanced enough, more detailed
- * information
- */
- if ((inqbuf->version & SID_ANSII) > 0) {
- if ((len = inqbuf->additional_length
- + ((char *) inqbuf->unused
- - (char *) inqbuf))
- > (sizeof(struct scsi_inquiry_data) - 1))
- len = sizeof(struct scsi_inquiry_data) - 1;
- desc = inqbuf->vendor;
- desc[len - (desc - (char *) inqbuf)] = 0;
- make_readable(manu, inqbuf->vendor, sizeof(manu));
- make_readable(model, inqbuf->product, sizeof(model));
- make_readable(version, inqbuf->revision, sizeof(version));
- } else {
- /*
- * If not advanced enough, use default values
- */
- desc = "early protocol device";
- make_readable(manu, "unknown", sizeof(manu));
- make_readable(model, "unknown", sizeof(model));
- make_readable(version, "????", sizeof(version));
- type = T_UNKNOWN;
- }
-
-#ifdef SCSIDEBUG
- sc_print_start(sc_link);
-
- printf("<%s %s %s> ", manu, model, version );
- printf("type %lu %sSCSI %d"
- ,(u_long)type
- ,remov ? "removable " : "fixed "
- ,inqbuf->version & SID_ANSII
- );
- if (qtype[0]) {
- sc_print_addr(sc_link);
- printf(" qualifier %lu: %s", (u_long)qualifier, qtype);
- }
-
- printf("\n");
- sc_print_finish();
-#endif
- /*
- * Try make as good a match as possible with
- * available sub drivers
- */
- bestmatch = (scsi_selectdev(
- qualifier, type, remov ? T_REMOV : T_FIXED, manu, model, version));
- 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->driver;
- return bestmatch;
-}
-
-/* Try to find the major number for a device during attach.
- */
-dev_t
-scsi_dev_lookup(d_open)
- d_open_t *d_open;
-{
- int i;
-
- dev_t d = NODEV;
-
- for (i = 0; i < nchrdev; i++)
- if (cdevsw[i] && cdevsw[i]->d_open == d_open)
- {
- d = makedev(i, 0);
- break;
- }
-
- return d;
-}
-
-/*
- * Compare name with pattern, return 0 on match.
- * Short pattern matches trailing blanks in name,
- * wildcard '*' in pattern matches rest of name
- */
-static int
-match(pattern, name)
- char *pattern;
- char *name;
-{
- char c;
- while (c = *pattern++)
- {
- if (c == '*') return 0;
- if ((c == '?') && (*name > ' ')) continue;
- if (c != *name++) return 1;
- }
- while (c = *name++)
- {
- if (c != ' ') return 1;
- }
- return 0;
-}
-
-/*
- * Try make as good a match as possible with
- * available sub drivers
- */
-static struct scsidevs *
-scsi_selectdev(qualifier, type, remov, manu, model, rev)
- u_int32_t qualifier, type;
- boolean remov;
- char *manu, *model, *rev;
-{
- struct scsidevs *bestmatch = NULL;
- struct scsidevs *thisentry;
-
- type |= qualifier; /* why? */
-
- for ( thisentry = knowndevs; thisentry->manufacturer; thisentry++ )
- {
- if (type != thisentry->type) {
- continue;
- }
- if (remov != thisentry->removable) {
- continue;
- }
-
- if (thisentry->flags & SC_SHOWME)
- printf("\n%s-\n%s-", thisentry->manufacturer, manu);
- if (match(thisentry->manufacturer, manu)) {
- continue;
- }
- if (thisentry->flags & SC_SHOWME)
- printf("\n%s-\n%s-", thisentry->model, model);
- if (match(thisentry->model, model)) {
- continue;
- }
- if (thisentry->flags & SC_SHOWME)
- printf("\n%s-\n%s-", thisentry->version, rev);
- if (match(thisentry->version, rev)) {
- continue;
- }
- bestmatch = thisentry;
- break;
- }
- if (bestmatch == (struct scsidevs *) 0) {
- bestmatch = &unknowndev;
- }
- return (bestmatch);
-}
diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h
deleted file mode 100644
index 6961077..0000000
--- a/sys/scsi/scsiconf.h
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- * Written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- *
- * $Id: scsiconf.h,v 1.60 1998/05/24 04:52:31 julian Exp $
- */
-#ifndef SCSI_SCSICONF_H
-#define SCSI_SCSICONF_H 1
-typedef int boolean;
-typedef int errval;
-
-#include <scsi/scsi_all.h>
-#include <sys/callout.h> /* XXX For ioconf.c */
-
-/*
- * The following documentation tries to describe the relationship between the
- * various structures defined in this file:
- *
- * each adapter type has a scsi_adapter struct. This describes the adapter and
- * identifies routines that can be called to use the adapter.
- * each device type has a scsi_device struct. This describes the device and
- * identifies routines that can be called to use the device.
- * each existing device position (scsibus + target + lun)
- * can be described by a scsi_link struct.
- * Only scsi positions that actually have devices, have a scsi_link
- * structure assigned. so in effect each device has scsi_link struct.
- * The scsi_link structure contains information identifying both the
- * device driver and the adapter driver for that position on that scsi bus,
- * and can be said to 'link' the two.
- * each individual scsi bus has an array that points to all the scsi_link
- * structs associated with that scsi bus. Slots with no device have
- * a NULL pointer.
- * each individual device also knows the address of its own scsi_link
- * structure.
- *
- * -------------
- *
- * The key to all this is the scsi_link structure which associates all the
- * other structures with each other in the correct configuration. The
- * scsi_link is the connecting information that allows each part of the
- * scsi system to find the associated other parts.
- */
-
-struct buf;
-struct scsi_xfer;
-#ifdef PC98
-struct cfdata;
-#endif
-
-/* Don't poke around inside of "scsi_data". Each low level
- * driver has its own definition for it.
- */
-struct scsi_data;
-struct scsi_link; /* scsi_link refers to scsi_device and vice-versa */
-
-struct proc;
-
-/*
- * These entrypoints are called by the high-end drivers to get services from
- * whatever low-end drivers they are attached to each adapter type has one of
- * these statically allocated.
- */
-struct scsi_adapter
-{
-/* 04*/ int32_t (*scsi_cmd) __P((struct scsi_xfer *xs));
-/* 08*/ void (*scsi_minphys) __P((struct buf *bp));
-#ifdef PC98
-/* 12*/ int32_t (*open_target_lu) __P((struct scsi_link *sc_link,
- struct cfdata *cf));
-#else
-/* 12*/ int32_t (*open_target_lu) __P((void));
-#endif
-/* 16*/ int32_t (*close_target_lu) __P((void));
-/* 20*/ u_int32_t (*adapter_info) __P((int unit)); /* see definitions below */
-/* 24*/ char *name; /* name of scsi bus controller */
-/* 32*/ u_long spare[2];
-};
-
-/*
- * return values for scsi_cmd()
- */
-#define SUCCESSFULLY_QUEUED 0
-#define TRY_AGAIN_LATER 1
-#define COMPLETE 2
-#define HAD_ERROR 3 /* do not use this, use COMPLETE */
-#define ESCAPE_NOT_SUPPORTED 4
-
-/*
- * Return value from sense handler. IMHO, These ought to be merged
- * in with the return codes above, all made negative to distinguish
- * from valid errno values, and replace "try again later" with "do retry"
- */
-#define SCSIRET_CONTINUE -1 /* Continue with standard sense processing */
-#define SCSIRET_DO_RETRY -2 /* Retry the command that got this sense */
-
-/*
- * Format of adapter_info() response data
- * e.g. maximum number of entries queuable to a device by the adapter
- */
-
-/*
- * 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
- * of these statically allocated.
- *
- * XXX dufault@hda.com: Each adapter driver has a scsi_device structure
- * that I don't think should be there.
- * This structure should be rearranged and cleaned up once the
- * instance down in the adapter drivers is removed.
- */
-
-/*
- * XXX this is so that everything that includes this bloated header doesn't
- * also need to include <sys/conf.h>.
- */
-typedef int yet_another_d_open_t __P((dev_t, int, int, struct proc *));
-
-struct scsi_device
-{
-/* 4*/ errval (*err_handler)(struct scsi_xfer *xs);
-/* 8*/ void (*start)(u_int32_t unit, u_int32_t flags);
-/* 12*/ int32_t (*async) __P((void));
-/* 16*/ int32_t (*done) __P((struct scsi_xfer *xs));
-/* 20*/ char *name; /* name of device type */
-/* 24*/ u_int32_t flags; /* device type dependent flags */
-/* 32*/ int32_t spare[2];
-/* 36*/ int32_t link_flags; /* set -> sc_link at attach time */
-/* 40*/ errval (*attach)(struct scsi_link *sc_link);
-/* 44*/ char *desc; /* Description of device */
-/* 48*/ yet_another_d_open_t *open;
-/* 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);
-/* 68*/ int (*dev_open)(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-/* 72*/ int (*dev_ioctl)(dev_t dev, u_long 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 */
-/* 84*/ struct extend_array *links;
-/* 88*/ int free_unit;
-/* 92*/ struct scsi_device *next; /* Next in list in the registry. */
-};
-/*
- * Macros to access soem fields above.
- */
-#define SCSI_LINK(DEV, UNIT) \
- ((struct scsi_link *)(extend_get((DEV)->links, (UNIT))))
-
-#define SCSI_DATA(DEV, UNIT) \
- ((SCSI_LINK((DEV), (UNIT)) ? (SCSI_LINK((DEV), (UNIT))->sd) : NULL))
-
-/*
- * SCSI_DEVICE_ENTRIES: A macro to generate all the entry points from the
- * name.
- */
-#define SCSI_DEVICE_ENTRIES(NAME) \
-static errval NAME##attach(struct scsi_link *sc_link); \
-extern struct scsi_device NAME##_switch; /* XXX actually static */ \
-void NAME##init(void) { \
- scsi_device_register(&NAME##_switch); \
-} \
-static int NAME##open(dev_t dev, int flags, int fmt, struct proc *p) { \
- return scsi_open(dev, flags, fmt, p, &NAME##_switch); \
-} \
-static int NAME##ioctl(dev_t dev, u_long cmd, caddr_t addr, \
- int flag, struct proc *p) { \
- return scsi_ioctl(dev, cmd, addr, flag, p, &NAME##_switch); \
-} \
-static int NAME##close(dev_t dev, int flag, int fmt, struct proc *p) { \
- return scsi_close(dev, flag, fmt, p, &NAME##_switch); \
-} \
-static void NAME##minphys(struct buf *bp) { \
- scsi_minphys(bp, &NAME##_switch); \
-} \
-static void NAME##strategy(struct buf *bp) { \
- scsi_strategy(bp, &NAME##_switch); \
-}
-
-#ifdef KERNEL
-/* Configuration tables for config.
- */
-/* A unit, type, etc can be SCCONF_ANY to indicate it is a '?'
- * in the config.
- */
-#define SCCONF_UNSPEC 255
-#define SCCONF_ANY 254
-
-struct isa_driver;
-struct scsi_ctlr_config
-{
- int scbus;
- char *driver;
- int unit;
- int bus;
-};
-
-struct scsi_device_config
-{
- char *name; /* SCSI device name (sd, st, etc) */
- int unit; /* desired device unit */
- int cunit; /* Controller unit */
- int target; /* SCSI ID (target) */
- int lun; /* SCSI lun */
- int flags; /* Flags from config */
-};
-
-extern void (*scsi_tinit[])(void);
-extern struct scsi_ctlr_config scsi_cinit[];
-extern struct scsi_device_config scsi_dinit[];
-
-#endif
-
-/*
- * Define various devices that we know mis-behave in some way,
- * and note how they are bad, so we can correct for them
- */
-struct st_mode {
-/* 4*/ u_int32_t blksiz;
-/* 6*/ u_int16_t quirks; /* same definitions as in XXX */
-/* 7*/ u_int8_t density;
-/* 8*/ u_int8_t spare[1];
-};
-
-typedef struct st_mode st_modes[4];
-
-/* define behaviour codes (quirks) */
-/* common to all SCSI devices */
-#define SCSI_Q_NO_SYNC 0x8000
-#define SCSI_Q_NO_FAST 0x4000
-#define SCSI_Q_NO_WIDE 0x2000
-
-/* tape specific ST_Q_* */
-#define ST_Q_NEEDS_PAGE_0 0x0001
-#define ST_Q_FORCE_FIXED_MODE 0x0002
-#define ST_Q_FORCE_VAR_MODE 0x0004
-#define ST_Q_SNS_HLP 0x0008 /* must do READ for good MODE SENSE */
-#define ST_Q_IGNORE_LOADS 0x0010
-#define ST_Q_BLKSIZ 0x0020 /* variable-block media_blksiz > 0 */
-#define ST_Q_CC_NOMSG 0x0040 /* no messages accepted in CC state */
-#define ST_Q_NO_1024 0x0080 /* never ever use 1024-byte fix blk */
-
-#define ST_Q_NO_SYNC SCSI_Q_NO_SYNC
-#define ST_Q_NO_FAST SCSI_Q_NO_FAST
-#define ST_Q_NO_WIDE SCSI_Q_NO_WIDE
-
-/* disk specific SD_Q_* */
-#define SD_Q_NO_TAGS 0x0001
-
-#define SD_Q_NO_SYNC SCSI_Q_NO_SYNC
-#define SD_Q_NO_FAST SCSI_Q_NO_FAST
-#define SD_Q_NO_WIDE SCSI_Q_NO_WIDE
-
-/* cd specific CD_Q_* */
-#define CD_Q_NO_TOUCH 0x0001
-#define CD_Q_BCD_TRACKS 0x0002
-#define CD_Q_NO_START 0x0004
-
-
-/* worm specific WORM_Q_* */
-#define WORM_Q_PLASMON 0x0001
-#define WORM_Q_PHILIPS 0x0002
-/*
- * This structure describes the connection between an adapter driver and
- * a device driver, and is used by each to call services provided by
- * the other, and to allow generic scsi glue code to call these services
- * as well.
- */
-struct scsi_link
-{
- u_int8_t target; /* targ of this dev */
- u_int8_t lun; /* lun of this dev */
- u_int8_t adapter_targ; /* what are we on the scsi bus*/
- u_int8_t adapter_unit; /* e.g. the 0 in aha0 */
- u_int8_t adapter_bus; /* e.g. the 0 in bus0 */
- u_int8_t scsibus; /* the Nth scsibus */
- u_int8_t dev_unit; /* e.g. the 0 in sd0 */
- u_int8_t opennings; /* available operations */
- u_int8_t active; /* operations in progress */
- u_int16_t flags; /* flags all devices have */
- u_int16_t quirks; /* device specific quirks */
- struct scsi_adapter *adapter; /* adapter entry points etc. */
- struct scsi_device *device; /* device entry points etc. */
- struct scsi_xfer *active_xs; /* operations under way */
- void *fordriver; /* for driver's private user */
- void *devmodes; /* dev specific mode tables */
- dev_t dev; /* Device major # (character) */
- struct scsi_data *sd; /* Device data structure */
- struct scsi_inquiry_data inqbuf; /* Inquiry data */
- void *adapter_softc; /* to call foo_scsi_cmd */
-};
-
-/* XXX-HA: dufault@hda.com: SDEV_BOUNCE is set down in the adapter drivers
- * in an sc_link structure to indicate that this host adapter requires
- * ISA DMA bounce buffers. I think the link structure should
- * be associated only with the type drive and not the adapter driver,
- * and the bounce flag should be in something associated with the
- * adapter driver.
- * XXX-HA And I added the "supports residuals properly" flag that ALSO goes
- * in an adapter structure. I figure I'll fix both at once.
- *
- * XXX SDEV_OPEN is used for two things: To prevent more than one
- * open and to make unit attentions errors be logged on the console.
- * These should be split up; I'm adding SDEV_IS_OPEN to enforce one
- * open only.
- *
- * XXX SDEV_UK is used to mark the "uk" device.
- */
-
-#define SDEV_MEDIA_LOADED 0x0001 /* device figures are still valid */
-#define SDEV_WAITING 0x0002 /* a process is waiting for this */
-#define SDEV_OPEN 0x0004 /* at least 1 open session */
-#define SDEV_BOUNCE 0x0008 /* XXX-HA: unit needs DMA bounce buffer */
-#define SDEV_DBX 0x00F0 /* debugging flags (scsi_debug.h) */
-#define SDEV_ONCE_ONLY 0x0100 /* unit can only be opened once */
-#define SDEV_BOOTVERBOSE 0x0200 /* be noisy during boot */
-#define SDEV_RESIDS_WORK 0x0400 /* XXX-HA: Residuals work */
-#define SDEV_TARGET_OPS 0x0800 /* XXX-HA: Supports target ops */
-#define SDEV_IS_OPEN 0x1000 /* at least 1 open session */
-#define SDEV_UK 0x2000 /* this is the "uk" device */
-#define SDEV_XLOCK 0x4000 /* Device is locked */
-#define SDEV_WANT 0x8000 /* A process is waiting for lock */
-
-/*
- * One of these is allocated and filled in for each scsi bus.
- * it holds pointers to allow the scsi bus to get to the driver
- * That is running each LUN on the bus
- * it also has a template entry which is the prototype struct
- * supplied by the adapter driver, this is used to initialise
- * the others, before they have the rest of the fields filled in
- */
-struct scsibus_data {
- u_char maxtarg;
- u_char maxlun;
- struct scsi_link *adapter_link; /* prototype supplied by adapter */
- struct scsi_link *(*sc_link)[][8]; /* dynamically allocated */
-};
-
-/*
- * Each scsi transaction is fully described by one of these structures
- * It includes information about the source of the command and also the
- * device and adapter for which the command is destined.
- * (via the scsi_link structure) *
- */
-struct scsi_xfer
-{
-/*04*/ struct scsi_xfer *next; /* when free */
-/*08*/ u_int32_t flags;
-/*12*/ struct scsi_link *sc_link; /* all about our device and adapter */
-/*13*/ u_int8_t retries; /* the number of times to retry */
-/*16*/ u_int8_t spare[3];
-/*20*/ int32_t timeout; /* in milliseconds */
-/*24*/ struct scsi_generic *cmd; /* The scsi command to execute */
-/*28*/ int32_t cmdlen; /* how long it is */
-/*32*/ u_char *data; /* dma address OR a uio address */
-/*36*/ int32_t datalen; /* data len (blank if uio) */
-/*40*/ int32_t resid; /* how much buffer was not touched */
-/*44*/ int32_t error; /* an error value */
-/*48*/ struct buf *bp; /* If we need to associate with a buf */
-/*80*/ struct scsi_sense_data sense; /* 32 bytes*/
- /*
- * Believe it or not, Some targets fall on the ground with
- * anything but a certain sense length.
- */
-/*84*/ int32_t req_sense_length; /* Explicit request sense length */
-/*88*/ int32_t status; /* SCSI status */
-/*100*/ struct scsi_generic cmdstore; /* stash the command in here */
- /*
- * Handle for scheduling
- * command timeouts.
- */
- struct callout_handle timeout_ch;
-};
-
-/*
- * Per-request Flag values
- */
-#define SCSI_NOSLEEP 0x01 /* Not a user... don't sleep */
-#define SCSI_NOMASK 0x02 /* dont allow interrupts.. booting */
-#define SCSI_NOSTART 0x04 /* left over from ancient history */
-#define SCSI_USER 0x08 /* Is a user cmd, call scsi_user_done */
-#define SCSI_ITSDONE 0x10 /* the transfer is as done as it gets */
-#define ITSDONE 0x10 /* the transfer is as done as it gets */
-#define SCSI_INUSE 0x20 /* The scsi_xfer block is in use */
-#define INUSE 0x20 /* The scsi_xfer block is in use */
-#define SCSI_SILENT 0x40 /* Don't report errors to console */
-#define SCSI_ERR_OK 0x80 /* An error on this operation is OK. */
-#define SCSI_RESET 0x100 /* Reset the device in question */
-#define SCSI_DATA_UIO 0x200 /* The data address refers to a UIO */
-#define SCSI_DATA_IN 0x400 /* expect data to come INTO memory */
-#define SCSI_DATA_OUT 0x800 /* expect data to flow OUT of memory */
-#define SCSI_TARGET 0x1000 /* This defines a TARGET mode op. */
-#define SCSI_ESCAPE 0x2000 /* Escape operation */
-#define SCSI_EOF 0x4000 /* The operation should return EOF */
-#define SCSI_RESID_VALID 0x8000 /* The resid field contains valid data */
-
-/*
- * Escape op codes. This provides an extensible setup for operations
- * that are not scsi commands. They are intended for modal operations.
- */
-
-#define SCSI_OP_TARGET 0x0001
-#define SCSI_OP_RESET 0x0002
-#define SCSI_OP_BDINFO 0x0003
-
-/*
- * Error values an adapter driver may return
- */
-#define XS_NOERROR 0x0 /* there is no error, (sense is invalid) */
-#define XS_SENSE 0x1 /* Check the returned sense for the error */
-#define XS_DRIVER_STUFFUP 0x2 /* Driver failed to perform operation */
-#define XS_TIMEOUT 0x03 /* The device timed out.. turned off? */
-#define XS_SWTIMEOUT 0x04 /* The Timeout reported was caught by SW */
-#define XS_BUSY 0x08 /* The device busy, try again later? */
-#define XS_LENGTH 0x09 /* Illegal length (over/under run) */
-#define XS_SELTIMEOUT 0x10 /* Device failed to respond to selection */
-
-#ifdef KERNEL
-void *extend_get(struct extend_array *ea, int index);
-void scsi_attachdevs __P((struct scsibus_data *scbus));
-u_int32_t scsi_read_capacity __P(( struct scsi_link *sc_link,
- u_int32_t *blk_size, u_int32_t flags));
-errval scsi_test_unit_ready __P(( struct scsi_link *sc_link, u_int32_t flags));
-errval scsi_reset_target __P((struct scsi_link *));
-errval scsi_target_mode __P((struct scsi_link *, int));
-errval scsi_inquire( struct scsi_link *sc_link,
- struct scsi_inquiry_data *inqbuf, u_int32_t flags);
-errval scsi_prevent( struct scsi_link *sc_link, u_int32_t type,u_int32_t flags);
-struct scsibus_data *scsi_alloc_bus __P((void));
-errval scsi_probe_bus __P((int, int, int));
-errval scsi_probe_busses __P(( int, int, int));
-errval scsi_start_unit( struct scsi_link *sc_link, u_int32_t flags);
-errval scsi_stop_unit(struct scsi_link *sc_link, u_int32_t eject, u_int32_t flags);
-void scsi_done(struct scsi_xfer *xs);
-void scsi_user_done(struct scsi_xfer *xs);
-errval scsi_scsi_cmd __P(( struct scsi_link *, struct scsi_generic *,
- u_int32_t, u_char *,
- u_int32_t, u_int32_t,
- u_int32_t, struct buf *,
- u_int32_t));
-int scsi_do_ioctl __P((dev_t dev, u_long 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, int fmt,
-struct proc *p)));
-
-int scsi_opened_ok __P((dev_t dev, int flag, int type, struct scsi_link *sc_link));
-errval scsi_set_bus __P((int, struct scsi_link *));
-
-char *scsi_sense_desc __P((int, int));
-void scsi_sense_print __P((struct scsi_xfer *));
-void show_scsi_cmd __P((struct scsi_xfer *));
-
-void scsi_uto3b __P((u_int32_t , u_char *));
-u_int32_t scsi_3btou __P((u_char *));
-int32_t scsi_3btoi __P((u_char *));
-void scsi_uto4b __P((u_int32_t, u_char *));
-u_int32_t scsi_4btou __P((u_char *));
-void scsi_uto2b __P((u_int32_t, u_char *));
-u_int32_t scsi_2btou __P((u_char *));
-
-void sc_print_addr __P((struct scsi_link *));
-void sc_print_start __P((struct scsi_link *));
-void sc_print_init __P((void));
-void sc_print_finish __P((void));
-
-#ifndef SCSIDEBUG
-void scsi_print_info __P((struct scsi_link *));
-#endif
-
-void scsi_device_register __P((struct scsi_device *sd));
-
-void scsi_configure_start __P((void));
-void scsi_configure_finish __P((void));
-
-void ukinit __P((void));
-
-#ifdef SCSI_2_DEF
-errval scsi_change_def( struct scsi_link *sc_link, u_int32_t flags);
-#endif
-#endif /* KERNEL */
-
-#define SCSI_EXTERNALLEN (sizeof(struct scsi_link))
-
-
-/* XXX This belongs in a tape file.
- */
-
-/**********************************************************************
- from the scsi2 spec
- Value Tracks Density(bpi) Code Type Reference Note
- 0x1 9 800 NRZI R X3.22-1983 2
- 0x2 9 1600 PE R X3.39-1986 2
- 0x3 9 6250 GCR R X3.54-1986 2
- 0x5 4/9 8000 GCR C X3.136-1986 1
- 0x6 9 3200 PE R X3.157-1987 2
- 0x7 4 6400 IMFM C X3.116-1986 1
- 0x8 4 8000 GCR CS X3.158-1986 1
- 0x9 18 37871 GCR C X3B5/87-099 2
- 0xA 22 6667 MFM C X3B5/86-199 1
- 0xB 4 1600 PE C X3.56-1986 1
- 0xC 24 12690 GCR C HI-TC1 1,5
- 0xD 24 25380 GCR C HI-TC2 1,5
- 0xF 15 10000 GCR C QIC-120 1,5
- 0x10 18 10000 GCR C QIC-150 1,5
- 0x11 26 16000 GCR C QIC-320(525?) 1,5
- 0x12 30 51667 RLL C QIC-1350 1,5
- 0x13 1 61000 DDS CS X3B5/88-185A 4
- 0x14 1 43245 RLL CS X3.202-1991 4
- 0x15 1 45434 RLL CS ECMA TC17 4
- 0x16 48 10000 MFM C X3.193-1990 1
- 0x17 48 42500 MFM C X3B5/91-174 1
-
- where Code means:
- NRZI Non Return to Zero, change on ones
- GCR Group Code Recording
- PE Phase Encoded
- IMFM Inverted Modified Frequency Modulation
- MFM Modified Frequency Modulation
- DDS Dat Data Storage
- RLL Run Length Encoding
-
- where Type means:
- R Real-to-Real
- C Cartridge
- CS cassette
-
- where Notes means:
- 1 Serial Recorded
- 2 Parallel Recorded
- 3 Old format know as QIC-11
- 4 Helical Scan
- 5 Not ANSI standard, rather industry standard.
-
-********************************************************************/
-
-#define HALFINCH_800 0x01
-#define HALFINCH_1600 0x02
-#define HALFINCH_6250 0x03
-#define QIC_11 0x04 /* from Archive 150S Theory of Op. XXX */
-#define QIC_24 0x05 /* may be bad, works for CIPHER ST150S XXX */
-#define QIC_120 0x0f
-#define QIC_150 0x10
-#define QIC_320 0x11
-#define QIC_525 0x11
-#define QIC_1320 0x12
-#define DDS 0x13
-#define DAT_1 0x13
-#define QIC_3080 0x29
-
-
-/* XXX (dufault@hda.com) This is used only by "su" and "sctarg".
- * The minor number field conflicts with the disk slice code,
- * and so it is tough to access the disks through the "su" device.
- */
-
-/* Device number fields:
- *
- * NON-FIXED SCSI devices:
- *
- * ?FC? ???? ???? ???? MMMMMMMM mmmmmmmm
- *
- * F: Fixed device (nexus in number): must be 0.
- * C: Control device; only user mode ioctl is supported.
- * ?: Don't know; those bits didn't use to exist, currently always 0.
- * M: Major device number.
- * m: Old style minor device number.
- *
- * FIXED SCSI devices:
- *
- * XXX Conflicts with the slice code. Maybe the slice code can be
- * changed to respect the F bit?
- *
- * ?FC? ?BBB TTTT ?LLL MMMMMMMM mmmmmmmm
- *
- * F: Fixed device (nexus in number); must be 1.
- * C: Control device; only user mode ioctl is supported.
- * B: SCSI bus
- * T: SCSI target ID
- * L: Logical unit
- * M: Major device number
- * m: Old style minor device number.
- */
-
-#define SCSI_FIXED_MASK 0x40000000
-#define SCSI_FIXED(DEV) (((DEV) & SCSI_FIXED_MASK))
-#define SCSI_CONTROL_MASK 0x20000000
-#define SCSI_CONTROL(DEV) (((DEV) & SCSI_CONTROL_MASK))
-
-#define SCSI_BUS(DEV) (((DEV) & 0x07000000) >> 24)
-#define SCSI_ID(DEV) (((DEV) & 0x00F00000) >> 20)
-#define SCSI_LUN(DEV) (((DEV) & 0x00070000) >> 16)
-
-#define SCSI_MKFIXED(B, T, L, P) ( \
- ((B) << 24) | \
- ((T) << 20) | \
- ((L) << 16) | \
- (P) | \
- SCSI_FIXED_MASK )
-
-#endif /*SCSI_SCSICONF_H*/
-/* END OF FILE */
diff --git a/sys/scsi/sctarg.c b/sys/scsi/sctarg.c
deleted file mode 100644
index d2f8f6f..0000000
--- a/sys/scsi/sctarg.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * sctarg: Target mode user interface
- *
- * 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: sctarg.c,v 1.27 1998/07/04 22:30:24 julian Exp $
- */
-
-#include "opt_bounce.h"
-#include "opt_devfs.h"
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-#include "ioconf.h"
-
-#define OPEN 0x01
-
-struct scsi_data {
- struct buf_queue_head buf_queue;
- int flags; /* Already open */
-};
-
-static d_open_t sctargopen;
-static d_read_t sctargread;
-static d_write_t sctargwrite;
-static d_close_t sctargclose;
-static d_ioctl_t sctargioctl;
-static d_strategy_t sctargstrategy;
-
-#define CDEV_MAJOR 65
-static struct cdevsw sctarg_cdevsw =
- { sctargopen, sctargclose, sctargread, sctargwrite, /*65*/
- sctargioctl, nostop, nullreset, nodevtotty,/* sctarg */
- seltrue, nommap, sctargstrategy, "sctarg", NULL, -1 };
-
-SCSI_DEVICE_ENTRIES(sctarg)
-
-static errval sctarg_open(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-static void sctargstart(u_int32_t unit, u_int32_t unused_flags);
-static void sctarg_strategy(struct buf *bp, struct scsi_link *sc_link);
-
-static struct scsi_device sctarg_switch =
-{
- NULL,
- sctargstart, /* we have a queue, and this is how we service it */
- NULL,
- NULL,
- "sctarg",
- 0,
- {0, 0},
- SDEV_ONCE_ONLY,
- sctargattach,
- "Processor Target",
- sctargopen,
- sizeof(struct scsi_data),
- T_TARGET,
- 0,
- 0,
- sctarg_open,
- 0,
- 0,
- sctarg_strategy,
-};
-
-static errval
-sctargattach(struct scsi_link *sc_link)
-{
- struct scsi_data *sctarg;
-
- sctarg = sc_link->sd;
- bufq_init(&sctarg->buf_queue);
- sctarg->flags = 0;
-
- return 0;
-}
-
-static errval
-sctarg_open(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link)
-{
- int ret = 0;
-
- /* Does this host adapter support target mode operation?
- */
- if ((sc_link->flags & SDEV_TARGET_OPS) == 0)
- return ENODEV; /* Operation not supported */
-
- if (SCSI_FIXED(dev)) {
- sc_link->scsibus = SCSI_BUS(dev);
- scsi_set_bus(sc_link->scsibus, sc_link);
-
- sc_link->target = SCSI_ID(dev);
- sc_link->lun = SCSI_LUN(dev);
- }
-
- if (sc_link->scsibus == SCCONF_UNSPEC ||
- sc_link->target == SCCONF_UNSPEC ||
- sc_link->lun == SCCONF_UNSPEC)
- return ENXIO;
-
- /* XXX: You can have more than one target device on a single
- * host adapter. We need a reference count.
- */
- if ((sc_link->sd->flags & OPEN) == 0) /* Enable target mode */
- {
- ret = scsi_target_mode(sc_link, 1);
- sc_link->sd->flags |= OPEN;
- }
-
- return ret;
-}
-
-static int
-sctargread( dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(sctargstrategy, NULL, dev, 1, minphys, uio));
-}
-
-static int
-sctargwrite ( dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(sctargstrategy, NULL, dev, 0, minphys, uio));
-}
-
-/*
- * sctargstart 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 (sctargstrategy)
- *
- * 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.
- * sctargstart() is called at splbio
- */
-static void
-sctargstart(unit, unused_flags)
- u_int32_t unit;
- u_int32_t unused_flags;
-{
- struct scsi_link *sc_link = SCSI_LINK(&sctarg_switch, unit);
- struct scsi_data *sctarg = 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_t flags;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("sctargstart "));
- /*
- * 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;
- }
-
- bp = bufq_first(&sctarg->buf_queue);
- if (bp == NULL)
- return;
- bufq_remove(&sctarg->buf_queue, bp);
-
- /*
- * Fill out the scsi command
- */
- bzero(&cmd, sizeof(cmd));
- flags = SCSI_TARGET;
- 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_data,
- bp->b_bcount,
- 0,
- 100000,
- bp,
- flags | SCSI_NOSLEEP) == SUCCESSFULLY_QUEUED) {
- } else {
- printf("sctarg%lu: oops not queued\n", (u_long)unit);
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- biodone(bp);
- }
- } /* go back and see if we can cram more work in.. */
-}
-
-static void
-sctarg_strategy(struct buf *bp, struct scsi_link *sc_link)
-{
- unsigned char unit;
- u_int32_t opri;
- struct scsi_data *sctarg;
-
- unit = minor((bp->b_dev));
- sctarg = 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 at the end of the queue of activities for this device.
- */
- bufq_insert_tail(&sctarg->buf_queue, bp);
-
- /*
- * 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..)
- */
- sctargstart(unit, 0);
-
- splx(opri);
- return;
-}
-
-static sctarg_devsw_installed = 0;
-#ifdef DEVFS
-static void *sctarg_devfs_token;
-#endif
-
-static void sctarg_drvinit(void *unused)
-{
- dev_t dev;
-
- if( ! sctarg_devsw_installed ) {
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev,&sctarg_cdevsw, NULL);
- sctarg_devsw_installed = 1;
-#ifdef DEVFS
- /* XXX should be in ADAPTER code */
- sctarg_devfs_token =
- devfs_add_devswf(&sctarg_cdevsw, 0, DV_CHR, 0, 0,
- 0600, "sctarg");
-#endif
- }
-}
-
-SYSINIT(sctargdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,sctarg_drvinit,NULL)
-
-
diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c
deleted file mode 100644
index 56aa859..0000000
--- a/sys/scsi/sd.c
+++ /dev/null
@@ -1,1065 +0,0 @@
-/*
- * Written by Julian Elischer (julian@dialix.oz.au)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992
- *
- * $Id: sd.c,v 1.139 1998/08/23 20:16:35 phk Exp $
- */
-
-#include "opt_bounce.h"
-#include "opt_devfs.h"
-#include "opt_hw_wdog.h"
-#include "opt_scsi.h"
-
-#define SPLSD splbio
-#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/dkbad.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/disklabel.h>
-#include <sys/diskslice.h>
-#include <sys/dkstat.h>
-#include <sys/conf.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /* DEVFS */
-
-#include <scsi/scsi_disk.h>
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-#include <vm/vm.h>
-#include <vm/vm_prot.h>
-#include <vm/pmap.h>
-#include <machine/md_var.h>
-#include <i386/i386/cons.h> /* XXX *//* for aborting dump */
-#ifdef PC98
-#include <pc98/pc98/pc98_machdep.h>
-#endif
-
-#include "ioconf.h"
-
-static u_int32_t sdstrats, sdqueues;
-
-#define SECSIZE 512
-#ifdef PC98
-#define SDOUTSTANDING 2
-#else
-#define SDOUTSTANDING 4
-#endif
-#define SD_RETRIES 4
-#define MAXTRANSFER 8 /* 1 page at a time */
-
-#define PARTITION(dev) dkpart(dev)
-#define SDUNIT(dev) dkunit(dev)
-
-/* XXX introduce a dkmodunit() macro for this. */
-#define SDSETUNIT(DEV, U) \
- makedev(major(DEV), dkmakeminor((U), dkslice(DEV), dkpart(DEV)))
-
-static errval sd_get_parms __P((int unit, int flags));
-#if 0
-static errval sd_reassign_blocks __P((int unit, int block));
-#endif
-static int sd_size(int unit, u_int32_t *sizep, u_int16_t *secsizep, int flags);
-static void sdstrategy1 __P((struct buf *));
-
-static int sd_sense_handler __P((struct scsi_xfer *));
-static void sdstart __P((u_int32_t, u_int32_t));
-
-struct scsi_data {
- u_int32_t flags;
-#define SDINIT 0x04 /* device has been init'd */
- struct disk_parms {
- u_char heads; /* Number of heads */
- u_int16_t cyls; /* Number of cylinders */
- u_char sectors;/*XXX*/ /* Number of sectors/track */
- u_int16_t secsiz; /* Number of bytes/sector */
- u_int32_t disksize; /* total number sectors */
- } params;
- struct diskslices *dk_slices; /* virtual drives */
- struct buf_queue_head buf_queue;
- int dkunit; /* disk stats unit number */
-#ifdef DEVFS
- void *b_devfs_token;
- void *c_devfs_token;
- void *ctl_devfs_token;
-#endif
-};
-
-
-static int sdunit(dev_t dev) { return SDUNIT(dev); }
-static dev_t sdsetunit(dev_t dev, int unit) { return SDSETUNIT(dev, unit); }
-static errval sd_open __P((dev_t dev, int mode, int fmt, struct proc *p,
- struct scsi_link *sc_link));
-static errval sd_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag,
- struct proc *p, struct scsi_link *sc_link);
-static errval sd_close __P((dev_t dev, int flag, int fmt, struct proc *p,
- struct scsi_link *sc_link));
-static void sd_strategy(struct buf *bp, struct scsi_link *sc_link);
-
-static d_open_t sdopen;
-static d_read_t sdread;
-static d_write_t sdwrite;
-static d_close_t sdclose;
-static d_ioctl_t sdioctl;
-static d_dump_t sddump;
-static d_psize_t sdsize;
-static d_strategy_t sdstrategy;
-
-#define CDEV_MAJOR 13
-#define BDEV_MAJOR 4
-
-static struct cdevsw sd_cdevsw = {
- sdopen, sdclose, sdread, sdwrite,
- sdioctl, nostop, nullreset, nodevtotty,
- seltrue, nommap, sdstrategy, "sd",
- NULL, -1, sddump, sdsize,
- D_DISK, 0, -1 };
-
-
-
-
-SCSI_DEVICE_ENTRIES(sd)
-
-static struct scsi_device sd_switch =
-{
- sd_sense_handler,
- sdstart, /* have a queue, served by this */
- NULL, /* have no async handler */
- NULL, /* Use default 'done' routine */
- "sd",
- 0,
- {0, 0},
- 0, /* Link flags */
- sdattach,
- "Direct-Access",
- sdopen,
- sizeof(struct scsi_data),
- T_DIRECT,
- sdunit,
- sdsetunit,
- sd_open,
- sd_ioctl,
- sd_close,
- sd_strategy,
-};
-static struct scsi_xfer sx;
-
-
-static __inline void
-sd_registerdev(int unit)
-{
- if(dk_ndrive < DK_NDRIVE) {
- sprintf(dk_names[dk_ndrive], "sd%d", unit);
- dk_wpms[dk_ndrive] = (8*1024*1024/2);
- SCSI_DATA(&sd_switch, unit)->dkunit = dk_ndrive++;
- } else {
- SCSI_DATA(&sd_switch, unit)->dkunit = -1;
- }
-}
-
-
-/*
- * The routine called by the low level scsi routine when it discovers
- * a device suitable for this driver.
- */
-static errval
-sdattach(struct scsi_link *sc_link)
-{
- u_int32_t unit;
- struct disk_parms *dp;
-#ifdef DEVFS
- int mynor;
-#endif
-
- struct scsi_data *sd = sc_link->sd;
-
- unit = sc_link->dev_unit;
-
- dp = &(sd->params);
-
- if (sc_link->opennings > SDOUTSTANDING)
- sc_link->opennings = SDOUTSTANDING;
-
- bufq_init(&sd->buf_queue);
- /*
- * In case it is a funny one, tell it to start
- * not needed for most hard drives (ignore failure)
- */
- scsi_start_unit(sc_link,
- SCSI_ERR_OK | SCSI_SILENT | SCSI_NOSLEEP | SCSI_NOMASK);
- /*
- * Use the subdriver to request information regarding
- * the drive. We cannot use interrupts yet, so the
- * request must specify this. This may fail with removable media.
- */
- if (sd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK) == 0) {
- /*
- * if we don't have actual parameters, assume 512 bytes/sec
- * (could happen on removable media - MOD)
- * -- this avoids the division below from falling over
- */
- printf("%luMB (%lu %u byte sectors)",
- (u_long)(dp->disksize / ((1024L * 1024L) / dp->secsiz)),
- (u_long)dp->disksize, dp->secsiz);
-
-#ifndef SCSI_REPORT_GEOMETRY
- if ( (sc_link->flags & SDEV_BOOTVERBOSE) )
-#endif
- {
- sc_print_addr(sc_link);
- printf("with %d cyls, %d heads, and an average %d sectors/track",
- dp->cyls, dp->heads, dp->sectors);
- }
- } else {
- printf("Media parameters not available");
- }
- sd->flags |= SDINIT;
- sd_registerdev(unit);
-
-#ifdef DEVFS
- mynor = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART);
- sd->b_devfs_token = devfs_add_devswf(&sd_cdevsw, mynor, DV_BLK,
- UID_ROOT, GID_OPERATOR, 0640,
- "sd%d", unit);
- sd->c_devfs_token = devfs_add_devswf(&sd_cdevsw, mynor, DV_CHR,
- UID_ROOT, GID_OPERATOR, 0640,
- "rsd%d", unit);
- mynor = dkmakeminor(unit, 0, 0); /* XXX */
- sd->ctl_devfs_token = devfs_add_devswf(&sd_cdevsw,
- mynor | SCSI_CONTROL_MASK,
- DV_CHR,
- UID_ROOT, GID_WHEEL, 0600,
- "rsd%d.ctl", unit);
-#endif
- return 0;
-}
-
-
-/*
- * open the device. Make sure the partition info is a up-to-date as can be.
- */
-static errval
-sd_open(dev_t dev, int mode, int fmt, struct proc *p, struct scsi_link *sc_link)
-{
- errval errcode = 0;
- u_int32_t unit;
- struct disklabel label;
- struct scsi_data *sd;
-
- unit = SDUNIT(dev);
- sd = sc_link->sd;
-
- /*
- * Make sure the disk has been initialised
- * At some point in the future, get the scsi driver
- * to look for a new device if we are not initted
- */
- if ((!sd) || (!(sd->flags & SDINIT))) {
- return (ENXIO);
- }
-
- SC_DEBUG(sc_link, SDEV_DB1,
- ("sd_open: dev=0x%lx (unit %lu, partition %d)\n",
- (u_long)dev, (u_long)unit, PARTITION(dev)));
-
- /*
- * "unit attention" errors should occur here if the
- * drive has been restarted or the pack changed.
- * just ingnore the result, it's a decoy instruction
- * The error handlers will act on the error though
- * and invalidate any media information we had.
- */
- scsi_test_unit_ready(sc_link, 0);
-
- errcode = scsi_device_lock(sc_link);
- if (errcode)
- return errcode;
-
- /*
- * If it's been invalidated, then forget the label
- */
- sc_link->flags |= SDEV_OPEN; /* unit attn becomes an err now */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED) && sd->dk_slices != NULL) {
- /*
- * If somebody still has it open, then forbid re-entry.
- */
- if (dsisopen(sd->dk_slices)) {
- errcode = ENXIO;
- goto close;
- }
-
- dsgone(&sd->dk_slices);
- }
-
- /*
- * Check that it is still responding and ok.
- */
- if (scsi_test_unit_ready(sc_link, 0)) {
- SC_DEBUG(sc_link, SDEV_DB3, ("device not reponding\n"));
- errcode = ENXIO;
- goto close;
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("device ok\n"));
-
- /*
- * Load the physical device parameters
- */
- if(errcode = sd_get_parms(unit, 0)) /* sets SDEV_MEDIA_LOADED */
- goto close;
-
- SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
-
- /* Lock the pack in. */
- scsi_prevent(sc_link, PR_PREVENT, SCSI_ERR_OK | SCSI_SILENT);
-
- /* Build label for whole disk. */
- bzero(&label, sizeof label);
- label.d_type = DTYPE_SCSI;
- label.d_secsize = sd->params.secsiz;
- label.d_nsectors = sd->params.sectors;
- label.d_ntracks = sd->params.heads;
- label.d_ncylinders = sd->params.cyls;
- label.d_secpercyl = sd->params.heads * sd->params.sectors;
- if (label.d_secpercyl == 0)
- label.d_secpercyl = 100;
- /* XXX as long as it's not 0 - readdisklabel divides by it (?) */
- label.d_secperunit = sd->params.disksize;
-
- /* Initialize slice tables. */
- errcode = dsopen("sd", dev, fmt, 0, &sd->dk_slices, &label, sdstrategy1,
- (ds_setgeom_t *)NULL, &sd_cdevsw);
- if (errcode != 0)
- goto close;
- SC_DEBUG(sc_link, SDEV_DB3, ("Slice tables initialized "));
-
- SC_DEBUG(sc_link, SDEV_DB3, ("open %lu %lu\n",
- (u_long)sdstrats, (u_long)sdqueues));
-
- scsi_device_unlock(sc_link);
- return 0;
-
-close:
- if (!dsisopen(sd->dk_slices))
- {
- scsi_prevent(sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT);
- sc_link->flags &= ~SDEV_OPEN;
- }
- scsi_device_unlock(sc_link);
- return errcode;
-}
-
-/*
- * close the device.. only called if we are the LAST occurence of an open
- * device. Convenient now but usually a pain.
- */
-static errval
-sd_close(dev_t dev,int mode, int fmt, struct proc *p, struct scsi_link *sc_link)
-{
- struct scsi_data *sd;
- errval errcode;
-
- sd = sc_link->sd;
- errcode = scsi_device_lock(sc_link);
- if (errcode)
- return errcode;
- dsclose(dev, fmt, sd->dk_slices);
- if (!dsisopen(sd->dk_slices)) {
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT | SCSI_ERR_OK);
- sc_link->flags &= ~SDEV_OPEN;
- }
- scsi_device_unlock(sc_link);
- return (0);
-}
-
-static int
-sdread(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(sdstrategy, NULL, dev, 1, minphys, uio));
-}
-
-static int
-sdwrite(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(sdstrategy, NULL, dev, 0, minphys, uio));
-}
-
-/*
- * Actually translate the requested transfer into one the physical driver
- * can understand. The transfer is described by a buf and will include
- * only one physical transfer.
- */
-static void
-sd_strategy(struct buf *bp, struct scsi_link *sc_link)
-{
- u_int32_t opri;
- struct scsi_data *sd;
- u_int32_t unit;
-
- sdstrats++;
- unit = SDUNIT((bp->b_dev));
- sd = sc_link->sd;
- /*
- * If the device has been made invalid, error out
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- bp->b_error = EIO;
- goto bad;
- }
-
- /*
- * check it's not too big a transfer for our adapter
- */
- scsi_minphys(bp,&sd_switch);
-
- /*
- * Do bounds checking, adjust transfer, and set b_pbklno.
- */
- if (dscheck(bp, sd->dk_slices) <= 0)
- goto done; /* XXX check b_resid */
-
- opri = SPLSD();
- /*
- * 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 disk activities for this disk
- */
-#ifdef SDDISKSORT
- bufq_disksort(&sd->buf_queue, bp);
-#else
- bufq_insert_tail(&sd->buf_queue, bp);
-#endif
-
- /*
- * Tell the device to get going on the transfer if it's
- * not doing anything, otherwise just wait for completion
- */
- sdstart(unit, 0);
-
- splx(opri);
- return /*0*/;
-bad:
- bp->b_flags |= B_ERROR;
-done:
-
- /*
- * Correctly set the buf to indicate a completed xfer
- */
- bp->b_resid = bp->b_bcount;
- biodone(bp);
- return /*0*/;
-}
-
-static void
-sdstrategy1(struct buf *bp)
-{
- /*
- * XXX - do something to make sdstrategy() but not this block while
- * we're doing dsinit() and dsioctl().
- */
- sdstrategy(bp);
-}
-
-/*
- * sdstart 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 in the buf. 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 (sdstrategy)
- *
- * 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.
- *
- * must be called at the correct (highish) spl level
- * sdstart() is called at SPLSD from sdstrategy and scsi_done
- */
-static void
-sdstart(u_int32_t unit, u_int32_t flags)
-{
- register struct scsi_link *sc_link = SCSI_LINK(&sd_switch, unit);
- register struct scsi_data *sd = sc_link->sd;
- struct buf *bp = NULL;
- struct scsi_rw_big cmd;
- u_int32_t blkno, nblk, secsize;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("sdstart "));
- /*
- * Check if the device has room for another command
- */
- while (sc_link->opennings) {
-
- /*
- * there is excess capacity, but a special waits
- * It'll need the adapter as soon as we clear out of the
- * way and let it run (user level wait).
- */
- if (sc_link->flags & SDEV_WAITING) {
- return;
- }
- /*
- * See if there is a buf with work for us to do..
- */
- bp = bufq_first(&sd->buf_queue);
- if (bp == NULL) { /* yes, an assign */
- return;
- }
- bufq_remove(&sd->buf_queue, bp);
-
- /*
- * If the device has become invalid, abort all the
- * reads and writes until all files have been closed and
- * re-openned
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- goto bad;
- }
- /*
- * We have a buf, now we know we are going to go through
- * With this thing..
- */
- secsize = sd->params.secsiz;
- blkno = bp->b_pblkno;
- if (bp->b_bcount & (secsize - 1))
- {
- goto bad;
- }
- nblk = bp->b_bcount / secsize;
-
- /*
- * Fill out the scsi command
- */
- cmd.op_code = (bp->b_flags & B_READ)
- ? READ_BIG : WRITE_BIG;
- cmd.addr_3 = (blkno & 0xff000000UL) >> 24;
- cmd.addr_2 = (blkno & 0xff0000) >> 16;
- cmd.addr_1 = (blkno & 0xff00) >> 8;
- cmd.addr_0 = blkno & 0xff;
- cmd.length2 = (nblk & 0xff00) >> 8;
- cmd.length1 = (nblk & 0xff);
- cmd.byte2 = cmd.reserved = cmd.control = 0;
- /*
- * Call the routine that chats with the adapter.
- * Note: we cannot sleep as we may be an interrupt
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- (u_char *) bp->b_data,
- bp->b_bcount,
- SD_RETRIES,
- 10000,
- bp,
- flags | ((bp->b_flags & B_READ) ?
- SCSI_DATA_IN : SCSI_DATA_OUT))
- == SUCCESSFULLY_QUEUED) {
- sdqueues++;
- if(sd->dkunit >= 0) {
- dk_xfer[sd->dkunit]++;
- dk_seek[sd->dkunit]++; /* don't know */
- dk_wds[sd->dkunit] += bp->b_bcount >> 6;
- }
- } else {
-bad:
- printf("sd%lu: oops not queued\n", (u_long)unit);
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- biodone(bp);
- }
- }
-}
-
-/*
- * Perform special action on behalf of the user
- * Knows about the internals of this device
- */
-static errval
-sd_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p,
- struct scsi_link *sc_link)
-{
- errval error;
- struct scsi_data *sd = sc_link->sd;
- SC_DEBUG(sc_link, SDEV_DB1, ("sdioctl (0x%lx)", cmd));
-
-#if 0
- /* Wait until we have exclusive access to the device. */
- /* XXX this is how wd does it. How did we work without this? */
- sdsleep(du->dk_ctrlr, "wdioct");
-#endif
-
- /*
- * If the device is not valid.. abandon ship
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED))
- return (EIO);
-
- if (cmd == DIOCSBAD)
- return (EINVAL); /* XXX */
-
- error = scsi_device_lock(sc_link);
- if (error)
- return error;
- error = dsioctl("sd", dev, cmd, addr, flag, &sd->dk_slices,
- sdstrategy1, (ds_setgeom_t *)NULL);
- scsi_device_unlock(sc_link);
- if (error != ENOIOCTL)
- return (error);
- if (PARTITION(dev) != RAW_PART)
- return (ENOTTY);
- return (scsi_do_ioctl(dev, cmd, addr, flag, p, sc_link));
-}
-
-/*
- * Find out from the device what its capacity is. It turns
- * out this is also the best way to find out the sector size.
- */
-static int
-sd_size(int unit, u_int32_t *sizep, u_int16_t *secsizep, int flags)
-{
- struct scsi_read_cap_data rdcap;
- struct scsi_read_capacity scsi_cmd;
- u_int32_t size;
- u_int32_t secsize;
- struct scsi_link *sc_link = SCSI_LINK(&sd_switch, unit);
-
- /*
- * make up a scsi command and ask the scsi driver to do
- * it for you.
- */
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = READ_CAPACITY;
-
- /*
- * If the command works, interpret the result as a 4 byte
- * number of blocks
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) & rdcap,
- sizeof(rdcap),
- SD_RETRIES,
- 2000,
- NULL,
- flags | SCSI_DATA_IN) != 0) {
- printf("sd%d: could not get size\n", unit);
- return (ENXIO);
- }
- size = rdcap.addr_0 + 1;
- size += rdcap.addr_1 << 8;
- size += rdcap.addr_2 << 16;
- size += rdcap.addr_3 << 24;
- secsize = rdcap.length_0;
- secsize += rdcap.length_1 << 8;
- secsize += rdcap.length_2 << 16;
- secsize += rdcap.length_3 << 24;
- *secsizep = secsize;
- *sizep = size;
- return (0);
-}
-
-#if 0
-/*
- * Tell the device to map out a defective block
- */
-static errval
-sd_reassign_blocks(unit, block)
- int unit, block;
-{
- struct scsi_reassign_blocks scsi_cmd;
- struct scsi_reassign_blocks_data rbdata;
- struct scsi_link *sc_link = SCSI_LINK(&sd_switch, unit);
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- bzero(&rbdata, sizeof(rbdata));
- scsi_cmd.op_code = REASSIGN_BLOCKS;
-
- rbdata.length_msb = 0;
- rbdata.length_lsb = sizeof(rbdata.defect_descriptor[0]);
- rbdata.defect_descriptor[0].dlbaddr_3 = ((block >> 24) & 0xff);
- rbdata.defect_descriptor[0].dlbaddr_2 = ((block >> 16) & 0xff);
- rbdata.defect_descriptor[0].dlbaddr_1 = ((block >> 8) & 0xff);
- rbdata.defect_descriptor[0].dlbaddr_0 = ((block) & 0xff);
-
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) & rbdata,
- sizeof(rbdata),
- SD_RETRIES,
- 5000,
- NULL,
- SCSI_DATA_OUT));
-}
-#endif
-
-#define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
-
-/*
- * Get the scsi driver to send a full inquiry to the
- * device and use the results to fill out the disk
- * parameter structure.
- * Even if we get an error, complete with some dummy information.
- * XXX this is backwards. The read_cap (sd_size()) should be done first.
- */
-static errval
-sd_get_parms(int unit, int flags)
-{
- struct scsi_link *sc_link = SCSI_LINK(&sd_switch, unit);
- struct scsi_data *sd = sc_link->sd;
- struct disk_parms *disk_parms = &sd->params;
- struct scsi_mode_sense scsi_cmd;
- struct scsi_mode_sense_data {
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- union disk_pages pages;
- } scsi_sense;
- u_int32_t sectors;
- int error = 0;
-
- /*
- * First check if we have it all loaded
- */
- if (sc_link->flags & SDEV_MEDIA_LOADED)
- return 0;
-
- /*
- * do a "mode sense page 4"
- */
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SENSE;
- scsi_cmd.page = 4;
- scsi_cmd.length = 0x20;
-#ifdef PC98
- if (sd_bios_parms(disk_parms, sc_link)) {
- } else
-#endif
- /*
- * If the command worked, use the results to fill out
- * the parameter structure
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) & scsi_sense,
- sizeof(scsi_sense),
- SD_RETRIES,
- 4000,
- NULL,
- flags | SCSI_DATA_IN) != 0) {
-
- printf("sd%d could not mode sense (4).", unit);
- printf(" Using fictitious geometry\n");
- /*
- * use adaptec standard fictitious geometry
- * this depends on which controller (e.g. 1542C is
- * different. but we have to put SOMETHING here..)
- */
- if (error = sd_size(unit, &sectors, &disk_parms->secsiz, flags)) {
- /* we couldn't get anyhthing. removable? */
- sectors = 32 * 64;
- disk_parms->secsiz= DEV_BSIZE;;
- }
- disk_parms->heads = 64;
- disk_parms->sectors = 32;
- disk_parms->cyls = sectors / (64 * 32);
- disk_parms->disksize = sectors;
- } else {
-
- SC_DEBUG(sc_link, SDEV_DB3,
- ("%lu cyls, %d heads, %u precomp, %u red_write, %u land_zone\n",
- (u_long)scsi_3btou(&scsi_sense.pages.rigid_geometry.ncyl_2),
- scsi_sense.pages.rigid_geometry.nheads,
- b2tol(scsi_sense.pages.rigid_geometry.st_cyl_wp),
- b2tol(scsi_sense.pages.rigid_geometry.st_cyl_rwc),
- b2tol(scsi_sense.pages.rigid_geometry.land_zone)));
-
- /*
- * KLUDGE!!(for zone recorded disks)
- * give a number of sectors so that sec * trks * cyls
- * is <= disk_size
- * can lead to wasted space! THINK ABOUT THIS !
- */
- disk_parms->heads = scsi_sense.pages.rigid_geometry.nheads;
- disk_parms->cyls = scsi_3btou(
- &scsi_sense.pages.rigid_geometry.ncyl_2);
- /* set in a default value */
- disk_parms->secsiz = scsi_3btou(scsi_sense.blk_desc.blklen);
-
- if (error = sd_size(unit, &sectors,
- &disk_parms->secsiz, flags)) {
- /* we couldn't get anyhthing. removable? */
- sectors = 64 * 32; /* just so non 0 */
- }
- disk_parms->disksize = sectors;
- /* Check if none of these values are zero */
- if(disk_parms->heads && disk_parms->cyls) {
- sectors /= (disk_parms->heads * disk_parms->cyls);
- } else {
- /* set it to something reasonable */
- disk_parms->heads = 64;
- disk_parms->cyls = sectors / (64 * 32);
- sectors = 32;
- }
- /* keep secsiz sane too - we may divide by it later */
- if(disk_parms->secsiz == 0)
- disk_parms->secsiz = SECSIZE;
- disk_parms->sectors = sectors; /* dubious on SCSI *//*XXX */
- }
- switch (sd->params.secsiz) {
- case 512:
- case 1024:
- case 2048:
- break;
- default:
- printf("sd%lu: Can't deal with %u bytes logical blocks\n",
- (u_long)unit, sd->params.secsiz);
- error = ENXIO;
- }
- if (error == 0)
- sc_link->flags |= SDEV_MEDIA_LOADED;
- return (error);
-}
-
-static int
-sdsize(dev_t dev)
-{
- struct scsi_data *sd;
-
- sd = SCSI_DATA(&sd_switch, (u_int32_t) SDUNIT(dev));
- if (sd == NULL)
- return (-1);
- return (dssize(dev, &sd->dk_slices, sdopen, sdclose));
-}
-
-/*
- * sense handler: Called to determine what to do when the
- * device returns a CHECK CONDITION.
- *
- * This will issue a retry when the device returns a
- * non-media hardware failure. The CDC-WREN IV does this
- * when you access it during thermal calibrarion, so the drive
- * is pretty useless without this.
- *
- * In general, you probably almost always would like to issue a retry
- * for your disk I/O. It can't hurt too much (the caller only retries
- * so many times) and it may save your butt.
- */
-
-static int
-sd_sense_handler(struct scsi_xfer *xs)
-{
- struct scsi_sense_data *sense;
- struct scsi_inquiry_data *inqbuf;
-
- sense = &(xs->sense);
-
- /* I don't know what the heck to do with a deferred error,
- * so I'll just kick it back to the caller.
- */
- if ((sense->error_code & SSD_ERRCODE) == 0x71)
- return SCSIRET_CONTINUE;
-
- if (((sense->error_code & SSD_ERRCODE) == 0x70) &&
- ((sense->ext.extended.flags & SSD_KEY) == 0x05))
- /* No point in retrying Illegal Requests */
- return SCSIRET_CONTINUE;
-
- inqbuf = &(xs->sc_link->inqbuf);
-
- /* It is dangerous to retry on removable drives without
- * looking carefully at the additional sense code
- * and sense code qualifier and ensuring the disk hasn't changed:
- */
- if (inqbuf->dev_qual2 & SID_REMOVABLE)
- return SCSIRET_CONTINUE;
-
- /* Retry all disk errors.
- */
- scsi_sense_print(xs);
- if (xs->retries)
- printf(", retries:%d\n", xs->retries);
- else
- printf(", FAILURE\n");
-
- return SCSIRET_DO_RETRY;
-}
-
-/*
- * dump all of physical memory into the partition specified, starting
- * at offset 'dumplo' into the partition.
- * XXX for SLICE starts at argument 'start'.
- */
-static errval
-sddump(dev_t dev)
-{ /* dump core after a system crash */
- struct disklabel *lp;
- int32_t num; /* number of sectors to write */
- u_int32_t unit, part;
- int32_t nblocks;
- int32_t blkoff;
- static int sddoingadump = 0;
- register struct scsi_data *sd; /* disk unit to do the IO */
- struct scsi_link *sc_link;
- int32_t blknum, blkcnt = MAXTRANSFER;
- char *addr;
- struct scsi_rw_big cmd;
- struct scsi_xfer *xs = &sx;
- errval retval;
-
- addr = (char *) 0; /* starting address */
-
- /* toss any characters present prior to dump */
- while (cncheckc() != -1) ;
-
- /* size of memory to dump */
- num = Maxmem;
- unit = SDUNIT(dev); /* eventually support floppies? */
- part = PARTITION(dev); /* file system */
-
- sc_link = SCSI_LINK(&sd_switch, unit);
-
- if (!sc_link)
- return ENXIO;
-
- sd = sc_link->sd;
-
- /* was it ever initialized etc. ? */
- if (!(sd->flags & SDINIT))
- return (ENXIO);
- if ((sc_link->flags & SDEV_MEDIA_LOADED) != SDEV_MEDIA_LOADED)
- return (ENXIO);
- if (sd->dk_slices == NULL)
- Debugger("sddump: no slices");
- if ((lp = dsgetlabel(dev, sd->dk_slices)) == NULL)
- return (ENXIO);
-
- /* Convert to disk sectors */
- /* XXX it must be 512 */
- num = (u_int32_t) num * PAGE_SIZE / sd->params.secsiz;
-
- /* check if controller active */
- if (sddoingadump)
- return (EFAULT);
-
- nblocks = lp->d_partitions[part].p_size;
- blkoff = lp->d_partitions[part].p_offset;
- /* XXX */
- blkoff += sd->dk_slices->dss_slices[dkslice(dev)].ds_offset;
-
- /* check transfer bounds against partition size */
- if ((dumplo < 0) || ((dumplo + num) > nblocks))
- return (EINVAL);
-
- sddoingadump = 1;
-
- blknum = dumplo + blkoff;
- while (num > 0) {
- if (is_physical_memory((vm_offset_t)addr))
- pmap_enter(kernel_pmap, (vm_offset_t)CADDR1,
- trunc_page(addr), VM_PROT_READ, TRUE);
- else
- pmap_enter(kernel_pmap, (vm_offset_t)CADDR1,
- trunc_page(0), VM_PROT_READ, TRUE);
- /*
- * Fill out the scsi command
- */
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = WRITE_BIG;
- cmd.addr_3 = (blknum & 0xff000000) >> 24;
- cmd.addr_2 = (blknum & 0xff0000) >> 16;
- cmd.addr_1 = (blknum & 0xff00) >> 8;
- cmd.addr_0 = blknum & 0xff;
- cmd.length2 = (blkcnt & 0xff00) >> 8;
- cmd.length1 = (blkcnt & 0xff);
- /*
- * Fill out the scsi_xfer structure
- * Note: we cannot sleep as we may be an interrupt
- * don't use scsi_scsi_cmd() as it may want
- * to wait for an xs.
- */
- bzero(xs, sizeof(sx));
- xs->flags |= SCSI_NOMASK | SCSI_NOSLEEP | INUSE | SCSI_DATA_OUT;
- xs->sc_link = sc_link;
- xs->retries = SD_RETRIES;
- xs->timeout = 10000; /* 10000 millisecs for a disk ! */
- xs->cmd = (struct scsi_generic *) &cmd;
- xs->cmdlen = sizeof(cmd);
- xs->resid = 0;
- xs->error = XS_NOERROR;
- xs->bp = 0;
- xs->data = (u_char *) CADDR1; /* XXX use pmap_enter() */
- xs->datalen = blkcnt * sd->params.secsiz;
-
- /*
- * Pass all this info to the scsi driver.
- */
- retval = (*(sc_link->adapter->scsi_cmd)) (xs);
- switch (retval) {
- case SUCCESSFULLY_QUEUED:
- case HAD_ERROR:
- return (ENXIO); /* we said not to sleep! */
- case COMPLETE:
- break;
- default:
- return (ENXIO); /* we said not to sleep! */
- }
-
- /*
- * If we are dumping core, it may take a while.
- * So reassure the user and hold off any watchdogs.
- */
- if ((uintptr_t)addr % (1024 * 1024) == 0) {
-#ifdef HW_WDOG
- if (wdog_tickler)
- (*wdog_tickler)();
-#endif /* HW_WDOG */
- printf("%ld ", (u_long)(num / 2048));
- }
- /* update block count */
- num -= blkcnt;
- blknum += blkcnt;
- addr += blkcnt * sd->params.secsiz;
-
- /* operator aborting dump? */
- if (cncheckc() != -1)
- return (EINTR);
- }
- return (0);
-}
-
-static sd_devsw_installed = 0;
-
-static void sd_drvinit(void *unused)
-{
-
- if( ! sd_devsw_installed ) {
- cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &sd_cdevsw);
- sd_devsw_installed = 1;
- }
-}
-
-SYSINIT(sddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,sd_drvinit,NULL)
-
diff --git a/sys/scsi/ssc.c b/sys/scsi/ssc.c
deleted file mode 100644
index 1014daa..0000000
--- a/sys/scsi/ssc.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/* "superscsi" pseudo device.
- * "superscsi" supports general SCSI utilities that can iterate
- * over all SCSI targets, including those without device entry
- * points.
- *
- * "superscsi" supports the SCIOCADDR ioctl to change the BUS, ID, LUN
- * of the target so that you can get to all devices. The only thing
- * you can do to "superscsi" is open it, set the target, perform ioctl
- * calls, and close it.
- *
- * Keep "superscsi" protected: you can drive a truck through the
- * security hole if you don't.
- *
- *Begin copyright
- *
- * Copyright (C) 1993, 1994, 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.
- *End copyright
- * $Id: ssc.c,v 1.18 1998/01/24 02:54:52 eivind Exp $
- */
-
-#include "opt_devfs.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/disklabel.h>
-#include <sys/scsiio.h>
-#include <sys/kernel.h>
-#include <sys/stat.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-#include <scsi/scsiconf.h>
-
-static d_open_t sscopen;
-static d_close_t sscclose;
-static d_ioctl_t sscioctl;
-
-extern d_open_t suopen;
-extern d_close_t suclose;
-extern d_ioctl_t suioctl;
-
-#define CDEV_MAJOR 49
-static struct cdevsw ssc_cdevsw =
- { sscopen, sscclose, noread, nowrite, /*49*/
- sscioctl, nostop, nullreset, nodevtotty,
- seltrue, nommap, nostrategy, "ssc", NULL, -1 };
-
-static dev_t sscdev = NODEV;
-
-static int
-sscopen(dev_t dev, int flag, int type, struct proc *p)
-{
- if (sscdev != NODEV)
- return suopen(sscdev, flag, type, p);
- return 0;
-}
-
-static int
-sscclose(dev_t dev, int fflag, int type, struct proc *p)
-{
-
- if (sscdev != NODEV)
- return suclose(sscdev, fflag, type, p);
- return 0;
-}
-
-static int
-sscioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
-{
- if (cmd == SCIOCADDR)
- {
- struct scsi_addr *sca;
- dev_t newdev;
- int ret;
-
- sca = (struct scsi_addr *) data;
- newdev = SCSI_MKFIXED(sca->scbus,sca->target,sca->lun,RAW_PART);
-
- if (sscdev != NODEV)
- {
- suclose(sscdev, fflag, S_IFCHR, p);
- sscdev = NODEV;
- }
-
- if ( (ret = suopen(newdev, fflag, S_IFCHR, p)) )
- return ret;
-
- sscdev = newdev;
-
- return 0;
- }
-
- if (sscdev != NODEV)
- return suioctl(sscdev, cmd, data, fflag, p);
-
- return ENXIO;
-}
-
-/*
- * I've elected not to support any other entries. There really is no
- * good reason other than I'm not sure how you would use them.
- */
-
-static ssc_devsw_installed = 0;
-#ifdef DEVFS
-static void *ssc_devfs_token;
-#endif
-
-static void
-ssc_drvinit(void *unused)
-{
- dev_t dev;
-
- if( ! ssc_devsw_installed ) {
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev,&ssc_cdevsw, NULL);
- ssc_devsw_installed = 1;
-#ifdef DEVFS
- ssc_devfs_token =
- devfs_add_devswf(&ssc_cdevsw, 0, DV_CHR, 0, 0,
- 0600, "ssc");
-#endif
- }
-}
-
-SYSINIT(sscdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ssc_drvinit,NULL)
-
diff --git a/sys/scsi/st.c b/sys/scsi/st.c
deleted file mode 100644
index b4feb02..0000000
--- a/sys/scsi/st.c
+++ /dev/null
@@ -1,2005 +0,0 @@
-/*
- * Written by Julian Elischer (julian@tfs.com)(now julian@DIALix.oz.au)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * $Id: st.c,v 1.93 1998/08/18 00:32:49 bde Exp $
- */
-
-/*
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- * major changes by Julian Elischer (julian@jules.dialix.oz.au) May 1993
- */
-
-/*
- * To do:
- * work out some better way of guessing what a good timeout is going
- * to be depending on whether we expect to retension or not.
- *
- */
-
-#include "opt_bounce.h"
-#include "opt_devfs.h"
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-
-#include <sys/fcntl.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
-#include <sys/mtio.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-
-#include <scsi/scsi_tape.h>
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-#include "ioconf.h"
-
-/* Defines for device specific stuff */
-#define PAGE_0_SENSE_DATA_SIZE 12
-#define DEF_FIXED_BSIZE 512
-#define ST_RETRIES 4 /* only on non IO commands */
-
-#define STUNIT(DEV) ((minor(DEV)&0xF0) >> 4) /* 4 bit unit. */
-#define STSETUNIT(DEV, U) makedev(major(DEV), ((U) << 4))
-
-#define MODE(z) ( (minor(z) & 0x03) )
-#define DSTY(z) ( ((minor(z) >> 2) & 0x03) )
-#define CTLMODE 3
-
-#define IS_CTLMODE(DEV) (MODE(DEV) == CTLMODE)
-
-static errval st_space __P((u_int32_t unit, int32_t number, u_int32_t what, u_int32_t flags));
-static errval st_rewind __P((u_int32_t unit, boolean immed, u_int32_t flags));
-static errval st_erase __P((u_int32_t unit, boolean immed, u_int32_t flags));
-static errval st_mode_sense __P((u_int32_t unit, u_int32_t flags, \
- struct tape_pages *page, u_int32_t pagelen, u_int32_t pagecode));
-static errval st_decide_mode __P((u_int32_t unit, boolean first_read));
-static errval st_read __P((u_int32_t unit, char *buf, u_int32_t size,
- u_int32_t flags));
-static errval st_rd_blk_lim __P((u_int32_t unit, u_int32_t flags));
-static errval st_touch_tape __P((u_int32_t unit));
-static errval st_write_filemarks __P((u_int32_t unit, int32_t number, u_int32_t flags));
-static errval st_load __P((u_int32_t unit, u_int32_t type, u_int32_t flags));
-static errval st_mode_select __P((u_int32_t unit, u_int32_t flags, \
- struct tape_pages *page, u_int32_t pagelen, u_int32_t byte2));
-static errval st_comp __P((u_int32_t unit, u_int32_t mode));
-static int32_t st_chkeod __P((u_int32_t unit, boolean position, int32_t *nmarks,
- u_int32_t flags));
-static void ststart(u_int32_t unit, u_int32_t flags);
-static void st_unmount __P((int unit, boolean eject));
-static errval st_mount_tape __P((dev_t dev, u_int32_t flags));
-static void st_loadquirks __P((struct scsi_link *sc_link));
-static errval st_interpret_sense __P((struct scsi_xfer *xs));
-
-#define ESUCCESS 0
-#define NOEJECT 0
-#define EJECT 1
-
-struct scsi_data {
-/*--------------------present operating parameters, flags etc.----------------*/
- u_int32_t flags; /* see below */
- u_int32_t blksiz; /* blksiz we are using */
- u_int32_t density; /* present density */
- u_int32_t comp; /* present compression mode */
- u_int32_t quirks; /* quirks for the open mode */
- u_int32_t last_dsty; /* last density openned */
-/*--------------------parameters reported by the device ----------------------*/
- u_int32_t blkmin; /* min blk size */
- u_int32_t blkmax; /* max blk size */
-/*--------------------parameters reported by the device for this media--------*/
- u_int32_t numblks; /* nominal blocks capacity */
- u_int32_t media_blksiz; /* 0 if not ST_FIXEDBLOCKS */
- u_int32_t media_density; /* this is what it said when asked */
-/*--------------------quirks for the whole drive------------------------------*/
- u_int32_t drive_quirks; /* quirks of this drive */
-/*--------------------How we should set up when openning each minor device----*/
- st_modes modes; /* plus more for each mode */
- u_int8_t modeflags[4]; /* flags for the modes */
-#define DENSITY_SET_BY_USER 0x01
-#define DENSITY_SET_BY_QUIRK 0x02
-#define BLKSIZE_SET_BY_USER 0x04
-#define BLKSIZE_SET_BY_QUIRK 0x08
-#define COMPRES_SET_BY_USER 0x10
-#define COMPRES_SET_BY_QUIRK 0x20
-/*--------------------storage for sense data returned by the drive------------*/
- unsigned char saved_page0[PAGE_0_SENSE_DATA_SIZE]; /*
- * additional sense data needed
- * for mode sense/select.
- */
- struct buf_queue_head buf_queue;
- struct scsi_xfer scsi_xfer; /* scsi xfer struct for this drive */
- u_int32_t xfer_block_wait; /* is a process waiting? */
-#ifdef DEVFS
- struct {
- void *rst;
- void *nrst;
- void *erst;
- /* end of aliases */
- void *rst_[4];
- void *nrst_[4];
- void *erst_[4];
- void *ctl_[4];
- void *ctl;
- } devfs_token;
-#endif
-};
-
-static int stunit(dev_t dev) { return STUNIT(dev); }
-static dev_t stsetunit(dev_t dev, int unit) { return STSETUNIT(dev, unit); }
-
-static errval st_open(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-static errval st_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag,
- struct proc *p, struct scsi_link *sc_link);
-static errval st_close(dev_t dev, int flag, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-static void st_strategy(struct buf *bp, struct scsi_link *sc_link);
-
-static d_open_t stopen;
-static d_read_t stread;
-static d_write_t stwrite;
-static d_close_t stclose;
-static d_ioctl_t stioctl;
-static d_strategy_t ststrategy;
-
-#define CDEV_MAJOR 14
-#define BDEV_MAJOR 5
-static struct cdevsw st_cdevsw = {
- stopen, stclose, stread, stwrite,
- stioctl, nostop, nullreset, nodevtotty,
- seltrue, nommap, ststrategy, "st",
- NULL, -1 };
-
-SCSI_DEVICE_ENTRIES(st)
-
-static struct scsi_device st_switch =
-{
- st_interpret_sense, /* check errors with us first */
- ststart, /* we have a queue, and this is how we service it */
- NULL,
- NULL, /* use the default 'done' routine */
- "st",
- 0,
- {0, 0},
- 0, /* Link flags */
- stattach,
- "Sequential-Access",
- stopen,
- sizeof(struct scsi_data),
- T_SEQUENTIAL,
- stunit,
- stsetunit,
- st_open,
- st_ioctl,
- st_close,
- st_strategy,
-};
-
-#define ST_INITIALIZED 0x01
-#define ST_INFO_VALID 0x02
-#define ST_OPEN 0x04
-#define ST_BLOCK_SET 0x08 /* block size, mode set by ioctl */
-#define ST_WRITTEN 0x10 /* data have been written, EOD needed */
-#define ST_FIXEDBLOCKS 0x20
-#define ST_AT_FILEMARK 0x40
-#define ST_EIO_PENDING 0x80 /* we couldn't report it then (had data) */
-#define ST_NEW_MOUNT 0x100 /* still need to decide mode */
-#define ST_READONLY 0x200 /* st_mode_sense says write protected */
-#define ST_FM_WRITTEN 0x400 /*
- * EOF file mark written -- used with
- * ~ST_WRITTEN to indicate that multiple file
- * marks have been written
- */
-#define ST_BLANK_READ 0x800 /* BLANK CHECK encountered already */
-#define ST_2FM_AT_EOD 0x1000 /* write 2 file marks at EOD */
-#define ST_MOUNTED 0x2000 /* Device is presently mounted */
-#define ST_SENSE_READ 0x4000 /* mode sense read from drive */
-
-#define ST_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ)
-#define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
- ST_FIXEDBLOCKS | ST_READONLY | \
- ST_FM_WRITTEN | ST_2FM_AT_EOD | ST_PER_ACTION)
-
-/*
- * The routine called by the low level scsi routine when it discovers
- * a device suitable for this driver
- */
-
-static errval
-stattach(struct scsi_link *sc_link)
-{
- u_int32_t unit;
-#ifdef DEVFS
- int ii;
-#endif /*DEVFS*/
-
- struct scsi_data *st = sc_link->sd;
-
- unit = sc_link->dev_unit;
-
- bufq_init(&st->buf_queue);
- /*
- * Check if the drive is a known criminal and take
- * Any steps needed to bring it into line
- */
- st_loadquirks(sc_link);
- /*
- * Use the subdriver to request information regarding
- * the drive. We cannot use interrupts yet, so the
- * request must specify this.
- */
- if (st_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT,
- NULL, 0, 0)) {
- printf("drive offline");
- } else {
- printf("density code 0x%lx, ", (u_long)st->media_density);
- if (!scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT)) {
- if (st->media_blksiz) {
- printf("%lu-byte", (u_long)st->media_blksiz);
- } else {
- printf("variable");
- }
- printf(" blocks, write-%s",
- (st->flags & ST_READONLY) ? "protected" : "enabled");
- } else {
- printf(" drive empty");
- }
- }
- /*
- * Set up the buf queue for this device
- */
- st->flags |= ST_INITIALIZED;
-#ifdef DEVFS
- for(ii=0; ii<4; ii++) {
- st->devfs_token.rst_[ii] =
- devfs_add_devswf(&st_cdevsw,
- (unit << 4 ) + (ii * 4), DV_CHR,
- UID_ROOT, GID_OPERATOR, 0660,
- "rst%lu.%d", (u_long)unit, ii);
- st->devfs_token.nrst_[ii] =
- devfs_add_devswf(&st_cdevsw,
- (unit << 4 ) + ((ii * 4) + 1), DV_CHR,
- UID_ROOT, GID_OPERATOR, 0660,
- "nrst%lu.%d", (u_long)unit, ii);
- st->devfs_token.erst_[ii] =
- devfs_add_devswf(&st_cdevsw,
- (unit << 4 ) + ((ii * 4) + 2), DV_CHR,
- UID_ROOT, GID_OPERATOR, 0660,
- "erst%lu.%d", (u_long)unit, ii);
- st->devfs_token.ctl_[ii] =
- devfs_add_devswf(&st_cdevsw,
- (unit << 4 ) + ((ii * 4) + 3), DV_CHR,
- UID_ROOT, GID_OPERATOR, 0600,
- "st%luctl.%d", (u_long)unit, ii);
- }
-
- st->devfs_token.ctl =
- devfs_add_devswf(&st_cdevsw, (unit << 4 ) | SCSI_CONTROL_MASK,
- DV_CHR, UID_ROOT, GID_WHEEL, 0600,
- "rst%d.ctl", unit);
- /** add links **/
- st->devfs_token.rst =
- devfs_link(st->devfs_token.rst_[0], "rst%lu", (u_long)unit);
- st->devfs_token.nrst =
- devfs_link(st->devfs_token.nrst_[0], "nrst%lu", (u_long)unit);
- st->devfs_token.erst =
- devfs_link(st->devfs_token.erst_[0], "erst%lu", (u_long)unit);
-#endif
- return 0;
-}
-
-
-/*
- * initialise the subdevices to the default (QUIRK) state.
- * this will remove any setting made by the system operator or previous
- * operations.
- */
-static void
-st_loadquirks(sc_link)
- struct scsi_link *sc_link;
-{
- struct scsi_data *st = sc_link->sd;
- int i;
- struct st_mode *mode;
- struct st_mode *mode2;
-
- mode = (struct st_mode*) sc_link->devmodes;
- if (!mode)
- return;
-
- st->quirks = st->drive_quirks = sc_link->quirks;
-
- mode2 = st->modes;
-
- for (i = 0; i < 4; i++) {
- bzero(mode2, sizeof(*mode2));
- st->modeflags[i] &= ~(BLKSIZE_SET_BY_QUIRK
- | DENSITY_SET_BY_QUIRK
- | BLKSIZE_SET_BY_USER
- | DENSITY_SET_BY_USER);
- if (mode->blksiz && ((mode->quirks | st->drive_quirks)
- & (ST_Q_FORCE_FIXED_MODE))) {
- mode2->blksiz = mode->blksiz;
- st->modeflags[i] |= BLKSIZE_SET_BY_QUIRK;
- } else {
- if ((mode->quirks | st->drive_quirks)
- & ST_Q_FORCE_VAR_MODE) {
- mode2->blksiz = 0;
- st->modeflags[i] |= BLKSIZE_SET_BY_QUIRK;
- }
- }
- if (mode->density) {
- mode2->density = mode->density;
- st->modeflags[i] |= DENSITY_SET_BY_QUIRK;
- }
- mode++;
- mode2++;
- }
-}
-
-/*
- * open the device.
- */
-static errval
-st_open(dev_t dev, int flags, int fmt, struct proc *p,
-struct scsi_link *sc_link)
-{
- u_int32_t unit, mode, dsty;
- errval errno = 0;
- struct scsi_data *st;
-
- unit = STUNIT(dev);
- mode = MODE(dev);
- dsty = DSTY(dev);
-
- st = sc_link->sd;
- /*
- * Make sure the device has been initialised
- */
- if ((st == NULL) || (!(st->flags & ST_INITIALIZED)))
- return (ENXIO);
-
- /*
- * Only allow one at a time
- */
- if (st->flags & ST_OPEN) {
- return (EBUSY);
- }
- /*
- * Throw out a dummy instruction to catch 'Unit attention
- * errors (the error handling will invalidate all our
- * device info if we get one, but otherwise, ignore it)
- */
- scsi_test_unit_ready(sc_link, SCSI_SILENT);
-
- sc_link->flags |= SDEV_OPEN; /* unit attn are now errors */
- /*
- * If the mode is 3 (e.g. minor = 3,7,11,15)
- * then the device has been openned to set defaults
- * This mode does NOT ALLOW I/O, only ioctls.
- * XXX: Where do we lock out I/O?
- */
- if (IS_CTLMODE(dev))
- return 0;
-
- /*
- * Check that the device is ready to use (media loaded?)
- * This time take notice of the return result
- */
- if ( (errno = scsi_test_unit_ready(sc_link, 0)) ) {
- uprintf("st%d: not ready\n", unit);
- st_unmount(unit, NOEJECT);
- return (errno);
- }
- /*
- * if it's a different mode, or if the media has been
- * invalidated, unmount the tape from the previous
- * session but continue with open processing
- */
- if ((st->last_dsty != dsty)
- || (!(sc_link->flags & SDEV_MEDIA_LOADED))) {
- st_unmount(unit, NOEJECT);
- }
- /*
- * If we are not mounted, then we should start a new
- * mount session.
- */
- if (!(st->flags & ST_MOUNTED)) {
- st_mount_tape(dev, flags);
- st->last_dsty = dsty;
- }
- /*
- * Make sure that a tape opened in write-only mode will have
- * file marks written on it when closed, even if not written to.
- * This is for SUN compatibility
- */
- if (flags & FWRITE)
- st->flags |= ST_WRITTEN;
-
- /* PREVENT ALLOW MEDIUM REMOVAL is optional per the SCSI-2 specs */
- scsi_prevent(sc_link, PR_PREVENT, SCSI_SILENT | SCSI_ERR_OK);
-
- SC_DEBUG(sc_link, SDEV_DB2, ("Open complete\n"));
-
- st->flags |= ST_OPEN;
- return 0;
-}
-
-/*
- * close the device.. only called if we are the LAST
- * occurence of an open device
- */
-static errval
-st_close(dev_t dev, int flag, int fmt, struct proc *p,
- struct scsi_link *sc_link)
-{
- u_int32_t unit, mode;
- struct scsi_data *st;
- errval errcode = 0;
-
- unit = STUNIT(dev);
- mode = MODE(dev);
- st = sc_link->sd;
-
- if ((st->flags & (ST_WRITTEN | ST_FM_WRITTEN)) == ST_WRITTEN)
- errcode = st_write_filemarks(unit, 1, 0);
-
- /*
- * Since the device has seen its last close, allow media removal.
- * Do this before we attempt an eject.
- */
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
-
- switch (mode & 0x3) {
- case 0:
- case 3: /* for now */
- st_unmount(unit, NOEJECT);
- break;
- case 1: /*leave mounted unless media seems to have been removed */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- st_unmount(unit, NOEJECT);
- }
- break;
- case 2:
- st_unmount(unit, EJECT);
- break;
- }
-
- sc_link->flags &= ~SDEV_OPEN;
- st->flags &= ~ST_OPEN;
-
- return (errcode);
-}
-
-/*
- * Start a new mount session.
- * Copy in all the default parameters from the selected device mode.
- * and try guess any that seem to be defaulted.
- */
-static errval
-st_mount_tape(dev, flags)
- dev_t dev;
- u_int32_t flags;
-{
- u_int32_t unit, mode, dsty;
- struct scsi_data *st;
- struct scsi_link *sc_link;
- errval errno = 0;
-
- unit = STUNIT(dev);
- mode = MODE(dev);
- dsty = DSTY(dev);
- sc_link = SCSI_LINK(&st_switch, unit);
- st = sc_link->sd;
-
- if (st->flags & ST_MOUNTED)
- return 0;
-
- SC_DEBUG(sc_link, SDEV_DB1, ("mounting\n "));
- st->flags |= ST_NEW_MOUNT;
- st->quirks = st->drive_quirks | st->modes[dsty].quirks;
- /*
- * If the media is new, then make sure we give it a chance to
- * to do a 'load' instruction. ( We assume it is new)
- */
- if ( (errno = st_load(unit, LD_LOAD, 0)) ) {
- return (errno);
- }
- /*
- * Throw another dummy instruction to catch
- * 'Unit attention' errors. Some drives appear to give
- * these after doing a Load instruction.
- * (noteably some DAT drives)
- */
- scsi_test_unit_ready(sc_link, SCSI_SILENT);
-
- /*
- * Some devices can't tell you much until they have been
- * asked to look at the media. This quirk does this.
- */
- if (st->quirks & ST_Q_SNS_HLP) {
- if ( (errno = st_touch_tape(unit)) )
- return errno;
- }
- /*
- * Load the physical device parameters
- * loads: blkmin, blkmax
- */
- if ( (errno = st_rd_blk_lim(unit, 0)) ) {
- return errno;
- }
- /*
- * Load the media dependent parameters
- * includes: media_blksiz,media_density,numblks
- * As we have a tape in, it should be reflected here.
- * If not you may need the "quirk" above.
- */
- if ( (errno = st_mode_sense(unit, 0, NULL, 0, 0)) ) {
- return errno;
- }
- /*
- * If we have gained a permanent density from somewhere,
- * then use it in preference to the one supplied by
- * default by the driver.
- */
- if (st->modeflags[dsty] & (DENSITY_SET_BY_QUIRK | DENSITY_SET_BY_USER)) {
- st->density = st->modes[dsty].density;
- } else {
- st->density = st->media_density;
- }
- /*
- * If we have gained a permanent blocksize
- * then use it in preference to the one supplied by
- * default by the driver.
- */
- st->flags &= ~ST_FIXEDBLOCKS;
- if (st->modeflags[dsty] & (BLKSIZE_SET_BY_QUIRK | BLKSIZE_SET_BY_USER)) {
- st->blksiz = st->modes[dsty].blksiz;
- if (st->blksiz) {
- st->flags |= ST_FIXEDBLOCKS;
- }
- } else {
- if ( (errno = st_decide_mode(unit, FALSE)) ) {
- return errno;
- }
- }
- if ( (errno = st_mode_select(unit, 0, NULL, 0, 0)) ) {
- printf("st%lu: Cannot set selected mode", (u_long)unit);
- return errno;
- }
- st->flags &= ~ST_NEW_MOUNT;
- st->flags |= ST_MOUNTED;
- sc_link->flags |= SDEV_MEDIA_LOADED;
-
- return 0;
-}
-
-/*
- * End the present mount session.
- * Rewind, and optionally eject the tape.
- * Reset various flags to indicate that all new
- * operations require another mount operation
- */
-void
-st_unmount(int unit, boolean eject)
-{
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
- int32_t nmarks;
-
- if (!(st->flags & ST_MOUNTED))
- return;
- SC_DEBUG(sc_link, SDEV_DB1, ("unmounting\n"));
- st_chkeod(unit, FALSE, &nmarks, SCSI_SILENT);
- st_rewind(unit, FALSE, SCSI_SILENT);
- if (eject) {
- st_load(unit, LD_UNLOAD, SCSI_SILENT);
- }
- st->flags &= ~(ST_MOUNTED | ST_NEW_MOUNT);
- sc_link->flags &= ~SDEV_MEDIA_LOADED;
-}
-
-/*
- * Given all we know about the device, media, mode, 'quirks' and
- * initial operation, make a decision as to how we should be set
- * to run (regarding blocking and EOD marks)
- */
-static errval
-st_decide_mode(unit, first_read)
- u_int32_t unit;
- boolean first_read;
-{
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("starting block mode decision\n"));
-
- /*
- * If the user hasn't already specified fixed or variable-length
- * blocks and the block size (zero if variable-length), we'll
- * have to try to figure them out ourselves.
- *
- * Our first shot at a method is, "The quirks made me do it!"
- */
- switch ((int)(st->quirks & (ST_Q_FORCE_FIXED_MODE | ST_Q_FORCE_VAR_MODE))) {
- case (ST_Q_FORCE_FIXED_MODE | ST_Q_FORCE_VAR_MODE):
- printf("st%lu: bad quirks\n", (u_long)unit);
- return (EINVAL);
- case ST_Q_FORCE_FIXED_MODE: /*specified fixed, but not what size */
- st->flags |= ST_FIXEDBLOCKS;
- if (st->blkmin && (st->blkmin == st->blkmax))
- st->blksiz = st->blkmin;
- else if (st->media_blksiz > 0)
- st->blksiz = st->media_blksiz;
- else
- st->blksiz = DEF_FIXED_BSIZE;
- SC_DEBUG(sc_link, SDEV_DB3, ("Quirks force fixed mode(%lu)\n",
- (u_long)st->blksiz));
- goto done;
- case ST_Q_FORCE_VAR_MODE:
- st->flags &= ~ST_FIXEDBLOCKS;
- st->blksiz = 0;
- SC_DEBUG(sc_link, SDEV_DB3, ("Quirks force variable mode\n"));
- goto done;
- }
- /*
- * If the drive can only handle fixed-length blocks and only at
- * one size, perhaps we should just do that.
- */
- if (st->blkmin && (st->blkmin == st->blkmax)) {
- st->flags |= ST_FIXEDBLOCKS;
- st->blksiz = st->blkmin;
- SC_DEBUG(sc_link, SDEV_DB3,
- ("blkmin == blkmax of %lu\n", (u_long)st->blkmin));
- goto done;
- }
- /*
- * If the tape density mandates (or even suggests) use of fixed
- * or variable-length blocks, comply.
- */
- switch ((int)st->density) {
- case HALFINCH_800:
- case HALFINCH_1600:
- case HALFINCH_6250:
- case DDS:
- case QIC_525:
- case QIC_1320:
- case QIC_3080:
- st->flags &= ~ST_FIXEDBLOCKS;
- st->blksiz = 0;
- SC_DEBUG(sc_link, SDEV_DB3, ("density specified variable\n"));
- goto done;
- case QIC_11:
- case QIC_24:
- case QIC_120:
- case QIC_150:
- st->flags |= ST_FIXEDBLOCKS;
- if (st->media_blksiz > 0) {
- st->blksiz = st->media_blksiz;
- } else {
- st->blksiz = DEF_FIXED_BSIZE;
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("density specified fixed\n"));
- goto done;
- }
- /*
- * If we're about to read the tape, perhaps we should choose
- * fixed or variable-length blocks and block size according to
- * what the drive found on the tape.
- */
- if (first_read
- && (!(st->quirks & ST_Q_BLKSIZ)
- || (st->media_blksiz == 0)
- || (st->media_blksiz == DEF_FIXED_BSIZE)
- || (st->media_blksiz == 1024))) {
- if (st->media_blksiz == 0) {
- st->flags &= ~ST_FIXEDBLOCKS;
- } else {
- st->flags |= ST_FIXEDBLOCKS;
- }
- st->blksiz = st->media_blksiz;
- SC_DEBUG(sc_link, SDEV_DB3,
- ("Used media_blksiz of %lu\n", (u_long)st->media_blksiz));
- goto done;
- }
- /*
- * We're getting no hints from any direction. Choose variable-
- * length blocks arbitrarily.
- */
- st->flags &= ~ST_FIXEDBLOCKS;
- st->blksiz = 0;
- SC_DEBUG(sc_link, SDEV_DB3, ("Give up and default to variable mode\n"));
-done:
-
- /*
- * Decide whether or not to write two file marks to signify end-
- * of-data. Make the decision as a function of density. If
- * the decision is not to use a second file mark, the SCSI BLANK
- * CHECK condition code will be recognized as end-of-data when
- * first read.
- * (I think this should be a by-product of fixed/variable..julian)
- */
- switch ((int)st->density) {
-/* case 8 mm: What is the SCSI density code for 8 mm, anyway? */
- case QIC_11:
- case QIC_24:
- case QIC_120:
- case QIC_150:
- case QIC_525:
- case QIC_1320:
- case QIC_3080:
- st->flags &= ~ST_2FM_AT_EOD;
- break;
- default:
- st->flags |= ST_2FM_AT_EOD;
- }
- return 0;
-}
-
-static int
-stread(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(ststrategy, NULL, dev, 1, minphys, uio));
-}
-
-static int
-stwrite(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(ststrategy, NULL, dev, 0, minphys, uio));
-}
-
-/*
- * Actually translate the requested transfer into
- * one the physical driver can understand
- * The transfer is described by a buf and will include
- * only one physical transfer.
- */
-static void
-st_strategy(struct buf *bp, struct scsi_link *sc_link)
-{
- u_int32_t unit;
- u_int32_t opri;
- struct scsi_data *st;
- int len;
-
- unit = STUNIT((bp->b_dev));
- st = sc_link->sd;
- /*
- * If it's a null transfer, return immediatly
- */
- if ((len = bp->b_bcount) == 0) {
- goto done;
- }
- /*
- * Check the adapter can do it
- */
- scsi_minphys(bp,&st_switch);
- /*
- * Odd sized request on fixed drives are verboten
- */
- if (st->flags & ST_FIXEDBLOCKS) {
- if (bp->b_bcount % st->blksiz) {
- printf("st%lu: bad request, must be multiple of %lu\n",
- (u_long)unit, (u_long)st->blksiz);
- bp->b_error = EIO;
- goto bad;
- }
- }
- /*
- * as are out-of-range requests on variable drives.
- * (or if we got chopped by minphys)
- */
- else {
- if ((bp->b_bcount < st->blkmin || bp->b_bcount > st->blkmax)) {
- printf(
- "st%lu: bad request, must be between %lu and %lu\n",
- (u_long)unit, (u_long)st->blkmin,
- (u_long)st->blkmax);
- bp->b_error = EIO;
- goto bad;
- }
- if (len != bp->b_bcount) {
- printf(
- "st%lu: bad request, must be less than %ld bytes\n",
- (u_long)unit, bp->b_bcount + 1);
- bp->b_error = EIO;
- goto bad;
- }
- }
- 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 on user..
- * (but it could fork() ))
- */
- bufq_insert_tail(&st->buf_queue, bp);
-
- /*
- * 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..)
- */
- ststart(unit, 0);
-
- splx(opri);
- return;
-bad:
- bp->b_flags |= B_ERROR;
-done:
- /*
- * Correctly set the buf to indicate a completed xfer
- */
- biodone(bp);
- return;
-}
-
-/*
- * ststart 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 (ststrategy)
- *
- * 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.
- * ststart() is called at splbio
- */
-static void
-ststart(unit, flags)
- u_int32_t unit;
- u_int32_t flags;
-{
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
- register struct buf *bp = 0;
- struct scsi_rw_tape cmd;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("ststart "));
- /*
- * 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;
- }
-
- bp = bufq_first(&st->buf_queue);
- if (bp == NULL) { /* yes, an assign */
- return;
- }
- bufq_remove(&st->buf_queue, bp);
-
- /*
- * if the device has been unmounted by the user
- * then throw away all requests until done
- */
- if ((!(st->flags & ST_MOUNTED))
- || (!(sc_link->flags & SDEV_MEDIA_LOADED))) {
- /* make sure that one implies the other.. */
- sc_link->flags &= ~SDEV_MEDIA_LOADED;
- goto badnews;
- }
- /*
- * only FIXEDBLOCK devices have pending operations
- */
- if (st->flags & ST_FIXEDBLOCKS) {
- /*
- * If we are at a filemark but have not reported it yet
- * then we should report it now
- */
- if (st->flags & ST_AT_FILEMARK) {
- if ((bp->b_flags & B_READ) == B_WRITE) {
- /*
- * Handling of ST_AT_FILEMARK in
- * st_space will fill in the right file
- * mark count.
- * Back up over filemark
- */
- if (st_space(unit, 0, SP_FILEMARKS, 0) !=
- ESUCCESS)
- goto badnews;
- } else {
- bp->b_resid = bp->b_bcount;
- bp->b_error = 0;
- bp->b_flags &= ~B_ERROR;
- st->flags &= ~ST_AT_FILEMARK;
- biodone(bp);
- continue; /* seek more work */
- }
- }
- /*
- * If we are at EIO (e.g. EOM) but have not reported it
- * yet then we should report it now
- */
- if (st->flags & ST_EIO_PENDING) {
- bp->b_resid = bp->b_bcount;
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- st->flags &= ~ST_EIO_PENDING;
- biodone(bp);
- continue; /* seek more work */
- }
- }
- /*
- * Fill out the scsi command
- */
- bzero(&cmd, sizeof(cmd));
- if ((bp->b_flags & B_READ) == B_WRITE) {
- cmd.op_code = WRITE_COMMAND_TAPE;
- st->flags &= ~ST_FM_WRITTEN;
- st->flags |= ST_WRITTEN;
- flags |= SCSI_DATA_OUT;
- } else {
- cmd.op_code = READ_COMMAND_TAPE;
- flags |= SCSI_DATA_IN;
- }
- /*
- * Handle "fixed-block-mode" tape drives by using the
- * block count instead of the length.
- */
- if (st->flags & ST_FIXEDBLOCKS) {
- cmd.byte2 |= SRWT_FIXED;
- scsi_uto3b(bp->b_bcount / st->blksiz, cmd.len);
- } else {
- 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_data,
- bp->b_bcount,
- 0, /* can't retry a read on a tape really */
- 1000000,
- bp,
- flags) == SUCCESSFULLY_QUEUED) {
- } else {
-badnews:
- printf("st%lu: oops not queued\n", (u_long)unit);
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- biodone(bp);
- }
- } /* go back and see if we can cram more work in.. */
-}
-
-/*
- * Perform special action on behalf of the user;
- * knows about the internals of this device
- */
-static errval
-st_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag,
-struct proc *p, struct scsi_link *sc_link)
-{
- errval errcode = 0;
- u_int32_t unit;
- u_int32_t number, flags, dsty;
- struct scsi_data *st;
- u_int32_t hold_blksiz;
- u_int32_t hold_density;
- int32_t nmarks;
- struct mtop *mt = (struct mtop *) arg;
-
- /*
- * Find the device that the user is talking about
- */
- flags = 0; /* give error messages, act on errors etc. */
- unit = STUNIT(dev);
- dsty = DSTY(dev);
- st = sc_link->sd;
- hold_blksiz = st->blksiz;
- hold_density = st->density;
-
- switch (cmd) {
-
- case MTIOCGET:
- {
- struct mtget *g = (struct mtget *) arg;
-
- SC_DEBUG(sc_link, SDEV_DB1, ("[ioctl: get status]\n"));
- bzero(g, sizeof(struct mtget));
- g->mt_type = 0x7; /* Ultrix compat *//*? */
- g->mt_density = st->density;
- g->mt_blksiz = st->blksiz;
- g->mt_comp = st->comp;
- g->mt_density0 = st->modes[0].density;
- g->mt_density1 = st->modes[1].density;
- g->mt_density2 = st->modes[2].density;
- g->mt_density3 = st->modes[3].density;
- g->mt_blksiz0 = st->modes[0].blksiz;
- g->mt_blksiz1 = st->modes[1].blksiz;
- g->mt_blksiz2 = st->modes[2].blksiz;
- g->mt_blksiz3 = st->modes[3].blksiz;
- g->mt_comp0 = 0;
- g->mt_comp1 = 0;
- g->mt_comp2 = 0;
- g->mt_comp3 = 0;
- break;
- }
- case MTIOCTOP:
- {
-
- SC_DEBUG(sc_link, SDEV_DB1,
- ("[ioctl: op=0x%x count=0x%lx]\n",
- mt->mt_op, (long)mt->mt_count));
-
- /* compat: in U*x it is a short */
- number = mt->mt_count;
- switch ((short) (mt->mt_op)) {
- case MTWEOF: /* write an end-of-file record */
- errcode = st_write_filemarks(unit, number, flags);
- break;
- case MTBSF: /* backward space file */
- number = -number;
- case MTFSF: /* forward space file */
- errcode = st_chkeod(unit, FALSE, &nmarks, flags);
- if (errcode == ESUCCESS)
- errcode = st_space(unit, number - nmarks,
- SP_FILEMARKS, flags);
- break;
- case MTBSR: /* backward space record */
- number = -number;
- case MTFSR: /* forward space record */
- errcode = st_chkeod(unit, TRUE, &nmarks, flags);
- if (errcode == ESUCCESS)
- errcode = st_space(unit, number, SP_BLKS, flags);
- break;
- case MTEOD: /* space to end of recorded medium */
- errcode = st_chkeod(unit, FALSE, &nmarks, flags);
- if (errcode == ESUCCESS)
- errcode = st_space(unit, 0, SP_EOM,
- flags);
- break;
- case MTREW: /* rewind */
- errcode = st_rewind(unit, FALSE, flags);
- break;
- case MTERASE: /* erase */
- errcode = st_erase(unit, FALSE, flags);
- break;
- case MTRETENS: /* re-tension tape */
- errcode = st_load(unit, LD_LOAD|LD_RETEN,
- flags);
- break;
- case MTOFFL: /* rewind and put the drive offline */
- /*
- * Be sure to allow media removal before
- * attempting the eject.
- */
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
- st_unmount(unit, EJECT);
- break;
- case MTNOP: /* no operation, sets status only */
- case MTCACHE: /* enable controller cache */
- case MTNOCACHE: /* disable controller cache */
- break;
- case MTSETBSIZ: /* Set block size for device */
-#ifdef NOTYET
- if (!(st->flags & ST_NEW_MOUNT)) {
- uprintf("re-mount tape before changing blocksize");
- errcode = EINVAL;
- break;
- }
-#endif
- if (number == 0) {
- st->flags &= ~ST_FIXEDBLOCKS;
- } else {
- if ((st->blkmin || st->blkmax) /* they exist */
- &&((number < st->blkmin
- || number > st->blkmax))) {
- errcode = EINVAL;
- break;
- }
- st->flags |= ST_FIXEDBLOCKS;
- }
- st->blksiz = number;
- st->flags |= ST_BLOCK_SET; /*XXX */
- goto try_new_value;
-
- case MTSETDNSTY: /* Set density for device and mode */
- if (number > (u_int8_t)0xff) {
- /* Guard against overflows */
- errcode = EINVAL;
- } else {
- st->density = number;
- goto try_new_value;
- }
- break;
- case MTCOMP: /* enable default compression */
- errcode = st_comp(unit,number);
- break;
- default:
- errcode = EINVAL;
- }
- break;
- }
- case MTIOCIEOT:
- case MTIOCEEOT:
- break;
- default:
- if(IS_CTLMODE(dev))
- errcode = scsi_do_ioctl(dev, cmd, arg, flag, p, sc_link);
- else
- errcode = ENOTTY;
- break;
- }
- return errcode;
-/*-----------------------------*/
-try_new_value:
- /*
- * Check that the mode being asked for is aggreeable to the
- * drive. If not, put it back the way it was.
- */
- if ( (errcode = st_mode_select(unit, 0, NULL, 0, 0)) ) {
- /*
- * put back as it was
- */
- printf("st%lu: Cannot set selected mode", (u_long)unit);
- st->density = hold_density;
- st->blksiz = hold_blksiz;
- if (st->blksiz) {
- st->flags |= ST_FIXEDBLOCKS;
- } else {
- st->flags &= ~ST_FIXEDBLOCKS;
- }
- return (errcode);
- }
- /*
- * As the drive liked it, if we are setting a new default,
- * set it into the structures as such.
- *
- * The means for deciding this are not finalised yet
- */
- if (IS_CTLMODE(dev)) {
- /* special mode */
- /* XXX */
- switch ((short) (mt->mt_op)) {
- case MTSETBSIZ:
- st->modes[dsty].blksiz = st->blksiz;
- st->modeflags[dsty] |= BLKSIZE_SET_BY_USER;
- break;
- case MTSETDNSTY:
- st->modes[dsty].density = st->density;
- st->modeflags[dsty] |= DENSITY_SET_BY_USER;
- break;
- }
- }
- return 0;
-}
-
-/*
- * Do a synchronous read.
- */
-static errval
-st_read(unit, buf, size, flags)
- u_int32_t unit, size, flags;
- char *buf;
-{
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
- struct scsi_rw_tape scsi_cmd;
-
- /*
- * If it's a null transfer, return immediatly
- */
- if (size == 0) {
- return (ESUCCESS);
- }
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = READ_COMMAND_TAPE;
- if (st->flags & ST_FIXEDBLOCKS) {
- scsi_cmd.byte2 |= SRWT_FIXED;
- scsi_uto3b(size / (st->blksiz ? st->blksiz : DEF_FIXED_BSIZE),
- scsi_cmd.len);
- } else {
- scsi_uto3b(size, scsi_cmd.len);
- }
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) buf,
- size,
- 0, /* not on io commands */
- 1000000,
- NULL,
- flags | SCSI_DATA_IN));
-}
-#ifdef __STDC__
-#define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
-#else
-#define b2tol(a) (((unsigned)(a/**/_1) << 8) + (unsigned)a/**/_0 )
-#endif
-
-/*
- * Ask the drive what its min and max blk sizes are.
- */
-static errval
-st_rd_blk_lim(unit, flags)
- u_int32_t unit, flags;
-{
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
- struct scsi_blk_limits scsi_cmd;
- struct scsi_blk_limits_data scsi_blkl;
- errval errno;
-
- /*
- * First check if we have it all loaded
- */
- if ((sc_link->flags & SDEV_MEDIA_LOADED))
- return 0;
-
- /*
- * do a 'Read Block Limits'
- */
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = READ_BLK_LIMITS;
-
- /*
- * do the command, update the global values
- */
- if ( (errno = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) & scsi_blkl,
- sizeof(scsi_blkl),
- ST_RETRIES,
- 5000,
- NULL,
- flags | SCSI_DATA_IN)) ) {
- return errno;
- }
- st->blkmin = b2tol(scsi_blkl.min_length);
- st->blkmax = scsi_3btou(&scsi_blkl.max_length_2);
-
- SC_DEBUG(sc_link, SDEV_DB3,
- ("(%lu <= blksiz <= %lu)\n",
- (u_long)st->blkmin, (u_long)st->blkmax));
- return 0;
-}
-
-/*
- * Get the scsi driver to send a full inquiry to the
- * device and use the results to fill out the global
- * parameter structure.
- *
- * called from:
- * attach
- * open
- * ioctl (to reset original blksize)
- */
-static errval
-st_mode_sense(unit, flags, page, pagelen, pagecode)
- u_int32_t unit, flags;
- struct tape_pages *page;
- u_int32_t pagelen,pagecode;
-{
- u_int32_t dat_len;
- errval errno;
- struct scsi_mode_sense scsi_cmd;
- struct {
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- struct tape_pages page;
- } dat;
-
- /* Tandberg tape drives returns page 00
- * with the sense data, whether or not
- * you want it( ie the don't like you
- * saying you want anything less!!!!!
- * They also expect page 00
- * back when you issue a mode select
- */
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
-
- st->flags &= ~ST_SENSE_READ;
- /*
- * Check if we need to use a default page..
- */
- if ((st->quirks & ST_Q_NEEDS_PAGE_0) && (!page)) {
- pagelen = PAGE_0_SENSE_DATA_SIZE;
- page = (struct tape_pages *) st->saved_page0;
- pagecode = 0;
- }
- /*
- * Now work out the total dat size etc.
- */
- dat_len = sizeof(struct scsi_mode_header)
- + sizeof(struct blk_desc)
- + (page ? pagelen : 0);
- /*
- * Set up a mode sense
- */
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SENSE;
- scsi_cmd.page = (u_char) pagecode;
- scsi_cmd.length = dat_len;
-
- /*
- * do the command,
- * use the results to set blksiz, numblks and density
- * or if we need it as a template for the mode select
- * store it away.
- */
- if ( (errno = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) &dat,
- dat_len,
- ST_RETRIES,
- 5000,
- NULL,
- flags | SCSI_DATA_IN)) ) {
- return errno;
- }
- st->numblks = scsi_3btou(dat.blk_desc.nblocks);
- st->media_blksiz = scsi_3btou(dat.blk_desc.blklen);
- st->media_density = dat.blk_desc.density;
- if (dat.header.dev_spec & SMH_DSP_WRITE_PROT) {
- st->flags |= ST_READONLY;
- }
- SC_DEBUG(sc_link, SDEV_DB3,
- ("density code 0x%lx, %lu-byte blocks, write-%s, ",
- (u_long)st->media_density, (u_long)st->media_blksiz,
- st->flags & ST_READONLY ? "protected" : "enabled"));
- SC_DEBUG(sc_link, SDEV_DB3, ("%sbuffered\n",
- ((dat.header.dev_spec & SMH_DSP_BUFF_MODE) ? "" : "un")));
- if (page) {
- bcopy(&dat.page, page, pagelen);
- }
- st->flags |= ST_SENSE_READ;
- return 0;
-}
-
-/*
- * Send a filled out parameter structure to the drive to
- * set it into the desire modes etc.
- */
-static errval
-st_mode_select(unit, flags, page, pagelen, byte2)
- u_int32_t unit, flags;
- struct tape_pages *page;
- u_int32_t pagelen;
- u_int32_t byte2;
-{
- u_int32_t dat_len;
- struct scsi_mode_select scsi_cmd;
- struct {
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- struct tape_pages page;
- } dat;
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
-
- /*
- * Check if we need to use a default page..
- * Gee, hope we saved one before now........
- */
- if ((st->quirks & ST_Q_NEEDS_PAGE_0) && (!page)) {
- pagelen = PAGE_0_SENSE_DATA_SIZE;
- page = (struct tape_pages *) st->saved_page0;
- }
- /*
- * Now work out the total dat size etc.
- */
- dat_len = sizeof(struct scsi_mode_header)
- + sizeof(struct blk_desc)
- + (page ? pagelen : 0);
- /*
- * Set up for a mode select
- */
- bzero(&dat, dat_len);
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SELECT;
- scsi_cmd.length = dat_len;
- scsi_cmd.byte2 = (u_char)byte2;
- dat.header.blk_desc_len = sizeof(struct blk_desc);
- dat.header.dev_spec |= SMH_DSP_BUFF_MODE_ON;
- dat.blk_desc.density = st->density;
- if (st->flags & ST_FIXEDBLOCKS) {
- scsi_uto3b(st->blksiz, dat.blk_desc.blklen);
- }
- if (page) {
- bcopy(page, &dat.page, pagelen);
- /* the Tandberg tapes need the block size to */
- /* be set on each mode sense/select. */
- }
- /*
- * do the command
- */
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) &dat,
- dat_len,
- ST_RETRIES,
- 5000,
- NULL,
- flags | SCSI_DATA_OUT));
-}
-
-static int noisy_st = 0;
-/***************************************************************\
-* Set the compression mode of the drive to on (1) or off (0) *
- still doesn't work! grrr!
-\***************************************************************/
-static errval
-st_comp(unit,mode)
-u_int32_t unit,mode;
-{
- struct tape_pages page;
- int pagesize;
- int retval;
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
-
- bzero(&page, sizeof(page));
- pagesize = sizeof(page.pages.configuration) + PAGE_HEADERLEN;
-
- if ( (retval = st_mode_sense(unit, 0,
- &page, pagesize, ST_PAGE_CONFIGURATION)) )
- {
- printf("sense returned an error of %d\n",retval);
- return retval;
- }
- if ( noisy_st)
- printf("drive reports value of %d, setting %lu\n",
- page.pages.configuration.data_compress_alg,
- (u_long)mode);
-
- page.pg_code &= ST_P_CODE;
- page.pg_length = sizeof(page.pages.configuration);
-
- switch(mode)
- {
- case 0:
- page.pages.configuration.data_compress_alg = 0;
- break;
- case 1:
- page.pages.configuration.data_compress_alg = 1;
- break;
- default:
- printf("st%lu: bad value for compression mode\n", (u_long)unit);
- return EINVAL;
- }
- /*
- * send ST_PAGE_CONFIGURATION page as SCSI-II command because it
- * is a SCSI-II structure. This requires the PF bit (0x10) to be
- * set for byte2.
- */
- if ( (retval = st_mode_select(unit, 0, &page, pagesize, 0x10)) )
- {
- printf("select returned an error of %d\n",retval);
- return retval;
- }
- st->comp = mode;
- return 0;
-}
-/*
- * skip N blocks/filemarks/seq filemarks/eom
- */
-static errval
-st_space(unit, number, what, flags)
- u_int32_t unit, what, flags;
- int32_t number;
-{
- errval error;
- struct scsi_space scsi_cmd;
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
-
- switch ((int)what) {
- case SP_BLKS:
- if (st->flags & ST_PER_ACTION) {
- if (number > 0) {
- st->flags &= ~ST_PER_ACTION;
- return (EIO);
- } else if (number < 0) {
- if (st->flags & ST_AT_FILEMARK) {
- /*
- * Handling of ST_AT_FILEMARK
- * in st_space will fill in the
- * right file mark count.
- */
- error = st_space(unit, 0, SP_FILEMARKS,
- flags);
- if (error)
- return (error);
- }
- if (st->flags & ST_BLANK_READ) {
- st->flags &= ~ST_BLANK_READ;
- return (EIO);
- }
- st->flags &= ~ST_EIO_PENDING;
- }
- }
- break;
- case SP_FILEMARKS:
- if (st->flags & ST_EIO_PENDING) {
- if (number > 0) { /* pretend we just discover the error */
- st->flags &= ~ST_EIO_PENDING;
- return (EIO);
- } else if (number < 0) { /* back away from the error */
- st->flags &= ~ST_EIO_PENDING;
- }
- }
- if (st->flags & ST_AT_FILEMARK) {
- st->flags &= ~ST_AT_FILEMARK;
- number--;
- }
- if ((st->flags & ST_BLANK_READ) && (number < 0)) { /* back away from unwritten tape */
- st->flags &= ~ST_BLANK_READ;
- number++; /* dubious */
- }
- break;
- case SP_EOM:
- if (st->flags & ST_EIO_PENDING)
- {
- /* we are already at EOM */
- st->flags &= ~ST_EIO_PENDING;
- return(ESUCCESS);
- }
- number = 1; /* we have only one end-of-medium */
- break;
- }
- if (number == 0) {
- return (ESUCCESS);
- }
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = SPACE;
- scsi_cmd.byte2 = what & SS_CODE;
- scsi_uto3b(number, scsi_cmd.number);
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 0, /* no retries please , just fail */
- 3600000, /* wait up to an hour for completion */
- NULL,
- flags));
-}
-
-/*
- * write N filemarks
- */
-static errval
-st_write_filemarks(unit, number, flags)
- u_int32_t unit, flags;
- int32_t number;
-{
- struct scsi_write_filemarks scsi_cmd;
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
-
- /*
- * It's hard to write a negative number of file marks.
- * Don't try.
- */
- if (number < 0) {
- return EINVAL;
- }
- switch ((int)number) {
- case 0: /* really a command to sync the drive's buffers */
- break;
- case 1:
- if (st->flags & ST_FM_WRITTEN) { /* already have one down */
- st->flags &= ~ST_WRITTEN;
- } else {
- st->flags |= ST_FM_WRITTEN;
- }
- st->flags &= ~ST_PER_ACTION;
- break;
- default:
- st->flags &= ~(ST_PER_ACTION | ST_WRITTEN);
- }
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = WRITE_FILEMARKS;
- scsi_uto3b(number, scsi_cmd.number);
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 0, /* no retries, just fail */
- 1000000, /* 100 secs.. (may need to repos head ) */
- NULL,
- flags);
-}
-
-/*
- * Make sure the right number of file marks is on tape if the
- * tape has been written. If the position argument is true,
- * leave the tape positioned where it was originally.
- *
- * nmarks returns the number of marks to skip (or, if position
- * true, which were skipped) to get back original position.
- */
-static int32_t
-st_chkeod(unit, position, nmarks, flags)
- u_int32_t unit;
- boolean position;
- int32_t *nmarks;
- u_int32_t flags;
-{
- errval error;
- struct scsi_data *st = SCSI_DATA(&st_switch, unit);
-
- switch ((int)(st->flags & (ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD))) {
- default:
- *nmarks = 0;
- return (ESUCCESS);
- case ST_WRITTEN:
- case ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD:
- *nmarks = 1;
- break;
- case ST_WRITTEN | ST_2FM_AT_EOD:
- *nmarks = 2;
- }
- error = st_write_filemarks(unit, *nmarks, flags);
- if (position && (error == ESUCCESS))
- error = st_space(unit, -*nmarks, SP_FILEMARKS, flags);
- return (error);
-}
-
-/*
- * load/unload (with retension if true)
- */
-static errval
-st_load(unit, type, flags)
- u_int32_t unit, type, flags;
-{
- struct scsi_load scsi_cmd;
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- if (type != LD_LOAD) {
- errval error;
- int32_t nmarks;
-
- error = st_chkeod(unit, FALSE, &nmarks, flags);
- if (error != ESUCCESS)
- return (error);
- sc_link->flags &= ~SDEV_MEDIA_LOADED;
- }
- if (st->quirks & ST_Q_IGNORE_LOADS)
- return (0);
- scsi_cmd.op_code = LOAD_UNLOAD;
- scsi_cmd.how |= type;
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- ST_RETRIES,
- 900000, /* 15 min */
- NULL,
- flags));
-}
-
-/*
- * Rewind the device
- */
-static errval
-st_rewind(unit, immed, flags)
- u_int32_t unit, flags;
- boolean immed;
-{
- struct scsi_rewind scsi_cmd;
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
- errval error;
- int32_t nmarks;
-
- error = st_chkeod(unit, FALSE, &nmarks, flags);
- if (error != ESUCCESS)
- return (error);
- st->flags &= ~ST_PER_ACTION;
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = REWIND;
- scsi_cmd.byte2 = immed ? SR_IMMED : 0;
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- ST_RETRIES,
- immed ? 5000 : 300000, /* 5 sec or 5 min */
- NULL,
- flags));
-}
-
-/*
-** Erase the device
-*/
-static errval
-st_erase(unit, immed, flags)
- u_int32_t unit, flags;
- boolean immed;
-{
- struct scsi_erase scsi_cmd;
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
- errval error;
- int32_t nmarks;
-
- error = st_chkeod(unit, FALSE, &nmarks, flags);
- if (error != ESUCCESS)
- return (error);
- /*
- ** Archive Viper 2525 technical manual 5.7 (ERASE 19h):
- ** tape has to be positioned to BOT first before erase command
- ** is issued or command is rejected. So we rewind the tape first
- ** and exit with an error, if the tape can't be rewinded.
- */
- error = st_rewind(unit, FALSE, SCSI_SILENT);
- if (error != ESUCCESS)
- return (error);
- st->flags &= ~ST_PER_ACTION;
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = ERASE;
- scsi_cmd.byte2 = SE_LONG; /* LONG_ERASE */
- scsi_cmd.byte2 += immed ? SE_IMMED : 0; /* immed bit is here the 2nd! */
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- ST_RETRIES,
- immed ? 5000 : (200 * 60 * 1000), /* 5 sec or 200 min */
- NULL,
- flags));
-}
-
-/*
- * Look at the returned sense and act on the error and detirmine
- * The unix error number to pass back... (0 = report no error)
- * (SCSIRET_CONTINUE = continue processing)
- */
-static errval
-st_interpret_sense(xs)
- struct scsi_xfer *xs;
-{
- struct scsi_link *sc_link = xs->sc_link;
- struct scsi_sense_data *sense = &(xs->sense);
- boolean silent = xs->flags & SCSI_SILENT;
- u_int32_t unit = sc_link->dev_unit;
- struct scsi_data *st = SCSI_DATA(&st_switch, unit);
- u_int32_t key;
- int32_t info;
-
- /*
- * Get the sense fields and work out what code
- */
- if (sense->error_code & SSD_ERRCODE_VALID) {
- info = ntohl(*((int32_t *) sense->ext.extended.info));
- } else {
- if (st->flags & ST_FIXEDBLOCKS) {
- info = xs->datalen / st->blksiz;
- } else {
- info = xs->datalen;
- }
- }
-
- key = sense->ext.extended.flags & SSD_KEY;
-
- if (((sense->error_code & SSD_ERRCODE) != 0x70)
- || (key == 0x7)) /* Media Write Protected */ {
- return SCSIRET_CONTINUE;/* let the generic code handle it */
- }
- if(sense->ext.extended.flags & (SSD_EOM|SSD_FILEMARK|SSD_ILI)) {
- if (st->flags & ST_FIXEDBLOCKS) {
- xs->resid = info * st->blksiz;
- xs->flags |= SCSI_RESID_VALID;
- if (sense->ext.extended.flags & SSD_EOM) {
- st->flags |= ST_EIO_PENDING;
- }
- if (sense->ext.extended.flags & SSD_FILEMARK) {
- st->flags |= ST_AT_FILEMARK;
- }
- if (sense->ext.extended.flags & SSD_ILI) {
- st->flags |= ST_EIO_PENDING;
- if (sense->error_code & SSD_ERRCODE_VALID &&
- !silent)
- printf(
- "st%lu: block wrong size, %ld blocks residual\n",
- (u_long)unit, (long)info);
- /*XXX*/ /* is this how it works ? */
- /* check def of ILI for fixed blk tapes */
-
- /*
- * This quirk code helps the drive read
- * the first tape block, regardless of
- * format. That is required for these
- * drives to return proper MODE SENSE
- * information.
- */
- if ((st->quirks & ST_Q_SNS_HLP) &&
- !(st->flags & ST_SENSE_READ)) {
- st->blksiz -= 512;
- }
- }
- /*
- * If no data was tranfered, do it immediatly
- */
- if (xs->resid >= xs->datalen) {
- xs->flags &= ~SCSI_RESID_VALID;
- if (st->flags & ST_AT_FILEMARK) {
- xs->flags |= SCSI_EOF;
- st->flags &= ~ST_AT_FILEMARK;
- return 0;
- }
- if (st->flags & ST_EIO_PENDING) {
- st->flags &= ~ST_EIO_PENDING;
- return EIO;
- }
- }
- return 0;
- } else { /* must be variable mode */
- xs->resid = xs->datalen; /* to be sure */
- if (sense->ext.extended.flags & SSD_EOM) {
- return (EIO);
- }
- if (sense->ext.extended.flags & SSD_FILEMARK) {
- xs->flags |= SCSI_EOF;
- }
- if (sense->ext.extended.flags & SSD_ILI) {
- if (info < 0) {
- /*
- * the record was bigger than the read
- */
- if (!silent)
- printf(
- "st%lu: %ld-byte record too big\n",
- (u_long)unit,
- (long)(xs->datalen - info));
- return (EIO);
- }
- xs->resid = info;
- xs->flags |= SCSI_RESID_VALID;
- }
- }
- return 0;
- }
-
- if (key == 0x8) {
- xs->flags |= SCSI_EOF; /* some drives need this */
- /*
- * This quirk code helps the drive read the
- * first tape block, regardless of format. That
- * is required for these drives to return proper
- * MODE SENSE information.
- */
- if ((st->quirks & ST_Q_SNS_HLP) &&
- !(st->flags & ST_SENSE_READ)) {
- /* still starting */
- st->blksiz -= 512;
- } else if (!(st->flags & (ST_2FM_AT_EOD | ST_BLANK_READ))) {
- st->flags |= ST_BLANK_READ;
- xs->flags |= SCSI_EOF;
- return (ESUCCESS);
- }
- }
- return SCSIRET_CONTINUE; /* Use the the generic handler */
-}
-
-/*
- * The quirk here is that the drive returns some value to st_mode_sense
- * incorrectly until the tape has actually passed by the head.
- *
- * The method is to set the drive to large fixed-block state (user-specified
- * density and 1024-byte blocks), then read and rewind to get it to sense the
- * tape. If that doesn't work, try 512-byte fixed blocks. If that doesn't
- * work, as a last resort, try variable- length blocks. The result will be
- * the ability to do an accurate st_mode_sense.
- *
- * We know we can do a rewind because we just did a load, which implies rewind.
- * Rewind seems preferable to space backward if we have a virgin tape.
- *
- * The rest of the code for this quirk is in ILI processing and BLANK CHECK
- * error processing, both part of st_interpret_sense.
- */
-static errval
-st_touch_tape(unit)
- u_int32_t unit;
-{
- struct scsi_data *st = SCSI_DATA(&st_switch, unit);
- char *buf;
- u_int32_t readsiz;
- errval errno;
-
-#ifdef BOUNCE_BUFFERS
- buf = (caddr_t) vm_bounce_kva_alloc(btoc(1024));
-#else
- buf = malloc(1024, M_TEMP, M_NOWAIT);
-#endif
- if (!buf)
- return (ENOMEM);
-
- if (( errno = st_mode_sense(unit, 0, NULL, 0, 0)) ) {
- goto bad;
- }
- st->blksiz = (st->quirks & ST_Q_NO_1024)? 512: 1024;
- do {
- switch ((int)st->blksiz) {
- case 512:
- case 1024:
- readsiz = st->blksiz;
- st->flags |= ST_FIXEDBLOCKS;
- break;
- default:
- readsiz = 1;
- st->flags &= ~ST_FIXEDBLOCKS;
- } if ( (errno = st_mode_select(unit, 0, NULL, 0, 0)) ) {
- goto bad;
- }
- st_read(unit, buf, readsiz, SCSI_SILENT);
- if ( (errno = st_rewind(unit, FALSE, 0)) ) {
-bad: free(buf, M_TEMP);
- return (errno);
- }
- } while (readsiz != 1 && readsiz > st->blksiz);
-#ifdef BOUNCE_BUFFERS
- vm_bounce_kva_alloc_free((vm_offset_t) buf, btoc(1024));
-#else
- free(buf, M_TEMP);
-#endif
- return 0;
-}
-
-static st_devsw_installed = 0;
-
-static void
-st_drvinit(void *unused)
-{
-
- if( ! st_devsw_installed ) {
- dev_t dev;
-
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev, &st_cdevsw, NULL);
- st_devsw_installed = 1;
- }
-}
-
-SYSINIT(stdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,st_drvinit,NULL)
-
-
diff --git a/sys/scsi/su.c b/sys/scsi/su.c
deleted file mode 100644
index 785e831..0000000
--- a/sys/scsi/su.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/* su: SCSI Universal. This is a universal SCSI device that
- * has a fixed minor number format. This allows you to refer
- * to your devices by BUS, ID, LUN instead of st0, st1, ...
- *
- * This code looks up the underlying device for a given SCSI
- * target and uses that driver.
- *
- *Begin copyright
- *
- * Copyright (C) 1993, 1994, 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.
- *End copyright
- *
- * $Id: su.c,v 1.20 1998/07/04 22:30:25 julian Exp $
- *
- * Tabstops 4
- * XXX devfs entries for this device should be handled by generic scsiconfig
- * Add a bdevsw interface.. ?
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/stat.h>
-#include <sys/buf.h>
-#include <sys/kernel.h>
-#include <scsi/scsiconf.h>
-#define CDEV_MAJOR 18
-
-/* These three used by ssc. */
-extern d_open_t suopen;
-extern d_close_t suclose;
-extern d_ioctl_t suioctl;
-
-static d_read_t suread;
-static d_write_t suwrite;
-static d_poll_t supoll;
-static d_strategy_t sustrategy;
-
-static struct cdevsw su_cdevsw =
- { suopen, suclose, suread, suwrite, /*18*/
- suioctl, nostop, nullreset, nodevtotty,/* scsi */
- supoll, nommap, sustrategy, "su", NULL, -1 };
-
-
-/* Build an old style device number (unit encoded in the minor number)
- * from a base old one (no flag bits) and a full new one
- * (BUS, LUN, TARG in the minor number, and flag bits).
- *
- * OLDDEV has the major number and device unit only. It was constructed
- * at attach time and is stored in the scsi_link structure.
- *
- * NEWDEV can have whatever in it, but only the old control flags and the
- * super bit are present. IT CAN'T HAVE ANY UNIT INFORMATION or you'll
- * wind up with the wrong unit.
- */
-#define OLD_DEV(NEWDEV, OLDDEV) ((OLDDEV) | ((NEWDEV) & 0x080000FF))
-
-/* cnxio: non existent device entries. */
-
-static d_open_t nxopen;
-static d_close_t nxclose;
-static d_read_t nxread;
-static d_write_t nxwrite;
-static d_ioctl_t nxioctl;
-#define nxstop nostop /* one void return is as good as another */
-#define nxreset noreset /* one unused function is as good as another */
-#define nxdevtotty nodevtotty /* one NULL return is as good as another */
-#define nxmmap nommap /* one -1 return is as good as another */
-#define nxstrategy nostrategy /* one NULL value is as good as another */
-static d_dump_t nxdump;
-#define nxpsize nopsize /* one NULL value is as good as another */
-
-static struct cdevsw cnxio = {
- nxopen,
- nxclose,
- nxread,
- nxwrite,
- nxioctl,
- nxstop,
- nxreset,
- nxdevtotty,
- seltrue,
- nxmmap,
- nxstrategy,
- "NON",
- NULL,
- -1,
- nxdump,
- nxpsize,
- 0,
- 0,
- -1
-};
-
-/* getsws: Look up the base dev switch for a given "by minor number" style
- * device.
- */
-static int
-getsws(dev_t dev, int type, struct cdevsw **devswpp, dev_t *base)
-{
- int ret = 0;
- struct scsi_link *scsi_link;
- int chr_dev, blk_dev;
-
- struct cdevsw *devswp;
-
- int bus = SCSI_BUS(dev),
- lun = SCSI_LUN(dev),
- id = SCSI_ID(dev);
-
- /* Try to look up the base device by finding the major number in
- * the scsi_link structure:
- */
- if ((scsi_link = scsi_link_get(bus, id, lun)) == 0 ||
- scsi_link->dev == NODEV)
- {
- ret = ENXIO;
- devswp = &cnxio;
- chr_dev = NODEV;
- blk_dev = NODEV;
- }
- else
- {
- int bmaj, cmaj;
-
- cmaj = major(scsi_link->dev);
- devswp = cdevsw[cmaj];
- chr_dev = OLD_DEV(dev, scsi_link->dev);
- bmaj = devswp->d_bmaj;
- blk_dev = OLD_DEV(dev, makedev(bmaj, minor(scsi_link->dev)));
- }
-
- if (devswp)
- *devswpp = devswp;
-
- if (type == S_IFCHR)
- *base = chr_dev;
- else
- *base = blk_dev;
-
- return ret;
-}
-
-int
-suopen(dev_t dev, int flag, int type, struct proc *p)
-{
- struct cdevsw *devswp;
- dev_t base;
-
- if (getsws(dev, type, &devswp, &base))
- {
- /* Device not configured? Reprobe then try again.
- */
- int bus = SCSI_BUS(dev), lun = SCSI_LUN(dev), id = SCSI_ID(dev);
-
- if (scsi_probe_bus(bus, id, lun) || getsws(dev, type, &devswp,
- &base))
- return ENXIO;
- }
-
- /* There is a properly configured underlying device.
- * Synthesize an appropriate device number:
- */
- return (*devswp->d_open)(base, flag, type, p);
-}
-
-int
-suclose(dev_t dev, int fflag, int type, struct proc *p)
-{
- struct cdevsw *devswp;
- dev_t base;
-
- (void)getsws(dev, type, &devswp, &base);
-
- return (*devswp->d_close)(base, fflag, type, p);
-}
-
-static void
-sustrategy(struct buf *bp)
-{
- dev_t base;
- struct cdevsw *devswp;
- dev_t dev = bp->b_dev;
-
- /* XXX: I have no way of knowing if this was through the
- * block or the character entry point.
- */
- (void)getsws(dev, S_IFBLK, &devswp, &base);
-
- bp->b_dev = base;
-
- (*devswp->d_strategy)(bp);
-
- bp->b_dev = dev; /* strat needs a dev_t */
-}
-
-int
-suioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
-{
- struct cdevsw *devswp;
- dev_t base;
-
- /* XXX: I have no way of knowing if this was through the
- * block or the character entry point.
- */
- (void)getsws(dev, S_IFCHR, &devswp, &base);
-
- return (*devswp->d_ioctl)(base, cmd, data, fflag, p);
-}
-
-static int
-suread(dev_t dev, struct uio *uio, int ioflag)
-{
- dev_t base;
- struct cdevsw *devswp;
-
- (void)getsws(dev, S_IFCHR, &devswp, &base);
-
- return (*devswp->d_read)(base, uio, ioflag);
-}
-
-static int
-suwrite(dev_t dev, struct uio *uio, int ioflag)
-{
- dev_t base;
- struct cdevsw *devswp;
-
- (void)getsws(dev, S_IFCHR, &devswp, &base);
-
- return (*devswp->d_write)(base, uio, ioflag);
-}
-
-static int
-supoll(dev_t dev, int events, struct proc *p)
-{
- dev_t base;
- struct cdevsw *devswp;
-
- (void)getsws(dev, S_IFCHR, &devswp, &base);
-
- return (*devswp->d_poll)(base, events, p);
-}
-
-static int
-nxopen(dev, flags, fmt, p)
- dev_t dev;
- int flags;
- int fmt;
- struct proc *p;
-{
-
- return (ENXIO);
-}
-
-static int
-nxclose(dev, flags, fmt, p)
- dev_t dev;
- int flags;
- int fmt;
- struct proc *p;
-{
-
- printf("nxclose(0x%x) called\n", dev);
- return (ENXIO);
-}
-
-static int
-nxread(dev, uio, ioflag)
- dev_t dev;
- struct uio *uio;
- int ioflag;
-{
-
- printf("nxread(0x%x) called\n", dev);
- return (ENXIO);
-}
-
-static int
-nxwrite(dev, uio, ioflag)
- dev_t dev;
- struct uio *uio;
- int ioflag;
-{
-
- printf("nxwrite(0x%x) called\n", dev);
- return (ENXIO);
-}
-
-static int
-nxioctl(dev, cmd, data, flags, p)
- dev_t dev;
- u_long cmd;
- caddr_t data;
- int flags;
- struct proc *p;
-{
-
- printf("nxioctl(0x%x) called\n", dev);
- return (ENXIO);
-}
-
-static int
-nxdump(dev)
- dev_t dev;
-{
-
- printf("nxdump(0x%x) called\n", dev);
- return (ENXIO);
-}
-
-static su_devsw_installed = 0;
-
-static void
-su_drvinit(void *unused)
-{
- dev_t dev;
-
- if( ! su_devsw_installed ) {
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev,&su_cdevsw, NULL);
- su_devsw_installed = 1;
- }
-}
-
-SYSINIT(sudev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,su_drvinit,NULL)
-
-
diff --git a/sys/scsi/uk.c b/sys/scsi/uk.c
deleted file mode 100644
index a9b8edf..0000000
--- a/sys/scsi/uk.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Driver for a device we can't identify.
- * by Julian Elischer (julian@tfs.com)
- *
- * $Id: uk.c,v 1.18 1997/08/02 14:33:16 bde Exp $
- *
- * If you find that you are adding any code to this file look closely
- * at putting it in "scsi_driver.c" instead.
- */
-
-#include <opt_devfs.h>
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_driver.h>
-
-struct scsi_data {
-#ifdef DEVFS
- void *devfs_data_tok;
-#endif
-};
-
-static d_open_t ukopen;
-static d_close_t ukclose;
-static d_ioctl_t ukioctl;
-
-#define CDEV_MAJOR 31
-static struct cdevsw uk_cdevsw =
- { ukopen, ukclose, noread, nowrite, /*31*/
- ukioctl, nostop, nullreset, nodevtotty,/* unknown */
- seltrue, nommap, NULL, "uk" ,NULL, -1 };
-
-SCSI_DEVICE_ENTRIES(uk)
-
-struct scsi_device uk_switch =
-{
- NULL,
- NULL,
- NULL,
- NULL,
- "uk",
- 0,
- {0, 0},
- SDEV_ONCE_ONLY|SDEV_UK, /* Only one open allowed */
- ukattach,
- "Unknown",
- ukopen,
- sizeof(struct scsi_data),
- T_UNKNOWN,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
-};
-
-
-static uk_devsw_installed = 0;
-
-static errval
-ukattach(struct scsi_link *sc_link)
-{
-#ifdef DEVFS
- struct scsi_data *uk = sc_link->sd;
-
- uk->devfs_data_tok = devfs_add_devswf(&uk_cdevsw,
- sc_link->dev_unit,
- DV_CHR,
- UID_ROOT, GID_WHEEL, 0600,
- "uk%d", sc_link->dev_unit);
-#endif
- return 0;
-}
-
-
-static void uk_drvinit(void *unused)
-{
- dev_t dev;
-
- if( ! uk_devsw_installed ) {
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev,&uk_cdevsw, NULL);
- uk_devsw_installed = 1;
- }
-}
-
-SYSINIT(ukdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,uk_drvinit,NULL)
-
-
diff --git a/sys/scsi/worm.c b/sys/scsi/worm.c
deleted file mode 100644
index 1601d8e..0000000
--- a/sys/scsi/worm.c
+++ /dev/null
@@ -1,1811 +0,0 @@
-/*
- * worm: Write Once device driver
- *
- * Copyright (C) 1995, HD Associates, Inc.
- * PO Box 276
- * Pepperell, MA 01463
- * 508 433 5266
- * dufault@hda.com
- *
- * Copyright (C) 1996-97 interface business GmbH
- * Naumannstr. 1
- * D-01309 Dresden
- * F.R. Germany
- * <joerg_wunsch@interface-business.de>
- *
- * 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: worm.c,v 1.58 1998/07/04 22:30:25 julian Exp $
- */
-
-#include "opt_bounce.h"
-#include "opt_devfs.h"
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/cdio.h>
-#include <sys/wormio.h>
-#include <sys/fcntl.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_disk.h>
-#include <scsi/scsi_driver.h>
-#include <scsi/scsi_worm.h>
-#include <scsi/scsi_cd.h>
-#include <sys/dkstat.h>
-#include <sys/malloc.h>
-
-#include "ioconf.h"
-
-struct worm_quirks
-{
- /*
- * The device-specific functions that need to be called during
- * the several steps.
- */
- errval (*prepare_disk)(struct scsi_link *, int dummy, int speed);
- errval (*prepare_track)(struct scsi_link *, struct wormio_prepare_track *t);
- errval (*finalize_track)(struct scsi_link *);
- errval (*finalize_disk)(struct scsi_link *, int toc_type, int onp);
- errval (*write_session)(struct scsi_link *, struct wormio_write_session *);
- errval (*read_first_writable_address)(struct scsi_link *sc_link,
- int track, int mode, int raw, int audio, int *addr);
-};
-
-
-struct scsi_data
-{
- struct buf_queue_head buf_queue;
- int dkunit; /* disk stats unit number */
- u_int32_t blk_size; /* Size of each blocks */
-#ifdef DEVFS
- void *b_devfs_token;
- void *c_devfs_token;
- void *ctl_devfs_token;
-#endif
-
- struct worm_quirks *quirks; /* model-specific functions */
- struct wormio_prepare_track preptrack; /* scratch region */
- struct wormio_write_session *write_session; /* scratch region */
-
- u_int8_t dummy; /* use dummy writes */
- u_int8_t speed; /* select drive speed */
-
- u_int32_t worm_flags; /* driver-internal flags */
-#define WORMFL_DISK_PREPED 0x01 /* disk parameters have been spec'ed */
-#define WORMFL_TRACK_PREPED 0x02 /* track parameters have been sent */
-#define WORMFL_WRITTEN 0x04 /* track has been written */
-#define WORMFL_IOCTL_ONLY 0x08 /* O_NDELAY, only ioctls allowed */
-#define WORMFL_TRACK_PREP 0x10 /* track parameters have been spec'ed */
-
- int error; /* last error */
-};
-
-static struct {
- int asc;
- int devmode;
- int error;
- int ret;
-} worm_error[] = {
- {0x24, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_ABSORPTION_CONTROL_ERROR, 0},
- {0xb0, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_CALIBRATION_AREA_ALMOST_FULL, 0},
- {0xb4, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_CALIBRATION_AREA_FULL, SCSIRET_CONTINUE},
- {0xb5, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_DUMMY_BLOCKS_ADDED, 0},
- {0xaa, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_END_OF_MEDIUM, SCSIRET_CONTINUE},
- {0xad, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_BUFFER_UNDERRUN, SCSIRET_CONTINUE},
- {0xaf, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_OPTIMUM_POWER_CALIBRATION_ERROR, SCSIRET_CONTINUE},
- {0, 0, 0, 0}
-};
-
-static void wormstart(u_int32_t unit, u_int32_t flags);
-
-static errval worm_open(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-static errval worm_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag,
- struct proc *p, struct scsi_link *sc_link);
-static errval worm_close(dev_t dev, int flag, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-static void worm_strategy(struct buf *bp, struct scsi_link *sc_link);
-static errval worm_read_toc(struct scsi_link *sc_link,
- u_int32_t mode, u_int32_t start,
- struct cd_toc_entry *data, u_int32_t len);
-static errval worm_rezero_unit(struct scsi_link *sc_link);
-static errval worm_read_session_info(struct scsi_link *, struct wormio_session_info *);
-static int worm_sense_handler(struct scsi_xfer *);
-static errval worm_set_blksize(struct scsi_link *sc_link, int size);
-
-/* XXX should be moved out to an LKM */
-static errval rf4100_prepare_disk(struct scsi_link *, int dummy, int speed);
-static errval rf4100_prepare_track(struct scsi_link *, struct wormio_prepare_track *);
-static errval rf4100_finalize_track(struct scsi_link *);
-static errval rf4100_finalize_disk(struct scsi_link *, int toc_type, int onp);
-
-static errval hp4020i_prepare_disk(struct scsi_link *, int dummy, int speed);
-static errval hp4020i_prepare_track(struct scsi_link *, struct wormio_prepare_track *);
-static errval hp4020i_finalize_track(struct scsi_link *);
-static errval hp4020i_finalize_disk(struct scsi_link *, int toc_type, int onp);
-static errval hp4020i_write_session(struct scsi_link *, struct wormio_write_session *);
-static errval hp4020i_read_first_writable_address (struct scsi_link *sc_link,
- int track, int mode, int raw, int audio, int *addr);
-
-static worm_devsw_installed = 0;
-
-static d_open_t wormopen;
-static d_read_t wormread;
-static d_write_t wormwrite;
-static d_close_t wormclose;
-static d_ioctl_t wormioctl;
-static d_strategy_t wormstrategy;
-
-#define CDEV_MAJOR 62
-#define BDEV_MAJOR 23
-
-static struct cdevsw worm_cdevsw = {
- wormopen, wormclose, wormread, wormwrite,
- wormioctl, nostop, nullreset, nodevtotty,
- seltrue, nommap, wormstrategy, "worm",
- NULL, -1, nodump, nopsize,
- D_DISK, 0, -1 };
-
-static int
-wormunit(dev_t dev)
-{
- return (minor(dev) & ~(SCSI_FIXED_MASK|SCSI_CONTROL_MASK));
-}
-
-SCSI_DEVICE_ENTRIES(worm)
-
-static struct scsi_device worm_switch =
-{
- worm_sense_handler,
- 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,
- wormunit,
- 0,
- worm_open,
- worm_ioctl,
- worm_close,
- worm_strategy,
-};
-
-static struct worm_quirks worm_quirks_plasmon = {
- rf4100_prepare_disk, rf4100_prepare_track,
- rf4100_finalize_track, rf4100_finalize_disk,
- 0, hp4020i_read_first_writable_address
-};
-static struct worm_quirks worm_quirks_philips = {
- hp4020i_prepare_disk, hp4020i_prepare_track,
- hp4020i_finalize_track, hp4020i_finalize_disk,
- hp4020i_write_session, hp4020i_read_first_writable_address
-};
-
-static __inline void
-worm_registerdev(int unit)
-{
- if (dk_ndrive < DK_NDRIVE) {
- sprintf(dk_names[dk_ndrive], "worm%d", unit);
- dk_wpms[dk_ndrive] = (1*1024*1024/2); /* 1MB/sec XXX - fake! */
- SCSI_DATA(&worm_switch, unit)->dkunit = dk_ndrive++;
- } else {
- SCSI_DATA(&worm_switch, unit)->dkunit = -1;
- }
-}
-
-static errval
-worm_size(struct scsi_link *sc_link, int flags)
-{
- errval ret;
- struct scsi_data *worm = sc_link->sd;
- int blk_size;
- u_int32_t n_blks;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("worm_size"));
-
- n_blks = scsi_read_capacity(sc_link, &blk_size, flags);
-
- /*
- * CD-R devices can assume various sizes, depending on the
- * intended purpose of the track. Hence, READ CAPACITY
- * doesn't give us any good results. We make a more educated
- * guess when it comes to prepare a track.
- */
-
- if (n_blks > 0) {
- sc_link->flags |= SDEV_MEDIA_LOADED;
- ret = 0;
- } else {
- sc_link->flags &= ~SDEV_MEDIA_LOADED;
- ret = ENXIO;
- }
-
- return ret;
-}
-
-static errval
-wormattach(struct scsi_link *sc_link)
-{
- u_int32_t unit = sc_link->dev_unit;
-#ifdef DEVFS
- int mynor;
-#endif
- struct scsi_data *worm = sc_link->sd;
-
- if (sc_link->devmodes == 0)
- printf(", warning: unknown drive type");
-
- bufq_init(&worm->buf_queue);
-
-#ifdef DEVFS
- mynor = wormunit(sc_link->dev);
- worm->b_devfs_token =
- devfs_add_devswf(&worm_cdevsw, mynor,
- DV_BLK, 0, 0, 0444, "worm%d", mynor);
- worm->c_devfs_token =
- devfs_add_devswf(&worm_cdevsw, mynor,
- DV_CHR, 0, 0, 0644, "rworm%d", mynor);
- worm->ctl_devfs_token =
- devfs_add_devswf(&worm_cdevsw, mynor | SCSI_CONTROL_MASK,
- DV_CHR, 0, 0, 0600, "rworm%d.ctl", mynor);
-#endif
- worm_registerdev(unit);
- return 0;
-}
-
-static int
-wormread(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(wormstrategy, NULL, dev, 1, minphys, uio));
-}
-
-static int
-wormwrite(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(wormstrategy, NULL, dev, 0, minphys, uio));
-}
-
-/*
- * 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.
- *
- * Writes will fail if the disk and track not been prepared via the control
- * device.
- */
-static void
-wormstart(unit, flags)
- u_int32_t unit;
- u_int32_t flags;
-{
- struct scsi_link *sc_link = SCSI_LINK(&worm_switch, unit);
- struct scsi_data *worm = sc_link->sd;
- register struct buf *bp = 0;
- struct scsi_rw_big cmd;
-
- u_int32_t lba; /* Logical block address */
- u_int32_t 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(sc_link);
- return;
- }
-
- bp = bufq_first(&worm->buf_queue);
- if (bp == NULL)
- return;
-
- bufq_remove(&worm->buf_queue, bp);
-
- if ((bp->b_flags & B_READ) == B_WRITE) {
- if ((worm->worm_flags & WORMFL_TRACK_PREPED) == 0) {
- if ((worm->worm_flags & WORMFL_TRACK_PREP) == 0 &&
- !worm->write_session) {
- SC_DEBUG(sc_link, SDEV_DB3, ("sequence error\n"));
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- worm->error = WORM_SEQUENCE_ERROR;
- biodone(bp);
- goto badnews;
- } else {
- if (worm->write_session) {
- if ((worm->quirks->write_session)
- (sc_link, worm->write_session)) {
- biodone(bp);
- goto badnews;
- }
- } else
- if (worm->quirks->prepare_track(sc_link, &worm->preptrack)
- != 0) {
- biodone(bp);
- goto badnews;
- }
- worm->worm_flags |= WORMFL_TRACK_PREPED;
- }
- }
- }
- /*
- * 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;
- }
-
- worm->error = 0;
-
- lba = bp->b_blkno / (worm->blk_size / DEV_BSIZE);
- tl = bp->b_bcount / worm->blk_size;
-
- if (bp->b_flags & B_READ)
- /*
- * Leave the LBA as 0 for write operations, it
- * is reserved in this case (and wouldn't make
- * any sense to set it at all, since CD-R write
- * operations are in `streaming' mode anyway.
- */
- scsi_uto4b(lba, &cmd.addr_3);
- scsi_uto2b(tl, &cmd.length2);
-
- /*
- * 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_data,
- bp->b_bcount,
- 0,
- 100000,
- bp,
- flags | SCSI_NOSLEEP) == SUCCESSFULLY_QUEUED) {
- if (worm->dkunit >= 0) { /* Cloned from od.c, possibly with same mistakes. :) */
- dk_xfer[worm->dkunit]++;
- dk_seek[worm->dkunit] = 1; /* single track */
- dk_wds[worm->dkunit] += bp->b_bcount >> 6;
- }
- if ((bp->b_flags & B_READ) == B_WRITE)
- worm->worm_flags |= WORMFL_WRITTEN;
- } else {
- printf("worm%lu: oops not queued\n", (u_long)unit);
- if (bp) {
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- biodone(bp);
- }
- }
- } /* go back and see if we can cram more work in.. */
-badnews: ;
-}
-
-static void
-worm_strategy(struct buf *bp, struct scsi_link *sc_link)
-{
- unsigned char unit;
- u_int32_t opri;
- struct scsi_data *worm;
-
- unit = wormunit(bp->b_dev);
- worm = sc_link->sd;
-
- if ((worm->worm_flags & WORMFL_IOCTL_ONLY) != 0) {
- SC_DEBUG(sc_link, SDEV_DB3,
- ("attempted IO on ioctl-only descriptor\n"));
- bp->b_error = EBADF;
- bp->b_flags |= B_ERROR;
- biodone(bp);
- return;
- }
-
- /*
- * check it's not too big a transfer for our adapter
- */
- wormminphys(bp);
-
- 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.
- */
- bufq_insert_tail(&worm->buf_queue, bp);
-
- wormstart(unit, 0);
-
- splx(opri);
- return;
-}
-
-/*
- * Open the device.
- * Only called for the "real" device, not for the control device.
- */
-static int
-worm_open(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link)
-{
- struct scsi_data *worm;
- errval error;
-
- error = 0;
- worm = sc_link->sd;
-
- if (sc_link->flags & SDEV_OPEN)
- return EBUSY;
-
- /*
- * Unknown drive type: only the control device can be opened
- * in this case, so scsi(8) and things like cdrecord will
- * work.
- */
- if (sc_link->devmodes == 0)
- return ENXIO;
-
- /*
- * 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);
-
- /*
- * The semantics of the "flags" is as follows:
- *
- * If the device has been opened with O_NONBLOCK set, no
- * actual IO will be allowed, and the command sequence is only
- * subject to the restrictions as in worm_ioctl() below.
- */
- /*
- * Next time actually take notice of error returns,
- * unit attn errors are now errors.
- */
- sc_link->flags |= SDEV_OPEN;
-
- if (scsi_test_unit_ready(sc_link, SCSI_SILENT) != 0) {
- SC_DEBUG(sc_link, SDEV_DB3, ("not ready\n"));
- error = ENXIO;
- goto out;
- }
-
- if ((flags & O_NONBLOCK) == 0) {
- scsi_start_unit(sc_link, SCSI_SILENT);
- scsi_prevent(sc_link, PR_PREVENT, SCSI_SILENT);
-
- if((flags & FWRITE) != 0) {
- if ((error = worm_rezero_unit(sc_link)) != 0 ||
- (error = worm_size(sc_link, 0)) != 0) {
- SC_DEBUG(sc_link, SDEV_DB3,
- ("rezero, or get size failed\n"));
- error = EIO;
- goto out;
- }
- } else {
- /* read/only */
- if ((error = worm_size(sc_link, 0)) != 0) {
- SC_DEBUG(sc_link, SDEV_DB3,
- ("get size failed\n"));
- error = EIO;
- goto out;
- }
- worm->blk_size = 2048;
- }
- } else
- worm->worm_flags |= WORMFL_IOCTL_ONLY;
-
- switch (*(int *) sc_link->devmodes) {
- case WORM_Q_PLASMON:
- worm->quirks = &worm_quirks_plasmon;
- break;
- case WORM_Q_PHILIPS:
- worm->quirks = &worm_quirks_philips;
- break;
- default:
- error = ENXIO;
- }
- worm->error = 0;
-
- out:
- if (error) {
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
- worm->worm_flags &= ~(WORMFL_TRACK_PREPED| WORMFL_TRACK_PREP);
- sc_link->flags &= ~SDEV_OPEN;
- }
-
- return error;
-}
-
-static int
-worm_close(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link)
-{
- struct scsi_data *worm = sc_link->sd;
- errval error;
-
- error = 0;
-
- if ((worm->worm_flags & WORMFL_IOCTL_ONLY) == 0) {
- if ((flags & FWRITE) != 0) {
- worm->error = 0;
- if ((worm->worm_flags & WORMFL_TRACK_PREPED) != 0) {
- error = (worm->quirks->finalize_track)(sc_link);
- worm->worm_flags &=
- ~(WORMFL_TRACK_PREPED | WORMFL_TRACK_PREP);
- }
- }
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
- } else {
- worm->worm_flags &= ~WORMFL_IOCTL_ONLY;
- if (worm->write_session) {
-#ifdef BOUNCE_BUFFERS
- vm_bounce_kva_alloc_free((vm_offset_t)worm->write_session,
- btoc(sizeof(struct wormio_write_session) +
- worm->write_session->length));
-#else
- free(worm->write_session, M_DEVBUF);
-#endif
- worm->write_session = 0;
- }
- }
- sc_link->flags &= ~SDEV_OPEN;
-
- return error;
-}
-
-/*
- * Perform special action on behalf of the user.
- * Knows about the internals of this device
- */
-errval
-worm_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p,
- struct scsi_link *sc_link)
-{
- errval error = 0;
- u_int8_t unit;
- register struct scsi_data *worm;
-
- /*
- * Find the device that the user is talking about
- */
- unit = wormunit(dev);
- worm = sc_link->sd;
- SC_DEBUG(sc_link, SDEV_DB2, ("wormioctl 0x%lx ", cmd));
-
- switch (cmd) {
- case WORMIOCPREPDISK:
- {
- struct wormio_prepare_disk *w =
- (struct wormio_prepare_disk *)addr;
- if (w->dummy != 0 && w->dummy != 1)
- error = EINVAL;
- else {
- error = (worm->quirks->prepare_disk)
- (sc_link, w->dummy, w->speed);
- if (error == 0) {
- worm->worm_flags |= WORMFL_DISK_PREPED;
- worm->dummy = w->dummy;
- worm->speed = w->speed;
- }
- }
- }
- break;
-
- case WORMIOCPREPTRACK:
- {
- struct wormio_prepare_track *w =
- (struct wormio_prepare_track *)addr;
- if (w->audio != 0 && w->audio != 1)
- error = EINVAL;
- else if (w->audio == 0 && w->preemp)
- error = EINVAL;
- else if ((worm->worm_flags & WORMFL_DISK_PREPED)==0) {
- error = EINVAL;
- worm->error = WORM_SEQUENCE_ERROR;
- } else {
- /*
- * This sets a flag only. Actual preparation of a
- * track will be deferred up to the first write.
- */
- worm->worm_flags |= WORMFL_TRACK_PREP;
- worm->preptrack = *w;
- if (worm->write_session) {
-#ifdef BOUNCE_BUFFERS
- vm_bounce_kva_alloc_free((vm_offset_t)worm->write_session,
- btoc(sizeof(struct wormio_write_session) +
- worm->write_session->length));
-#else
- free(worm->write_session, M_DEVBUF);
-#endif
- worm->write_session = 0;
- }
- }
- }
- break;
-
- case WORMIOCFINISHTRACK:
- if ((worm->worm_flags & WORMFL_TRACK_PREPED) != 0)
- error = (worm->quirks->finalize_track)(sc_link);
- worm->worm_flags &= ~(WORMFL_TRACK_PREPED | WORMFL_TRACK_PREP);
- break;
-
- case WORMIOCFIXATION:
- {
- struct wormio_fixation *w =
- (struct wormio_fixation *)addr;
-
- if ((worm->worm_flags & WORMFL_WRITTEN) == 0)
- error = EINVAL;
- else if (w->toc_type < WORM_TOC_TYPE_AUDIO ||
- w->toc_type > WORM_TOC_TYPE_CDI)
- error = EINVAL;
- else if (w->onp != 0 && w->onp != 1)
- error = EINVAL;
- else {
- worm->worm_flags = 0;
- /* no fixation needed if dummy write */
- if (worm->dummy == 0) {
- worm->error = 0;
- error = (worm->quirks->finalize_disk)
- (sc_link, w->toc_type, w->onp);
- }
- }
- }
- break;
-
- case WORMIOCREADSESSIONINFO:
- {
- struct wormio_session_info si;
- error = worm_read_session_info(sc_link, &si);
- if (error)
- break;
- NTOHS(si.lead_in);
- NTOHS(si.lead_out);
- bcopy(&si, addr, sizeof si);
- }
- break;
-
- case WORMIOCWRITESESSION:
- if (worm->quirks->write_session) {
- if ((worm->worm_flags & WORMFL_DISK_PREPED)==0) {
- error = EINVAL;
- worm->error = WORM_SEQUENCE_ERROR;
- } else {
-#ifdef BOUNCE_BUFFERS
- worm->write_session = (struct wormio_write_session *)
- vm_bounce_kva_alloc(
- btoc(sizeof(struct wormio_write_session) +
- ((struct wormio_write_session *) addr)->length));
- if (!worm->write_session) {
- error = ENOMEM;
- break;
- }
-#else
- worm->write_session = malloc(sizeof(struct wormio_write_session) +
- ((struct wormio_write_session *) addr)->length,
- M_DEVBUF, M_WAITOK);
-#endif
- bcopy(addr, worm->write_session, sizeof(struct wormio_write_session));
- worm->write_session->track_desc = sizeof(struct wormio_write_session) +
- (u_char *) worm->write_session;
- bcopy(((struct wormio_write_session *) addr)->track_desc,
- worm->write_session->track_desc, ((struct wormio_write_session *) addr)->length);
- }
- } else
- error = ENXIO;
- break;
-
- case WORMIOCFIRSTWRITABLEADDR:
- if (worm->quirks->read_first_writable_address) {
- int address;
- struct wormio_first_writable_addr *a =
- (struct wormio_first_writable_addr *) addr;
- if ((a->audio & ~1) || (a->raw & ~1) || (a->mode & ~3)
- || (a->track & ~0x7f)) {
- error = EINVAL;
- break;
- }
- error = worm->quirks->read_first_writable_address(sc_link, a->track,
- a->mode, a->raw,
- a->audio, &address);
- if (error)
- break;
- error = copyout(&address, a->addr, sizeof(int));
- } else
- error = ENXIO;
- break;
-
- case WORMIOERROR:
- bcopy(&(worm->error), addr, sizeof (int));
- break;
-
- case CDIOREADTOCHEADER:
- {
- struct ioc_toc_header th;
- error = worm_read_toc(sc_link, 0, 0,
- (struct cd_toc_entry *)&th,
- sizeof th);
- if (error)
- break;
- NTOHS(th.len);
- bcopy(&th, addr, sizeof th);
- }
- break;
-
- case CDIOREADTOCENTRYS:
- {
- struct {
- struct ioc_toc_header header;
- struct cd_toc_entry entries[100];
- } data;
- struct {
- struct ioc_toc_header header;
- struct cd_toc_entry entry;
- } lead;
- struct ioc_read_toc_entry *te =
- (struct ioc_read_toc_entry *) addr;
- struct ioc_toc_header *th;
- u_int32_t len, readlen, idx, num;
- u_int32_t starting_track = te->starting_track;
-
- if (te->data_len < sizeof(struct cd_toc_entry)
- || (te->data_len % sizeof(struct cd_toc_entry)) != 0
- || te->address_format != CD_MSF_FORMAT
- && te->address_format != CD_LBA_FORMAT) {
- error = EINVAL;
- break;
- }
-
- th = &data.header;
- error = worm_read_toc(sc_link, 0, 0,
- (struct cd_toc_entry *)th,
- sizeof (*th));
- if (error)
- break;
-
- if (starting_track == 0)
- starting_track = th->starting_track;
- else if (starting_track == 0xaa)
- starting_track = th->ending_track + 1;
- else if (starting_track < th->starting_track ||
- starting_track > th->ending_track + 1) {
- error = EINVAL;
- break;
- }
-
- /* calculate reading length without leadout entry */
- readlen = (th->ending_track - starting_track + 1) *
- sizeof(struct cd_toc_entry);
-
- /* and with leadout entry */
- len = readlen + sizeof(struct cd_toc_entry);
- if (te->data_len < len) {
- len = te->data_len;
- if (readlen > len)
- readlen = len;
- }
- if (len > sizeof(data.entries)) {
- error = EINVAL;
- break;
- }
- num = len / sizeof(struct cd_toc_entry);
-
- if (readlen > 0) {
- error = worm_read_toc(sc_link,
- te->address_format,
- starting_track,
- (struct cd_toc_entry *)&data,
- readlen + sizeof (*th));
- if (error)
- break;
- }
-
- /* make leadout entry if needed */
- idx = starting_track + num - 1;
- if (idx == th->ending_track + 1) {
- error = worm_read_toc(sc_link,
- te->address_format, 0xaa,
- (struct cd_toc_entry *)&lead,
- sizeof(lead));
- if (error)
- break;
- data.entries[idx - starting_track] = lead.entry;
- }
-
- error = copyout(data.entries, te->data, len);
- }
- break;
-
- case CDIOREADTOCENTRY:
- {
- struct {
- struct ioc_toc_header header;
- struct cd_toc_entry entry;
- } data;
- struct ioc_read_toc_single_entry *te =
- (struct ioc_read_toc_single_entry *) addr;
- struct ioc_toc_header *th;
- u_int32_t track;
-
- if (te->address_format != CD_MSF_FORMAT
- && te->address_format != CD_LBA_FORMAT) {
- error = EINVAL;
- break;
- }
-
- th = &data.header;
- error = worm_read_toc(sc_link, 0, 0,
- (struct cd_toc_entry *)th,
- sizeof (*th));
- if (error)
- break;
-
- track = te->track;
- if (track == 0)
- track = th->starting_track;
- else if (track == 0xaa)
- /* OK */;
- else if (track < th->starting_track ||
- track > th->ending_track + 1) {
- error = EINVAL;
- break;
- }
-
- error = worm_read_toc(sc_link, te->address_format,
- track,
- (struct cd_toc_entry *)&data,
- sizeof data);
- if (error)
- break;
-
- bcopy(&data.entry, &te->entry,
- sizeof(struct cd_toc_entry));
- }
- break;
-
- default:
- error = ENOTTY;
- break;
- }
- return (error);
-}
-
-
-static errval
-worm_rezero_unit(struct scsi_link *sc_link)
-{
- struct scsi_rezero_unit cmd;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("worm_rezero_unit"));
-
- /*
- * Re-initialize the unit, just to be sure.
- */
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = REZERO_UNIT;
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- 0, /* no data transfer */
- 0,
- /*WORMRETRY*/ 4,
- 5000,
- NULL,
- 0);
-}
-
-static errval
-worm_read_session_info(struct scsi_link *sc_link, struct wormio_session_info *data)
-{
- struct scsi_read_session_info cmd;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("worm_read_session_info"));
-
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = READ_SESSION_INFO;
- cmd.transfer_length = sizeof(struct wormio_session_info);
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- (u_char *) data,
- sizeof(struct wormio_session_info),
- /*WORMRETRY*/ 4,
- 5000,
- NULL,
- SCSI_DATA_IN);
-}
-
-/*
- * Read table of contents
- *
- * Stolen from cd.c
- */
-static errval
-worm_read_toc(struct scsi_link *sc_link, u_int32_t mode, u_int32_t start,
- struct cd_toc_entry *data, u_int32_t len)
-{
- struct scsi_read_toc scsi_cmd;
- u_int32_t ntoc;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- ntoc = len;
-
- scsi_cmd.op_code = READ_TOC;
- if (mode == CD_MSF_FORMAT)
- scsi_cmd.byte2 |= CD_MSF;
- scsi_cmd.from_track = start;
- scsi_cmd.data_len[0] = (ntoc) >> 8;
- scsi_cmd.data_len[1] = (ntoc) & 0xff;
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(struct scsi_read_toc),
- (u_char *) data,
- len,
- /*WORMRETRY*/ 4,
- 5000,
- NULL,
- SCSI_DATA_IN));
-}
-
-static int
-worm_sense_handler(struct scsi_xfer *xs)
-{
- struct scsi_data *worm;
- struct scsi_sense_data *sense;
- struct scsi_sense_extended *ext;
- int asc, devmode, i;
-
- worm = xs->sc_link->sd;
- sense = &(xs->sense);
- ext = (struct scsi_sense_extended *) &(sense->ext.extended);
- asc = ext->add_sense_code;
- devmode = *(int *) xs->sc_link->devmodes;
-
- for (i = 0; worm_error[i].asc; i++)
- if ((asc == worm_error[i].asc) && (devmode & worm_error[i].devmode)) {
- worm->error = worm_error[i].error;
- return worm_error[i].ret;
- }
- worm->error = -1;
- return SCSIRET_CONTINUE;
-}
-
-static errval
-worm_set_blksize(struct scsi_link *sc_link, int size)
-{
- struct scsi_mode_select scsi_cmd;
- struct {
- struct scsi_mode_header header;
- struct blk_desc desc;
- } dat;
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- bzero(&dat, sizeof(dat));
- scsi_cmd.op_code = MODE_SELECT;
- scsi_cmd.length = sizeof(dat);
- dat.header.blk_desc_len = sizeof(struct blk_desc);
- scsi_uto3b(size, dat.desc.blklen);
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) &dat,
- sizeof(dat),
- /*WORM_RETRIES*/ 4,
- 5000,
- NULL,
- SCSI_DATA_OUT);
-}
-
-static void
-worm_drvinit(void *unused)
-{
-
- if (!worm_devsw_installed) {
- cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &worm_cdevsw);
- worm_devsw_installed = 1;
- }
-}
-
-SYSINIT(wormdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,worm_drvinit,NULL)
-
-/*
- * Begin device-specific stuff. Subject to being moved out to LKMs.
- */
-
-static u_char
-ascii_to_6bit (char c)
-{
- if (c < '0' || c > 'Z' || (c > '9' && c < 'A'))
- return 0;
- if (c <= '9')
- return c - '0';
- else
- return c - 'A' + 11;
-}
-/*
- * PLASMON RF4100/4102
- * Perhaps other Plasmon's, too.
- *
- * NB: By now, you'll certainly have to compare the SCSI reference
- * manual in order to understand the following.
- */
-
-/* The following mode pages might apply to other drives as well. */
-
-struct plasmon_rf4100_pages
-{
- u_char page_code;
-#define RF4100_PAGE_CODE_20 0x20
-#define RF4100_PAGE_CODE_21 0x21
-#define RF4100_PAGE_CODE_22 0x22
-#define RF4100_PAGE_CODE_23 0x23
-#define RF4100_PAGE_CODE_24 0x24
-#define RF4100_PAGE_CODE_25 0x25
- u_char param_len;
- union
- {
- /* page 0x20 omitted by now */
- struct
- {
- u_char reserved1;
- u_char mode;
-#define RF4100_RAW_MODE 0x10 /* raw mode enabled */
-#define RF4100_MIXED_MODE 0x08 /* mixed mode data enabled */
-#define RF4100_AUDIO_MODE 0x04 /* audio mode data enabled */
-#define RF4100_MODE_1 0x01 /* mode 1 blocks are enabled */
-#define RF4100_MODE_2 0x02 /* mode 2 blocks are enabled */
- u_char track_number;
- u_char isrc_i1; /* country code, ASCII */
- u_char isrc_i2;
- u_char isrc_i3; /* owner code, ASCII */
- u_char isrc_i4;
- u_char isrc_i5;
- u_char isrc_i6_7; /* country code, BCD */
- u_char isrc_i8_9; /* serial number, BCD */
- u_char isrc_i10_11;
- u_char isrc_i12_0;
- u_char reserved2[2];
- }
- page_0x21;
- /* mode page 0x22 omitted by now */
- struct
- {
- u_char speed_select;
-#define RF4100_SPEED_AUDIO 0x01
-#define RF4100_SPEED_DOUBLE 0x02
- u_char dummy_write;
-#define RF4100_DUMMY_WRITE 0x01
- u_char reserved[4];
- }
- page_0x23;
- /* pages 0x24 and 0x25 omitted by now */
- }
- pages;
-};
-
-
-static errval
-rf4100_prepare_disk(struct scsi_link *sc_link, int dummy, int speed)
-{
- struct scsi_mode_select scsi_cmd;
- struct {
- struct scsi_mode_header header;
- struct plasmon_rf4100_pages page;
- } dat;
- u_int32_t pagelen, dat_len;
-
- pagelen = sizeof(dat.page.pages.page_0x23) + PAGE_HEADERLEN;
- dat_len = sizeof(struct scsi_mode_header) + pagelen;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("rf4100_prepare_disk"));
-
- if (speed != RF4100_SPEED_AUDIO && speed != RF4100_SPEED_DOUBLE)
- return EINVAL;
-
- /*
- * Set up a mode page 0x23
- */
- bzero(&dat, sizeof(dat));
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SELECT;
- scsi_cmd.length = dat_len;
- /* dat.header.dev_spec = host application code; (see spec) */
- dat.page.page_code = RF4100_PAGE_CODE_23;
- dat.page.param_len = sizeof(dat.page.pages.page_0x23);
- dat.page.pages.page_0x23.speed_select = speed;
- dat.page.pages.page_0x23.dummy_write = dummy? RF4100_DUMMY_WRITE: 0;
- /*
- * Fire it off.
- */
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) &dat,
- dat_len,
- /*WORM_RETRIES*/ 4,
- 5000,
- NULL,
- SCSI_DATA_OUT);
-}
-
-
-static errval
-rf4100_prepare_track(struct scsi_link *sc_link, struct wormio_prepare_track *t)
-{
- struct scsi_mode_select scsi_cmd;
- struct scsi_data *worm;
- struct {
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- struct plasmon_rf4100_pages page;
- } dat;
- u_int32_t pagelen, dat_len, blk_len;
- int year;
-
- worm = sc_link->sd;
-
- pagelen = sizeof(dat.page.pages.page_0x21) + PAGE_HEADERLEN;
- dat_len = sizeof(struct scsi_mode_header)
- + sizeof(struct blk_desc)
- + pagelen;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("rf4100_prepare_track"));
-
- /*
- * Set up a mode page 0x21. Note that the block descriptor is
- * mandatory in at least one of the MODE SELECT commands, in
- * order to select the block length in question. We do this
- * here, just prior to opening the write channel. (Spec:
- * ``All information for the write is included in the MODE
- * SELECT, MODE PAGE 21h, and the write channel can be
- * considered open on receipt of the first WRITE command.'' I
- * didn't have luck with an explicit WRITE TRACK command
- * anyway, this might be different for other CD-R drives. -
- * Jörg)
- */
- bzero(&dat, sizeof(dat));
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SELECT;
- scsi_cmd.length = dat_len;
- dat.header.blk_desc_len = sizeof(struct blk_desc);
- dat.page.page_code = RF4100_PAGE_CODE_21;
- dat.page.param_len = sizeof(dat.page.pages.page_0x21);
- /* dat.header.dev_spec = host application code; (see spec) */
- if (t->audio) {
- blk_len = 2352;
- dat.page.pages.page_0x21.mode = RF4100_AUDIO_MODE +
- (t->preemp? RF4100_MODE_1 : 0);
- } else
- switch (t->track_type) {
- case BLOCK_RAW:
- blk_len = 2352;
- dat.page.pages.page_0x21.mode = RF4100_RAW_MODE;
- break;
- case BLOCK_MODE_1:
- blk_len = 2048;
- dat.page.pages.page_0x21.mode = RF4100_MODE_1;
- break;
- case BLOCK_MODE_2:
- blk_len = 2336;
- dat.page.pages.page_0x21.mode = RF4100_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_1:
- blk_len = 2048;
- dat.page.pages.page_0x21.mode = RF4100_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_1b:
- blk_len = 2056;
- dat.page.pages.page_0x21.mode = RF4100_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_2:
- blk_len = 2324;
- dat.page.pages.page_0x21.mode = RF4100_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_2b:
- blk_len = 2332;
- dat.page.pages.page_0x21.mode = RF4100_MODE_2;
- break;
- default:
- return EINVAL;
- }
- dat.page.pages.page_0x21.mode |= t->copy_bits << 5;
-
- worm->blk_size = blk_len;
-
- dat.page.pages.page_0x21.track_number = t->track_number;
-
- dat.page.pages.page_0x21.isrc_i1 = ascii_to_6bit(t->ISRC_country[0]);
- dat.page.pages.page_0x21.isrc_i2 = ascii_to_6bit(t->ISRC_country[1]);
- dat.page.pages.page_0x21.isrc_i3 = ascii_to_6bit(t->ISRC_owner[0]);
- dat.page.pages.page_0x21.isrc_i4 = ascii_to_6bit(t->ISRC_owner[1]);
- dat.page.pages.page_0x21.isrc_i5 = ascii_to_6bit(t->ISRC_owner[2]);
- year = t->ISRC_year % 100;
- if (year < 0)
- return EINVAL;
- dat.page.pages.page_0x21.isrc_i6_7 = bin2bcd(year);
- if (t->ISRC_serial[0]) {
- dat.page.pages.page_0x21.isrc_i8_9 = ((t->ISRC_serial[0]-'0') << 4) |
- (t->ISRC_serial[1] - '0');
- dat.page.pages.page_0x21.isrc_i10_11 = ((t->ISRC_serial[2]-'0') << 4) |
- (t->ISRC_serial[3] - '0');
- dat.page.pages.page_0x21.isrc_i12_0 = (t->ISRC_serial[4] - '0' << 4);
- }
- scsi_uto3b(blk_len, dat.blk_desc.blklen);
-
- /*
- * Fire it off.
- */
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) &dat,
- dat_len,
- /*WORM_RETRIES*/ 4,
- 5000,
- NULL,
- SCSI_DATA_OUT);
-}
-
-
-static errval
-rf4100_finalize_track(struct scsi_link *sc_link)
-{
- struct scsi_synchronize_cache cmd;
- int error;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("rf4100_finalize_track"));
-
- /*
- * Only a "synchronize cache" is needed.
- */
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = SYNCHRONIZE_CACHE;
- error = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- 0, /* no data transfer */
- 0,
- 1,
- 60000, /* this may take a while */
- NULL,
- 0);
- if (!error)
- error = worm_set_blksize(sc_link, 2048);
-
- return error;
-}
-
-
-static errval
-rf4100_finalize_disk(struct scsi_link *sc_link, int toc_type, int onp)
-{
- struct scsi_fixation cmd;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("rf4100_finalize_disk"));
-
- if (toc_type < 0 || toc_type > WORM_TOC_TYPE_CDI)
- return EINVAL;
-
- /*
- * Fixate this session. Mark the next one as opened if onp
- * is true. Otherwise, the disk will be finalized once and
- * for all. ONP stands for "open next program area".
- */
-
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = FIXATION;
- cmd.action = (onp? WORM_FIXATION_ONP: 0) + toc_type;
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- 0, /* no data transfer */
- 0,
- 1,
- 20*60*1000, /* takes a huge amount of time */
- NULL,
- 0);
-}
-
-/*
- * End Plasmon RF4100/4102 section.
- */
-
-/*
- * HP C4324/C4325 (This is what the scsi spec. and firmware says)
- * Drive model 4020i
- * This is very similar to the Plasmon above.
- */
-
-/* The following mode pages might apply to other drives as well. */
-
-struct hp_4020i_pages
-{
- u_char page_code;
-#define HP4020I_PAGE_CODE_20 0x20
-#define HP4020I_PAGE_CODE_21 0x21
-#define HP4020I_PAGE_CODE_22 0x22
-#define HP4020I_PAGE_CODE_23 0x23
-#define HP4020I_PAGE_CODE_24 0x24
-#define HP4020I_PAGE_CODE_25 0x25
- u_char param_len;
- union
- {
- /* page 0x20 omitted by now */
- struct
- {
- u_char reserved1;
- u_char mode;
-#define HP4020I_RAW_MODE 0x10 /* raw mode enabled */
-#define HP4020I_MIXED_MODE 0x08 /* mixed mode data enabled */
-#define HP4020I_AUDIO_MODE 0x04 /* audio mode data enabled */
-#define HP4020I_MODE_1 0x01 /* mode 1 blocks are enabled */
-#define HP4020I_MODE_2 0x02 /* mode 2 blocks are enabled */
- u_char track_number;
- u_char isrc_i1; /* country code, ASCII */
- u_char isrc_i2;
- u_char isrc_i3; /* owner code, ASCII */
- u_char isrc_i4;
- u_char isrc_i5;
- u_char isrc_i6_7; /* year code, BCD */
- u_char isrc_i8_9; /* serial number, BCD */
- u_char isrc_i10_11;
- u_char isrc_i12_0;
- u_char reserved2[2];
- }
- page_0x21;
- struct
- {
- u_char catalog_valid;
- u_char catalog_c1_c2; /* catalog number, BCD */
- u_char catalog_c3_c4;
- u_char catalog_c5_c6;
- u_char catalog_c7_c8;
- u_char catalog_c9_c10;
- u_char catalog_c11_c12;
- u_char catalog_c13_0;
- } page_0x22;
- struct
- {
- u_char speed_select;
-#define HP4020I_SPEED_AUDIO 0x01
-#define HP4020I_SPEED_DOUBLE 0x02
- u_char dummy_write;
-#define HP4020I_DUMMY_WRITE 0x01
- u_char reserved[4];
- }
- page_0x23;
- /* pages 0x24 and 0x25 omitted by now */
- }
- pages;
-};
-
-static errval
-hp4020i_prepare_disk(struct scsi_link *sc_link, int dummy, int speed)
-{
- struct scsi_mode_select scsi_cmd;
- struct {
- struct scsi_mode_header header;
- struct hp_4020i_pages page;
- } dat;
- u_int32_t pagelen, dat_len;
-
- pagelen = sizeof(dat.page.pages.page_0x23) + PAGE_HEADERLEN;
- dat_len = sizeof(struct scsi_mode_header) + pagelen;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("hp4020i_prepare_disk"));
-
- if (speed != HP4020I_SPEED_AUDIO && speed != HP4020I_SPEED_DOUBLE)
- return EINVAL;
-
- /*
- * Set up a mode page 0x23
- */
- bzero(&dat, sizeof(dat));
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SELECT;
- scsi_cmd.byte2 |= SMS_PF;
- scsi_cmd.length = dat_len;
- /* dat.header.dev_spec = host application code; (see spec) */
- dat.page.page_code = HP4020I_PAGE_CODE_23;
- dat.page.param_len = sizeof(dat.page.pages.page_0x23);
- dat.page.pages.page_0x23.speed_select = speed;
- dat.page.pages.page_0x23.dummy_write = dummy? HP4020I_DUMMY_WRITE: 0;
- /*
- * Fire it off.
- */
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) &dat,
- dat_len,
- /*WORM_RETRIES*/ 4,
- 5000,
- NULL,
- SCSI_DATA_OUT);
-}
-
-
-static errval
-hp4020i_prepare_track(struct scsi_link *sc_link, struct wormio_prepare_track *t)
-{
- struct scsi_mode_select scsi_cmd;
- struct scsi_data *worm;
- struct {
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- struct hp_4020i_pages page;
- } dat;
- u_int32_t pagelen, dat_len, blk_len;
- int year;
-
- worm = sc_link->sd;
-
- pagelen = sizeof(dat.page.pages.page_0x21) + PAGE_HEADERLEN;
- dat_len = sizeof(struct scsi_mode_header)
- + sizeof(struct blk_desc)
- + pagelen;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("hp4020i_prepare_track"));
-
-
- /*
- * Set up a mode page 0x21. Note that the block descriptor is
- * mandatory in at least one of the MODE SELECT commands, in
- * order to select the block length in question. We do this
- * here, just prior to opening the write channel. (Spec:
- * ``All information for the write is included in the MODE
- * SELECT, MODE PAGE 21h, and the write channel can be
- * considered open on receipt of the first WRITE command.'' I
- * didn't have luck with an explicit WRITE TRACK command
- * anyway, this might be different for other CD-R drives. -
- * Jörg)
- */
- bzero(&dat, sizeof(dat));
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SELECT;
- scsi_cmd.byte2 |= SMS_PF;
- scsi_cmd.length = dat_len;
- dat.header.blk_desc_len = sizeof(struct blk_desc);
- dat.page.page_code = HP4020I_PAGE_CODE_21;
- dat.page.param_len = sizeof(dat.page.pages.page_0x21);
- /* dat.header.dev_spec = host application code; (see spec) */
- if (t->audio) {
- blk_len = 2352;
- dat.page.pages.page_0x21.mode = HP4020I_AUDIO_MODE +
- (t->preemp? HP4020I_MODE_1 : 0);
- } else
- switch (t->track_type) {
- case BLOCK_RAW:
- blk_len = 2352;
- dat.page.pages.page_0x21.mode = HP4020I_RAW_MODE;
- break;
- case BLOCK_MODE_1:
- blk_len = 2048;
- dat.page.pages.page_0x21.mode = HP4020I_MODE_1;
- break;
- case BLOCK_MODE_2:
- blk_len = 2336;
- dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_1:
- blk_len = 2048;
- dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_1b:
- blk_len = 2056;
- dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_2:
- blk_len = 2324;
- dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_2b:
- blk_len = 2332;
- dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
- break;
- default:
- return EINVAL;
- }
- dat.page.pages.page_0x21.mode |= t->copy_bits << 5;
-
- worm->blk_size = blk_len;
-
- dat.page.pages.page_0x21.track_number = t->track_number;
-
- dat.page.pages.page_0x21.isrc_i1 = ascii_to_6bit(t->ISRC_country[0]);
- dat.page.pages.page_0x21.isrc_i2 = ascii_to_6bit(t->ISRC_country[1]);
- dat.page.pages.page_0x21.isrc_i3 = ascii_to_6bit(t->ISRC_owner[0]);
- dat.page.pages.page_0x21.isrc_i4 = ascii_to_6bit(t->ISRC_owner[1]);
- dat.page.pages.page_0x21.isrc_i5 = ascii_to_6bit(t->ISRC_owner[2]);
- year = t->ISRC_year % 100;
- if (year < 0)
- return EINVAL;
- dat.page.pages.page_0x21.isrc_i6_7 = bin2bcd(year);
- if (t->ISRC_serial[0]) {
- dat.page.pages.page_0x21.isrc_i8_9 = ((t->ISRC_serial[0]-'0') << 4) |
- (t->ISRC_serial[1] - '0');
- dat.page.pages.page_0x21.isrc_i10_11 = ((t->ISRC_serial[2]-'0') << 4) |
- (t->ISRC_serial[3] - '0');
- dat.page.pages.page_0x21.isrc_i12_0 = (t->ISRC_serial[4] - '0' << 4);
- }
-
- scsi_uto3b(blk_len, dat.blk_desc.blklen);
-
- /*
- * Fire it off.
- */
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) &dat,
- dat_len,
- /*WORM_RETRIES*/ 4,
- 5000,
- NULL,
- SCSI_DATA_OUT);
-}
-
-
-static errval
-hp4020i_finalize_track(struct scsi_link *sc_link)
-{
- struct scsi_synchronize_cache cmd;
- int error;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("hp4020i_finalize_track"));
-
- /*
- * Only a "synchronize cache" is needed.
- */
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = SYNCHRONIZE_CACHE;
- error = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- 0, /* no data transfer */
- 0,
- 1,
- 60000, /* this may take a while */
- NULL,
- 0);
- if (!error)
- error = worm_set_blksize(sc_link, 2048);
-
- return error;
-}
-
-
-static errval
-hp4020i_finalize_disk(struct scsi_link *sc_link, int toc_type, int onp)
-{
- struct scsi_fixation cmd;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("hp4020i_finalize_disk"));
-
- if (toc_type < 0 || toc_type > WORM_TOC_TYPE_CDI)
- return EINVAL;
-
- /*
- * Fixate this session. Mark the next one as opened if onp
- * is true. Otherwise, the disk will be finalized once and
- * for all. ONP stands for "open next program area".
- */
-
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = FIXATION;
- cmd.action = (onp? WORM_FIXATION_ONP: 0) + toc_type;
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- 0, /* no data transfer */
- 0,
- 1,
- 20*60*1000, /* takes a huge amount of time */
- NULL,
- 0);
-}
-static errval
-hp4020i_write_session(struct scsi_link *sc_link, struct wormio_write_session *ws)
-{
- struct {
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- struct hp_4020i_pages page;
- } dat;
- struct scsi_mode_select cmd1;
- struct scsi_write_session cmd2;
- struct scsi_data *worm;
- u_int32_t pagelen, dat_len, blk_len;
- errval error;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("hp4020i_write_session"));
-
- if (ws->toc_type < 0 || ws->toc_type > WORM_TOC_TYPE_CDI || ws->lofp & ~3)
- return EINVAL;
-
- pagelen = sizeof(dat.page.pages.page_0x22) + PAGE_HEADERLEN;
- dat_len = sizeof(struct scsi_mode_header)
- + sizeof(struct blk_desc)
- + pagelen;
-
- worm = sc_link->sd;
-
- /* set the block size to 2352 and the catalog */
- bzero(&dat, sizeof(dat));
- bzero(&cmd1, sizeof(cmd1));
- cmd1.op_code = MODE_SELECT;
- cmd1.byte2 |= SMS_PF;
- cmd1.length = dat_len;
- dat.header.blk_desc_len = sizeof(struct blk_desc);
- dat.page.page_code = HP4020I_PAGE_CODE_22;
- dat.page.param_len = sizeof(dat.page.pages.page_0x22);
- blk_len = 2352;
- if (ws->catalog[0] >= '0' && ws->catalog[0] <= '9') {
- dat.page.pages.page_0x22.catalog_valid = 1;
- dat.page.pages.page_0x22.catalog_c1_c2 = ((ws->catalog[0]-'0') << 4)
- | ((ws->catalog[1]-'0') << 4);
- dat.page.pages.page_0x22.catalog_c3_c4 = ((ws->catalog[2]-'0') << 4)
- | ((ws->catalog[3]-'0') << 4);
- dat.page.pages.page_0x22.catalog_c5_c6 = ((ws->catalog[4]-'0') << 4)
- | ((ws->catalog[5]-'0') << 4);
- dat.page.pages.page_0x22.catalog_c7_c8 = ((ws->catalog[6]-'0') << 4)
- | ((ws->catalog[7]-'0') << 4);
- dat.page.pages.page_0x22.catalog_c9_c10 = ((ws->catalog[8]-'0') << 4)
- | ((ws->catalog[9]-'0') << 4);
- dat.page.pages.page_0x22.catalog_c11_c12 = ((ws->catalog[10]-'0') << 4)
- | ((ws->catalog[11]-'0') << 4);
- dat.page.pages.page_0x22.catalog_c13_0 = ((ws->catalog[12]-'0') << 4);
- }
- scsi_uto3b(blk_len, dat.blk_desc.blklen);
-
- error = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd1,
- sizeof(cmd1),
- (u_char *) &dat,
- dat_len,
- /*WORM_RETRIES*/ 4,
- 5000,
- NULL,
- SCSI_DATA_OUT);
-
- if (!error) {
- worm->blk_size = blk_len;
- bzero(&cmd2, sizeof(cmd2));
- cmd2.op_code = WRITE_SESSION;
- cmd2.action = (ws->lofp << 4) | (ws->onp? WORM_FIXATION_ONP: 0) + ws->toc_type;
- scsi_uto2b(ws->length, &cmd2.transfer_length_2);
-
- error = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd2,
- sizeof(cmd2),
- ws->track_desc,
- ws->length,
- 1,
- 5000,
- NULL,
- SCSI_DATA_OUT);
- }
- return error;
-}
-
-static errval
-hp4020i_read_first_writable_address (struct scsi_link *sc_link,
- int track, int mode, int raw, int audio, int *addr)
-{
- struct scsi_first_writable_address cmd;
- char data[6];
- errval error;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("worm_read_first_writable_address"));
-
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = FIRST_WRITEABLE_ADDR;
- cmd.track_number = track;
- cmd.mode = (raw << 3) | (audio << 2) | mode;
- cmd.transfer_length = sizeof(data);
- error = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- (u_char *) data,
- sizeof(data),
- /*WORMRETRY*/ 4,
- 5000,
- NULL,
- SCSI_DATA_IN);
- *addr = scsi_4btou (data+1);
- return error;
-}
-
-/*
- * End HP C4324/C4325 (4020i) section.
- */
OpenPOWER on IntegriCloud