diff options
author | gibbs <gibbs@FreeBSD.org> | 1998-09-15 10:40:55 +0000 |
---|---|---|
committer | gibbs <gibbs@FreeBSD.org> | 1998-09-15 10:40:55 +0000 |
commit | 79200df6729d1afbc24596e05c0bee54a2544616 (patch) | |
tree | 454f8a346e1e8ffbde91ed6c5a172835b1d7d78c /sys/scsi | |
parent | 4035fc4bcc3a3a3a921bfaa090dd3f7f02b9737a (diff) | |
download | FreeBSD-src-79200df6729d1afbc24596e05c0bee54a2544616.zip FreeBSD-src-79200df6729d1afbc24596e05c0bee54a2544616.tar.gz |
Obsoleted by CAM.
Diffstat (limited to 'sys/scsi')
-rw-r--r-- | sys/scsi/README | 203 | ||||
-rw-r--r-- | sys/scsi/cd.c | 1419 | ||||
-rw-r--r-- | sys/scsi/ch.c | 750 | ||||
-rw-r--r-- | sys/scsi/od.c | 966 | ||||
-rw-r--r-- | sys/scsi/pt.c | 326 | ||||
-rw-r--r-- | sys/scsi/scsi_all.h | 351 | ||||
-rw-r--r-- | sys/scsi/scsi_base.c | 1370 | ||||
-rw-r--r-- | sys/scsi/scsi_cd.h | 216 | ||||
-rw-r--r-- | sys/scsi/scsi_changer.h | 400 | ||||
-rw-r--r-- | sys/scsi/scsi_debug.h | 59 | ||||
-rw-r--r-- | sys/scsi/scsi_disk.h | 221 | ||||
-rw-r--r-- | sys/scsi/scsi_driver.c | 245 | ||||
-rw-r--r-- | sys/scsi/scsi_driver.h | 64 | ||||
-rw-r--r-- | sys/scsi/scsi_generic.h | 63 | ||||
-rw-r--r-- | sys/scsi/scsi_ioctl.c | 406 | ||||
-rw-r--r-- | sys/scsi/scsi_message.h | 37 | ||||
-rw-r--r-- | sys/scsi/scsi_sense.c | 309 | ||||
-rw-r--r-- | sys/scsi/scsi_tape.h | 247 | ||||
-rw-r--r-- | sys/scsi/scsi_worm.h | 128 | ||||
-rw-r--r-- | sys/scsi/scsiconf.c | 1573 | ||||
-rw-r--r-- | sys/scsi/scsiconf.h | 618 | ||||
-rw-r--r-- | sys/scsi/sctarg.c | 319 | ||||
-rw-r--r-- | sys/scsi/sd.c | 1065 | ||||
-rw-r--r-- | sys/scsi/ssc.c | 162 | ||||
-rw-r--r-- | sys/scsi/st.c | 2005 | ||||
-rw-r--r-- | sys/scsi/su.c | 361 | ||||
-rw-r--r-- | sys/scsi/uk.c | 96 | ||||
-rw-r--r-- | sys/scsi/worm.c | 1811 |
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, §ors, &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, §ors, - &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. - */ |