summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/i386/isa/aha1542.c1851
-rw-r--r--sys/i386/scsi/93cx6.c181
-rw-r--r--sys/i386/scsi/93cx6.h93
-rw-r--r--sys/i386/scsi/advansys.c783
-rw-r--r--sys/i386/scsi/advansys.h50
-rw-r--r--sys/i386/scsi/aic7xxx.c3867
-rw-r--r--sys/i386/scsi/aic7xxx.h403
-rw-r--r--sys/i386/scsi/bt.c1583
-rw-r--r--sys/i386/scsi/btreg.h149
-rw-r--r--sys/pci/aic7870.c997
-rw-r--r--sys/pci/bt9xx.c117
-rw-r--r--sys/scsi/README203
-rw-r--r--sys/scsi/cd.c1419
-rw-r--r--sys/scsi/ch.c750
-rw-r--r--sys/scsi/od.c966
-rw-r--r--sys/scsi/pt.c326
-rw-r--r--sys/scsi/scsi_all.h351
-rw-r--r--sys/scsi/scsi_base.c1370
-rw-r--r--sys/scsi/scsi_cd.h216
-rw-r--r--sys/scsi/scsi_changer.h400
-rw-r--r--sys/scsi/scsi_debug.h59
-rw-r--r--sys/scsi/scsi_disk.h221
-rw-r--r--sys/scsi/scsi_driver.c245
-rw-r--r--sys/scsi/scsi_driver.h64
-rw-r--r--sys/scsi/scsi_generic.h63
-rw-r--r--sys/scsi/scsi_ioctl.c406
-rw-r--r--sys/scsi/scsi_message.h37
-rw-r--r--sys/scsi/scsi_sense.c309
-rw-r--r--sys/scsi/scsi_tape.h247
-rw-r--r--sys/scsi/scsi_worm.h128
-rw-r--r--sys/scsi/scsiconf.c1573
-rw-r--r--sys/scsi/scsiconf.h618
-rw-r--r--sys/scsi/sctarg.c319
-rw-r--r--sys/scsi/sd.c1065
-rw-r--r--sys/scsi/ssc.c162
-rw-r--r--sys/scsi/st.c2005
-rw-r--r--sys/scsi/su.c361
-rw-r--r--sys/scsi/uk.c96
-rw-r--r--sys/scsi/worm.c1811
39 files changed, 0 insertions, 25864 deletions
diff --git a/sys/i386/isa/aha1542.c b/sys/i386/isa/aha1542.c
deleted file mode 100644
index b5f17a6..0000000
--- a/sys/i386/isa/aha1542.c
+++ /dev/null
@@ -1,1851 +0,0 @@
-/*
- * (Mostly) 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.
- *
- * $Id: aha1542.c,v 1.78 1998/06/21 14:53:07 bde Exp $
- */
-
-/*
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- */
-
-#include "aha.h"
-#include "opt_tune_1542.h"
-
-#include <sys/param.h>
-#include <sys/buf.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/systm.h>
-
-#include <machine/clock.h>
-#include <machine/stdarg.h>
-
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
-#include <i386/isa/isa_device.h>
-
-/************************** board definitions *******************************/
-
-/*
- * I/O Port Interface
- */
-
-#define AHA_BASE aha->aha_base
-#define AHA_CTRL_STAT_PORT (AHA_BASE + 0x0) /* control & status */
-#define AHA_CMD_DATA_PORT (AHA_BASE + 0x1) /* cmds and datas */
-#define AHA_INTR_PORT (AHA_BASE + 0x2) /* Intr. stat */
-
-/*
- * AHA_CTRL_STAT bits (write)
- */
-
-#define AHA_HRST 0x80 /* Hardware reset */
-#define AHA_SRST 0x40 /* Software reset */
-#define AHA_IRST 0x20 /* Interrupt reset */
-#define AHA_SCRST 0x10 /* SCSI bus reset */
-
-/*
- * AHA_CTRL_STAT bits (read)
- */
-
-#define AHA_STST 0x80 /* Self test in Progress */
-#define AHA_DIAGF 0x40 /* Diagnostic Failure */
-#define AHA_INIT 0x20 /* Mbx Init required */
-#define AHA_IDLE 0x10 /* Host Adapter Idle */
-#define AHA_CDF 0x08 /* cmd/data out port full */
-#define AHA_DF 0x04 /* Data in port full */
-#define AHA_INVDCMD 0x01 /* Invalid command */
-
-/*
- * AHA_CMD_DATA bits (write)
- */
-
-#define AHA_NOP 0x00 /* No operation */
-#define AHA_MBX_INIT 0x01 /* Mbx initialization */
-#define AHA_START_SCSI 0x02 /* start scsi command */
-#define AHA_START_BIOS 0x03 /* start bios command */
-#define AHA_INQUIRE 0x04 /* Adapter Inquiry */
-#define AHA_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
-#define AHA_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
-#define AHA_BUS_ON_TIME_SET 0x07 /* set bus-on time */
-#define AHA_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
-#define AHA_SPEED_SET 0x09 /* set transfer speed */
-#define AHA_DEV_GET 0x0a /* return installed devices */
-#define AHA_CONF_GET 0x0b /* return configuration data */
-#define AHA_TARGET_EN 0x0c /* enable target mode */
-#define AHA_SETUP_GET 0x0d /* return setup data */
-#define AHA_WRITE_CH2 0x1a /* write channel 2 buffer */
-#define AHA_READ_CH2 0x1b /* read channel 2 buffer */
-#define AHA_WRITE_FIFO 0x1c /* write fifo buffer */
-#define AHA_READ_FIFO 0x1d /* read fifo buffer */
-#define AHA_ECHO 0x1e /* Echo command data */
-#define AHA_EXT_BIOS 0x28 /* return extended bios info */
-#define AHA_MBX_ENABLE 0x29 /* enable mail box interface */
-
-struct aha_cmd_buf {
- u_char byte[16];
-};
-
-/*
- * AHA_INTR_PORT bits (read)
- */
-
-#define AHA_ANY_INTR 0x80 /* Any interrupt */
-#define AHA_SCRD 0x08 /* SCSI reset detected */
-#define AHA_HACC 0x04 /* Command complete */
-#define AHA_MBOA 0x02 /* MBX out empty */
-#define AHA_MBIF 0x01 /* MBX in full */
-
-/*
- * Mail box defs
- */
-
-#define AHA_MBX_SIZE 16 /* mail box size */
-
-struct aha_mbx {
- struct aha_mbx_out {
- unsigned char cmd;
- unsigned char ccb_addr[3];
- } mbo[AHA_MBX_SIZE];
- struct aha_mbx_in {
- unsigned char stat;
- unsigned char ccb_addr[3];
- } mbi[AHA_MBX_SIZE];
-};
-
-/*
- * mbo.cmd values
- */
-
-#define AHA_MBO_FREE 0x0 /* MBO entry is free */
-#define AHA_MBO_START 0x1 /* MBO activate entry */
-#define AHA_MBO_ABORT 0x2 /* MBO abort entry */
-
-/*
- * mbi.stat values
- */
-
-#define AHA_MBI_FREE 0x0 /* MBI entry is free */
-#define AHA_MBI_OK 0x1 /* completed without error */
-#define AHA_MBI_ABORT 0x2 /* aborted ccb */
-#define AHA_MBI_UNKNOWN 0x3 /* Tried to abort invalid CCB */
-#define AHA_MBI_ERROR 0x4 /* Completed with error */
-
-#define AHA_MBI_TGT_NO_CCB 0x10 /* Target received, no CCB ready */
-
-/* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */
-#define AHA_NSEG 17 /* Number of scatter gather segments <= 16 */
- /* allow 64 K i/o (min) */
-
-struct aha_ccb {
- unsigned char opcode;
- unsigned char lun:3;
- unsigned char data_in:1; /* must be 0 */
- unsigned char data_out:1; /* must be 0 */
- unsigned char target:3;
- unsigned char scsi_cmd_length;
- unsigned char req_sense_length;
- unsigned char data_length[3];
- unsigned char data_addr[3];
- unsigned char link_addr[3];
- unsigned char link_id;
- unsigned char host_stat;
- unsigned char target_stat;
- unsigned char reserved[2];
- struct scsi_generic scsi_cmd;
- struct scsi_sense_data scsi_sense;
- struct aha_scat_gath {
- unsigned char seg_len[3];
- unsigned char seg_addr[3];
- } scat_gath[AHA_NSEG];
- struct aha_ccb *next;
- struct scsi_xfer *xfer; /* the scsi_xfer for this cmd */
- struct aha_mbx_out *mbx; /* pointer to mail box */
- int flags;
-#define CCB_FREE 0
-#define CCB_ACTIVE 1
-#define CCB_ABORTED 2
-};
-
-/*
- * opcode fields
- */
-
-#define AHA_INITIATOR_CCB 0x00 /* SCSI Initiator CCB */
-#define AHA_TARGET_CCB 0x01 /* SCSI Target CCB */
-#define AHA_INIT_SCAT_GATH_CCB 0x02 /* SCSI Initiator with scatter gather */
-#define AHA_RESET_CCB 0x81 /* SCSI Bus reset */
-
-#define AHA_INIT_RESID_CCB 0x03 /* SCSI Initiator CCB */
-#define AHA_INIT_SG_RESID_CCB 0x04 /* SCSI initiator with scatter gather */
-
-/*
- * aha_ccb.host_stat values
- */
-
-#define AHA_OK 0x00 /* cmd ok */
-#define AHA_LINK_OK 0x0a /* Link cmd ok */
-#define AHA_LINK_IT 0x0b /* Link cmd ok + int */
-#define AHA_SEL_TIMEOUT 0x11 /* Selection time out */
-#define AHA_OVER_UNDER 0x12 /* Data over/under run */
-#define AHA_BUS_FREE 0x13 /* Bus dropped at unexpected time */
-#define AHA_INV_BUS 0x14 /* Invalid bus phase/sequence */
-#define AHA_BAD_MBO 0x15 /* Incorrect MBO cmd */
-#define AHA_BAD_CCB 0x16 /* Incorrect ccb opcode */
-#define AHA_BAD_LINK 0x17 /* Not same values of LUN for links */
-#define AHA_INV_TARGET 0x18 /* Invalid target direction */
-#define AHA_CCB_DUP 0x19 /* Duplicate CCB received */
-#define AHA_INV_CCB 0x1a /* Invalid CCB or segment list */
-#define AHA_ABORTED 42
-
-struct aha_setup {
- u_char sync_neg:1;
- u_char parity:1;
- u_char:6;
- u_char speed;
- u_char bus_on;
- u_char bus_off;
- u_char num_mbx;
- u_char mbx[3];
- struct {
- u_char offset:4;
- u_char period:3;
- u_char valid:1;
- } sync[8];
- u_char disc_sts;
-};
-
-struct aha_config {
- u_char chan;
- u_char intr;
- u_char scsi_dev:3;
- u_char:5;
-};
-
-struct aha_inquire
-{
- u_char boardid; /* type of board */
- /* 0x20 (' ') = BusLogic 545, but it gets
- the command wrong, only returns
- one byte */
- /* 0x31 ('1') = AHA-1540 */
- /* 0x41 ('A') = AHA-1540A/1542A/1542B */
- /* 0x42 ('B') = AHA-1640 */
- /* 0x43 ('C') = AHA-1542C */
- /* 0x44 ('D') = AHA-1542CF */
- /* 0x45 ('E') = AHA-1542CF, BIOS v2.01 */
- /* 0x46 ('F') = AHA-1542CP, "Plug'nPlay" */
- u_char spec_opts; /* special options ID */
- /* 0x41 = Board is standard model */
- u_char revision_1; /* firmware revision [0-9A-Z] */
- u_char revision_2; /* firmware revision [0-9A-Z] */
-};
-
-struct aha_extbios
-{
- u_char flags; /* Bit 3 == 1 extended bios enabled */
- u_char mailboxlock; /* mail box lock code to unlock it */
-};
-
-#define INT9 0x01
-#define INT10 0x02
-#define INT11 0x04
-#define INT12 0x08
-#define INT14 0x20
-#define INT15 0x40
-
-#define CHAN0 0x01
-#define CHAN5 0x20
-#define CHAN6 0x40
-#define CHAN7 0x80
-
-/*********************************** end of board definitions***************/
-
-#define PHYSTOKV(x) ((intptr_t)(((long int)(x)) ^ aha->kv_phys_xor))
-#define KVTOPHYS(x) vtophys(x)
-#define AHA_DMA_PAGES AHA_NSEG
-
-#define PAGESIZ 4096
-
-#ifdef AHADEBUG
-int aha_debug = 1;
-#endif /*AHADEBUG */
-
-static struct aha_data {
- int aha_base; /* base port for each board */
- /*
- * xor this with a physaddr to get a kv addr and visa versa
- * for items in THIS STRUCT only.
- * Used to get the CCD's physical and kv addresses from each
- * other.
- */
- long int kv_phys_xor;
- struct aha_mbx aha_mbx; /* all the mailboxes */
- struct aha_ccb *aha_ccb_free; /* the next free ccb */
- struct aha_ccb aha_ccb[AHA_MBX_SIZE]; /* all the CCBs */
- int unit; /* unit number */
- int aha_int; /* irq level */
- int aha_dma; /* DMA req channel */
- int aha_scsi_dev; /* scsi bus address */
- int flags;
-
- /* We use different op codes for different revs of the board
- * if we think residual codes will work.
- */
- short init_opcode; /* Command to use for initiator */
- short sg_opcode; /* Command to use for scatter/gather */
- struct scsi_link sc_link; /* prototype for subdevs */
-} *ahadata[NAHA];
-
-static u_int32_t aha_adapter_info __P((int unit));
-static int ahaattach __P((struct isa_device *dev));
-#ifdef TUNE_1542
-static int aha_bus_speed_check __P((struct aha_data *aha, int speed));
-static int aha_set_bus_speed __P((struct aha_data *aha));
-#endif
-static int aha_cmd __P((struct aha_data *aha, int icnt, int ocnt, int wait,
- u_char *retval, u_char opcode, ...));
-static void aha_done __P((struct aha_data *aha, struct aha_ccb *ccb));
-static int aha_escape __P((struct scsi_xfer *xs, struct aha_ccb *ccb));
-static void aha_free_ccb __P((struct aha_data *aha, struct aha_ccb *ccb,
- int flags));
-static struct aha_ccb *
- aha_get_ccb __P((struct aha_data *aha, int flags));
-static int aha_init __P((struct aha_data *aha));
-static void ahaminphys __P((struct buf *bp));
-static int aha_poll __P((struct aha_data *aha, struct scsi_xfer *xs,
- struct aha_ccb *ccb));
-static int ahaprobe __P((struct isa_device *dev));
-static int32_t aha_scsi_cmd __P((struct scsi_xfer *xs));
-static timeout_t
- aha_timeout;
-static char *board_rev __P((struct aha_data *aha, int type));
-static int physcontig __P((int kv, int len));
-static void put_host_stat __P((int host_stat));
-
-static struct scsi_adapter aha_switch =
-{
- aha_scsi_cmd,
- ahaminphys,
- 0,
- 0,
- aha_adapter_info,
- "aha",
- { 0, 0 }
-};
-
-/* the below structure is so we have a default dev struct for out link struct */
-static struct scsi_device aha_dev =
-{
- NULL, /* Use default error handler */
- NULL, /* have a queue, served by this */
- NULL, /* have no async handler */
- NULL, /* Use default 'done' routine */
- "aha",
- 0,
- { 0, 0 }
-};
-
-struct isa_driver ahadriver =
-{
- ahaprobe,
- ahaattach,
- "aha"
-};
-
-static int ahaunit = 0;
-
-#define aha_abortmbx(mbx) \
- (mbx)->cmd = AHA_MBO_ABORT; \
- outb(AHA_CMD_DATA_PORT, AHA_START_SCSI);
-#define aha_startmbx(mbx) \
- (mbx)->cmd = AHA_MBO_START; \
- outb(AHA_CMD_DATA_PORT, AHA_START_SCSI);
-
-#define AHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */
-
-/*
- * aha_cmd(struct aha_data *aha,icnt, ocnt,wait, retval, opcode, ...)
- * Activate Adapter command
- * icnt: number of args (outbound bytes written after opcode)
- * ocnt: number of expected returned bytes
- * wait: number of seconds to wait for response
- * retval: buffer where to place returned bytes
- * opcode: opcode AHA_NOP, AHA_MBX_INIT, AHA_START_SCSI, etc
- * ... : parameters to the command specified by opcode
- *
- * Performs an adapter command through the ports. Not to be confused
- * with a scsi command, which is read in via the dma. One of the adapter
- * commands tells it to read in a scsi command but that one is done
- * separately. This is only called during set-up.
- *
- */
-static int
-#ifdef __STDC__
-aha_cmd(struct aha_data *aha, int icnt, int ocnt, int wait, u_char *retval,
- u_char opcode, ... )
-#else
-aha_cmd(aha, icnt, ocnt, wait, retval, opcode, va_alist)
- struct aha_data *aha,
- int icnt,
- int ocnt,
- int wait,
- u_char *retval,
- u_char opcode,
- va_dcl
-#endif
-{
- va_list ap;
- u_char oc;
- u_char data;
- register int i;
- int sts;
-
- /*
- * multiply the wait argument by a big constant
- * zero defaults to 1 sec..
- * all wait loops are in 50uSec cycles
- */
- if (wait)
- wait *= 20000;
- else
- wait = 20000;
- /*
- * Wait for the adapter to go idle, unless it's one of
- * the commands which don't need this
- */
- if (opcode != AHA_MBX_INIT && opcode != AHA_START_SCSI) {
- i = 20000; /*do this for upto about a second */
- while (--i) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts & AHA_IDLE) {
- break;
- }
- DELAY(50);
- }
- if (!i) {
- printf("aha%d: aha_cmd, host not idle(0x%x)\n",
- aha->unit, sts);
- return (ENXIO);
- }
- }
- /*
- * Now that it is idle, if we expect output, preflush the
- * queue feeding to us.
- */
- if (ocnt) {
- while ((inb(AHA_CTRL_STAT_PORT)) & AHA_DF)
- inb(AHA_CMD_DATA_PORT);
- }
- /*
- * Output the command and the number of arguments given
- * for each byte, first check the port is empty.
- */
- va_start(ap, opcode);
- for(data = opcode; icnt >=0; icnt--, data = (u_char)va_arg(ap, int)) {
- sts = inb(AHA_CTRL_STAT_PORT);
- for (i = wait; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (!(sts & AHA_CDF))
- break;
- DELAY(50);
- }
- if (i == 0) {
- printf("aha%d: aha_cmd, cmd/data port full\n",
- aha->unit);
- outb(AHA_CTRL_STAT_PORT, AHA_SRST);
- return (ENXIO);
- }
- outb(AHA_CMD_DATA_PORT, data);
- }
- /*
- * If we expect input, loop that many times, each time,
- * looking for the data register to have valid data
- */
- while (ocnt--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- for (i = wait; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts & AHA_DF)
- break;
- DELAY(50);
- }
- if (i == 0) {
- printf("aha%d: aha_cmd, cmd/data port empty %d\n",
- aha->unit, ocnt);
- return (ENXIO);
- }
- oc = inb(AHA_CMD_DATA_PORT);
- if (retval)
- *retval++ = oc;
- }
- /*
- * Wait for the board to report a finised instruction
- */
- i = 20000;
- while (--i) {
- sts = inb(AHA_INTR_PORT);
- if (sts & AHA_HACC) {
- break;
- }
- DELAY(50);
- }
- if (i == 0) {
- printf("aha%d: aha_cmd, host not finished(0x%x)\n",
- aha->unit, sts);
- return (ENXIO);
- }
- outb(AHA_CTRL_STAT_PORT, AHA_IRST);
- return 0;
-}
-
-/*
- * Check if the device can be found at the port given
- * and if so, set it up ready for further work
- * as an argument, takes the isa_device structure from
- * autoconf.c
- */
-static int
-ahaprobe(dev)
- struct isa_device *dev;
-{
- int unit = ahaunit;
- struct aha_data *aha;
-
- /*
- * find unit and check we have that many defined
- */
- if (unit >= NAHA) {
- printf("aha%d: unit number too high\n", unit);
- return 0;
- }
- dev->id_unit = unit;
-
- /*
- * a quick safety check so we can be sleazy later
- */
- if (sizeof(struct aha_data) > PAGESIZ) {
- printf("aha struct > pagesize\n");
- return 0;
- }
- /*
- * Allocate a storage area for us
- */
- if (ahadata[unit]) {
- printf("aha%d: memory already allocated\n", unit);
- return 0;
- }
- aha = malloc(sizeof(struct aha_data), M_TEMP, M_NOWAIT);
- if (!aha) {
- printf("aha%d: cannot malloc!\n", unit);
- return 0;
- }
- bzero(aha, sizeof(struct aha_data));
- ahadata[unit] = aha;
- aha->unit = unit;
- aha->aha_base = dev->id_iobase;
-
- /*
- * Try initialise a unit at this location
- * sets up dma and bus speed, loads aha->aha_int
- */
- if (aha_init(aha) != 0) {
- ahadata[unit] = NULL;
- free(aha, M_TEMP);
- return 0;
- }
- /*
- * Calculate the xor product of the aha struct's
- * physical and virtual address. This allows us
- * to change addresses within the structure
- * from physical to virtual easily, as long as
- * the structure is less than 1 page in size.
- * This is used to recognise CCBs which are in
- * this struct and which are refered to by the
- * hardware using physical addresses.
- * (assumes malloc returns a chunk that doesn't
- * span pages)
- * eventually use the hash table in aha1742.c
- */
- aha->kv_phys_xor = (intptr_t) aha ^ (KVTOPHYS(aha));
-
- /*
- * If it's there, put in it's interrupt vectors
- */
- dev->id_irq = (1 << aha->aha_int);
- dev->id_drq = aha->aha_dma;
- ahaunit++;
- return 0x4;
-}
-
-/*
- * Attach all the sub-devices we can find
- */
-static int
-ahaattach(dev)
- struct isa_device *dev;
-{
- int unit = dev->id_unit;
- struct aha_data *aha = ahadata[unit];
- struct scsibus_data *scbus;
-
- /*
- * fill in the prototype scsi_link.
- */
- aha->sc_link.adapter_unit = unit;
- aha->sc_link.adapter_targ = aha->aha_scsi_dev;
- aha->sc_link.adapter_softc = aha;
- aha->sc_link.adapter = &aha_switch;
- aha->sc_link.device = &aha_dev;
- aha->sc_link.flags = aha->flags;;
-
- /*
- * Prepare the scsibus_data area for the upperlevel
- * scsi code.
- */
- scbus = scsi_alloc_bus();
- if(!scbus)
- return 0;
- scbus->adapter_link = &aha->sc_link;
-
- /*
- * ask the adapter what subunits are present
- */
- scsi_attachdevs(scbus);
-
- return 1;
-}
-
-/*
- * Return some information to the caller about the adapter and its
- * capabilities.
- */
-static u_int32_t
-aha_adapter_info(unit)
- int unit;
-{
- return (2); /* 2 outstanding requests at a time per device */
-}
-
-/*
- * Catch an interrupt from the adaptor
- */
-void
-ahaintr(unit)
- int unit;
-{
- unsigned char stat;
- register int i;
- struct aha_data *aha = ahadata[unit];
-
-#ifdef AHADEBUG
- printf("ahaintr ");
-#endif /*AHADEBUG */
- /*
- * First acknowledge the interrupt, Then if it's not telling about
- * a completed operation just return.
- */
- stat = inb(AHA_INTR_PORT);
- outb(AHA_CTRL_STAT_PORT, AHA_IRST);
- if (!(stat & AHA_MBIF))
- return;
-#ifdef AHADEBUG
- printf("mbxin ");
-#endif /*AHADEBUG */
- /*
- * If it IS then process the completed operation
- */
- for (i = 0; i < AHA_MBX_SIZE; i++) {
- struct aha_mbx_in *mbi = aha->aha_mbx.mbi + i;
-
- if (mbi->stat != AHA_MBI_FREE) {
- struct aha_ccb *ccb =
- (struct aha_ccb *)PHYSTOKV(scsi_3btou(mbi->ccb_addr));
-
- stat = mbi->stat;
-
- switch (stat) {
- case AHA_MBI_OK:
- break;
-
- case AHA_MBI_ABORT:
-#ifdef AHADEBUG
- if (aha_debug)
- printf("abort");
-#endif /*AHADEBUG */
- ccb->host_stat = AHA_ABORTED;
- break;
-
- case AHA_MBI_TGT_NO_CCB:
- /* We enabled target mode and received a SEND
- * or RECEIVE command from the initiator, but
- * we don't have any CCB registered to handle the command.
- * At this point it would be nice to wakeup a
- * process sleeping on this event via an ioctl,
- * returning whether it is a SEND or RECEIVE and the
- * required length.
- * However, I want to look at the CAM documentation before
- * I start extending the API at all.
- */
-#ifdef NOISE_WHEN_TGT_NO_CDB
- printf("Target received, but no CCB ready.\n");
- printf("Initiator & lun: %02x\n", mbi->ccb_addr[0]);
- printf("Max data length: %06x\n",
- (mbi->ccb_addr[1] << 16) | (mbi->ccb_addr[2] << 8)
- + 255);
-#endif
-#ifdef AHADEBUG
- if (aha_debug)
- printf("target-no-ccb");
-#endif /*AHADEBUG */
- ccb = 0;
- break;
-
- case AHA_MBI_UNKNOWN:
- ccb = 0;
-#ifdef AHADEBUG
- if (aha_debug)
- printf("unknown ccb for abort ");
-#endif /*AHADEBUG */
- /* may have missed it */
- /* no such ccb known for abort */
-
- case AHA_MBI_ERROR:
- /* XXX ccb is still set up? Driver fails without it? */
- break;
-
- default:
- panic("Impossible mbxi status");
-
- }
-#ifdef AHADEBUG
- if (aha_debug && ccb && stat != AHA_MBI_OK) {
- u_char *cp;
- cp = (u_char *) (&(ccb->scsi_cmd));
- printf("op=%x %x %x %x %x %x\n",
- cp[0], cp[1], cp[2],
- cp[3], cp[4], cp[5]);
- printf("stat %x for mbi[%d]\n"
- ,mbi->stat, i);
- printf("addr = 0x%x\n", ccb);
- }
-#endif /*AHADEBUG */
- if (ccb) {
- untimeout(aha_timeout, (caddr_t)ccb,
- ccb->xfer->timeout_ch);
- aha_done(aha, ccb);
- }
- mbi->stat = AHA_MBI_FREE;
- }
- }
-}
-
-/*
- * A ccb (and hence a mbx-out) is put onto the
- * free list.
- */
-static void
-aha_free_ccb(aha, ccb, flags)
- struct aha_data *aha;
- struct aha_ccb *ccb;
- int flags;
-{
- unsigned int opri = 0;
-
- if (!(flags & SCSI_NOMASK))
- opri = splbio();
-
- ccb->next = aha->aha_ccb_free;
- aha->aha_ccb_free = ccb;
- ccb->flags = CCB_FREE;
- /*
- * If there were none, wake anybody waiting for
- * one to come free, starting with queued entries
- */
- if (!ccb->next) {
- wakeup((caddr_t)&aha->aha_ccb_free);
- }
- if (!(flags & SCSI_NOMASK))
- splx(opri);
-}
-
-/*
- * Get a free ccb (and hence mbox-out entry)
- */
-static struct aha_ccb *
-aha_get_ccb(aha, flags)
- struct aha_data *aha;
- int flags;
-{
- unsigned opri = 0;
- struct aha_ccb *rc;
-
- if (!(flags & SCSI_NOMASK))
- opri = splbio();
- /*
- * If we can and have to, sleep waiting for one
- * to come free
- */
- while ((!(rc = aha->aha_ccb_free)) && (!(flags & SCSI_NOSLEEP))) {
- tsleep((caddr_t)&aha->aha_ccb_free, PRIBIO, "ahaccb", 0);
- }
- if (rc) {
- aha->aha_ccb_free = aha->aha_ccb_free->next;
- rc->flags = CCB_ACTIVE;
- }
- if (!(flags & SCSI_NOMASK))
- splx(opri);
- return (rc);
-}
-
-static void
-put_host_stat(int host_stat)
-{
- int i;
-
- struct { int host_stat; char *text; } tab[] = {
- { AHA_OK, "Cmd ok" },
- { AHA_LINK_OK, "Link cmd ok" },
- { AHA_LINK_IT, "Link cmd ok + int" },
- { AHA_SEL_TIMEOUT, "Selection time out" },
- { AHA_OVER_UNDER, "Data over/under run" },
- { AHA_BUS_FREE, "Bus dropped at unexpected time" },
- { AHA_INV_BUS, "Invalid bus phase/sequence" },
- { AHA_BAD_MBO, "Incorrect MBO cmd" },
- { AHA_BAD_CCB, "Incorrect ccb opcode" },
- { AHA_BAD_LINK, "Not same values of LUN for links" },
- { AHA_INV_TARGET, "Invalid target direction" },
- { AHA_CCB_DUP, "Duplicate CCB received" },
- { AHA_INV_CCB, "Invalid CCB or segment list" },
- { AHA_ABORTED, "Software abort" },
- };
-
- for (i = 0; i < (int)(sizeof(tab) / sizeof(tab[0])); i++) {
- if (tab[i].host_stat == host_stat) {
- printf("%s\n", tab[i].text);
- return;
- }
- }
-
- printf("Unknown host_stat %02x\n", host_stat);
-}
-
-/*
- * We have a ccb which has been processed by the
- * adaptor, now we look to see how the operation
- * went. Wake up the owner if waiting
- */
-static void
-aha_done(aha, ccb)
- struct aha_data *aha;
- struct aha_ccb *ccb;
-{
- struct scsi_sense_data *s1, *s2;
- struct scsi_xfer *xs = ccb->xfer;
-
- SC_DEBUG(xs->sc_link, SDEV_DB2, ("aha_done\n"));
- /*
- * Otherwise, put the results of the operation
- * into the xfer and call whoever started it
- */
- if (!(xs->flags & INUSE)) {
- printf("aha%d: exiting but not in use!\n", aha->unit);
-#ifdef DIAGNOSTIC
- panic("aha1542 exiting but not in use");
-#endif
- }
- xs->status = ccb->target_stat;
- xs->resid = 0;
-
- if (((ccb->host_stat != AHA_OK) || (ccb->target_stat != SCSI_OK))
- && ((xs->flags & SCSI_ERR_OK) == 0)) {
- /*
- * We have an error, that we cannot ignore.
- */
- s1 = (struct scsi_sense_data *) (((char *) (&ccb->scsi_cmd))
- + ccb->scsi_cmd_length);
- s2 = &(xs->sense);
-
- if (ccb->host_stat) {
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("host err 0x%x\n",
- ccb->host_stat));
- switch (ccb->host_stat) {
- case AHA_ABORTED:
- xs->error = XS_TIMEOUT;
- break;
- case AHA_SEL_TIMEOUT:
- xs->error = XS_SELTIMEOUT;
- break;
-
- case AHA_OVER_UNDER: /* Over run / under run */
- switch(ccb->opcode)
- {
- case AHA_TARGET_CCB:
- xs->resid = xs->datalen - scsi_3btoi(ccb->data_length);
- xs->flags |= SCSI_RESID_VALID;
- if (xs->resid <= 0)
- xs->error = XS_LENGTH;
- break;
-
- case AHA_INIT_RESID_CCB:
- case AHA_INIT_SG_RESID_CCB:
- xs->resid = scsi_3btoi(ccb->data_length);
- xs->flags |= SCSI_RESID_VALID;
- if (xs->resid <= 0)
- xs->error = XS_LENGTH;
- break;
-
- default:
- xs->error = XS_LENGTH;
- }
- break;
-
- default: /* Other scsi protocol messes */
- xs->error = XS_DRIVER_STUFFUP;
- printf("aha%d: ", aha->unit);
- put_host_stat(ccb->host_stat);
- }
- } else {
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("target err 0x%x\n",
- ccb->target_stat));
- switch (ccb->target_stat) {
- case 0x02:
- /* structure copy!!!!! */
- *s2 = *s1;
- xs->error = XS_SENSE;
- break;
- case 0x08:
- xs->error = XS_BUSY;
- break;
- default:
- printf("aha%d:target_stat%x\n",
- aha->unit, ccb->target_stat);
- xs->error = XS_DRIVER_STUFFUP;
- }
- }
- }
-
- xs->flags |= ITSDONE;
- aha_free_ccb(aha, ccb, xs->flags);
- scsi_done(xs);
-}
-
-/* Macro to determine that a rev is potentially a new valid one
- * so that the driver doesn't keep breaking on new revs as it
- * did for the CF and CP.
- */
-#define PROBABLY_NEW_BOARD(REV) (REV > 0x43 && REV < 0x56)
-
-static char *board_rev(struct aha_data *aha, int type)
-{
- switch(type)
- {
- case 0x20: return "Buslogic 545?";
- case 0x31: return "AHA-1540";
- case 0x41: return "AHA-154x[AB]";
- case 0x42: return "AHA-1640";
- case 0x43: return "AHA-1542C";
- case 0x44: return "AHA-1542CF";
- case 0x45: return "AHA-1542CF BIOS v2.01";
- case 0x46: return "AHA-1542CP";
-
- default:
-
-
- if (PROBABLY_NEW_BOARD(type))
- {
- printf("aha%d: Assuming type %02x is a new board.\n",
- aha->unit, type);
- return "New Adaptec rev?";
- }
-
- printf("aha%d: type %02x is an unknown board.\n",
- aha->unit, type);
- return "Unknown board";
- }
-}
-
-/*
- * Start the board, ready for normal operation
- */
-static int
-aha_init(aha)
- struct aha_data *aha;
-{
- char *desc;
- unsigned char ad[3];
- volatile int i, sts;
- struct aha_config conf;
- struct aha_inquire inquire;
- struct aha_extbios extbios;
-
- /* Assume that residual codes don't work. If they
- * do we enable that after we figure out what kind of
- * board it is.
- */
- aha->init_opcode = AHA_INITIATOR_CCB;
- aha->sg_opcode = AHA_INIT_SCAT_GATH_CCB;
-
- /*
- * reset board, If it doesn't respond, assume
- * that it's not there.. good for the probe
- */
-
- outb(AHA_CTRL_STAT_PORT, AHA_HRST | AHA_SRST);
-
- for (i = AHA_RESET_TIMEOUT; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts == (AHA_IDLE | AHA_INIT)) {
- break;
- }
- DELAY(1000); /* calibrated in msec */
- }
-#ifdef AHADEBUG
- printf("aha_init: AHA_RESET_TIMEOUT went to %d\n", i);
-#endif /* AHADEBUG */
- if (i == 0) {
-#ifdef AHADEBUG
- if (aha_debug)
- printf("aha_init: No answer from board\n");
-#endif /*AHADEBUG */
- return (ENXIO);
- }
-
- /*
- * Assume we have a board at this stage, do an adapter inquire
- * to find out what type of controller it is. If the AHA_INQUIRE
- * command fails, blatter about it, nuke the boardid so the 1542C
- * stuff gets skipped over, and reset the board again.
- */
- if(aha_cmd(aha, 0, sizeof(inquire), 1,
- (u_char *)&inquire, AHA_INQUIRE)) {
- /*
- * Blah.. not a real adaptec board!!!
- * Seems that the Buslogic 545S and the DTC3290 both get
- * this wrong.
- */
- printf ("aha%d: not a REAL adaptec board, may cause warnings\n",
- aha->unit);
- inquire.boardid = 0;
- outb(AHA_CTRL_STAT_PORT, AHA_HRST | AHA_SRST);
- for (i = AHA_RESET_TIMEOUT; i; i--) {
- sts = inb(AHA_CTRL_STAT_PORT);
- if (sts == (AHA_IDLE | AHA_INIT)) {
- break;
- }
- DELAY(1000); /* calibrated in msec */
- }
-#ifdef AHADEBUG
- printf("aha_init2: AHA_RESET_TIMEOUT went to %d\n", i);
-#endif /* AHADEBUG */
- if (i == 0) {
-#ifdef AHADEBUG
- if (aha_debug)
- printf("aha_init2: No answer from board\n");
-#endif /*AHADEBUG */
- return (ENXIO);
- }
- }
-#ifdef AHADEBUG
- printf("aha%d: inquire %x, %x, %x, %x\n",
- aha->unit,
- inquire.boardid, inquire.spec_opts,
- inquire.revision_1, inquire.revision_2);
-#endif /* AHADEBUG */
-
- aha->flags = SDEV_BOUNCE;
-
-#define PRVERBOSE(x) if (bootverbose) printf x
-
- /*
- * If we are a new type of 1542 board (anything newer than a 1542C)
- * then disable the extended bios so that the
- * mailbox interface is unlocked.
- * This is also true for the 1542B Version 3.20. First Adaptec
- * board that supports >1Gb drives.
- * No need to check the extended bios flags as some of the
- * extensions that cause us problems are not flagged in that byte.
- */
- desc = board_rev(aha, inquire.boardid);
-
- PRVERBOSE( ("aha%d: Rev %02x (%s) V%c.%c",
- aha->unit, inquire.boardid, desc, inquire.revision_1,
- inquire.revision_2) );
-
- if (PROBABLY_NEW_BOARD(inquire.boardid) ||
- (inquire.boardid == 0x41
- && inquire.revision_1 == 0x31 && inquire.revision_2 == 0x34)) {
- aha_cmd(aha, 0, sizeof(extbios), 0,
- (u_char *)&extbios, AHA_EXT_BIOS);
-#ifdef AHADEBUG
- printf("aha%d: extended bios flags %x\n", aha->unit, extbios.flags);
-#endif /* AHADEBUG */
-
- PRVERBOSE( (", enabling mailbox") );
-
- aha_cmd(aha, 2, 0, 0, 0, AHA_MBX_ENABLE,
- 0, extbios.mailboxlock);
- }
-
- /* Which boards support residuals? Some early 1542A's apparently
- * don't. The 1542B with V0.5 of the software does, so I've
- * arbitrarily set that as the earliest rev.
- */
- if (PROBABLY_NEW_BOARD(inquire.boardid) ||
- (inquire.boardid == 0x41
- && (inquire.revision_1 > '0' || inquire.revision_2 >= '5'))) {
-
- PRVERBOSE( (", enabling residuals") );
-
- aha->init_opcode = AHA_INIT_RESID_CCB;
- aha->sg_opcode = AHA_INIT_SG_RESID_CCB;
- }
-
- /* Which boards support target operations? The 1542C completely
- * locks up the SCSI bus if you enable them. I'm only sure
- * about the B, which was sold in the OEM market as a target
- * board.
- */
- if (inquire.boardid == 0x41) {
- PRVERBOSE( (", target ops") );
- aha->flags |= SDEV_TARGET_OPS;
- }
-
- PRVERBOSE( ("\n") );
-
- /*
- * setup dma channel from jumpers and save int
- * level
- */
- PRVERBOSE(("aha%d: reading board settings, ", aha->unit));
-
- if (inquire.boardid == 0x20) {
- DELAY(1000); /* for Bustek 545 */
- }
-
- aha_cmd(aha, 0, sizeof(conf), 0, (u_char *)&conf, AHA_CONF_GET);
- switch (conf.chan) {
- case CHAN0:
- outb(0x0b, 0x0c);
- outb(0x0a, 0x00);
- aha->aha_dma = 0;
- break;
- case CHAN5:
- outb(0xd6, 0xc1);
- outb(0xd4, 0x01);
- aha->aha_dma = 5;
- break;
- case CHAN6:
- outb(0xd6, 0xc2);
- outb(0xd4, 0x02);
- aha->aha_dma = 6;
- break;
- case CHAN7:
- outb(0xd6, 0xc3);
- outb(0xd4, 0x03);
- aha->aha_dma = 7;
- break;
- default:
- printf("aha%d: illegal dma jumper setting\n", aha->unit);
- return (EIO);
- }
-
- PRVERBOSE( ("dma=%d ", aha->aha_dma) );
-
- switch (conf.intr) {
- case INT9:
- aha->aha_int = 9;
- break;
- case INT10:
- aha->aha_int = 10;
- break;
- case INT11:
- aha->aha_int = 11;
- break;
- case INT12:
- aha->aha_int = 12;
- break;
- case INT14:
- aha->aha_int = 14;
- break;
- case INT15:
- aha->aha_int = 15;
- break;
- default:
- printf("aha%d: illegal int jumper setting\n", aha->unit);
- return (EIO);
- }
-
- PRVERBOSE( ("int=%d ", aha->aha_int) );
-
- /* who are we on the scsi bus? */
- aha->aha_scsi_dev = conf.scsi_dev;
-
- PRVERBOSE( ("id=%d ", aha->aha_scsi_dev) );
-
- /*
- * Change the bus on/off times to not clash with other dma users.
- */
- aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
- aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
-
-#ifdef TUNE_1542
- /*
- * Initialize memory transfer speed
- * Not compiled in by default because it breaks some machines
- */
- if (!(aha_set_bus_speed(aha))) {
- return (EIO);
- }
-#else
- PRVERBOSE( (" (bus speed defaulted)\n") );
-#endif /*TUNE_1542*/
- /*
- * Initialize mail box
- */
- scsi_uto3b(KVTOPHYS(&aha->aha_mbx), ad);
-
- aha_cmd(aha, 4, 0, 0, 0, AHA_MBX_INIT,
- AHA_MBX_SIZE,
- ad[0],
- ad[1],
- ad[2]);
-
- /*
- * link the ccb's with the mbox-out entries and
- * into a free-list
- * this is a kludge but it works
- */
- for (i = 0; i < AHA_MBX_SIZE; i++) {
- aha->aha_ccb[i].next = aha->aha_ccb_free;
- aha->aha_ccb_free = &aha->aha_ccb[i];
- aha->aha_ccb_free->flags = CCB_FREE;
- aha->aha_ccb_free->mbx = &aha->aha_mbx.mbo[i];
- scsi_uto3b(KVTOPHYS(aha->aha_ccb_free), aha->aha_mbx.mbo[i].ccb_addr);
- }
- /*
- * Note that we are going and return (to probe)
- */
- return 0;
-}
-
-static void
-ahaminphys(bp)
- struct buf *bp;
-{
-/* aha seems to explode with 17 segs (64k may require 17 segs) */
-/* on old boards so use a max of 16 segs if you have problems here */
- if (bp->b_bcount > ((AHA_NSEG - 1) * PAGESIZ)) {
- bp->b_bcount = ((AHA_NSEG - 1) * PAGESIZ);
- }
-}
-
-static int
-aha_escape(xs, ccb)
- struct scsi_xfer *xs;
- struct aha_ccb *ccb;
-{
- int ret = 0;
- int s;
-
- if (xs->cmd)
- {
- switch(xs->cmd->opcode)
- {
- case SCSI_OP_RESET:
- ccb->opcode = AHA_RESET_CCB;
- ret = 0;
- break;
-
- case SCSI_OP_TARGET:
- s= splbio();
- aha_cmd((struct aha_data *)xs->sc_link->adapter_softc,
- 2, 0, 0, 0, AHA_TARGET_EN,
- (int)xs->cmd->bytes[0], (int)1);
- splx(s);
- ret = COMPLETE;
- break;
-
- default:
- ret = ESCAPE_NOT_SUPPORTED;
- break;
- }
- }
- else
- {
- ccb->opcode = AHA_RESET_CCB;
- ret = 0;
- }
-
- return ret;
-}
-
-#define physdb(ARG) (void)(ARG)
-
-/* physcontig: Scan forward from a KV and return length to the
- * end of physically contiguous addresses. This belongs in
- * i386/.../something_or_other.c
- * XXX: Find the right thing in the kernel.
- */
-static int physcontig(int kv, int len)
-{
- int len_was = len;
- u_long kvl = (u_long)kv;
-
- int phys_len;
- u_long phys, prev_phys;
-
- prev_phys = KVTOPHYS(kvl);
-
- /* We go at least to the end of this page:
- */
- phys_len = PAGESIZ - (prev_phys & (PAGESIZ - 1));
- len -= phys_len;
- kvl += phys_len;
- prev_phys &= ~(PAGESIZ - 1);
-
- while (len > 0)
- {
- phys = KVTOPHYS(kvl);
-
- if (phys != prev_phys + PAGESIZ)
- {
- physdb(("phys %08x != prev_phys %08x + PAGESIZ\n",
- phys, prev_phys));
-
- break;
- }
-
- prev_phys = phys;
- kvl += PAGESIZ;
- len -= PAGESIZ;
- }
-
- phys_len = (len < 0) ? len_was : (len_was - len);
-
- physdb(("physcontig(%08x, %d) = %d\n", kv, len_was, phys_len));
-
- return phys_len;
-}
-/*
- * start a scsi operation given the command and
- * the data address. Also needs the unit, target
- * and lu
- */
-static int32_t
-aha_scsi_cmd(xs)
- struct scsi_xfer *xs;
-{
- struct scsi_link *sc_link = xs->sc_link;
- struct aha_data *aha;
- struct aha_ccb *ccb;
- struct aha_scat_gath *sg;
- int seg; /* scatter gather seg being worked on */
- int thiskv;
- int thisphys, nextphys;
- int bytes_this_seg, bytes_this_page, datalen, flags;
- int s;
-
- aha = (struct aha_data *)sc_link->adapter_softc;
-
- SC_DEBUG(xs->sc_link, SDEV_DB2, ("aha_scsi_cmd\n"));
- /*
- * get a ccb (mbox-out) to use. If the transfer
- * is from a buf (possibly from interrupt time)
- * then we can't allow it to sleep
- */
- flags = xs->flags;
- if (!(ccb = aha_get_ccb(aha, flags))) {
- xs->error = XS_DRIVER_STUFFUP;
- return (TRY_AGAIN_LATER);
- }
- if (ccb->mbx->cmd != AHA_MBO_FREE)
- printf("aha%d: MBO %02x and not %02x (free)\n",
- aha->unit, ccb->mbx->cmd, AHA_MBO_FREE);
-
- /*
- * Put all the arguments for the xfer in the ccb
- */
- ccb->xfer = xs;
- if (flags & SCSI_RESET) {
- ccb->opcode = AHA_RESET_CCB;
- } else {
- /* can't use S/G if zero length */
- ccb->opcode = (xs->datalen ?
- aha->sg_opcode
- : aha->init_opcode);
- }
- ccb->target = sc_link->target;
- ccb->data_out = 0;
- ccb->data_in = 0;
- ccb->lun = sc_link->lun;
- ccb->scsi_cmd_length = xs->cmdlen;
-
- /* Some devices (e.g, Microtek ScanMaker II)
- * fall on the ground if you ask for anything but
- * an exact number of sense bytes (wiping out the
- * sense data)
- * XXX: This was lost at some point in scsi_ioctl.c.
- */
- ccb->req_sense_length = (xs->req_sense_length)
- ? xs->req_sense_length
- : sizeof(ccb->scsi_sense);
-
- /* XXX: I propose we move the reset handling into the escape
- * handling.
- */
- if (flags & SCSI_RESET) {
- flags |= SCSI_ESCAPE;
- xs->cmd->opcode = SCSI_OP_RESET;
- }
-
- /* Set up the CCB. For an escape function, the escape hook may
- * set it up for us.
- */
-
- if (flags & SCSI_ESCAPE) {
- int ret;
- ret = aha_escape(xs, ccb);
- if (ret)
- return ret;
- }
- else if (flags & SCSI_TARGET)
- {
- ccb->opcode = AHA_TARGET_CCB;
-
- /* These must be set up for target mode:
- */
- if (flags & SCSI_DATA_IN)
- ccb->data_in = 1;
- if (flags & SCSI_DATA_OUT)
- ccb->data_out = 1;
- }
- else
- {
- ccb->opcode = (xs->datalen? /* can't use S/G if zero length */
- AHA_INIT_SCAT_GATH_CCB
- :AHA_INITIATOR_CCB);
- }
-
- switch(ccb->opcode)
- {
- case AHA_TARGET_CCB:
- if (xs->data)
- scsi_uto3b(KVTOPHYS((int)xs->data), ccb->data_addr);
- else
- scsi_uto3b(0, ccb->data_addr);
-
- /* For non scatter-gather I/O (and Target mode doesn't do
- * scatter-gather) we need to truncate the transfer
- * at the first non consecutive physical address.
- */
- scsi_uto3b(physcontig((int)xs->data, xs->datalen), ccb->data_length);
- break;
-
- /* This should be folded in with TARGET_CCB once
- * physcontig is debugged.
- */
- case AHA_INITIATOR_CCB:
- case AHA_INIT_RESID_CCB:
-
- if (xs->data)
- scsi_uto3b(KVTOPHYS((int)xs->data), ccb->data_addr);
- else
- scsi_uto3b(0, ccb->data_addr);
-
- scsi_uto3b(xs->datalen, ccb->data_length);
- break;
-
- case AHA_RESET_CCB:
- scsi_uto3b(0, ccb->data_addr);
- scsi_uto3b(0, ccb->data_length);
- break;
-
- case AHA_INIT_SCAT_GATH_CCB:
- case AHA_INIT_SG_RESID_CCB:
- scsi_uto3b(KVTOPHYS(ccb->scat_gath), ccb->data_addr );
- sg = ccb->scat_gath ;
- seg = 0;
-#ifdef TFS_ONLY
- if (flags & SCSI_DATA_UIO) {
- iovp = ((struct uio *) xs->data)->uio_iov;
- datalen = ((struct uio *) xs->data)->uio_iovcnt;
- while ((datalen) && (seg < AHA_NSEG)) {
- scsi_uto3b(iovp->iov_base, sg->seg_addr);
- scsi_uto3b(iovp->iov_len, sg->seg_len);
- SC_DEBUGN(xs->sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)"
- ,iovp->iov_len
- ,iovp->iov_base));
- sg++;
- iovp++;
- seg++;
- datalen--;
- }
- } else
-#endif /*TFS_ONLY */
- {
- /*
- * Set up the scatter gather block
- */
-
- SC_DEBUG(xs->sc_link, SDEV_DB4,
- ("%ld @%p:- ", xs->datalen, xs->data));
- datalen = xs->datalen;
- thiskv = (int) xs->data;
- thisphys = KVTOPHYS(thiskv);
-
- while ((datalen) && (seg < AHA_NSEG)) {
- bytes_this_seg = 0;
-
- /* put in the base address */
- scsi_uto3b(thisphys, sg->seg_addr);
-
- SC_DEBUGN(xs->sc_link, SDEV_DB4,
- ("0x%x", thisphys));
-
- /* do it at least once */
- nextphys = thisphys;
- while ((datalen) && (thisphys == nextphys)) {
- /*
- * This page is contiguous (physically)
- * with the the last, just extend the
- * length
- */
- /* check it fits on the ISA bus */
- if (thisphys > 0xFFFFFF)
- {
- printf("aha%d: DMA beyond"
- " end Of ISA: 0x%x\n",
- aha->unit, thisphys);
- xs->error = XS_DRIVER_STUFFUP;
- aha_free_ccb(aha, ccb, flags);
- return (HAD_ERROR);
- }
- /** how far to the end of the page ***/
- nextphys = (thisphys & (~(PAGESIZ - 1)))
- + PAGESIZ;
- bytes_this_page = nextphys - thisphys;
- /**** or the data ****/
- bytes_this_page = min(bytes_this_page
- ,datalen);
- bytes_this_seg += bytes_this_page;
- datalen -= bytes_this_page;
-
- /**** get more ready for the next page ****/
- thiskv = (thiskv & (~(PAGESIZ - 1)))
- + PAGESIZ;
- if (datalen)
- thisphys = KVTOPHYS(thiskv);
- }
- /*
- * next page isn't contiguous, finish the seg
- */
- SC_DEBUGN(xs->sc_link, SDEV_DB4,
- ("(0x%x)", bytes_this_seg));
- scsi_uto3b(bytes_this_seg, sg->seg_len);
- sg++;
- seg++;
- }
- }
- scsi_uto3b(seg * sizeof(struct aha_scat_gath), ccb->data_length);
- SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n"));
-
- if (datalen) { /* there's still data, must have run out of segs! */
- printf("aha%d: aha_scsi_cmd, more than %d DMA segs\n",
- aha->unit, AHA_NSEG);
- xs->error = XS_DRIVER_STUFFUP;
- aha_free_ccb(aha, ccb, flags);
- return (HAD_ERROR);
- }
- break;
-
- default:
- printf("aha_scsi_cmd%d: Illegal CCB opcode.\n", aha->unit);
- xs->error = XS_DRIVER_STUFFUP;
- aha_free_ccb(aha,ccb,flags);
- return HAD_ERROR;
- }
-
- scsi_uto3b(0, ccb->link_addr);
- /*
- * Put the scsi command in the ccb and start it
- */
- if (!(flags & SCSI_ESCAPE))
- bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
- if (!(flags & SCSI_NOMASK)) {
- s = splbio(); /* stop instant timeouts */
- xs->timeout_ch = timeout(aha_timeout, (caddr_t)ccb,
- (xs->timeout * hz) / 1000);
- aha_startmbx(ccb->mbx);
- /*
- * Usually return SUCCESSFULLY QUEUED
- */
- splx(s);
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("sent\n"));
- return (SUCCESSFULLY_QUEUED);
- }
- aha_startmbx(ccb->mbx);
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd sent, waiting\n"));
-
- /*
- * If we can't use interrupts, poll on completion
- */
- return (aha_poll(aha, xs, ccb)); /* only during boot */
-}
-
-/*
- * Poll a particular unit, looking for a particular xs
- */
-static int
-aha_poll(aha, xs, ccb)
- struct aha_data *aha;
- struct scsi_xfer *xs;
- struct aha_ccb *ccb;
-{
- int count = xs->timeout;
- u_char stat;
-
- /*timeouts are in msec, so we loop in 1000uSec cycles */
- while (count) {
- /*
- * If we had interrupts enabled, would we
- * have got an interrupt?
- */
- stat = inb(AHA_INTR_PORT);
- if (stat & AHA_ANY_INTR) {
- ahaintr(aha->unit);
- }
- if (xs->flags & ITSDONE) {
- break;
- }
- DELAY(1000); /* only happens in boot so ok */
- count--;
- }
- if (count == 0) {
- /*
- * We timed out, so call the timeout handler
- * manually, accout for the fact that the
- * clock is not running yet by taking out the
- * clock queue entry it makes
- */
- aha_timeout((caddr_t)ccb);
-
- /*
- * because we are polling,
- * take out the timeout entry aha_timeout made
- */
- untimeout(aha_timeout, (caddr_t)ccb, ccb->xfer->timeout_ch);
- count = 2000;
- while (count) {
- /*
- * Once again, wait for the int bit
- */
- stat = inb(AHA_INTR_PORT);
- if (stat & AHA_ANY_INTR) {
- ahaintr(aha->unit);
- }
- if (xs->flags & ITSDONE) {
- break;
- }
- DELAY(1000); /* only happens in boot so ok */
- count--;
- }
- if (count == 0) {
- /*
- * We timed out again.. this is bad
- * Notice that this time there is no
- * clock queue entry to remove
- */
- aha_timeout((caddr_t)ccb);
- }
- }
- if (xs->error)
- return (HAD_ERROR);
- return (COMPLETE);
-
-}
-
-#ifdef TUNE_1542
-/*
- * Try all the speeds from slowest to fastest.. if it finds a
- * speed that fails, back off one notch from the last working
- * speed (unless there is no other notch).
- * Returns the nSEC value of the time used
- * or 0 if it could get a working speed (or the NEXT speed
- * failed)
- */
-static struct bus_speed
-{
- char arg;
- int nsecs;
-}aha_bus_speeds[] =
-{
- {0x88,100},
- {0x99,150},
- {0xaa,200},
- {0xbb,250},
- {0xcc,300},
- {0xdd,350},
- {0xee,400},
- {0xff,450}
-};
-
-static int
-aha_set_bus_speed(aha)
- struct aha_data *aha;
-{
- int speed;
- int lastworking;
- int retval,retval2;
-
- lastworking = -1;
- speed = 7;
- while (1) {
- retval = aha_bus_speed_check(aha,speed);
- if(retval != 0) {
- lastworking = speed;
- }
- if((retval == 0) || (speed == 0)) {
- if(lastworking == -1) {
- printf("No working bus speed for aha154X\n");
- return 0;
- }
- printf("%d nSEC ok, using "
- ,aha_bus_speeds[lastworking].nsecs);
- if(lastworking == 7) { /* is slowest already */
- printf("marginal ");
- } else {
- lastworking++;
- }
- retval2 = aha_bus_speed_check(aha,lastworking);
- if(retval2 == 0) {
- printf("test retry failed.. aborting.\n");
- return 0;
- }
- printf("%d nSEC\n",retval2);
- return retval2 ;
-
- }
- speed--;
- }
-}
-
-/*
- * Set the DMA speed to the Nth speed and try an xfer. If it
- * fails return 0, if it succeeds return the nSec value selected
- * If there is no such speed return HAD_ERROR.
- */
-static char aha_test_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz!@";
-
-u_char aha_scratch_buf[256];
-
-static int
-aha_bus_speed_check(aha, speed)
- struct aha_data *aha;
- int speed;
-{
- int numspeeds = sizeof(aha_bus_speeds) / sizeof(struct bus_speed);
- int loopcount;
- u_char ad[3];
-
- /*
- * Check we have such an entry
- */
- if (speed >= numspeeds)
- return (HAD_ERROR); /* illegal speed */
-
- /*
- * Set the dma-speed
- */
- aha_cmd(aha, 1, 0, 0, 0, AHA_SPEED_SET, aha_bus_speeds[speed].arg);
-
- /*
- * put the test data into the buffer and calculate
- * its address. Read it onto the board
- */
- scsi_uto3b(KVTOPHYS(aha_scratch_buf), ad);
- for(loopcount = 2000;loopcount;loopcount--)
- {
- strcpy(aha_scratch_buf, aha_test_string);
-
- aha_cmd(aha, 3, 0, 0, 0, AHA_WRITE_FIFO, ad[0], ad[1], ad[2]);
-
- /*
- * clear the buffer then copy the contents back from the
- * board.
- */
- bzero(aha_scratch_buf, 54); /* 54 bytes transfered by test */
-
- aha_cmd(aha, 3, 0, 0, 0, AHA_READ_FIFO, ad[0], ad[1], ad[2]);
-
- /*
- * Compare the original data and the final data and
- * return the correct value depending upon the result
- */
- if (strcmp(aha_test_string, aha_scratch_buf))
- return 0; /* failed test */
- }
- /* copy succeded assume speed ok */
-
- return (aha_bus_speeds[speed].nsecs);
-
-}
-#endif /*TUNE_1542*/
-
-static void
-aha_timeout(void *arg1)
-{
- struct aha_ccb * ccb = (struct aha_ccb *)arg1;
- int s = splbio();
- struct aha_data *aha;
-
- aha = (struct aha_data *)ccb->xfer->sc_link->adapter_softc;
- sc_print_addr(ccb->xfer->sc_link);
- printf("timed out ");
-
- /*
- * If The ccb's mbx is not free, then
- * the board has gone south
- */
- if (ccb->mbx->cmd != AHA_MBO_FREE) {
- printf("\nadapter not taking commands.. frozen?!\n");
-#ifdef DIAGNOSTIC
- panic("aha1542 frozen");
-#endif
- }
- /*
- * If it has been through before, then
- * a previous abort has failed, don't
- * try abort again
- */
- if (ccb->flags == CCB_ABORTED) {
- /* abort timed out */
- printf(" AGAIN\n");
- ccb->xfer->retries = 0; /* I MEAN IT ! */
- ccb->host_stat = AHA_ABORTED;
- aha_done(aha, ccb);
- } else {
- /* abort the operation that has timed out */
- printf("\n");
- aha_abortmbx(ccb->mbx);
- /* 4 secs for the abort */
- ccb->xfer->timeout_ch = timeout(aha_timeout,
- (caddr_t)ccb, 4 * hz);
- ccb->flags = CCB_ABORTED;
- } splx(s);
-}
diff --git a/sys/i386/scsi/93cx6.c b/sys/i386/scsi/93cx6.c
deleted file mode 100644
index 6a1ecb1..0000000
--- a/sys/i386/scsi/93cx6.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Interface for the 93C66/56/46/26/06 serial eeprom parts.
- *
- * Copyright (c) 1995, 1996 Daniel M. Eischen
- * 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 immediately at the beginning of the file, without modification,
- * 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. Absolutely no warranty of function or purpose is made by the author
- * Daniel M. Eischen.
- * 4. Modifications may be freely made to this file if the above conditions
- * are met.
- *
- * $Id: 93cx6.c,v 1.10 1997/02/22 09:38:36 peter Exp $
- */
-
-/*
- * The instruction set of the 93C66/56/46/26/06 chips are as follows:
- *
- * Start OP *
- * Function Bit Code Address** Data Description
- * -------------------------------------------------------------------
- * READ 1 10 A5 - A0 Reads data stored in memory,
- * starting at specified address
- * EWEN 1 00 11XXXX Write enable must preceed
- * all programming modes
- * ERASE 1 11 A5 - A0 Erase register A5A4A3A2A1A0
- * WRITE 1 01 A5 - A0 D15 - D0 Writes register
- * ERAL 1 00 10XXXX Erase all registers
- * WRAL 1 00 01XXXX D15 - D0 Writes to all registers
- * EWDS 1 00 00XXXX Disables all programming
- * instructions
- * *Note: A value of X for address is a don't care condition.
- * **Note: There are 8 address bits for the 93C56/66 chips unlike
- * the 93C46/26/06 chips which have 6 address bits.
- *
- * The 93C46 has a four wire interface: clock, chip select, data in, and
- * data out. In order to perform one of the above functions, you need
- * to enable the chip select for a clock period (typically a minimum of
- * 1 usec, with the clock high and low a minimum of 750 and 250 nsec
- * respectively). While the chip select remains high, you can clock in
- * the instructions (above) starting with the start bit, followed by the
- * OP code, Address, and Data (if needed). For the READ instruction, the
- * requested 16-bit register contents is read from the data out line but
- * is preceded by an initial zero (leading 0, followed by 16-bits, MSB
- * first). The clock cycling from low to high initiates the next data
- * bit to be sent from the chip.
- *
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#if defined(__FreeBSD__)
-#include <i386/scsi/93cx6.h>
-#elif defined(__NetBSD__)
-#include <machine/bus.h>
-#include <dev/ic/smc93cx6var.h>
-#endif
-
-/*
- * Right now, we only have to read the SEEPROM. But we make it easier to
- * add other 93Cx6 functions.
- */
-static struct seeprom_cmd {
- unsigned char len;
- unsigned char bits[3];
-} seeprom_read = {3, {1, 1, 0}};
-
-/*
- * Wait for the SEERDY to go high; about 800 ns.
- */
-#define CLOCK_PULSE(sd, rdy) \
- while ((SEEPROM_INB(sd) & rdy) == 0) { \
- ; /* Do nothing */ \
- }
-
-/*
- * Read the serial EEPROM and returns 1 if successful and 0 if
- * not successful.
- */
-int
-read_seeprom(sd, buf, start_addr, count)
- struct seeprom_descriptor *sd;
- u_int16_t *buf;
-#if defined(__FreeBSD__)
- u_int start_addr;
- u_int count;
-#elif defined(__NetBSD__)
- bus_io_size_t start_addr;
- bus_io_size_t count;
-#endif
-{
- int i = 0;
- u_int k = 0;
- u_int16_t v;
- u_int8_t temp;
-
- /*
- * Read the requested registers of the seeprom. The loop
- * will range from 0 to count-1.
- */
- for (k = start_addr; k < count + start_addr; k++) {
- /* Send chip select for one clock cycle. */
- temp = sd->sd_MS ^ sd->sd_CS;
- SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
- CLOCK_PULSE(sd, sd->sd_RDY);
-
- /*
- * Now we're ready to send the read command followed by the
- * address of the 16-bit register we want to read.
- */
- for (i = 0; i < seeprom_read.len; i++) {
- if (seeprom_read.bits[i] != 0)
- temp ^= sd->sd_DO;
- SEEPROM_OUTB(sd, temp);
- CLOCK_PULSE(sd, sd->sd_RDY);
- SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
- CLOCK_PULSE(sd, sd->sd_RDY);
- if (seeprom_read.bits[i] != 0)
- temp ^= sd->sd_DO;
- }
- /* Send the 6 or 8 bit address (MSB first, LSB last). */
- for (i = (sd->sd_chip - 1); i >= 0; i--) {
- if ((k & (1 << i)) != 0)
- temp ^= sd->sd_DO;
- SEEPROM_OUTB(sd, temp);
- CLOCK_PULSE(sd, sd->sd_RDY);
- SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
- CLOCK_PULSE(sd, sd->sd_RDY);
- if ((k & (1 << i)) != 0)
- temp ^= sd->sd_DO;
- }
-
- /*
- * Now read the 16 bit register. An initial 0 precedes the
- * register contents which begins with bit 15 (MSB) and ends
- * with bit 0 (LSB). The initial 0 will be shifted off the
- * top of our word as we let the loop run from 0 to 16.
- */
- v = 0;
- for (i = 16; i >= 0; i--) {
- SEEPROM_OUTB(sd, temp);
- CLOCK_PULSE(sd, sd->sd_RDY);
- v <<= 1;
- if (SEEPROM_INB(sd) & sd->sd_DI)
- v |= 1;
- SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
- CLOCK_PULSE(sd, sd->sd_RDY);
- }
-
- buf[k - start_addr] = v;
-
- /* Reset the chip select for the next command cycle. */
- temp = sd->sd_MS;
- SEEPROM_OUTB(sd, temp);
- CLOCK_PULSE(sd, sd->sd_RDY);
- SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
- CLOCK_PULSE(sd, sd->sd_RDY);
- SEEPROM_OUTB(sd, temp);
- CLOCK_PULSE(sd, sd->sd_RDY);
- }
-#if 0
- printf ("Serial EEPROM:");
- for (k = 0; k < count; k = k + 1) {
- if (((k % 8) == 0) && (k != 0))
- {
- printf ("\n ");
- }
- printf (" 0x%x", buf[k]);
- }
- printf ("\n");
-#endif
- return (1);
-}
diff --git a/sys/i386/scsi/93cx6.h b/sys/i386/scsi/93cx6.h
deleted file mode 100644
index a253e75..0000000
--- a/sys/i386/scsi/93cx6.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Interface to the 93C46 serial EEPROM that is used to store BIOS
- * settings for the aic7xxx based adaptec SCSI controllers. It can
- * also be used for 93C26 and 93C06 serial EEPROMS.
- *
- * Copyright (c) 1994, 1995 Justin T. Gibbs.
- * 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 immediately at the beginning of the file, without modification,
- * 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. Absolutely no warranty of function or purpose is made by the author
- * Justin T. Gibbs.
- * 4. Modifications may be freely made to this file if the above conditions
- * are met.
- *
- * $Id: 93cx6.h,v 1.7 1997/02/22 09:38:37 peter Exp $
- */
-
-#include <sys/param.h>
-#if !defined(__NetBSD__)
-#include <sys/systm.h>
-#endif
-
-typedef enum {
- C46 = 6,
- C56_66 = 8
-} seeprom_chip_t;
-
-struct seeprom_descriptor {
-#if defined(__FreeBSD__)
- u_int32_t sd_iobase;
- volatile u_int8_t *sd_maddr;
-#elif defined(__NetBSD__)
- bus_chipset_tag_t sd_bc;
- bus_io_handle_t sd_ioh;
- bus_io_size_t sd_offset;
-#endif
- seeprom_chip_t sd_chip;
- u_int16_t sd_MS;
- u_int16_t sd_RDY;
- u_int16_t sd_CS;
- u_int16_t sd_CK;
- u_int16_t sd_DO;
- u_int16_t sd_DI;
-};
-
-/*
- * This function will read count 16-bit words from the serial EEPROM and
- * return their value in buf. The port address of the aic7xxx serial EEPROM
- * control register is passed in as offset. The following parameters are
- * also passed in:
- *
- * CS - Chip select
- * CK - Clock
- * DO - Data out
- * DI - Data in
- * RDY - SEEPROM ready
- * MS - Memory port mode select
- *
- * A failed read attempt returns 0, and a successful read returns 1.
- */
-
-#if defined(__FreeBSD__)
-#define SEEPROM_INB(sd) \
- (((sd)->sd_maddr != NULL) ? \
- *((sd)->sd_maddr) : \
- inb((sd)->sd_iobase))
-#define SEEPROM_OUTB(sd, value) \
- (((sd)->sd_maddr != NULL) ? \
- (void)(*((sd)->sd_maddr) = (value)) : \
- outb((sd)->sd_iobase, (value)))
-
-#elif defined(__NetBSD__)
-#define SEEPROM_INB(sd) \
- bus_io_read_1(sd->sd_bc, sd->sd_ioh, sd->sd_offset)
-#define SEEPROM_OUTB(sd, value) \
- bus_io_write_1(sd->sd_bc, sd->sd_ioh, sd->sd_offset, value)
-#endif
-
-#if defined(__FreeBSD__)
-int read_seeprom __P((struct seeprom_descriptor *sd,
- u_int16_t *buf, u_int start_addr, u_int count));
-#elif defined(__NetBSD__)
-int read_seeprom __P((struct seeprom_descriptor *sd,
- u_int16_t *buf, bus_io_size_t start_addr, bus_io_size_t count));
-#endif
diff --git a/sys/i386/scsi/advansys.c b/sys/i386/scsi/advansys.c
deleted file mode 100644
index e48362e..0000000
--- a/sys/i386/scsi/advansys.c
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * Generic driver for the Advanced Systems Inc. SCSI controllers
- * Product specific probe and attach routines can be found in:
- *
- * i386/isa/adv_isa.c ABP5140, ABP542, ABP5150, ABP842, ABP852
- *
- * Copyright (c) 1996 Justin T. Gibbs.
- * 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 immediately at the beginning of the file, without modification,
- * 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. 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 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 AUTHOR 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$
- */
-/*
- * Ported from:
- * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
- *
- * Copyright (c) 1995-1996 Advanced System Products, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
-
-#include <machine/clock.h>
-
-#include <scsi/scsi_all.h>
-#include <scsi/scsi_message.h>
-#include <scsi/scsiconf.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-
-#include <i386/scsi/advansys.h>
-
-static void adv_scsi_cmd __P((struct scsi_xfer *xs));
-static void advminphys __P((struct buf *bp));
-static timeout_t
- adv_timeout;
-static int adv_qdone __P((struct adv_softc *adv));
-static void adv_done __P((struct adv_softc *adv,
- struct adv_q_done_info *qdonep));
-static int adv_poll __P((struct adv_softc *ahc, struct scsi_xfer *xs));
-
-struct adv_softc *advsoftcs[NADV]; /* XXX Config should handle this */
-
-static struct scsi_adapter adv_switch =
-{
- adv_scsi_cmd,
- advminphys,
- NULL,
- NULL,
- "adv"
-};
-
-static void
-adv_scsi_cmd(xs)
- struct scsi_xfer *xs;
-{
- struct adv_softc *adv;
- struct adv_scsi_q scsiq;
- struct adv_sg_head sghead;
-
- SC_DEBUG(xs->sc_link, SDEV_DB2, ("adv_scsi_cmd\n"));
-
- adv = (struct adv_softc *)xs->sc_link->scsibus->adpt_link.adpt_softc;
-
- /*
- * Build up the request
- */
- scsiq.q1.cntl = 0;
- scsiq.q1.sg_queue_cnt = 0;
- scsiq.q1.status = 0;
- scsiq.q1.q_no = 0;
- scsiq.q1.target_id = ADV_TID_TO_TARGET_ID(xs->sc_link->target);
- scsiq.q1.target_lun = xs->sc_link->lun;
- scsiq.q1.sense_addr = (u_int32_t)vtophys(&xs->sense);
- scsiq.q1.sense_len = sizeof(xs->sense);
- scsiq.q1.data_cnt = 0;
- scsiq.q1.data_addr = 0;
- scsiq.q1.user_def = 0;
- scsiq.q2.xs_ptr = (u_int32_t)xs;
- scsiq.q2.target_ix = ADV_TIDLUN_TO_IX(xs->sc_link->target, xs->sc_link->lun);
- scsiq.q2.flag = 0;
- scsiq.q2.cdb_len = xs->cmdlen;
- scsiq.q2.tag_code = xs->tag_type;
- scsiq.q2.vm_id = 0;
- scsiq.sg_head = NULL;
- scsiq.cdbptr = &xs->cmd;
-
- if (xs->datalen) {
- /*
- * Determin the number of segments needed for this
- * transfer. We should only use SG if we need more
- * than one.
- */
- int seg;
- u_int32_t datalen;
- vm_offset_t vaddr;
- u_int32_t paddr;
- u_int32_t nextpaddr;
- struct adv_sg_entry *sg;
-
- seg = 0;
- datalen = xs->datalen;
- vaddr = (vm_offset_t)xs->data;
- paddr = vtophys(vaddr);
- sg = &sghead.sg_list[0];
-
- while ((datalen > 0) && (seg < ADV_MAX_SG_LIST)) {
- /* put in the base address and length */
- sg->addr = paddr;
- sg->bytes = 0;
-
- /* do it at least once */
- nextpaddr = paddr;
-
- while ((datalen > 0) && (paddr == nextpaddr)) {
- u_int32_t size;
- /*
- * This page is contiguous (physically)
- * with the the last, just extend the
- * length
- */
- /* how far to the end of the page */
- nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE;
-
- /*
- * Compute the maximum size
- */
- size = nextpaddr - paddr;
- if (size > datalen)
- size = datalen;
-
- sg->bytes += size;
- vaddr += size;
- datalen -= size;
- if (datalen > 0)
- paddr = vtophys(vaddr);
- }
- /*
- * next page isn't contiguous, finish the seg
- */
- seg++;
- sg++;
- }
- if (seg > 1) {
- scsiq.q1.cntl |= QC_SG_HEAD;
- scsiq.sg_head = &sghead;
- sghead.entry_cnt = sghead.entry_to_copy = seg;
- sghead.res = 0;
- }
- scsiq.q1.data_addr = sghead.sg_list[0].addr;
- scsiq.q1.data_cnt = sghead.sg_list[0].bytes;
- }
-
- if (adv_execute_scsi_queue(adv, &scsiq) != 0) {
- xs->error = XS_QUEUE_RESOURCE_SHORTAGE;
- scsi_done(xs);
- } else if ((xs->flags & SCSI_POLL) != 0) {
- /*
- * If we can't use interrupts, poll for completion
- */
- int s;
-
- s = splbio();
- if (adv_poll(adv, xs)) {
- if (!(xs->flags & SCSI_SILENT))
- printf("cmd fail\n");
- adv_timeout(xs);
- }
- splx(s);
- }
-}
-
-
-static void
-advminphys(bp)
- struct buf *bp;
-{
- if (bp->b_bcount > ((ADV_MAX_SG_LIST - 1) * PAGE_SIZE))
- bp->b_bcount = ((ADV_MAX_SG_LIST - 1) * PAGE_SIZE);
-}
-
-static void
-adv_timeout(arg)
- void *arg;
-{
- printf("adv: Ooops. Had a timeout\n");
-}
-
-struct adv_softc *
-adv_alloc(unit, iobase)
- int unit;
- u_long iobase;
-{
- struct adv_softc *adv;
- int i;
-
- if (unit >= NADV) {
- printf("adv: unit number (%d) too high\n", unit);
- return NULL;
- }
-
- /*
- * Allocate a storage area for us
- */
- if (advsoftcs[unit]) {
- printf("adv%d: memory already allocated\n", unit);
- return NULL;
- }
-
- adv = malloc(sizeof(struct adv_softc), M_DEVBUF, M_NOWAIT);
- if (!adv) {
- printf("adv%d: cannot malloc!\n", unit);
- return NULL;
- }
- bzero(adv, sizeof(struct adv_softc));
- advsoftcs[unit] = adv;
- adv->unit = unit;
- adv->iobase = iobase;
-
- /* Set reasonable defaults incase we can't read the EEPROM */
- adv->max_openings = ADV_DEF_MAX_TOTAL_QNG;
- adv->start_motor = TARGET_BIT_VECTOR_SET;
- adv->disc_enable = TARGET_BIT_VECTOR_SET;
- adv->cmd_qng_enabled = TARGET_BIT_VECTOR_SET;
- adv->scsi_id = 7;
-
- for (i = 0; i <= ADV_MAX_TID; i++)
- adv->sdtr_data[i] = ADV_DEF_SDTR_OFFSET | (ADV_DEF_SDTR_INDEX << 4);
-
- return(adv);
-}
-
-void
-adv_free(adv)
- struct adv_softc *adv;
-{
- if (adv->sense_buffers != NULL)
- free(adv->sense_buffers, M_DEVBUF);
- free(adv, M_DEVBUF);
-}
-
-int
-adv_init(adv)
- struct adv_softc *adv;
-{
- struct adv_eeprom_config eeprom_config;
- int checksum, i;
- u_int16_t config_lsw;
- u_int16_t config_msw;
-
- adv_get_board_type(adv);
-
- /*
- * Stop script execution.
- */
- adv_write_lram_16(adv, ADV_HALTCODE_W, 0x00FE);
- adv_stop_execution(adv);
- adv_reset_chip_and_scsi_bus(adv);
- /*
- * The generic SCSI code does a minimum delay for us
- * already.
- */
- /* DELAY(3 * 1000 * 1000);*/ /* 3 Second Delay */
- if (adv_is_chip_halted(adv) == 0) {
- printf("adv%d: Unable to halt adapter. Initialization"
- "failed\n", adv->unit);
- return (1);
- }
- ADV_OUTW(adv, ADV_REG_PROG_COUNTER, ADV_MCODE_START_ADDR);
- if (ADV_INW(adv, ADV_REG_PROG_COUNTER) != ADV_MCODE_START_ADDR) {
- printf("adv%d: Unable to set program counter. Initialization"
- "failed\n", adv->unit);
- return (1);
- }
-
- config_lsw = ADV_INW(adv, ADV_CONFIG_LSW);
- config_msw = ADV_INW(adv, ADV_CONFIG_MSW);
-
-#if 0
- /* XXX Move to PCI probe code */
- if (adv->type & ADV_PCI) {
-#if CC_DISABLE_PCI_PARITY_INT
- config_msw &= 0xFFC0;
- ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw);
-#endif
-
- if (asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) {
- asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ADD_ONE_BYTE;
- }
- }
-#endif
- if ((config_msw & ADV_CFG_MSW_CLR_MASK) != 0) {
- config_msw &= (~(ADV_CFG_MSW_CLR_MASK));
- /*
- * XXX The Linux code flags this as an error,
- * but what should we report to the user???
- * It seems that clearing the config register
- * makes this error recoverable.
- */
- ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw);
- }
-
- /* Suck in the configuration from the EEProm */
- checksum = adv_get_eeprom_config(adv, &eeprom_config);
-
- eeprom_config.cfg_msw &= (~(ADV_CFG_MSW_CLR_MASK));
-
- if (ADV_INW(adv, ADV_CHIP_STATUS) & ADV_CSW_AUTO_CONFIG) {
- /*
- * XXX The Linux code sets a warning level for this
- * condition, yet nothing of meaning is printed to
- * the user. What does this mean???
- */
- if (adv->chip_version == 3) {
- if (eeprom_config.cfg_lsw != config_lsw) {
- /* XXX Yet another supposed Warning */
- eeprom_config.cfg_lsw =
- ADV_INW(adv, ADV_CONFIG_LSW);
- }
- if (eeprom_config.cfg_msw != config_msw) {
- /* XXX Yet another supposed Warning */
- eeprom_config.cfg_msw =
- ADV_INW(adv, ADV_CONFIG_MSW);
- }
- }
- }
- eeprom_config.cfg_lsw |= ADV_CFG_LSW_HOST_INT_ON;
- if (checksum == eeprom_config.chksum) {
- if (adv_test_external_lram(adv) == 0) {
- if (adv->type & ADV_PCI) {
- eeprom_config.cfg_msw |= 0x0800;
- config_msw |= 0x0800;
- ADV_OUTW(adv, ADV_CONFIG_MSW, config_msw);
- eeprom_config.max_total_qng = ADV_MAX_PCI_INRAM_TOTAL_QNG;
- eeprom_config.max_tag_qng = ADV_MAX_INRAM_TAG_QNG;
- }
- }
- /* XXX What about wide bussed cards?? */
- for (i = 0; i <= 7; i++)
- adv->sdtr_data[i] = eeprom_config.sdtr_data[i];
-
- /* Range/Sanity checking */
- if (eeprom_config.max_total_qng < ADV_MIN_TOTAL_QNG) {
- eeprom_config.max_total_qng = ADV_MIN_TOTAL_QNG;
- }
- if (eeprom_config.max_total_qng > ADV_MAX_TOTAL_QNG) {
- eeprom_config.max_total_qng = ADV_MAX_TOTAL_QNG;
- }
- if (eeprom_config.max_tag_qng > eeprom_config.max_total_qng) {
- eeprom_config.max_tag_qng = eeprom_config.max_total_qng;
- }
- if (eeprom_config.max_tag_qng < ADV_MIN_TAG_Q_PER_DVC) {
- eeprom_config.max_tag_qng = ADV_MIN_TAG_Q_PER_DVC;
- }
- adv->max_openings = eeprom_config.max_total_qng;
-
- if ((eeprom_config.use_cmd_qng & eeprom_config.disc_enable) !=
- eeprom_config.use_cmd_qng) {
- eeprom_config.disc_enable |= eeprom_config.use_cmd_qng;
- printf("adv:%d: WARNING! One or more targets with tagged "
- "queuing enabled have the disconnection priveledge "
- "disabled.\n"
- "adv:%d: Overriding disconnection settings to "
- "allow tagged queueing devices to disconnect.\n ",
- adv->unit, adv->unit);
- }
-#if 0
- /*
- * XXX We should range check our target ID
- * based on the width of our bus
- */
- EEPROM_SET_SCSIID(eeprom_config,
- EEPROM_SCSIID(eeprom_config) & ADV_MAX_TID);
-#endif
- adv->initiate_sdtr = eeprom_config.init_sdtr;
- adv->disc_enable = eeprom_config.disc_enable;
- adv->cmd_qng_enabled = eeprom_config.use_cmd_qng;
- adv->isa_dma_speed = EEPROM_DMA_SPEED(eeprom_config);
- adv->scsi_id = EEPROM_SCSIID(eeprom_config);
- adv->start_motor = eeprom_config.start_motor;
- adv->control = eeprom_config.cntl;
- adv->no_scam = eeprom_config.no_scam;
- } else {
- /*
- * Use the defaults that adv was initialized with.
- */
- /*
- * XXX Fixup EEPROM with default values???
- */
- printf("adv%d: Warning EEPROM Checksum mismatch. "
- "Using default device parameters\n", adv->unit);
- }
-
-#if 0
- /* XXX Do this in the PCI probe */
- if ((adv->btype & ADV_PCI) &&
- !(asc_dvc->dvc_cntl & ASC_CNTL_NO_PCI_FIX_ASYN_XFER)) {
- if ((asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_A) ||
- (asc_dvc->cfg->pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) {
- asc_dvc->pci_fix_asyn_xfer = ASC_ALL_DEVICE_BIT_SET;
- }
- }
-#endif
- if (adv_set_eeprom_config(adv, &eeprom_config) != 0)
- printf("adv:%d: WARNING! Failure writing to EEPROM.\n");
-
- /* Allocate space for our sense buffers */
- /* XXX this should really be done by the generic SCSI layer by ensuring
- * that all scsi_xfer structs are allocated below 16M if any controller
- * needs to bounce.
- */
- if (adv->type & ADV_ISA) {
- adv->sense_buffers = (struct scsi_sense_data *)contigmalloc(sizeof(struct scsi_sense_data) * adv->max_openings,
- M_DEVBUF, M_NOWAIT, 0ul, 0xfffffful, 1ul,
- 0x10000ul);
- if (adv->sense_buffers == NULL) {
- printf("adv%d: Unable to allocate sense buffer space.\n");
- return (1);
- }
-
- }
-
- if (adv_init_lram_and_mcode(adv))
- return (1);
-
- return (0);
-}
-
-void
-adv_intr(arg)
- void *arg;
-{
- struct adv_softc *adv;
- u_int16_t chipstat;
- u_int16_t saved_ram_addr;
- u_int8_t ctrl_reg;
- u_int8_t saved_ctrl_reg;
- int status;
- u_int8_t host_flag;
-
- adv = (struct adv_softc *)arg;
-
- ctrl_reg = ADV_INB(adv, ADV_CHIP_CTRL);
- saved_ctrl_reg = ctrl_reg & (~(ADV_CC_SCSI_RESET | ADV_CC_CHIP_RESET |
- ADV_CC_SINGLE_STEP | ADV_CC_DIAG | ADV_CC_TEST));
-
-
- if ((chipstat = ADV_INW(adv, ADV_CHIP_STATUS)) & ADV_CSW_INT_PENDING) {
-
- adv_ack_interrupt(adv);
-
- host_flag = adv_read_lram_8(adv, ADVV_HOST_FLAG_B);
- adv_write_lram_8(adv, ADVV_HOST_FLAG_B,
- host_flag | ADV_HOST_FLAG_IN_ISR);
- saved_ram_addr = ADV_INW(adv, ADV_LRAM_ADDR);
-
- if ((chipstat & ADV_CSW_HALTED)
- && (ctrl_reg & ADV_CC_SINGLE_STEP)) {
- adv_isr_chip_halted(adv);
- saved_ctrl_reg &= ~ADV_CC_HALT;
- } else {
- if ((adv->control & ADV_CNTL_INT_MULTI_Q) != 0) {
- while (((status = adv_qdone(adv)) & 0x01) != 0)
- ;
- } else {
- do {
- status = adv_qdone(adv);
- } while (status == 0x11);
- }
- }
- ADV_OUTW(adv, ADV_LRAM_ADDR, saved_ram_addr);
-#ifdef DIAGNOSTIC
- if (ADV_INW(adv, ADV_LRAM_ADDR) != saved_ram_addr)
- panic("adv_intr: Unable to set LRAM addr");
-#endif
- adv_write_lram_8(adv, ADVV_HOST_FLAG_B, host_flag);
- }
-
- ADV_OUTB(adv, ADV_CHIP_CTRL, saved_ctrl_reg);
-}
-
-int
-adv_qdone(adv)
- struct adv_softc *adv;
-{
- u_int8_t next_qp;
- u_int8_t i;
- u_int8_t n_q_used;
- u_int8_t sg_list_qp;
- u_int8_t sg_queue_cnt;
- u_int8_t done_q_tail;
- u_int8_t tid_no;
- target_bit_vector target_id;
- u_int16_t q_addr;
- u_int16_t sg_q_addr;
- struct adv_q_done_info scsiq_buf;
- struct adv_q_done_info *scsiq;
- int false_overrun;
- u_int8_t tag_code;
-
- n_q_used = 1;
- scsiq = &scsiq_buf;
- done_q_tail = adv_read_lram_16(adv, ADVV_DONE_Q_TAIL_W) & 0xFF;
- q_addr = ADV_QNO_TO_QADDR(done_q_tail);
- next_qp = adv_read_lram_8(adv, q_addr + ADV_SCSIQ_B_FWD);
- if (next_qp != ADV_QLINK_END) {
- adv_write_lram_16(adv, ADVV_DONE_Q_TAIL_W, next_qp);
- q_addr = ADV_QNO_TO_QADDR(next_qp);
-
- sg_queue_cnt = adv_copy_lram_doneq(adv, q_addr, scsiq, adv->max_dma_count);
-
- adv_write_lram_8(adv, q_addr + ADV_SCSIQ_B_STATUS,
- scsiq->q_status & ~(QS_READY | QS_ABORTED));
- tid_no = ADV_TIX_TO_TID(scsiq->d2.target_ix);
- target_id = ADV_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
- if ((scsiq->cntl & QC_SG_HEAD) != 0) {
- sg_q_addr = q_addr;
- sg_list_qp = next_qp;
- for (i = 0; i < sg_queue_cnt; i++) {
- sg_list_qp = adv_read_lram_8(adv,
- sg_q_addr + ADV_SCSIQ_B_FWD);
- sg_q_addr = ADV_QNO_TO_QADDR(sg_list_qp);
-#ifdef DIAGNOSTIC
- if (sg_list_qp == ASC_QLINK_END) {
- panic("adv_qdone: Corrupted SG list encountered");
- }
-#endif
- adv_write_lram_8(adv, sg_q_addr + ADV_SCSIQ_B_STATUS,
- QS_FREE);
- }
-
- n_q_used = sg_queue_cnt + 1;
- adv_write_lram_16(adv, ADVV_DONE_Q_TAIL_W, sg_list_qp);
- }
-#if 0
- /* XXX Fix later */
- if (adv->queue_full_or_busy & target_id) {
- cur_target_qng = adv_read_lram_8(adv,
- ADV_QADR_BEG + scsiq->d2.target_ix);
- if (cur_target_qng < adv->max_dvc_qng[tid_no]) {
- scsi_busy = adv_read_lram_8(adv, ADVV_SCSIBUSY_B);
- scsi_busy &= ~target_id;
- adv_write_lram_8(adv, ADVV_SCSIBUSY_B, scsi_busy);
- adv->queue_full_or_busy &= ~target_id;
- }
- }
-#endif
-#ifdef DIAGNOSTIC
- if (adv->cur_total_qng < n_q_used)
- panic("adv_qdone: Attempting to free more queues than are active");
-#endif
- adv->cur_active -= n_q_used;
-
- if ((scsiq->d2.xs_ptr == 0) ||
- ((scsiq->q_status & QS_ABORTED) != 0))
- return (0x11);
- else if (scsiq->q_status == QS_DONE) {
-
- false_overrun = FALSE;
-
- if (adv->bug_fix_control & ADV_BUG_FIX_ADD_ONE_BYTE) {
- tag_code = adv_read_lram_8(adv, q_addr + ADV_SCSIQ_B_TAG_CODE);
- if (tag_code & ADV_TAG_FLAG_ADD_ONE_BYTE) {
- if (scsiq->remain_bytes != 0) {
- scsiq->remain_bytes--;
- if (scsiq->remain_bytes == 0)
- false_overrun = TRUE;
- }
- }
- }
- if ((scsiq->d3.done_stat == QD_WITH_ERROR) &&
- (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN)) {
- if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) {
- scsiq->d3.done_stat = QD_NO_ERROR;
- scsiq->d3.host_stat = QHSTA_NO_ERROR;
- } else if (false_overrun) {
- scsiq->d3.done_stat = QD_NO_ERROR;
- scsiq->d3.host_stat = QHSTA_NO_ERROR;
- }
- }
-
- if ((scsiq->cntl & QC_NO_CALLBACK) == 0)
- adv_done(adv, scsiq);
- else {
- if ((adv_read_lram_8(adv, q_addr + ADV_SCSIQ_CDB_BEG) ==
- START_STOP)) {
- adv->unit_not_ready &= ~target_id;
- if (scsiq->d3.done_stat != QD_NO_ERROR)
- adv->start_motor &= ~target_id;
- }
- }
- return (1);
- } else {
- panic("adv_qdone: completed scsiq with unknown status");
-#if 0
- /*
- * XXX Doesn't this simply indicate a software bug?
- * What does setting the lram error code do for
- * you. Would we even recover?
- */
- AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
-
- FATAL_ERR_QDONE:
- if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
- (*asc_isr_callback) (asc_dvc, scsiq);
- }
- return (0x80);
-#endif
- }
- }
- return (0);
-}
-
-
-void
-adv_done(adv, qdonep)
- struct adv_softc *adv;
- struct adv_q_done_info *qdonep;
-{
- struct scsi_xfer *xs;
-
- xs = (struct scsi_xfer *)qdonep->d2.xs_ptr;
-
- xs->status = qdonep->d3.scsi_stat;
- /*
- * 'qdonep' contains the command's ending status.
- */
- switch (qdonep->d3.done_stat) {
- case QD_NO_ERROR:
- switch (qdonep->d3.host_stat) {
- case QHSTA_NO_ERROR:
- break;
- case QHSTA_M_SEL_TIMEOUT:
- xs->error = XS_SELTIMEOUT;
- break;
- default:
- /* QHSTA error occurred */
-#if 0
- /* XXX Can I get more explicit information here? */
- xs->error = XS_DRIVER_STUFFUP;
-#endif
- break;
- }
- break;
-
- case QD_WITH_ERROR:
- switch (qdonep->d3.host_stat) {
- case QHSTA_NO_ERROR:
- if ((qdonep->d3.scsi_stat == STATUS_CHECK_CONDITION)
- || (qdonep->d3.scsi_stat == STATUS_COMMAND_TERMINATED)) {
- /* We have valid sense information to return */
- xs->error = XS_SENSE;
- if (adv->sense_buffers != NULL)
- /* Structure copy */
- xs->sense = adv->sense_buffers[qdonep->q_no];
- }
- break;
- case QHSTA_M_SEL_TIMEOUT:
- xs->error = XS_SELTIMEOUT;
- break;
- default:
-#if 0
- /* XXX Can I get more explicit information here? */
- xs->error = XS_DRIVER_STUFFUP;
-#endif
- break;
- }
- break;
-
- case QD_ABORTED_BY_HOST:
- /* XXX Should have an explicit ABORTED error code */
- xs->error = XS_ABORTED;
- break;
-
- default:
-#if 0
- printf("adv_done: Unknown done status 0x%x\n",
- qdonep->d3.done_stat);
- xs->error = XS_DRIVER_STUFFUP;
-#endif
- break;
- }
- xs->flags |= SCSI_ITSDONE;
- scsi_done(xs);
- return;
-}
-
-/*
- * Function to poll for command completion when
- * interrupts are disabled (crash dumps)
- */
-static int
-adv_poll(adv, xs)
- struct adv_softc *adv;
- struct scsi_xfer *xs;
-{
- int wait;
-
- wait = xs->timeout;
- do {
- DELAY(1000);
- adv_intr((void *)adv);
- } while (--wait && ((xs->flags & SCSI_ITSDONE) == 0));
- if (wait == 0) {
- printf("adv%d: board is not responding\n", adv->unit);
- return (EIO);
- }
- return (0);
-}
-
-/*
- * Attach all the sub-devices we can find
- */
-int
-adv_attach(adv)
- struct adv_softc *adv;
-{
- struct scsi_bus *scbus;
- struct scsi_queue *scsiq;
-
- scsiq = scsi_alloc_queue(adv->max_openings);
- if (scsiq == NULL)
- return 0;
-
- /*
- * Prepare the scsi_bus area for the upperlevel scsi code.
- */
- scbus = scsi_alloc_bus(&adv_switch, adv, adv->unit, scsiq);
- if (scbus == NULL) {
- scsi_free_queue(scsiq);
- return 0;
- }
-
- /* Override defaults */
- if ((adv->type & ADV_ISA) != 0)
- scbus->adpt_link.adpt_flags |= SADPT_BOUNCE;
- scbus->adpt_link.adpt_target = adv->scsi_id;
- scbus->adpt_link.adpt_openings = 2; /* XXX Is this correct for these cards? */
- scbus->adpt_link.adpt_tagged_openings = adv->max_openings;
-
- /*
- * ask the adapter what subunits are present
- */
- if(bootverbose)
- printf("adv%d: Probing SCSI bus\n", adv->unit);
-
- scsi_attachdevs(scbus);
-
- return 1;
-}
diff --git a/sys/i386/scsi/advansys.h b/sys/i386/scsi/advansys.h
deleted file mode 100644
index 47bca6a..0000000
--- a/sys/i386/scsi/advansys.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Generic driver for the Advanced Systems Inc. SCSI controllers
- * Product specific probe and attach routines can be found in:
- *
- * XXX Fill this in.
- *
- * Copyright (c) 1996 Justin T. Gibbs.
- * 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 immediately at the beginning of the file, without modification,
- * 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. 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 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 AUTHOR 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$
- */
-
-#ifndef _ADVANSYS_H_
-#define _ADVANSYS_H_
-
-#include "adv.h"
-#include <dev/advansys/advlib.h>
-
-struct adv_softc * adv_alloc __P((int unit, u_long iobase));
-void adv_free __P((struct adv_softc *adv));
-int adv_init __P((struct adv_softc *adv));
-void adv_intr __P((void *arg));
-int adv_attach __P((struct adv_softc *adv));
-
-extern struct adv_softc *advsoftcs[NADV]; /* XXX Config should handle this */
-#endif /* _ADVANSYS_H_ */
diff --git a/sys/i386/scsi/aic7xxx.c b/sys/i386/scsi/aic7xxx.c
deleted file mode 100644
index 4ded5b5..0000000
--- a/sys/i386/scsi/aic7xxx.c
+++ /dev/null
@@ -1,3867 +0,0 @@
-/*
- * Generic driver for the aic7xxx based adaptec SCSI controllers
- * Product specific probe and attach routines can be found in:
- * i386/eisa/aic7770.c 27/284X and aic7770 motherboard controllers
- * pci/aic7870.c 3940, 2940, aic7880, aic7870, aic7860,
- * and aic7850 controllers
- *
- * Copyright (c) 1994-1997 Justin Gibbs.
- * 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,
- * without modification, immediately at the beginning of the file.
- * 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. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * Where this Software is combined with software released under the terms of
- * the GNU Public License ("GPL") and the terms of the GPL would require the
- * combined work to also be released under the terms of the GPL, the terms
- * and conditions of this License will apply in addition to those of the
- * GPL with the exception of any terms or conditions of this License that
- * conflict with, or are expressly prohibited by, the GPL.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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: aic7xxx.c,v 1.126 1997/09/27 19:38:27 gibbs Exp $
- */
-/*
- * TODO:
- * Implement Target Mode
- *
- * A few notes on features of the driver.
- *
- * SCB paging takes advantage of the fact that devices stay disconnected
- * from the bus a relatively long time and that while they're disconnected,
- * having the SCBs for these transactions down on the host adapter is of
- * little use. Instead of leaving this idle SCB down on the card we copy
- * it back up into kernel memory and reuse the SCB slot on the card to
- * schedule another transaction. This can be a real payoff when doing random
- * I/O to tagged queueing devices since there are more transactions active at
- * once for the device to sort for optimal seek reduction. The algorithm goes
- * like this...
- *
- * The sequencer maintains two lists of its hardware SCBs. The first is the
- * singly linked free list which tracks all SCBs that are not currently in
- * use. The second is the doubly linked disconnected list which holds the
- * SCBs of transactions that are in the disconnected state sorted most
- * recently disconnected first. When the kernel queues a transaction to
- * the card, a hardware SCB to "house" this transaction is retrieved from
- * either of these two lists. If the SCB came from the disconnected list,
- * a check is made to see if any data transfer or SCB linking (more on linking
- * in a bit) information has been changed since it was copied from the host
- * and if so, DMAs the SCB back up before it can be used. Once a hardware
- * SCB has been obtained, the SCB is DMAed from the host. Before any work
- * can begin on this SCB, the sequencer must ensure that either the SCB is
- * for a tagged transaction or the target is not already working on another
- * non-tagged transaction. If a conflict arises in the non-tagged case, the
- * sequencer finds the SCB for the active transactions and sets the SCB_LINKED
- * field in that SCB to this next SCB to execute. To facilitate finding
- * active non-tagged SCBs, the last four bytes of up to the first four hardware
- * SCBs serve as a storage area for the currently active SCB ID for each
- * target.
- *
- * When a device reconnects, a search is made of the hardware SCBs to find
- * the SCB for this transaction. If the search fails, a hardware SCB is
- * pulled from either the free or disconnected SCB list and the proper
- * SCB is DMAed from the host. If the SCB_ABORTED control bit is set
- * in the control byte of the SCB while it was disconnected, the sequencer
- * will send an abort or abort tag message to the target during the
- * reconnection and signal the kernel that the abort was successfull.
- *
- * When a command completes, a check for non-zero status and residuals is
- * made. If either of these conditions exists, the SCB is DMAed back up to
- * the host so that it can interpret this information. Additionally, in the
- * case of bad status, the sequencer generates a special interrupt and pauses
- * itself. This allows the host to setup a request sense command if it
- * chooses for this target synchronously with the error so that sense
- * information isn't lost.
- *
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#if defined(__NetBSD__)
-#include <sys/device.h>
-#include <machine/bus.h>
-#include <machine/intr.h>
-#endif /* defined(__NetBSD__) */
-
-#include <sys/malloc.h>
-#include <sys/buf.h>
-
-#include <scsi/scsi_message.h>
-#if defined(__NetBSD__)
-#include <scsi/scsi_debug.h>
-#endif
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-
-#if defined(__FreeBSD__)
-#include <machine/clock.h>
-#endif
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
-#if defined(__FreeBSD__)
-#include <i386/scsi/aic7xxx.h>
-#include <dev/aic7xxx/sequencer.h>
-#include <aic7xxx_reg.h>
-#include <aic7xxx_seq.h>
-#endif /* defined(__FreeBSD__) */
-
-#if defined(__NetBSD__)
-#include <dev/ic/aic7xxxreg.h>
-#include <dev/ic/aic7xxxvar.h>
-
-#define bootverbose 1
-
-#if DEBUGTARGET < 0 /* Negative numbers for disabling cause warnings */
-#define DEBUGTARGET 17
-#endif
-#endif /* defined(__NetBSD__) */
-
-#include <sys/kernel.h>
-
-#define MAX(a,b) (((a) > (b)) ? (a) : (b))
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-#define ALL_TARGETS -1
-#define ALL_LUNS -1
-#define ALL_CHANNELS '\0'
-
-#if defined(__FreeBSD__)
-u_long ahc_unit = 0;
-#endif
-
-#ifdef AHC_DEBUG
-static int ahc_debug = AHC_DEBUG;
-#endif
-
-#ifdef AHC_BROKEN_CACHE
-int ahc_broken_cache = 1;
-
-/*
- * "wbinvd" cause writing back whole cache (both CPU internal & external)
- * to memory, so that the instruction takes a lot of time.
- * This makes machine slow.
- */
-#define INVALIDATE_CACHE() __asm __volatile("wbinvd")
-#endif
-
-/**** bit definitions for SCSIDEF ****/
-#define HSCSIID 0x07 /* our SCSI ID */
-#define HWSCSIID 0x0f /* our SCSI ID if Wide Bus */
-
-static void ahcminphys __P((struct buf *bp));
-static int32_t ahc_scsi_cmd __P((struct scsi_xfer *xs));
-static void ahc_run_waiting_queue __P((struct ahc_softc *ahc));
-static struct scb *
- ahc_get_scb __P((struct ahc_softc *ahc, u_int32_t flags));
-static void ahc_free_scb __P((struct ahc_softc *ahc, struct scb *scb));
-static struct scb *
- ahc_alloc_scb __P((struct ahc_softc *ahc));
-static __inline void pause_sequencer __P((struct ahc_softc *ahc));
-static __inline void unpause_sequencer __P((struct ahc_softc *ahc,
- int unpause_always));
-static __inline void restart_sequencer __P((struct ahc_softc *ahc));
-
-#define AHC_BUSRESET_DELAY 1000 /* Reset delay in us */
-
-static struct scsi_adapter ahc_switch =
-{
- ahc_scsi_cmd,
- ahcminphys,
- NULL,
- NULL,
-#if defined(__FreeBSD__)
- NULL,
- "ahc",
- { 0, 0 }
-#endif
-};
-
-static struct scsi_device ahc_dev =
-{
- NULL, /* Use default error handler */
- NULL, /* have a queue, served by this */
- NULL, /* have no async handler */
- NULL, /* Use default 'done' routine */
-#if defined(__FreeBSD__)
- "ahc",
- 0,
- { 0, 0 }
-#endif
-};
-
-static __inline void
-pause_sequencer(ahc)
- struct ahc_softc *ahc;
-{
- ahc_outb(ahc, HCNTRL, ahc->pause);
-
- /*
- * Since the sequencer can disable pausing in a critical section, we
- * must loop until it actually stops.
- */
- while ((ahc_inb(ahc, HCNTRL) & PAUSE) == 0)
- ;
-}
-
-static __inline void
-unpause_sequencer(ahc, unpause_always)
- struct ahc_softc *ahc;
- int unpause_always;
-{
- if (unpause_always
- || (ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0)
- ahc_outb(ahc, HCNTRL, ahc->unpause);
-}
-
-/*
- * Restart the sequencer program from address zero
- */
-static __inline void
-restart_sequencer(ahc)
- struct ahc_softc *ahc;
-{
- pause_sequencer(ahc);
- ahc_outb(ahc, SEQCTL, SEQRESET|FASTMODE);
- unpause_sequencer(ahc, /*unpause_always*/TRUE);
-}
-
-#if defined(__FreeBSD__)
-#define IS_SCSIBUS_B(ahc, sc_link) \
- (((u_int32_t)((sc_link)->fordriver) & SELBUSB) != 0)
-#else /* NetBSD/OpenBSD */
-#define IS_SCSIBUS_B(ahc, sc_link) \
- ((sc_link)->scsibus == (ahc)->sc_link_b.scsibus)
-#endif
-
-#define SCB_TARGET(scb) \
- (((scb)->hscb->tcl & TID) >> 4)
-#define SCB_LUN(scb) \
- ((scb)->hscb->tcl & LID)
-#define SCB_IS_SCSIBUS_B(scb) \
- (((scb)->hscb->tcl & SELBUSB) != 0)
-
-static u_int8_t ahc_abort_wscb __P((struct ahc_softc *ahc, struct scb *scbp,
- u_int8_t scbpos, u_int8_t prev,
- u_int32_t xs_error));
-static void ahc_done __P((struct ahc_softc *ahc, struct scb *scbp));
-static void ahc_handle_seqint __P((struct ahc_softc *ahc, u_int8_t intstat));
-static void ahc_handle_scsiint __P((struct ahc_softc *ahc,
- u_int8_t intstat));
-static void ahc_handle_devreset __P((struct ahc_softc *ahc,
- int target, char channel));
-static void ahc_loadseq __P((struct ahc_softc *ahc));
-static struct patch *
- ahc_next_patch __P((struct patch *cur_patch, int options,
- int instrptr));
-static void ahc_download_instr(struct ahc_softc *ahc, int options,
- int instrptr, u_int8_t *dconsts);
-static int ahc_match_scb __P((struct scb *scb, int target, char channel,
- int lun, u_int8_t tag));
-static int ahc_poll __P((struct ahc_softc *ahc, int wait));
-#ifdef AHC_DEBUG
-static void ahc_print_scb __P((struct scb *scb));
-#endif
-static u_int8_t ahc_find_scb __P((struct ahc_softc *ahc, struct scb *scb));
-static int ahc_search_qinfifo __P((struct ahc_softc *ahc, int target,
- char channel, int lun, u_int8_t tag,
- u_int32_t flags, u_int32_t xs_error,
- int requeue));
-static int ahc_reset_channel __P((struct ahc_softc *ahc, char channel,
- u_int32_t xs_error, int initiate_reset));
-static int ahc_reset_device __P((struct ahc_softc *ahc, int target,
- char channel, int lun, u_int8_t tag,
- u_int32_t xs_error));
-static u_int8_t ahc_rem_scb_from_disc_list __P((struct ahc_softc *ahc,
- u_int8_t scbptr));
-static void ahc_add_curscb_to_free_list __P((struct ahc_softc *ahc));
-static void ahc_clear_intstat __P((struct ahc_softc *ahc));
-static void ahc_reset_current_bus __P((struct ahc_softc *ahc));
-static void ahc_run_done_queue __P((struct ahc_softc *ahc));
-static void ahc_untimeout_done_queue __P((struct ahc_softc *ahc));
-static void ahc_scsirate __P((struct ahc_softc* ahc, u_int8_t *scsirate,
- u_int8_t *period, u_int8_t *offset,
- char channel, int target));
-#if defined(__FreeBSD__)
-static timeout_t
- ahc_timeout;
-#elif defined(__NetBSD__)
-static void ahc_timeout __P((void *));
-#endif
-
-static u_int8_t ahc_index_busy_target __P((struct ahc_softc *ahc, int target,
- char channel, int unbusy));
-
-static void ahc_busy_target __P((struct ahc_softc *ahc, int target,
- char channel, u_int8_t scbid));
-
-static void ahc_construct_sdtr __P((struct ahc_softc *ahc, int start_byte,
- u_int8_t period, u_int8_t offset));
-
-static void ahc_construct_wdtr __P((struct ahc_softc *ahc, int start_byte,
- u_int8_t bus_width));
-
-static void ahc_calc_residual __P((struct scb *scb));
-
-#if defined(__FreeBSD__)
-
-char *ahc_name(ahc)
- struct ahc_softc *ahc;
-{
- static char name[10];
-
- sprintf(name, "ahc%d", ahc->unit);
- return (name);
-}
-
-#elif defined(__NetBSD__)
-struct cfdriver ahc_cd = {
- NULL, "ahc", DV_DULL
-};
-#endif
-
-#ifdef AHC_DEBUG
-static void
-ahc_print_scb(scb)
- struct scb *scb;
-{
- struct hardware_scb *hscb = scb->hscb;
-
- printf("scb:%p control:0x%x tcl:0x%x cmdlen:%d cmdpointer:0x%lx\n",
- scb,
- hscb->control,
- hscb->tcl,
- hscb->cmdlen,
- hscb->cmdpointer );
- printf(" datlen:%d data:0x%lx segs:0x%x segp:0x%lx\n",
- hscb->datalen,
- hscb->data,
- hscb->SG_segment_count,
- hscb->SG_list_pointer);
- printf(" sg_addr:%lx sg_len:%ld\n",
- hscb->ahc_dma[0].addr,
- hscb->ahc_dma[0].len);
-}
-
-#endif
-
-static struct {
- u_int8_t errno;
- char *errmesg;
-} hard_error[] = {
- { ILLHADDR, "Illegal Host Access" },
- { ILLSADDR, "Illegal Sequencer Address referrenced" },
- { ILLOPCODE, "Illegal Opcode in sequencer program" },
- { PARERR, "Sequencer Ram Parity Error" }
-};
-
-
-/*
- * Valid SCSIRATE values. (p. 3-17)
- * Provides a mapping of tranfer periods in ns to the proper value to
- * stick in the scsiscfr reg to use that transfer rate.
- */
-static struct {
- int sxfr;
- /* Rates in Ultra mode have bit 8 of sxfr set */
-#define ULTRA_SXFR 0x100
- u_int8_t period; /* Period to send to SCSI target */
- char *rate;
-} ahc_syncrates[] = {
- { 0x100, 12, "20.0" },
- { 0x110, 15, "16.0" },
- { 0x120, 18, "13.4" },
- { 0x000, 25, "10.0" },
- { 0x010, 31, "8.0" },
- { 0x020, 37, "6.67" },
- { 0x030, 43, "5.7" },
- { 0x040, 50, "5.0" },
- { 0x050, 56, "4.4" },
- { 0x060, 62, "4.0" },
- { 0x070, 68, "3.6" }
-};
-
-static int ahc_num_syncrates =
- sizeof(ahc_syncrates) / sizeof(ahc_syncrates[0]);
-
-/*
- * Allocate a controller structure for a new device and initialize it.
- */
-#if defined(__FreeBSD__)
-struct ahc_softc *
-ahc_alloc(unit, iobase, maddr, type, flags, scb_data)
- int unit;
- u_int32_t iobase;
-#elif defined(__NetBSD__)
-void
-ahc_construct(ahc, bc, ioh, maddr, type, flags)
- struct ahc_softc *ahc;
- bus_chipset_tag_t bc;
- bus_io_handle_t ioh;
-#endif
- vm_offset_t maddr;
- ahc_type type;
- ahc_flag flags;
- struct scb_data *scb_data;
-{
- /*
- * find unit and check we have that many defined
- */
-#if defined(__FreeBSD__)
- struct ahc_softc *ahc;
- size_t alloc_size;
-
- /*
- * Allocate a storage area for us
- */
- if (scb_data == NULL)
- /*
- * We are not sharing SCB space with another controller
- * so allocate our own SCB data space.
- */
- alloc_size = sizeof(struct full_ahc_softc);
- else
- alloc_size = sizeof(struct ahc_softc);
- ahc = malloc(alloc_size, M_DEVBUF, M_NOWAIT);
- if (!ahc) {
- printf("ahc%d: cannot malloc!\n", unit);
- return NULL;
- }
- bzero(ahc, alloc_size);
-#endif
- if (scb_data == NULL) {
- struct full_ahc_softc* full_softc = (struct full_ahc_softc*)ahc;
- ahc->scb_data = &full_softc->scb_data_storage;
- STAILQ_INIT(&ahc->scb_data->free_scbs);
- } else
- ahc->scb_data = scb_data;
- STAILQ_INIT(&ahc->waiting_scbs);
- STAILQ_INIT(&ahc->cmplete_scbs);
-#if defined(__FreeBSD__)
- ahc->unit = unit;
-#endif
-#if defined(__FreeBSD__)
- ahc->baseport = iobase;
-#elif defined(__NetBSD__)
- ahc->sc_bc = bc;
- ahc->sc_ioh = ioh;
-#endif
- ahc->maddr = (volatile u_int8_t *)maddr;
- ahc->type = type;
- ahc->flags = flags;
- ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS) | INTEN;
- ahc->pause = ahc->unpause | PAUSE;
-
-#if defined(__FreeBSD__)
- return (ahc);
-#endif
-}
-
-void
-ahc_free(ahc)
- struct ahc_softc *ahc;
-{
-#if defined(__FreeBSD__)
- free(ahc, M_DEVBUF);
- return;
-#endif
-}
-
-void
-ahc_reset(ahc)
- struct ahc_softc *ahc;
-{
- u_int8_t hcntrl;
- int wait;
-
- /* Retain the IRQ type accross the chip reset */
- hcntrl = (ahc_inb(ahc, HCNTRL) & IRQMS) | INTEN;
-
- ahc_outb(ahc, HCNTRL, CHIPRST | PAUSE);
- /*
- * Ensure that the reset has finished
- */
- wait = 1000;
- while (--wait && !(ahc_inb(ahc, HCNTRL) & CHIPRSTACK))
- DELAY(1000);
- if (wait == 0) {
- printf("%s: WARNING - Failed chip reset! "
- "Trying to initialize anyway.\n", ahc_name(ahc));
- }
- ahc_outb(ahc, HCNTRL, hcntrl | PAUSE);
-}
-
-/*
- * Look up the valid period to SCSIRATE conversion in our table.
- */
-static void
-ahc_scsirate(ahc, scsirate, period, offset, channel, target )
- struct ahc_softc *ahc;
- u_int8_t *scsirate;
- u_int8_t *period;
- u_int8_t *offset;
- char channel;
- int target;
-{
- int i;
- u_int32_t ultra_enb_addr;
- u_int8_t sxfrctl0;
- u_int8_t ultra_enb;
-
- i = ahc_num_syncrates; /* Default to async */
-
- if (*period >= ahc_syncrates[0].period && *offset != 0) {
- for (i = 0; i < ahc_num_syncrates; i++) {
-
- if (*period <= ahc_syncrates[i].period) {
- /*
- * Watch out for Ultra speeds when ultra is not
- * enabled and vice-versa.
- */
- if (!(ahc->type & AHC_ULTRA)
- && (ahc_syncrates[i].sxfr & ULTRA_SXFR)) {
- /*
- * This should only happen if the
- * drive is the first to negotiate
- * and chooses a high rate. We'll
- * just move down the table util
- * we hit a non ultra speed.
- */
- continue;
- }
- *scsirate = (ahc_syncrates[i].sxfr & 0xF0)
- | (*offset & 0x0f);
- *period = ahc_syncrates[i].period;
-
- if (bootverbose) {
- printf("%s: target %d synchronous at "
- "%sMHz, offset = 0x%x\n",
- ahc_name(ahc), target,
- ahc_syncrates[i].rate, *offset );
- }
- break;
- }
- }
- }
- if (i >= ahc_num_syncrates) {
- /* Use asynchronous transfers. */
- *scsirate = 0;
- *period = 0;
- *offset = 0;
- if (bootverbose)
- printf("%s: target %d using asynchronous transfers\n",
- ahc_name(ahc), target );
- }
- /*
- * Ensure Ultra mode is set properly for
- * this target.
- */
- ultra_enb_addr = ULTRA_ENB;
- if (channel == 'B' || target > 7)
- ultra_enb_addr++;
- ultra_enb = ahc_inb(ahc, ultra_enb_addr);
- sxfrctl0 = ahc_inb(ahc, SXFRCTL0);
- if (*scsirate != 0 && (ahc_syncrates[i].sxfr & ULTRA_SXFR)) {
- ultra_enb |= 0x01 << (target & 0x07);
- sxfrctl0 |= FAST20;
- } else {
- ultra_enb &= ~(0x01 << (target & 0x07));
- sxfrctl0 &= ~FAST20;
- }
- ahc_outb(ahc, ultra_enb_addr, ultra_enb);
- ahc_outb(ahc, SXFRCTL0, sxfrctl0);
-}
-
-#if defined(__NetBSD__)
-int
-ahcprint(aux, name)
- void *aux;
- char *name;
-{
- if (name != NULL)
- printf("%s: scsibus ", name);
- return UNCONF;
-}
-#endif
-
-
-/*
- * Attach all the sub-devices we can find
- */
-int
-ahc_attach(ahc)
- struct ahc_softc *ahc;
-{
- struct scsibus_data *scbus;
-
-#ifdef AHC_BROKEN_CACHE
- if (cpu_class == CPUCLASS_386) /* doesn't have "wbinvd" instruction */
- ahc_broken_cache = 0;
-#endif
- /*
- * fill in the prototype scsi_links.
- */
-#if defined(__FreeBSD__)
- ahc->sc_link.adapter_unit = ahc->unit;
- ahc->sc_link.adapter_targ = ahc->our_id;
- ahc->sc_link.fordriver = 0;
-#elif defined(__NetBSD__)
- ahc->sc_link.adapter_target = ahc->our_id;
-#endif
- ahc->sc_link.adapter_softc = ahc;
- ahc->sc_link.adapter = &ahc_switch;
- ahc->sc_link.opennings = 2;
- ahc->sc_link.device = &ahc_dev;
- ahc->sc_link.flags = DEBUGLEVEL;
-
- if (ahc->type & AHC_TWIN) {
- /* Configure the second scsi bus */
- ahc->sc_link_b = ahc->sc_link;
-#if defined(__FreeBSD__)
- ahc->sc_link_b.adapter_targ = ahc->our_id_b;
- ahc->sc_link_b.adapter_bus = 1;
- ahc->sc_link_b.fordriver = (void *)SELBUSB;
-#elif defined(__NetBSD__)
- ahc->sc_link_b.adapter_target = ahc->our_id_b;
-#endif
- }
-
-
-#if defined(__FreeBSD__)
- /*
- * Prepare the scsibus_data area for the upperlevel
- * scsi code.
- */
- scbus = scsi_alloc_bus();
- if(!scbus)
- return 0;
- scbus->adapter_link = (ahc->flags & AHC_CHANNEL_B_PRIMARY) ?
- &ahc->sc_link_b : &ahc->sc_link;
- if (ahc->type & AHC_WIDE)
- scbus->maxtarg = 15;
-
- /*
- * ask the adapter what subunits are present
- */
- if (bootverbose)
- printf("ahc%d: Probing channel %c\n", ahc->unit,
- (ahc->flags & AHC_CHANNEL_B_PRIMARY) ? 'B' : 'A');
- scsi_attachdevs(scbus);
- scbus = NULL; /* Upper-level SCSI code owns this now */
-
- if (ahc->type & AHC_TWIN) {
- scbus = scsi_alloc_bus();
- if (!scbus)
- return 0;
- scbus->adapter_link = (ahc->flags & AHC_CHANNEL_B_PRIMARY) ?
- &ahc->sc_link : &ahc->sc_link_b;
- if (ahc->type & AHC_WIDE)
- scbus->maxtarg = 15;
- if (bootverbose)
- printf("ahc%d: Probing Channel %c\n", ahc->unit,
- (ahc->flags & AHC_CHANNEL_B_PRIMARY) ? 'A': 'B');
- scsi_attachdevs(scbus);
- scbus = NULL; /* Upper-level SCSI code owns this now */
- }
-#elif defined(__NetBSD__)
- /*
- * XXX - Update MI SCSI code
- *
- * if(ahc->type & AHC_WIDE)
- * max target of both channel A and B = 15;
- */
-
- /*
- * ask the adapter what subunits are present
- */
- if ((ahc->flags & AHC_CHANNEL_B_PRIMARY) == 0) {
- /* make IS_SCSIBUS_B() == false, while probing channel A */
- ahc->sc_link_b.scsibus = 0xff;
-
- if (ahc->type & AHC_TWIN)
- printf("%s: Probing channel A\n", ahc_name(ahc));
- config_found((void *)ahc, &ahc->sc_link, ahcprint);
- if (ahc->type & AHC_TWIN) {
- printf("%s: Probing channel B\n", ahc_name(ahc));
- config_found((void *)ahc, &ahc->sc_link_b, ahcprint);
- }
- } else {
- /*
- * if implementation of IS_SCSIBUS_B() is changed to use
- * ahc->sc_link.scsibus, then "ahc->sc_link.scsibus = 0xff;"
- * is needed, here.
- */
-
- /* assert(ahc->type & AHC_TWIN); */
- printf("%s: Probing channel B\n", ahc_name(ahc));
- config_found((void *)ahc, &ahc->sc_link_b, ahcprint);
- printf("%s: Probing channel A\n", ahc_name(ahc));
- config_found((void *)ahc, &ahc->sc_link, ahcprint);
- }
-#endif
- return 1;
-}
-
-/*
- * Catch an interrupt from the adapter
- */
-#if defined(__FreeBSD__)
-void
-#elif defined (__NetBSD__)
-int
-#endif
-ahc_intr(arg)
- void *arg;
-{
- struct ahc_softc *ahc;
- u_int8_t intstat;
-
- ahc = (struct ahc_softc *)arg;
- intstat = ahc_inb(ahc, INTSTAT);
- /*
- * Is this interrupt for me? or for
- * someone who is sharing my interrupt?
- */
- if (!(intstat & INT_PEND))
-#if defined(__FreeBSD__)
- return;
-#elif defined(__NetBSD__)
- return 0;
-#endif
-
- if (intstat & CMDCMPLT) {
- struct scb *scb;
- u_int8_t scb_index;
- u_int8_t qoutcnt;
- int int_cleared;
-
- int_cleared = 0;
- while ((qoutcnt = (ahc_inb(ahc, QOUTCNT) & ahc->qcntmask)) != 0) {
- ahc->cmdoutcnt += qoutcnt;
- for (; qoutcnt > 0; qoutcnt--) {
- scb_index = ahc_inb(ahc, QOUTFIFO);
- scb = ahc->scb_data->scbarray[scb_index];
- if (!scb || !(scb->flags & SCB_ACTIVE)) {
- printf("%s: WARNING "
- "no command for scb %d "
- "(cmdcmplt)\nQOUTCNT == %d\n",
- ahc_name(ahc), scb_index,
- qoutcnt);
- continue;
- }
- STAILQ_INSERT_TAIL(&ahc->cmplete_scbs, scb,
- links);
- }
- if ((ahc->flags & AHC_PAGESCBS) != 0) {
- if (ahc->cmdoutcnt >= ahc->qfullcount) {
- /*
- * Since paging only occurs on
- * aic78X0 chips, we can use
- * Auto Access Pause to clear
- * the command count.
- */
- ahc_outb(ahc, CMDOUTCNT, 0);
- ahc->cmdoutcnt = 0;
- }
- }
- while((scb = ahc->cmplete_scbs.stqh_first) != NULL) {
- STAILQ_REMOVE_HEAD(&ahc->cmplete_scbs, links);
- /*
- * Save off the residual if there is one.
- */
- if (scb->hscb->residual_SG_segment_count != 0)
- ahc_calc_residual(scb);
- if ((scb->flags & SCB_QUEUED_ABORT) != 0) {
- /* Have to clean up any possible
- * entries in the waiting queue and
- * QINFIFO.
- */
- int target;
- char channel;
- int lun;
- u_int8_t tag;
-
- tag = SCB_LIST_NULL;
- target = scb->xs->sc_link->target;
- lun = scb->xs->sc_link->lun;
- channel = (scb->hscb->tcl & SELBUSB)
- ? 'B': 'A';
- if (scb->hscb->control & TAG_ENB)
- tag = scb->hscb->tag;
- ahc_reset_device(ahc,
- target,
- channel,
- lun,
- tag,
- scb->xs->error);
- ahc_run_done_queue(ahc);
- }
- ahc_done(ahc, scb);
- }
- ahc_outb(ahc, CLRINT, CLRCMDINT);
- int_cleared++;
- }
-
- if (int_cleared == 0)
- ahc_outb(ahc, CLRINT, CLRCMDINT);
- }
- if (intstat & BRKADRINT) {
- /*
- * We upset the sequencer :-(
- * Lookup the error message
- */
- int i, error, num_errors;
-
- error = ahc_inb(ahc, ERROR);
- num_errors = sizeof(hard_error)/sizeof(hard_error[0]);
- for (i = 0; error != 1 && i < num_errors; i++)
- error >>= 1;
- printf("%s: brkadrint, %s at seqaddr = 0x%x\n",
- ahc_name(ahc), hard_error[i].errmesg,
- (ahc_inb(ahc, SEQADDR1) << 8) |
- ahc_inb(ahc, SEQADDR0));
-
- ahc_reset_device(ahc, ALL_TARGETS, ALL_CHANNELS, ALL_LUNS,
- SCB_LIST_NULL, XS_DRIVER_STUFFUP);
- ahc_run_done_queue(ahc);
- }
- if (intstat & SEQINT)
- ahc_handle_seqint(ahc, intstat);
-
- if (intstat & SCSIINT)
- ahc_handle_scsiint(ahc, intstat);
-
- if (ahc->waiting_scbs.stqh_first != NULL)
- ahc_run_waiting_queue(ahc);
-#if defined(__NetBSD__)
- return 1;
-#endif
-}
-
-static void
-ahc_handle_seqint(ahc, intstat)
- struct ahc_softc *ahc;
- u_int8_t intstat;
-{
- struct scb *scb;
- u_int16_t targ_mask;
- u_int8_t target;
- int scratch_offset;
- char channel;
-
- if ((ahc_inb(ahc, SEQ_FLAGS) & RESELECTED) != 0)
- target = ahc_inb(ahc, SELID);
- else
- target = ahc_inb(ahc, SCSIID);
- target = (target >> 4) & 0x0f;
- scratch_offset = target;
- channel = ahc_inb(ahc, SBLKCTL) & SELBUSB ? 'B': 'A';
- if (channel == 'B')
- scratch_offset += 8;
- targ_mask = (0x01 << scratch_offset);
-
- switch (intstat & SEQINT_MASK) {
- case NO_MATCH:
- {
- /*
- * This could be for a normal abort request.
- * Figure out the SCB that we were trying to find
- * and only give an error if we didn't ask for this
- * to happen.
- */
- u_int8_t scb_index;
- u_int8_t busy_scbid;
- u_int8_t arg1;
-
- busy_scbid = ahc_index_busy_target(ahc, target, channel,
- /*unbusy*/FALSE);
- arg1 = ahc_inb(ahc, ARG_1);
-
- if (arg1 == SCB_LIST_NULL)
- /* Untagged Request */
- scb_index = busy_scbid;
- else
- scb_index = arg1;
-
- if (scb_index < ahc->scb_data->numscbs) {
- scb = ahc->scb_data->scbarray[scb_index];
-
- if (scb->hscb->control & ABORT_SCB) {
- /*
- * We expected this. Let the busfree
- * handler take care of this when we
- * the abort is finially sent.
- * Set IDENTIFY_SEEN so that the busfree
- * handler knows that there is an SCB to
- * cleanup.
- */
- ahc_outb(ahc, SEQ_FLAGS, ahc_inb(ahc, SEQ_FLAGS)
- | IDENTIFY_SEEN);
- sc_print_addr(scb->xs->sc_link);
- printf("reconnect SCB abort successfull\n");
- break;
- }
- }
-
- printf("%s:%c:%d: no active SCB for reconnecting "
- "target - issuing BUS DEVICE RESET\n",
- ahc_name(ahc), channel, target);
- printf("SAVED_TCL == 0x%x ARG_1 == 0x%x SEQADDR == 0x%x\n",
- ahc_inb(ahc, SAVED_TCL), arg1,
- (ahc_inb(ahc, SEQADDR1) << 8)
- | ahc_inb(ahc, SEQADDR0));
-
- ahc_handle_devreset(ahc, target, channel);
-
- break;
- }
- case NO_MATCH_BUSY:
- {
- /*
- * XXX Leave this as a panic for the time being since
- * it indicates a bug in the timeout code for this
- * to happen.
- */
- u_int8_t scb_index;
-
- scb_index = ahc_inb(ahc, CUR_SCBID);
- scb = ahc->scb_data->scbarray[scb_index];
-
- panic("%s:%c:%d: Target busy link failure.\n",
- ahc_name(ahc), (scb->hscb->tcl & SELBUSB) ? 'B' : 'A',
- scb->xs->sc_link->target);
- }
- case SEND_REJECT:
- {
- u_int8_t rejbyte = ahc_inb(ahc, ACCUM);
- printf("%s:%c:%d: Warning - unknown message received from "
- "target (0x%x). SEQ_FLAGS == 0x%x. Rejecting\n",
- ahc_name(ahc), channel, target, rejbyte,
- ahc_inb(ahc, SEQ_FLAGS));
- break;
- }
- case NO_IDENT:
- {
- /*
- * The reconnecting target either did not send an identify
- * message, or did, but we didn't find and SCB to match and
- * before it could respond to our ATN/abort, it hit a dataphase.
- * The only safe thing to do is to blow it away with a bus
- * reset.
- */
- int found;
-
- printf("%s:%c:%d: Target did not send an IDENTIFY message. "
- "LASTPHASE = 0x%x, SAVED_TCL == 0x%x\n",
- ahc_name(ahc), channel, target, ahc_inb(ahc, LASTPHASE),
- ahc_inb(ahc, SAVED_TCL));
- found = ahc_reset_channel(ahc, channel, XS_TIMEOUT,
- /*initiate reset*/TRUE);
- printf("%s: Issued Channel %c Bus Reset. "
- "%d SCBs aborted\n", ahc_name(ahc), channel, found);
- break;
- }
- case BAD_PHASE:
- if (ahc_inb(ahc, LASTPHASE) == P_BUSFREE) {
- printf("%s:%c:%d: Missed busfree.\n", ahc_name(ahc),
- channel, target);
- restart_sequencer(ahc);
- } else {
- printf("%s:%c:%d: unknown scsi bus phase. Attempting "
- "to continue\n", ahc_name(ahc), channel, target);
- }
- break;
- case EXTENDED_MSG:
- {
- u_int8_t message_length;
- u_int8_t message_code;
- u_int8_t scb_index;
-
- message_length = ahc_inb(ahc, MSGIN_EXT_LEN);
- message_code = ahc_inb(ahc, MSGIN_EXT_OPCODE);
- scb_index = ahc_inb(ahc, SCB_TAG);
- scb = ahc->scb_data->scbarray[scb_index];
- switch (message_code) {
- case MSG_EXT_SDTR:
- {
- u_int8_t period;
- u_int8_t offset;
- u_int8_t saved_offset;
- u_int8_t targ_scratch;
- u_int8_t maxoffset;
- u_int8_t rate;
-
- if (message_length != MSG_EXT_SDTR_LEN) {
- ahc_outb(ahc, RETURN_1, SEND_REJ);
- break;
- }
- period = ahc_inb(ahc, MSGIN_EXT_BYTES);
- saved_offset = ahc_inb(ahc, MSGIN_EXT_BYTES + 1);
- targ_scratch = ahc_inb(ahc, TARG_SCRATCH
- + scratch_offset);
- if (targ_scratch & WIDEXFER)
- maxoffset = MAX_OFFSET_16BIT;
- else
- maxoffset = MAX_OFFSET_8BIT;
- offset = MIN(saved_offset, maxoffset);
- ahc_scsirate(ahc, &rate, &period, &offset,
- channel, target);
- /* Preserve the WideXfer flag */
- targ_scratch = rate | (targ_scratch & WIDEXFER);
-
- /*
- * Update both the target scratch area and the
- * current SCSIRATE.
- */
- ahc_outb(ahc, TARG_SCRATCH + scratch_offset,
- targ_scratch);
- ahc_outb(ahc, SCSIRATE, targ_scratch);
-
- /*
- * See if we initiated Sync Negotiation
- * and didn't have to fall down to async
- * transfers.
- */
- if ((scb->flags & SCB_MSGOUT_SDTR) != 0) {
- /* We started it */
- if (saved_offset == offset) {
- /*
- * Don't send an SDTR back to
- * the target
- */
- ahc_outb(ahc, RETURN_1, 0);
- } else
- /* Went too low - force async */
- ahc_outb(ahc, RETURN_1, SEND_REJ);
- } else {
- /*
- * Send our own SDTR in reply
- */
- printf("Sending SDTR!!\n");
- ahc_construct_sdtr(ahc, /*start_byte*/0,
- period, offset);
- ahc_outb(ahc, RETURN_1, SEND_MSG);
- }
- ahc->needsdtr &= ~targ_mask;
- break;
- }
- case MSG_EXT_WDTR:
- {
- u_int8_t scratch, bus_width;
-
- if (message_length != MSG_EXT_WDTR_LEN) {
- ahc_outb(ahc, RETURN_1, SEND_REJ);
- break;
- }
-
- bus_width = ahc_inb(ahc, MSGIN_EXT_BYTES);
- scratch = ahc_inb(ahc, TARG_SCRATCH + scratch_offset);
-
- if ((scb->flags & SCB_MSGOUT_WDTR) != 0) {
- /*
- * Don't send a WDTR back to the
- * target, since we asked first.
- */
- ahc_outb(ahc, RETURN_1, 0);
- switch (bus_width){
- case BUS_8_BIT:
- scratch &= 0x7f;
- break;
- case BUS_16_BIT:
- if (bootverbose)
- printf("%s: target %d using "
- "16Bit transfers\n",
- ahc_name(ahc), target);
- scratch |= WIDEXFER;
- break;
- case BUS_32_BIT:
- /*
- * How can we do 32bit transfers
- * on a 16bit bus?
- */
- ahc_outb(ahc, RETURN_1, SEND_REJ);
- printf("%s: target %d requested 32Bit "
- "transfers. Rejecting...\n",
- ahc_name(ahc), target);
- break;
- default:
- break;
- }
- } else {
- /*
- * Send our own WDTR in reply
- */
- switch (bus_width) {
- case BUS_8_BIT:
- scratch &= 0x7f;
- break;
- case BUS_32_BIT:
- case BUS_16_BIT:
- if (ahc->type & AHC_WIDE) {
- /* Negotiate 16_BITS */
- bus_width = BUS_16_BIT;
- if (bootverbose)
- printf("%s: target %d "
- "using 16Bit "
- "transfers\n",
- ahc_name(ahc),
- target);
- scratch |= WIDEXFER;
- } else
- bus_width = BUS_8_BIT;
- break;
- default:
- break;
- }
- ahc_construct_wdtr(ahc, /*start_byte*/0,
- bus_width);
- ahc_outb(ahc, RETURN_1, SEND_MSG);
- }
- ahc->needwdtr &= ~targ_mask;
- ahc_outb(ahc, TARG_SCRATCH + scratch_offset, scratch);
- ahc_outb(ahc, SCSIRATE, scratch);
- break;
- }
- default:
- /* Unknown extended message. Reject it. */
- ahc_outb(ahc, RETURN_1, SEND_REJ);
- }
- break;
- }
- case REJECT_MSG:
- {
- /*
- * What we care about here is if we had an
- * outstanding SDTR or WDTR message for this
- * target. If we did, this is a signal that
- * the target is refusing negotiation.
- */
-
- u_int8_t targ_scratch;
- u_int8_t scb_index;
-
- scb_index = ahc_inb(ahc, SCB_TAG);
- scb = ahc->scb_data->scbarray[scb_index];
-
- targ_scratch = ahc_inb(ahc, TARG_SCRATCH
- + scratch_offset);
-
- if ((scb->flags & SCB_MSGOUT_WDTR) != 0) {
- /* note 8bit xfers and clear flag */
- targ_scratch &= 0x7f;
- ahc->needwdtr &= ~targ_mask;
- printf("%s:%c:%d: refuses WIDE negotiation. Using "
- "8bit transfers\n", ahc_name(ahc),
- channel, target);
- } else if ((scb->flags & SCB_MSGOUT_SDTR) != 0) {
- /* note asynch xfers and clear flag */
- targ_scratch &= 0xf0;
- ahc->needsdtr &= ~targ_mask;
- printf("%s:%c:%d: refuses synchronous negotiation. "
- "Using asynchronous transfers\n",
- ahc_name(ahc),
- channel, target);
- } else {
- /*
- * Otherwise, we ignore it.
- */
-#ifdef AHC_DEBUG
- if (ahc_debug & AHC_SHOWMISC)
- printf("%s:%c:%d: Message reject -- ignored\n",
- ahc_name(ahc), channel, target);
-#endif
- break;
- }
- ahc_outb(ahc, TARG_SCRATCH + scratch_offset, targ_scratch);
- ahc_outb(ahc, SCSIRATE, targ_scratch);
- break;
- }
- case BAD_STATUS:
- {
- u_int8_t scb_index;
- struct scsi_xfer *xs;
- struct hardware_scb *hscb;
-
- /*
- * The sequencer will notify us when a command
- * has an error that would be of interest to
- * the kernel. This allows us to leave the sequencer
- * running in the common case of command completes
- * without error. The sequencer will already have
- * dma'd the SCB back up to us, so we can reference
- * the in kernel copy directly.
- */
-
- scb_index = ahc_inb(ahc, SCB_TAG);
- scb = ahc->scb_data->scbarray[scb_index];
- hscb = scb->hscb;
-
- /*
- * Set the default return value to 0 (don't
- * send sense). The sense code will change
- * this if needed and this reduces code
- * duplication.
- */
- ahc_outb(ahc, RETURN_1, 0);
- if (!(scb && (scb->flags & SCB_ACTIVE))) {
- printf("%s:%c:%d: ahc_intr - referenced scb "
- "not valid during seqint 0x%x scb(%d)\n",
- ahc_name(ahc),
- channel, target, intstat,
- scb_index);
- goto clear;
- }
-
- xs = scb->xs;
-
- xs->status = hscb->status;
- switch (hscb->status){
- case SCSI_OK:
- printf("%s: Interrupted for staus of"
- " 0???\n", ahc_name(ahc));
- break;
- case SCSI_CHECK:
-#ifdef AHC_DEBUG
- if (ahc_debug & AHC_SHOWSENSE) {
- sc_print_addr(xs->sc_link);
- printf("SCB %d: requests Check Status\n",
- scb->hscb->tag);
- }
-#endif
-
- if ((xs->error == XS_NOERROR)
- && !(scb->flags & SCB_SENSE)) {
- struct ahc_dma_seg *sg = scb->ahc_dma;
- struct scsi_sense *sc = &(scb->sense_cmd);
-
- /*
- * Save off the residual if there is one.
- */
- if (hscb->residual_SG_segment_count != 0)
- ahc_calc_residual(scb);
-
-#ifdef AHC_DEBUG
- if (ahc_debug & AHC_SHOWSENSE) {
- sc_print_addr(xs->sc_link);
- printf("Sending Sense\n");
- }
-#endif
-#if defined(__FreeBSD__)
- sc->op_code = REQUEST_SENSE;
-#elif defined(__NetBSD__)
- sc->opcode = REQUEST_SENSE;
-#endif
- sc->byte2 = xs->sc_link->lun << 5;
- sc->length = sizeof(struct scsi_sense_data);
- sc->control = 0;
-
- sg->addr = vtophys(&xs->sense);
- sg->len = sizeof(struct scsi_sense_data);
-
- /* XXX should allow disconnection, but
- * can't as it might allow overlapped
- * tagged commands.
- */
- /* hscb->control &= DISCENB; */
- hscb->control = 0;
- hscb->status = 0;
- hscb->SG_segment_count = 1;
- hscb->SG_list_pointer = vtophys(sg);
- hscb->data = sg->addr;
- /* Maintain SCB_LINKED_NEXT */
- hscb->datalen &= 0xFF000000;
- hscb->datalen |= sg->len;
- hscb->cmdpointer = vtophys(sc);
- hscb->cmdlen = sizeof(*sc);
- scb->sg_count = hscb->SG_segment_count;
- scb->flags |= SCB_SENSE;
- /*
- * Ensure the target is busy since this
- * will be an untagged request.
- */
- ahc_busy_target(ahc, target, channel,
- hscb->tag);
- ahc_outb(ahc, RETURN_1, SEND_SENSE);
-
- /*
- * Ensure we have enough time to actually
- * retrieve the sense.
- */
- untimeout(ahc_timeout, (caddr_t)scb,
- scb->xs->timeout_ch);
- scb->xs->timeout_ch = timeout(ahc_timeout,
- (caddr_t)scb, hz);
- break;
- }
- /*
- * Clear the SCB_SENSE Flag and have
- * the sequencer do a normal command
- * complete with either a "DRIVER_STUFFUP"
- * error or whatever other error condition
- * we already had.
- */
- scb->flags &= ~SCB_SENSE;
- if (xs->error == XS_NOERROR)
- xs->error = XS_DRIVER_STUFFUP;
- break;
- case SCSI_QUEUE_FULL:
- if (scb->hscb->control & TAG_ENB) {
- /*
- * The upper level SCSI code in 3.0
- * handles this properly...
- */
- struct scsi_link *sc_link;
-
- sc_link = xs->sc_link;
- if (sc_link->active > 2
- && sc_link->opennings != 0) {
- /* truncate the opennings */
- sc_link->opennings = 0;
- sc_print_addr(sc_link);
- printf("Tagged openings reduced to "
- "%d\n", sc_link->active);
- }
- /*
- * XXX requeue this unconditionally.
- */
- scb->xs->retries++;
- scb->xs->error = XS_BUSY;
- break;
- }
- /* Else treat as if it is a BUSY condition */
- scb->hscb->status = SCSI_BUSY;
- /* Fall Through... */
- case SCSI_BUSY:
- xs->error = XS_BUSY;
- sc_print_addr(xs->sc_link);
- printf("Target Busy\n");
- break;
- case SCSI_RSVD:
- xs->error = XS_BUSY; /*XXX*/
- sc_print_addr(xs->sc_link);
- printf("Target Reserved\n");
- break;
- default:
- sc_print_addr(xs->sc_link);
- printf("unexpected targ_status: %x\n", hscb->status);
- xs->error = XS_DRIVER_STUFFUP;
- break;
- }
- break;
- }
- case AWAITING_MSG:
- {
- int scb_index;
- u_int8_t message_offset;
-
- scb_index = ahc_inb(ahc, SCB_TAG);
- scb = ahc->scb_data->scbarray[scb_index];
-
- /*
- * This SCB had MK_MESSAGE set in its control byte,
- * informing the sequencer that we wanted to send a
- * special message to this target.
- */
- message_offset = ahc_inb(ahc, MSG_LEN);
- if (scb->flags & SCB_DEVICE_RESET) {
- ahc_outb(ahc, MSG_OUT, MSG_BUS_DEV_RESET);
- ahc_outb(ahc, MSG_LEN, 1);
- sc_print_addr(scb->xs->sc_link);
- printf("Bus Device Reset Message Sent\n");
- } else if (scb->flags & SCB_ABORT) {
- if ((scb->hscb->control & TAG_ENB) != 0)
- ahc_outb(ahc, MSG_OUT + message_offset,
- MSG_ABORT_TAG);
- else
- ahc_outb(ahc, MSG_OUT + message_offset,
- MSG_ABORT);
- ahc_outb(ahc, MSG_LEN, message_offset + 1);
- sc_print_addr(scb->xs->sc_link);
- printf("Abort Message Sent\n");
- } else if (scb->flags & SCB_MSGOUT_WDTR) {
- ahc_construct_wdtr(ahc, message_offset, BUS_16_BIT);
- } else if (scb->flags & SCB_MSGOUT_SDTR) {
- int sxfr;
- int i;
- u_int16_t ultraenable;
- u_int8_t target_scratch;
-
- /* Pull the user defined setting */
- target_scratch = ahc_inb(ahc, TARG_SCRATCH
- + scratch_offset);
-
- sxfr = target_scratch & SXFR;
- ultraenable = ahc_inb(ahc, ULTRA_ENB)
- | (ahc_inb(ahc, ULTRA_ENB + 1) << 8);
-
- if (ultraenable & targ_mask)
- /* Want an ultra speed in the table */
- sxfr |= 0x100;
-
- for (i = 0; i < ahc_num_syncrates; i++)
- if (sxfr == ahc_syncrates[i].sxfr)
- break;
-
- ahc_construct_sdtr(ahc, message_offset,
- ahc_syncrates[i].period,
- (target_scratch & WIDEXFER) ?
- MAX_OFFSET_16BIT : MAX_OFFSET_8BIT);
- } else
- panic("ahc_intr: AWAITING_MSG for an SCB that "
- "does not have a waiting message");
- break;
- }
- case DATA_OVERRUN:
- {
- /*
- * When the sequencer detects an overrun, it
- * sets STCNT to 0x00ffffff and allows the
- * target to complete its transfer in
- * BITBUCKET mode.
- */
- u_int8_t scbindex = ahc_inb(ahc, SCB_TAG);
- u_int8_t lastphase = ahc_inb(ahc, LASTPHASE);
- u_int32_t overrun;
- int i;
- scb = ahc->scb_data->scbarray[scbindex];
- overrun = ahc_inb(ahc, STCNT)
- | (ahc_inb(ahc, STCNT + 1) << 8)
- | (ahc_inb(ahc, STCNT + 2) << 16);
- overrun = 0x00ffffff - overrun;
- sc_print_addr(scb->xs->sc_link);
- printf("data overrun of %d bytes detected in %s phase."
- " Tag == 0x%x. Forcing a retry.\n", overrun,
- lastphase == P_DATAIN ? "Data-In" : "Data-Out",
- scb->hscb->tag);
- sc_print_addr(scb->xs->sc_link);
- printf("%s seen Data Phase. Length = %d. NumSGs = %d.\n",
- ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't",
- scb->xs->datalen, scb->sg_count);
- for (i = 0; i < scb->sg_count; i++) {
- printf("sg[%d] - Addr 0x%x : Length %d\n",
- i,
- scb->ahc_dma[i].addr,
- scb->ahc_dma[i].len);
- }
- /*
- * Set this and it will take affect when the
- * target does a command complete.
- */
- scb->xs->error = XS_DRIVER_STUFFUP;
- break;
- }
-#if NOT_YET
- /* XXX Fill these in later */
- case MESG_BUFFER_BUSY:
- break;
- case MSGIN_PHASEMIS:
- break;
-#endif
-#if 0
- case SCB_TRACE_POINT:
- {
- /*
- * Print out the bus phase
- */
- char *phase;
- u_int8_t scbindex = ahc_inb(ahc, SCB_TAG);
- u_int8_t lastphase = ahc_inb(ahc, LASTPHASE);
-
- scb = ahc->scb_data->scbarray[scbindex];
- sc_print_addr(scb->xs->sc_link);
-
- switch (lastphase) {
- case P_DATAOUT:
- phase = "Data-Out";
- break;
- case P_DATAIN:
- phase = "Data-In";
- break;
- case P_COMMAND:
- phase = "Command";
- break;
- case P_MESGOUT:
- phase = "Message-Out";
- break;
- case P_STATUS:
- phase = "Status";
- break;
- case P_MESGIN:
- phase = "Message-In";
- break;
- default:
- phase = "busfree";
- break;
- }
- printf("- %s\n", phase);
- break;
- }
-#endif
- case ABORT_CMDCMPLT:
- /* This interrupt serves to pause the sequencer
- * until we can clean up the QOUTFIFO allowing us
- * to hanle any abort SCBs that may have completed
- * yet still have an SCB in the QINFIFO or
- * waiting for selection queue. By the time we get
- * here, we should have already cleaned up the
- * queues, so all we need to do is unpause the sequencer.
- */
- break;
- default:
- printf("ahc_intr: seqint, "
- "intstat == 0x%x, scsisigi = 0x%x\n",
- intstat, ahc_inb(ahc, SCSISIGI));
- break;
- }
-
-clear:
- /*
- * Clear the upper byte that holds SEQINT status
- * codes and clear the SEQINT bit.
- */
- ahc_outb(ahc, CLRINT, CLRSEQINT);
-
- /*
- * The sequencer is paused immediately on
- * a SEQINT, so we should restart it when
- * we're done.
- */
- unpause_sequencer(ahc, /*unpause_always*/TRUE);
-}
-
-static void
-ahc_handle_scsiint(ahc, intstat)
- struct ahc_softc *ahc;
- u_int8_t intstat;
-{
- u_int8_t scb_index;
- u_int8_t status;
- struct scb *scb;
-
- scb_index = ahc_inb(ahc, SCB_TAG);
- status = ahc_inb(ahc, SSTAT1);
-
- if (scb_index < ahc->scb_data->numscbs) {
- scb = ahc->scb_data->scbarray[scb_index];
- if ((scb->flags & SCB_ACTIVE) == 0)
- scb = NULL;
- } else
- scb = NULL;
-
- if ((status & SCSIRSTI) != 0) {
- char channel;
- channel = (ahc_inb(ahc, SBLKCTL) & SELBUSB) ? 'B' : 'A';
- printf("%s: Someone reset channel %c\n",
- ahc_name(ahc), channel);
- ahc_reset_channel(ahc,
- channel,
- XS_BUSY,
- /* Initiate Reset */FALSE);
- scb = NULL;
- } else if ((status & BUSFREE) != 0 && (status & SELTO) == 0) {
- /*
- * First look at what phase we were last in.
- * If its message out, chances are pretty good
- * that the busfree was in response to one of
- * our abort requests.
- */
- u_int8_t lastphase = ahc_inb(ahc, LASTPHASE);
- u_int8_t target = (ahc_inb(ahc, SAVED_TCL) >> 4) & 0x0f;
- char channel = ahc_inb(ahc, SBLKCTL) & SELBUSB ? 'B': 'A';
- int printerror = 1;
-
- ahc_outb(ahc, SCSISEQ, 0);
- if (lastphase == P_MESGOUT) {
- u_int8_t sindex;
- u_int8_t message;
-
- sindex = ahc_inb(ahc, SINDEX);
- message = ahc_inb(ahc, sindex - 1);
-
- if (message == MSG_ABORT) {
-
- sc_print_addr(scb->xs->sc_link);
- printf("SCB %d - Abort Completed.\n",
- scb->hscb->tag);
- ahc_reset_device(ahc, target, channel,
- SCB_LUN(scb),
- SCB_LIST_NULL,
- XS_TIMEOUT);
- ahc_run_done_queue(ahc);
- scb = NULL;
- printerror = 0;
- } else if (message == MSG_ABORT_TAG) {
-
- sc_print_addr(scb->xs->sc_link);
- printf("SCB %d - Abort Tag Completed.\n",
- scb->hscb->tag);
- ahc_reset_device(ahc,
- target,
- channel,
- SCB_LUN(scb),
- scb->hscb->tag,
- XS_TIMEOUT);
- ahc_run_done_queue(ahc);
- scb = NULL;
- printerror = 0;
- } else if (message == MSG_BUS_DEV_RESET) {
- ahc_handle_devreset(ahc, target,
- channel);
- scb = NULL;
- printerror = 0;
- }
- }
- if (printerror != 0) {
- if (scb != NULL) {
- u_int8_t tag;
-
- if ((scb->hscb->control & TAG_ENB) != 0)
- tag = scb->hscb->tag;
- else
- tag = SCB_LIST_NULL;
- ahc_reset_device(ahc, target, channel,
- SCB_LUN(scb), tag, XS_TIMEOUT);
- } else {
- /*
- * XXX can we handle this better?
- * Reset the bus? Send a Bus Device Reset?
- */
- ahc_reset_device(ahc, target, channel,
- ALL_LUNS, SCB_LIST_NULL,
- XS_TIMEOUT);
- printf("%s: ", ahc_name(ahc));
- }
- printf("Unexpected busfree. LASTPHASE == 0x%x\n"
- "SEQADDR == 0x%x\n",
- lastphase, (ahc_inb(ahc, SEQADDR1) << 8)
- | ahc_inb(ahc, SEQADDR0));
- }
- ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
- ahc_outb(ahc, CLRSINT1, CLRBUSFREE);
- ahc_outb(ahc, CLRINT, CLRSCSIINT);
- restart_sequencer(ahc);
- } else if ((status & SELTO) != 0) {
- struct scsi_xfer *xs;
- u_int8_t scbptr;
- u_int8_t nextscb;
-
- scbptr = ahc_inb(ahc, WAITING_SCBH);
- ahc_outb(ahc, SCBPTR, scbptr);
- scb_index = ahc_inb(ahc, SCB_TAG);
-
- if (scb_index < ahc->scb_data->numscbs) {
- scb = ahc->scb_data->scbarray[scb_index];
- if ((scb->flags & SCB_ACTIVE) == 0)
- scb = NULL;
- } else
- scb = NULL;
-
- if (scb == NULL) {
- printf("%s: ahc_intr - referenced scb not "
- "valid during SELTO scb(%d)\n",
- ahc_name(ahc), scb_index);
- printf("SEQADDR = 0x%x SCSISEQ = 0x%x "
- "SSTAT0 = 0x%x SSTAT1 = 0x%x\n",
- ahc_inb(ahc, SEQADDR0)
- | (ahc_inb(ahc, SEQADDR1) << 8),
- ahc_inb(ahc, SCSISEQ), ahc_inb(ahc, SSTAT0),
- ahc_inb(ahc,SSTAT1));
- } else {
- /*
- * XXX If we queued an abort tag, go clean up the
- * disconnected list.
- */
- xs = scb->xs;
- xs->error = XS_SELTIMEOUT;
- /*
- * Clear any pending messages for the timed out
- * target, and mark the target as free
- */
- ahc_outb(ahc, MSG_LEN, 0);
- ahc_index_busy_target(ahc, SCB_TARGET(scb),
- SCB_IS_SCSIBUS_B(scb) ? 'B' : 'A',
- /*unbusy*/TRUE);
-
- ahc_outb(ahc, SCB_CONTROL, 0);
- /* Shift the waiting Q forward. */
- nextscb = ahc_inb(ahc, SCB_NEXT);
- ahc_outb(ahc, WAITING_SCBH, nextscb);
-
- ahc_add_curscb_to_free_list(ahc);
- }
- /* Stop the selection */
- ahc_outb(ahc, SCSISEQ, 0);
-
- ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE);
-
- ahc_outb(ahc, CLRINT, CLRSCSIINT);
-
- restart_sequencer(ahc);
- } else if (scb == NULL) {
- printf("%s: ahc_intr - referenced scb not "
- "valid during scsiint 0x%x scb(%d)\n"
- "SIMODE0 = 0x%x, SIMODE1 = 0x%x, SSTAT0 = 0x%x\n"
- "SEQADDR = 0x%x\n", ahc_name(ahc),
- status, scb_index, ahc_inb(ahc, SIMODE0),
- ahc_inb(ahc, SIMODE1), ahc_inb(ahc, SSTAT0),
- (ahc_inb(ahc, SEQADDR1) << 8)
- | ahc_inb(ahc, SEQADDR0));
- ahc_outb(ahc, CLRSINT1, status);
- ahc_outb(ahc, CLRINT, CLRSCSIINT);
- unpause_sequencer(ahc, /*unpause_always*/TRUE);
- scb = NULL;
- } else if ((status & SCSIPERR) != 0) {
- /*
- * Determine the bus phase and
- * queue an appropriate message
- */
- char *phase;
- u_int8_t mesg_out = MSG_NOOP;
- u_int8_t lastphase = ahc_inb(ahc, LASTPHASE);
- struct scsi_xfer *xs;
-
- xs = scb->xs;
- sc_print_addr(xs->sc_link);
-
- switch (lastphase) {
- case P_DATAOUT:
- phase = "Data-Out";
- break;
- case P_DATAIN:
- phase = "Data-In";
- mesg_out = MSG_INITIATOR_DET_ERR;
- break;
- case P_COMMAND:
- phase = "Command";
- break;
- case P_MESGOUT:
- phase = "Message-Out";
- break;
- case P_STATUS:
- phase = "Status";
- mesg_out = MSG_INITIATOR_DET_ERR;
- break;
- case P_MESGIN:
- phase = "Message-In";
- mesg_out = MSG_PARITY_ERROR;
- break;
- default:
- phase = "unknown";
- break;
- }
- printf("parity error during %s phase.\n", phase);
-
- /*
- * We've set the hardware to assert ATN if we
- * get a parity error on "in" phases, so all we
- * need to do is stuff the message buffer with
- * the appropriate message. "In" phases have set
- * mesg_out to something other than MSG_NOP.
- */
- if (mesg_out != MSG_NOOP) {
- ahc_outb(ahc, MSG_OUT, mesg_out);
- ahc_outb(ahc, MSG_LEN, 1);
- scb = NULL;
- } else
- /*
- * Should we allow the target to make
- * this decision for us? If we get a
- * sense request from the drive, we will
- * not fetch it since xs->error != XS_NOERROR.
- * perhaps we need two error fields in the
- * xs structure?
- */
- xs->error = XS_DRIVER_STUFFUP;
- ahc_outb(ahc, CLRSINT1, CLRSCSIPERR);
- ahc_outb(ahc, CLRINT, CLRSCSIINT);
- unpause_sequencer(ahc, /*unpause_always*/TRUE);
- } else {
- sc_print_addr(scb->xs->sc_link);
- printf("Unknown SCSIINT. Status = 0x%x\n", status);
- ahc_outb(ahc, CLRSINT1, status);
- ahc_outb(ahc, CLRINT, CLRSCSIINT);
- unpause_sequencer(ahc, /*unpause_always*/TRUE);
- scb = NULL;
- }
- if (scb != NULL) {
- /* We want to process the command */
- ahc_done(ahc, scb);
- }
-}
-
-static void
-ahc_handle_devreset(ahc, target, channel)
- struct ahc_softc *ahc;
- int target;
- char channel;
-{
- u_int16_t targ_mask;
- u_int8_t targ_scratch;
- int scratch_offset = target;
- int found;
-
- if (channel == 'B')
- scratch_offset += 8;
- targ_mask = (0x01 << scratch_offset);
- /*
- * Go back to async/narrow transfers and
- * renegotiate.
- */
- ahc->needsdtr |= ahc->needsdtr_orig & targ_mask;
- ahc->needwdtr |= ahc->needwdtr_orig & targ_mask;
- ahc->sdtrpending &= ~targ_mask;
- ahc->wdtrpending &= ~targ_mask;
- targ_scratch = ahc_inb(ahc, TARG_SCRATCH + scratch_offset);
- targ_scratch &= SXFR;
- ahc_outb(ahc, TARG_SCRATCH + scratch_offset, targ_scratch);
- found = ahc_reset_device(ahc, target, channel, ALL_LUNS,
- SCB_LIST_NULL, XS_NOERROR);
- printf("%s: Bus Device Reset delivered. %d SCBs aborted\n",
- ahc_name(ahc), found);
- ahc_run_done_queue(ahc);
-}
-
-/*
- * We have a scb which has been processed by the
- * adaptor, now we look to see how the operation
- * went.
- */
-static void
-ahc_done(ahc, scb)
- struct ahc_softc *ahc;
- struct scb *scb;
-{
- struct scsi_xfer *xs = scb->xs;
-
- SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahc_done\n"));
- /*
- * If the recovery SCB completes, we have to be
- * out of our timeout.
- */
- if (scb->flags & SCB_RECOVERY_SCB) {
- ahc->in_timeout = FALSE;
- sc_print_addr(scb->xs->sc_link);
- printf("no longer in timeout\n");
- }
- /*
- * Put the results of the operation
- * into the xfer and call whoever started it
- */
- /* Don't override the error value. */
- if (xs->error == XS_NOERROR
- && (scb->flags & SCB_SENSE) != 0)
- xs->error = XS_SENSE;
-
-#if defined(__FreeBSD__)
- if ((xs->flags & SCSI_ERR_OK) && !(xs->error == XS_SENSE)) {
- /* All went correctly OR errors expected */
- xs->error = XS_NOERROR;
- }
-#elif defined(__NetBSD__)
- /*
- * Since NetBSD doesn't have error ignoring operation mode
- * (SCSI_ERR_OK in FreeBSD), we don't have to care this case.
- */
-#endif
- xs->flags |= ITSDONE;
-#ifdef AHC_TAGENABLE
- /*
- * This functionality will be provided by the generic SCSI layer
- * in FreeBSD 3.0.
- */
- if (xs->cmd->opcode == INQUIRY && xs->error == XS_NOERROR) {
- struct scsi_inquiry_data *inq_data;
- u_int16_t mask = 0x01 << (xs->sc_link->target |
- (scb->hscb->tcl & 0x08));
- /*
- * Sneak a look at the results of the SCSI Inquiry
- * command and see if we can do Tagged queing. This
- * should really be done by the higher level drivers.
- */
- inq_data = (struct scsi_inquiry_data *)xs->data;
- if ((inq_data->flags & SID_CmdQue)
- && !(ahc->tagenable & mask)) {
- printf("%s: target %d Tagged Queuing Device\n",
- ahc_name(ahc), xs->sc_link->target);
- ahc->tagenable |= mask;
- if (ahc->scb_data->maxhscbs >= 16
- || (ahc->flags & AHC_PAGESCBS)) {
- /* Default to 8 tags */
- xs->sc_link->opennings += 6;
- } else {
- /*
- * Default to 4 tags on whimpy
- * cards that don't have much SCB
- * space and can't page. This prevents
- * a single device from hogging all
- * slots. We should really have a better
- * way of providing fairness.
- */
- xs->sc_link->opennings += 2;
- }
- }
- }
-#endif /* AHC_TAGENABLE */
- if ((scb->flags & (SCB_MSGOUT_WDTR|SCB_MSGOUT_SDTR)) != 0) {
- /*
- * Turn off the pending flags for any DTR messages
- * regardless of whether they completed successfully
- * or not. This ensures that we don't have lingering
- * state after we abort an SCB.
- */
- u_int16_t mask;
-
- mask = (0x01 << (xs->sc_link->target
- | (IS_SCSIBUS_B(ahc, xs->sc_link) ? SELBUSB : 0)));
- if (scb->flags & SCB_MSGOUT_WDTR)
- ahc->wdtrpending &= ~mask;
- if (scb->flags & SCB_MSGOUT_SDTR)
- ahc->sdtrpending &= ~mask;
- }
- untimeout(ahc_timeout, (caddr_t)scb, scb->xs->timeout_ch);
- ahc_free_scb(ahc, scb);
- /*
- * If we're polling, we rely on the ITS_DONE flag in the xs structure
- * to know that the command has completed. Unfortunately, scsi_done
- * can cause the same xs to get requeued putting us in an infinite
- * loop. So, we defer the scsi_done call until the poll routine exits
- * its loop. I hate the way this works.
- */
- if ((xs->flags & SCSI_NOMASK) == 0)
- scsi_done(xs);
-}
-
-/*
- * Start the board, ready for normal operation
- */
-int
-ahc_init(ahc)
- struct ahc_softc *ahc;
-{
- u_int8_t scsi_conf, sblkctl, sxfrctl1, i;
- u_int16_t ultraenable = 0;
- int max_targ = 15;
- /*
- * Assume we have a board at this stage and it has been reset.
- */
-
- /* Handle the SCBPAGING option */
-#ifndef AHC_SCBPAGING_ENABLE
- ahc->flags &= ~AHC_PAGESCBS;
-#endif
-
- /* Determine channel configuration and who we are on the scsi bus. */
- switch ((sblkctl = ahc_inb(ahc, SBLKCTL) & 0x0a)) {
- case 0:
- ahc->our_id = (ahc_inb(ahc, SCSICONF) & HSCSIID);
- ahc->flags &= ~AHC_CHANNEL_B_PRIMARY;
- if ((ahc->type & AHC_39X) != 0) {
- char channel = 'A';
-
- if ((ahc->flags & (AHC_CHNLB|AHC_CHNLC)) != 0)
- channel = ahc->flags & AHC_CHNLB ? 'B' : 'C';
- printf("Channel %c, SCSI Id=%d, ", channel,
- ahc->our_id);
- } else
- printf("Single Channel, SCSI Id=%d, ", ahc->our_id);
- ahc_outb(ahc, SEQ_FLAGS, ahc->flags & AHC_PAGESCBS);
- break;
- case 2:
- ahc->our_id = (ahc_inb(ahc, SCSICONF + 1) & HWSCSIID);
- ahc->flags &= ~AHC_CHANNEL_B_PRIMARY;
- if ((ahc->type & AHC_39X) != 0) {
- char channel = 'A';
-
- if ((ahc->flags & (AHC_CHNLB|AHC_CHNLC)) != 0)
- channel = ahc->flags & AHC_CHNLB ? 'B' : 'C';
- printf("Wide Channel %c, SCSI Id=%d, ", channel,
- ahc->our_id);
- } else
- printf("Wide Channel, SCSI Id=%d, ", ahc->our_id);
- ahc->type |= AHC_WIDE;
- ahc_outb(ahc, SEQ_FLAGS, WIDE_BUS | (ahc->flags & AHC_PAGESCBS));
- break;
- case 8:
- ahc->our_id = (ahc_inb(ahc, SCSICONF) & HSCSIID);
- ahc->our_id_b = (ahc_inb(ahc, SCSICONF + 1) & HSCSIID);
- printf("Twin Channel, A SCSI Id=%d, B SCSI Id=%d, ",
- ahc->our_id, ahc->our_id_b);
- ahc->type |= AHC_TWIN;
- ahc_outb(ahc, SEQ_FLAGS, TWIN_BUS | (ahc->flags & AHC_PAGESCBS));
- break;
- default:
- printf(" Unsupported adapter type. Ignoring\n");
- return(-1);
- }
-
- /* Determine the number of SCBs and initialize them */
-
- if (ahc->scb_data->maxhscbs == 0) {
- /* SCB 0 heads the free list */
- ahc_outb(ahc, FREE_SCBH, 0);
- for (i = 0; i < AHC_SCB_MAX; i++) {
- ahc_outb(ahc, SCBPTR, i);
- ahc_outb(ahc, SCB_CONTROL, i);
- if(ahc_inb(ahc, SCB_CONTROL) != i)
- break;
- ahc_outb(ahc, SCBPTR, 0);
- if(ahc_inb(ahc, SCB_CONTROL) != 0)
- break;
- ahc_outb(ahc, SCBPTR, i);
-
- /* Clear the control byte. */
- ahc_outb(ahc, SCB_CONTROL, 0);
-
- /* Set the next pointer */
- ahc_outb(ahc, SCB_NEXT, i+1);
-
- /* Make the tag number invalid */
- ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL);
-
- /* No Busy non-tagged targets yet */
- ahc_outb(ahc, SCB_BUSYTARGETS, SCB_LIST_NULL);
- ahc_outb(ahc, SCB_BUSYTARGETS + 1, SCB_LIST_NULL);
- ahc_outb(ahc, SCB_BUSYTARGETS + 2, SCB_LIST_NULL);
- ahc_outb(ahc, SCB_BUSYTARGETS + 3, SCB_LIST_NULL);
- }
-
- /* Make that the last SCB terminates the free list */
- ahc_outb(ahc, SCBPTR, i-1);
- ahc_outb(ahc, SCB_NEXT, SCB_LIST_NULL);
-
- /* Ensure we clear the 0 SCB's control byte. */
- ahc_outb(ahc, SCBPTR, 0);
- ahc_outb(ahc, SCB_CONTROL, 0);
-
- ahc->scb_data->maxhscbs = i;
- }
-
- if ((ahc->scb_data->maxhscbs < AHC_SCB_MAX)
- && (ahc->flags & AHC_PAGESCBS)) {
- u_int8_t max_scbid = 255;
-
- /* Determine the number of valid bits in the FIFOs */
- ahc_outb(ahc, QINFIFO, max_scbid);
- max_scbid = ahc_inb(ahc, QINFIFO);
- ahc->scb_data->maxscbs = MIN(AHC_SCB_MAX, max_scbid + 1);
- printf("%d/%d SCBs\n", ahc->scb_data->maxhscbs,
- ahc->scb_data->maxscbs);
- } else {
- ahc->scb_data->maxscbs = ahc->scb_data->maxhscbs;
- ahc->flags &= ~AHC_PAGESCBS;
- printf("%d SCBs\n", ahc->scb_data->maxhscbs);
- }
-
-#ifdef AHC_DEBUG
- if (ahc_debug & AHC_SHOWMISC) {
- printf("%s: hardware scb %d bytes; kernel scb %d bytes; "
- "ahc_dma %d bytes\n",
- ahc_name(ahc),
- sizeof(struct hardware_scb),
- sizeof(struct scb),
- sizeof(struct ahc_dma_seg));
- }
-#endif /* AHC_DEBUG */
-
- /* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1, for both channels*/
- if (ahc->type & AHC_TWIN) {
- /*
- * The device is gated to channel B after a chip reset,
- * so set those values first
- */
- ahc_outb(ahc, SCSIID, ahc->our_id_b);
- scsi_conf = ahc_inb(ahc, SCSICONF + 1);
- sxfrctl1 = ahc_inb(ahc, SXFRCTL1);
- ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
- |(sxfrctl1 & STPWEN)
- |ENSTIMER|ACTNEGEN);
- ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
- if (ahc->type & AHC_ULTRA)
- ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN|FAST20);
- else
- ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
-
- if (scsi_conf & RESET_SCSI) {
- /* Reset the bus */
- if (bootverbose)
- printf("%s: Resetting Channel B\n",
- ahc_name(ahc));
- ahc_reset_current_bus(ahc);
- }
-
- /* Select Channel A */
- ahc_outb(ahc, SBLKCTL, 0);
- }
- ahc_outb(ahc, SCSIID, ahc->our_id);
- scsi_conf = ahc_inb(ahc, SCSICONF);
- sxfrctl1 = ahc_inb(ahc, SXFRCTL1);
- ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
- |(sxfrctl1 & STPWEN)
- |ENSTIMER|ACTNEGEN);
- ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
- if (ahc->type & AHC_ULTRA)
- ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN|FAST20);
- else
- ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
-
- if (scsi_conf & RESET_SCSI) {
- /* Reset the bus */
- if (bootverbose)
- printf("%s: Resetting Channel A\n", ahc_name(ahc));
-
- ahc_reset_current_bus(ahc);
- }
-
- /*
- * Look at the information that board initialization or
- * the board bios has left us. In the lower four bits of each
- * target's scratch space any value other than 0 indicates
- * that we should initiate synchronous transfers. If it's zero,
- * the user or the BIOS has decided to disable synchronous
- * negotiation to that target so we don't activate the needsdtr
- * flag.
- */
- ahc->needsdtr_orig = 0;
- ahc->needwdtr_orig = 0;
-
- /* Grab the disconnection disable table and invert it for our needs */
- if (ahc->flags & AHC_USEDEFAULTS) {
- printf("%s: Host Adapter Bios disabled. Using default SCSI "
- "device parameters\n", ahc_name(ahc));
- ahc->discenable = 0xff;
- } else
- ahc->discenable = ~((ahc_inb(ahc, DISC_DSB + 1) << 8)
- | ahc_inb(ahc, DISC_DSB));
-
- if (!(ahc->type & (AHC_WIDE|AHC_TWIN)))
- max_targ = 7;
-
- for (i = 0; i <= max_targ; i++) {
- u_int8_t target_settings;
- if (ahc->flags & AHC_USEDEFAULTS) {
- target_settings = 0; /* 10MHz/20MHz */
- ahc->needsdtr_orig |= (0x01 << i);
- ahc->needwdtr_orig |= (0x01 << i);
- if (ahc->type & AHC_ULTRA)
- ultraenable |= (0x01 << i);
- } else {
- /* Take the settings leftover in scratch RAM. */
- target_settings = ahc_inb(ahc, TARG_SCRATCH + i);
-
- if (target_settings & 0x0f) {
- ahc->needsdtr_orig |= (0x01 << i);
- /*Default to a asynchronous transfers(0 offset)*/
- target_settings &= 0xf0;
- }
- if (target_settings & 0x80) {
- ahc->needwdtr_orig |= (0x01 << i);
- /*
- * We'll set the Wide flag when we
- * are successful with Wide negotiation.
- * Turn it off for now so we aren't
- * confused.
- */
- target_settings &= 0x7f;
- }
- if (ahc->type & AHC_ULTRA) {
- /*
- * Enable Ultra for any target that
- * has a valid ultra syncrate setting.
- */
- u_int8_t rate = target_settings & 0x70;
- if (rate == 0x00 || rate == 0x10 ||
- rate == 0x20 || rate == 0x40) {
- if (rate == 0x40) {
- /* Treat 10MHz specially */
- target_settings &= ~0x70;
- } else
- ultraenable |= (0x01 << i);
- }
- }
- }
- ahc_outb(ahc, TARG_SCRATCH+i,target_settings);
- }
- /*
- * If we are not a WIDE device, forget WDTR. This
- * makes the driver work on some cards that don't
- * leave these fields cleared when the BIOS is not
- * installed.
- */
- if ((ahc->type & AHC_WIDE) == 0)
- ahc->needwdtr_orig = 0;
- ahc->needsdtr = ahc->needsdtr_orig;
- ahc->needwdtr = ahc->needwdtr_orig;
- ahc->sdtrpending = 0;
- ahc->wdtrpending = 0;
- ahc->tagenable = 0;
- ahc->orderedtag = 0;
-
- ahc_outb(ahc, ULTRA_ENB, ultraenable & 0xff);
- ahc_outb(ahc, ULTRA_ENB + 1, (ultraenable >> 8) & 0xff);
-
-#ifdef AHC_DEBUG
- /* How did we do? */
- if (ahc_debug & AHC_SHOWMISC)
- printf("NEEDSDTR == 0x%x\nNEEDWDTR == 0x%x\n"
- "DISCENABLE == 0x%x\n", ahc->needsdtr,
- ahc->needwdtr, ahc->discenable);
-#endif
- /*
- * Allocate enough "hardware scbs" to handle
- * the maximum number of concurrent transactions
- * we can have active. We have to use contigmalloc
- * if this array crosses a page boundary since the
- * sequencer depends on this array being physically
- * contiguous.
- */
- if (ahc->scb_data->hscbs == NULL) {
- size_t array_size;
- u_int32_t hscb_physaddr;
-
- array_size = ahc->scb_data->maxscbs*sizeof(struct hardware_scb);
- if (array_size > PAGE_SIZE) {
- ahc->scb_data->hscbs = (struct hardware_scb *)
- contigmalloc(array_size, M_DEVBUF,
- M_NOWAIT, 0ul, 0xffffffff,
- PAGE_SIZE, 0x10000);
- } else {
- ahc->scb_data->hscbs = (struct hardware_scb *)
- malloc(array_size, M_DEVBUF, M_NOWAIT);
- }
-
- if (ahc->scb_data->hscbs == NULL) {
- printf("%s: unable to allocate hardware SCB array. "
- "Failing attach\n", ahc_name(ahc));
- return (-1);
- }
- /* At least the control byte of each hscb needs to be zeroed */
- bzero(ahc->scb_data->hscbs, array_size);
-
- /* Tell the sequencer where it can find the hscb array. */
- hscb_physaddr = vtophys(ahc->scb_data->hscbs);
- ahc_outb(ahc, HSCB_ADDR, hscb_physaddr & 0xFF);
- ahc_outb(ahc, HSCB_ADDR + 1, (hscb_physaddr >> 8)& 0xFF);
- ahc_outb(ahc, HSCB_ADDR + 2, (hscb_physaddr >> 16)& 0xFF);
- ahc_outb(ahc, HSCB_ADDR + 3, (hscb_physaddr >> 24)& 0xFF);
- }
-
- /*
- * Q-Full-Count. Some cards have more Q space
- * then SCBs.
- */
- if (ahc->type & AHC_AIC7770) {
- ahc->qfullcount = 4;
- ahc->qcntmask = 0x07;
- } else if (ahc->type & AHC_AIC7850) {
- ahc->qfullcount = 8;
- ahc->qcntmask = 0x0f;
- } else if (ahc->scb_data->maxhscbs == 255) {
- /* 7870/7880 with external SRAM */
- ahc->qfullcount = 255;
- ahc->qcntmask = 0xff;
- } else {
- /* 7870/7880 */
- ahc->qfullcount = 16;
- ahc->qcntmask = 0x1f;
- }
-
- ahc_outb(ahc, CMDOUTCNT, 0);
-
- /* We don't have any waiting selections */
- ahc_outb(ahc, WAITING_SCBH, SCB_LIST_NULL);
-
- /* Our disconnection list is empty too */
- ahc_outb(ahc, DISCONNECTED_SCBH, SCB_LIST_NULL);
-
- /* Message out buffer starts empty */
- ahc_outb(ahc, MSG_LEN, 0x00);
-
- /*
- * Load the Sequencer program and Enable the adapter
- * in "fast" mode.
- */
- if (bootverbose)
- printf("%s: Downloading Sequencer Program...",
- ahc_name(ahc));
-
- ahc_loadseq(ahc);
-
- if (bootverbose)
- printf("Done\n");
-
- unpause_sequencer(ahc, /*unpause_always*/TRUE);
-
- /*
- * Note that we are going and return (to probe)
- */
- ahc->flags |= AHC_INIT;
- return (0);
-}
-
-static void
-ahcminphys(bp)
- struct buf *bp;
-{
-/*
- * Even though the card can transfer up to 16megs per command
- * we are limited by the number of segments in the dma segment
- * list that we can hold. The worst case is that all pages are
- * discontinuous physically, hense the "page per segment" limit
- * enforced here.
- */
- if (bp->b_bcount > ((AHC_NSEG - 1) * PAGE_SIZE)) {
- bp->b_bcount = ((AHC_NSEG - 1) * PAGE_SIZE);
- }
-#if defined(__NetBSD__)
- minphys(bp);
-#endif
-}
-
-/*
- * start a scsi operation given the command and
- * the data address, target, and lun all of which
- * are stored in the scsi_xfer struct
- */
-static int32_t
-ahc_scsi_cmd(xs)
- struct scsi_xfer *xs;
-{
- struct scb *scb;
- struct hardware_scb *hscb;
- struct ahc_softc *ahc;
- u_int16_t mask;
- int flags;
- int s;
-
- ahc = (struct ahc_softc *)xs->sc_link->adapter_softc;
- mask = (0x01 << (xs->sc_link->target
- | (IS_SCSIBUS_B(ahc, xs->sc_link) ? SELBUSB : 0)));
- SC_DEBUG(xs->sc_link, SDEV_DB2, ("ahc_scsi_cmd\n"));
- flags = xs->flags;
-
- /*
- * get an scb to use. If the transfer
- * is from a buf (possibly from interrupt time)
- * then we can't allow it to sleep
- */
- if ((scb = ahc_get_scb(ahc, flags)) == NULL) {
- xs->error = XS_DRIVER_STUFFUP;
- return (TRY_AGAIN_LATER);
- }
- hscb = scb->hscb;
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb));
- scb->xs = xs;
-
- /*
- * Put all the arguments for the xfer in the scb
- */
- if (ahc->discenable & mask) {
- hscb->control |= DISCENB;
- if (ahc->tagenable & mask)
- hscb->control |= MSG_SIMPLE_Q_TAG;
- if (ahc->orderedtag & mask) {
- /* XXX this should be handled by the upper SCSI layer */
- printf("Ordered Tag sent\n");
- hscb->control |= MSG_ORDERED_Q_TAG;
- ahc->orderedtag &= ~mask;
- }
- }
-
- if (flags & SCSI_RESET) {
- scb->flags |= SCB_DEVICE_RESET;
- hscb->control |= MK_MESSAGE;
- } else if ((ahc->needwdtr & mask) && !(ahc->wdtrpending & mask)) {
- ahc->wdtrpending |= mask;
- hscb->control |= MK_MESSAGE;
- scb->flags |= SCB_MSGOUT_WDTR;
- } else if((ahc->needsdtr & mask) && !(ahc->sdtrpending & mask)) {
- ahc->sdtrpending |= mask;
- hscb->control |= MK_MESSAGE;
- scb->flags |= SCB_MSGOUT_SDTR;
- }
-
-#if 0
- /* Set the trace flag if this is the target we want to trace */
- if (ahc->unit == 2 && xs->sc_link->target == 3)
- hscb->control |= TRACE_SCB;
-#endif
-
- hscb->tcl = ((xs->sc_link->target << 4) & 0xF0)
- | (IS_SCSIBUS_B(ahc,xs->sc_link)? SELBUSB : 0)
- | (xs->sc_link->lun & 0x07);
- hscb->cmdlen = xs->cmdlen;
- hscb->cmdpointer = vtophys(xs->cmd);
- xs->resid = 0;
- xs->status = 0;
-
- /* Only use S/G if non-zero length */
- if (xs->datalen) {
- int seg;
- u_int32_t datalen;
- vm_offset_t vaddr;
- u_int32_t paddr;
- u_int32_t nextpaddr;
- struct ahc_dma_seg *sg;
-
- seg = 0;
- datalen = xs->datalen;
- vaddr = (vm_offset_t)xs->data;
- paddr = vtophys(vaddr);
- sg = scb->ahc_dma;
- hscb->SG_list_pointer = vtophys(sg);
-
- while ((datalen > 0) && (seg < AHC_NSEG)) {
- /* put in the base address and length */
- sg->addr = paddr;
- sg->len = 0;
-
- /* do it at least once */
- nextpaddr = paddr;
-
- while ((datalen > 0) && (paddr == nextpaddr)) {
- u_int32_t size;
- /*
- * This page is contiguous (physically)
- * with the the last, just extend the
- * length
- */
- /* how far to the end of the page */
- nextpaddr = (paddr & (~PAGE_MASK)) + PAGE_SIZE;
-
- /*
- * Compute the maximum size
- */
- size = nextpaddr - paddr;
- if (size > datalen)
- size = datalen;
-
- sg->len += size;
- vaddr += size;
- datalen -= size;
- if (datalen > 0)
- paddr = vtophys(vaddr);
- }
- /*
- * next page isn't contiguous, finish the seg
- */
- seg++;
- sg++;
- }
- hscb->SG_segment_count = seg;
- scb->sg_count = hscb->SG_segment_count;
-
- /* Copy the first SG into the data pointer area */
- hscb->data = scb->ahc_dma->addr;
- hscb->datalen = scb->ahc_dma->len | (SCB_LIST_NULL << 24);
- if (datalen) {
- /* there's still data, must have run out of segs! */
- printf("%s: ahc_scsi_cmd: more than %d DMA segs\n",
- ahc_name(ahc), AHC_NSEG);
- xs->error = XS_DRIVER_STUFFUP;
- ahc_free_scb(ahc, scb);
- return (COMPLETE);
- }
-#ifdef AHC_BROKEN_CACHE
- if (ahc_broken_cache)
- INVALIDATE_CACHE();
-#endif
- } else {
- /*
- * No data xfer, use non S/G values
- */
- hscb->SG_segment_count = 0;
- scb->sg_count = hscb->SG_segment_count;
- hscb->SG_list_pointer = 0;
- hscb->data = 0;
- hscb->datalen = (SCB_LIST_NULL << 24);
- }
-
-#ifdef AHC_DEBUG
- if((ahc_debug & AHC_SHOWSCBS) && (xs->sc_link->target == DEBUGTARGET))
- ahc_print_scb(scb);
-#endif
- s = splbio();
-
- STAILQ_INSERT_TAIL(&ahc->waiting_scbs, scb, links);
-
- scb->flags |= SCB_ACTIVE|SCB_WAITINGQ;
-
- ahc_run_waiting_queue(ahc);
-
- if ((flags & SCSI_NOMASK) == 0) {
- scb->xs->timeout_ch = timeout(ahc_timeout, (caddr_t)scb,
- (xs->timeout * hz) / 1000);
- splx(s);
- return (SUCCESSFULLY_QUEUED);
- }
- /*
- * If we can't use interrupts, poll for completion
- */
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n"));
- do {
- if (ahc_poll(ahc, xs->timeout)) {
- if (!(xs->flags & SCSI_SILENT))
- printf("cmd fail\n");
- ahc_timeout(scb);
- break;
- }
- } while ((xs->flags & ITSDONE) == 0); /* a non command complete intr */
- scsi_done(xs);
- splx(s);
- return (COMPLETE);
-}
-
-/*
- * Look for space in the QINFIFO and queue as many SCBs in the waiting
- * queue as possible. Assumes that it is called at splbio().
- */
-static void
-ahc_run_waiting_queue(ahc)
- struct ahc_softc *ahc;
-{
- struct scb *scb;
-
- pause_sequencer(ahc);
-
- if (ahc->curqincnt >= ahc->qfullcount) {
- ahc->curqincnt = ahc_inb(ahc, QINCNT) & ahc->qcntmask;
- }
-
- while ((scb = ahc->waiting_scbs.stqh_first) != NULL
- && (ahc->curqincnt < ahc->qfullcount)) {
-
- STAILQ_REMOVE_HEAD(&ahc->waiting_scbs, links);
- scb->flags &= ~SCB_WAITINGQ;
-
- ahc_outb(ahc, QINFIFO, scb->hscb->tag);
-
- if ((ahc->flags & AHC_PAGESCBS) != 0)
- /*
- * We only care about this statistic when paging
- * since it is impossible to overflow the qinfifo
- * in the non-paging case.
- */
- ahc->curqincnt++;
- }
- unpause_sequencer(ahc, /*Unpause always*/FALSE);
-}
-
-/*
- * An scb (and hence an scb entry on the board) is put onto the
- * free list.
- */
-static void
-ahc_free_scb(ahc, scb)
- struct ahc_softc *ahc;
- struct scb *scb;
-{
- struct hardware_scb *hscb;
- int opri;
-
- hscb = scb->hscb;
-
- opri = splbio();
-
- /* Clean up for the next user */
- scb->flags = SCB_FREE;
- hscb->control = 0;
- hscb->status = 0;
-
- STAILQ_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links);
- if (scb->links.stqe_next == NULL) {
- /*
- * If there were no SCBs available, wake anybody waiting
- * for one to come free.
- */
- wakeup((caddr_t)&ahc->scb_data->free_scbs);
- }
-#ifdef AHC_DEBUG
- ahc->activescbs--;
-#endif
- splx(opri);
-}
-
-/*
- * Get a free scb, either one already assigned to a hardware slot
- * on the adapter or one that will require an SCB to be paged out before
- * use. If there are none, see if we can allocate a new SCB. Otherwise
- * either return an error or sleep.
- */
-static struct scb *
-ahc_get_scb(ahc, flags)
- struct ahc_softc *ahc;
- u_int32_t flags;
-{
- struct scb *scbp;
- int opri;
-
- opri = splbio();
- /*
- * If we can and have to, sleep waiting for one to come free
- * but only if we can't allocate a new one.
- */
- while (1) {
- if ((scbp = ahc->scb_data->free_scbs.stqh_first)) {
- STAILQ_REMOVE_HEAD(&ahc->scb_data->free_scbs, links);
- } else if(ahc->scb_data->numscbs < ahc->scb_data->maxscbs) {
- scbp = ahc_alloc_scb(ahc);
- if (scbp == NULL)
- printf("%s: Can't malloc SCB\n", ahc_name(ahc));
- } else if ((flags & SCSI_NOSLEEP) == 0) {
- tsleep((caddr_t)&ahc->scb_data->free_scbs, PRIBIO,
- "ahcscb", 0);
- continue;
- }
- break;
- }
-
-#ifdef AHC_DEBUG
- if (scbp) {
- ahc->activescbs++;
- if((ahc_debug & AHC_SHOWSCBCNT)
- && (ahc->activescbs == ahc->scb_data->maxhscbs))
- printf("%s: Max SCBs active\n", ahc_name(ahc));
- }
-#endif
-
- splx(opri);
-
- return (scbp);
-}
-
-
-static struct scb *
-ahc_alloc_scb(ahc)
- struct ahc_softc *ahc;
-{
- static struct ahc_dma_seg *next_sg_array = NULL;
- static int sg_arrays_free = 0;
- struct scb *newscb;
-
- newscb = (struct scb *) malloc(sizeof(struct scb), M_DEVBUF, M_NOWAIT);
- if (newscb != NULL) {
- bzero(newscb, sizeof(struct scb));
- if (next_sg_array == NULL) {
- size_t alloc_size = sizeof(struct ahc_dma_seg)
- * AHC_NSEG;
- sg_arrays_free = PAGE_SIZE / alloc_size;
- alloc_size *= sg_arrays_free;
- if (alloc_size == 0)
- panic("%s: SG list doesn't fit in a page",
- ahc_name(ahc));
- next_sg_array = (struct ahc_dma_seg *)
- malloc(alloc_size, M_DEVBUF, M_NOWAIT);
- }
- if (next_sg_array != NULL) {
- struct hardware_scb *hscb;
-
- newscb->ahc_dma = next_sg_array;
- sg_arrays_free--;
- if (sg_arrays_free == 0)
- next_sg_array = NULL;
- else
- next_sg_array = &next_sg_array[AHC_NSEG];
- hscb = &ahc->scb_data->hscbs[ahc->scb_data->numscbs];
- newscb->hscb = hscb;
- hscb->control = 0;
- hscb->status = 0;
- hscb->tag = ahc->scb_data->numscbs;
- hscb->residual_data_count[2] = 0;
- hscb->residual_data_count[1] = 0;
- hscb->residual_data_count[0] = 0;
- hscb->residual_SG_segment_count = 0;
- ahc->scb_data->numscbs++;
- /*
- * Place in the scbarray
- * Never is removed.
- */
- ahc->scb_data->scbarray[hscb->tag] = newscb;
- } else {
- free(newscb, M_DEVBUF);
- newscb = NULL;
- }
- }
- return newscb;
-}
-
-static void
-ahc_loadseq(struct ahc_softc *ahc)
-{
- int options;
- struct patch *cur_patch;
- int i;
- int downloaded;
- u_int8_t download_consts[4];
-
- options = 1; /* Code for all options */
- downloaded = 0;
- if ((ahc->type & AHC_ULTRA) != 0)
- options |= ULTRA;
- if ((ahc->type & AHC_TWIN) != 0)
- options |= TWIN_CHANNEL;
- if (ahc->scb_data->maxscbs > ahc->scb_data->maxhscbs)
- options |= SCB_PAGING;
-
- /* Setup downloadable constant table */
- download_consts[SCBCOUNT] = ahc->scb_data->maxhscbs;
- download_consts[COMP_SCBCOUNT] = -ahc->scb_data->maxscbs & 0xFF;
- download_consts[FIFODEPTH] = ahc->qfullcount;
- download_consts[QCNTMASK] = ahc->qcntmask;
-
- cur_patch = patches;
- ahc_outb(ahc, SEQCTL, PERRORDIS|LOADRAM);
- ahc_outb(ahc, SEQADDR0, 0);
- ahc_outb(ahc, SEQADDR1, 0);
-
- for(i = 0; i < sizeof(seqprog)/4; i++) {
- cur_patch = ahc_next_patch(cur_patch, options, i);
-
- if (cur_patch && cur_patch->begin <= i && cur_patch->end > i)
- /* Skip this instruction for this configuration */
- continue;
- ahc_download_instr(ahc, options, i, download_consts);
- downloaded++;
- }
-
- ahc_outb(ahc, SEQCTL, FASTMODE);
- ahc_outb(ahc, SEQADDR0, 0);
- ahc_outb(ahc, SEQADDR1, 0);
- if (bootverbose)
- printf("%s: %d instructions downloaded\n", ahc_name(ahc),
- downloaded);
-}
-
-static struct patch *
-ahc_next_patch(cur_patch, options, instrptr)
- struct patch *cur_patch;
- int options;
- int instrptr;
-{
- while(cur_patch != NULL) {
- if (((cur_patch->options & options) != 0
- && cur_patch->negative == FALSE)
- || ((cur_patch->options & options) == 0
- && cur_patch->negative == TRUE)
- || (instrptr >= cur_patch->end)) {
- /*
- * Either we want to keep this section of code,
- * or we have consumed this patch. Skip to the
- * next patch.
- */
- cur_patch++;
- if (cur_patch->options == 0)
- /* Out of patches */
- cur_patch = NULL;
- } else
- /* Found an okay patch */
- break;
- }
- return (cur_patch);
-}
-
-static void
-ahc_download_instr(struct ahc_softc *ahc, int options,
- int instrptr, u_int8_t *dconsts)
-{
- u_int8_t opcode;
- struct ins_format3 instr;
-
- /* Structure copy */
- instr = *(struct ins_format3 *)&seqprog[instrptr * 4];
-
- /* Pull the opcode */
- opcode = (instr.opcode_addr & ~DOWNLOAD_CONST_IMMEDIATE) >> 1;
- switch (opcode) {
- case AIC_OP_JMP:
- case AIC_OP_JC:
- case AIC_OP_JNC:
- case AIC_OP_CALL:
- case AIC_OP_JNE:
- case AIC_OP_JNZ:
- case AIC_OP_JE:
- case AIC_OP_JZ:
- {
- int address_offset;
- u_int address;
- struct patch *patch;
- int i;
-
- address_offset = 0;
- address = instr.address;
- address |= (instr.opcode_addr & ADDR_HIGH_BIT) << 8;
- for (i = 0; i < sizeof(patches)/sizeof(patches[0]); i++) {
- patch = &patches[i];
- if (((patch->options & options) == 0
- && patch->negative == FALSE)
- || ((patch->options & options) != 0
- && patch->negative == TRUE)) {
- if (address >= patch->end)
- address_offset +=
- patch->end - patch->begin;
- }
- }
- address -= address_offset;
- instr.address = address & 0xFF;
- instr.opcode_addr &= ~ADDR_HIGH_BIT;
- instr.opcode_addr |= (address >> 8) & ADDR_HIGH_BIT;
- /* FALLTHROUGH */
- }
- case AIC_OP_OR:
- case AIC_OP_AND:
- case AIC_OP_XOR:
- case AIC_OP_ADD:
- case AIC_OP_ADC:
- if ((instr.opcode_addr & DOWNLOAD_CONST_IMMEDIATE) != 0) {
- instr.immediate = dconsts[instr.immediate];
- }
- instr.opcode_addr &= ~DOWNLOAD_CONST_IMMEDIATE;
- /* FALLTHROUGH */
- case AIC_OP_ROL:
- ahc_outsb(ahc, SEQRAM, &instr.immediate, 4);
- break;
- default:
- panic("Unknown opcode encountered in seq program");
- break;
- }
-}
-
-/*
- * Function to poll for command completion when
- * interrupts are disabled (crash dumps)
- */
-static int
-ahc_poll(ahc, wait)
- struct ahc_softc *ahc;
- int wait; /* in msec */
-{
- while (--wait) {
- DELAY(1000);
- if (ahc_inb(ahc, INTSTAT) & INT_PEND)
- break;
- } if (wait == 0) {
- printf("%s: board is not responding\n", ahc_name(ahc));
- return (EIO);
- }
- ahc_intr((void *)ahc);
- return (0);
-}
-
-static void
-ahc_timeout(arg)
- void *arg;
-{
- struct scb *scb = (struct scb *)arg;
- struct ahc_softc *ahc;
- int s, found;
- u_int8_t bus_state;
- char channel;
-
- ahc = (struct ahc_softc *)scb->xs->sc_link->adapter_softc;
-
- s = splbio();
-
- /*
- * Ensure that the card doesn't do anything
- * behind our back. Also make sure that we
- * didn't "just" miss an interrupt that would
- * affect this timeout.
- */
- do {
- ahc_intr(ahc);
- pause_sequencer(ahc);
- } while (ahc_inb(ahc, INTSTAT) & INT_PEND);
-
- if (!(scb->flags & SCB_ACTIVE)) {
- /* Previous timeout took care of me already */
- printf("Timedout SCB handled by another timeout\n");
- unpause_sequencer(ahc, /*unpause_always*/TRUE);
- splx(s);
- return;
- }
-
- if (ahc->in_timeout) {
- /*
- * Some other SCB has started a recovery operation
- * and is still working on cleaning things up.
- */
- if ((scb->flags & SCB_RECOVERY_SCB) == 0) {
- /*
- * This is not the SCB that started this timeout
- * processing. Give this scb another lifetime so
- * that it can continue once we deal with the
- * timeout.
- */
- scb->flags |= SCB_TIMEDOUT;
- sc_print_addr(scb->xs->sc_link);
- printf("SCB 0x%x timedout while recovery in progress\n",
- scb->hscb->tag);
- scb->xs->timeout_ch =
- timeout(ahc_timeout, (caddr_t)scb,
- (scb->xs->timeout * hz) / 1000);
- unpause_sequencer(ahc, /*unpause_always*/TRUE);
- splx(s);
- return;
- }
- }
- ahc->in_timeout = TRUE;
-
- sc_print_addr(scb->xs->sc_link);
- printf("SCB 0x%x - timed out ", scb->hscb->tag);
- /*
- * Take a snapshot of the bus state and print out
- * some information so we can track down driver bugs.
- */
- bus_state = ahc_inb(ahc, LASTPHASE);
-
- switch(bus_state)
- {
- case P_DATAOUT:
- printf("in dataout phase");
- break;
- case P_DATAIN:
- printf("in datain phase");
- break;
- case P_COMMAND:
- printf("in command phase");
- break;
- case P_MESGOUT:
- printf("in message out phase");
- break;
- case P_STATUS:
- printf("in status phase");
- break;
- case P_MESGIN:
- printf("in message in phase");
- break;
- case P_BUSFREE:
- printf("while idle, LASTPHASE == 0x%x",
- bus_state);
- break;
- default:
- /*
- * We aren't in a valid phase, so assume we're
- * idle.
- */
- printf("invalid phase, LASTPHASE == 0x%x",
- bus_state);
- break;
- }
-
- printf(", SCSISIGI == 0x%x\n", ahc_inb(ahc, SCSISIGI));
-
- printf("SEQADDR = 0x%x SCSISEQ = 0x%x SSTAT0 = 0x%x SSTAT1 = 0x%x\n",
- ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8),
- ahc_inb(ahc, SCSISEQ), ahc_inb(ahc, SSTAT0),
- ahc_inb(ahc,SSTAT1));
- /* Decide our course of action */
-
- channel = (scb->hscb->tcl & SELBUSB) ? 'B': 'A';
- if (scb->flags & SCB_ABORT) {
- /*
- * Been down this road before.
- * Do a full bus reset.
- */
-bus_reset:
- scb->flags |= SCB_RECOVERY_SCB;
- found = ahc_reset_channel(ahc, channel, XS_TIMEOUT,
- /*Initiate Reset*/TRUE);
- printf("%s: Issued Channel %c Bus Reset. "
- "%d SCBs aborted\n", ahc_name(ahc), channel, found);
- } else if ((scb->hscb->control & TAG_ENB) != 0
- && (scb->flags & SCB_SENTORDEREDTAG) == 0) {
- /*
- * We could be starving this command
- * try sending an ordered tag command
- * to the target we come from.
- */
- u_int16_t mask;
-
- mask = (0x01 << (scb->xs->sc_link->target
- | (IS_SCSIBUS_B(ahc, scb->xs->sc_link) ?
- SELBUSB : 0)));
- scb->flags |= SCB_SENTORDEREDTAG|SCB_RECOVERY_SCB;
- ahc->orderedtag |= mask;
- scb->xs->timeout_ch = timeout(ahc_timeout, (caddr_t)scb,
- (5 * hz));
- unpause_sequencer(ahc, /*unpause_always*/TRUE);
- printf("Ordered Tag queued\n");
- } else {
- /*
- * Send an Abort Message:
- * The target that is holding up the bus may not
- * be the same as the one that triggered this timeout
- * (different commands have different timeout lengths).
- * Our strategy here is to queue an abort message
- * to the timed out target if it is disconnected.
- * Otherwise, if we have an active target we stuff the
- * message buffer with an abort message and assert ATN
- * in the hopes that the target will let go of the bus
- * and go to the mesgout phase. If this fails, we'll
- * get another timeout 2 seconds later which will attempt
- * a bus reset.
- */
- u_int8_t saved_scbptr;
- u_int8_t active_scb_index;
- struct scb *active_scb;
-
- saved_scbptr = ahc_inb(ahc, SCBPTR);
- active_scb_index = ahc_inb(ahc, SCB_TAG);
- active_scb = ahc->scb_data->scbarray[active_scb_index];
-
- if (bus_state != P_BUSFREE) {
- if (active_scb_index >= ahc->scb_data->numscbs) {
- /* Go "immediatly" to the bus reset */
- /*
- * XXX queue an abort for the timedout SCB
- * instead.
- */
- sc_print_addr(scb->xs->sc_link);
- printf("SCB %d: Yucky Immediate reset. "
- "Flags = 0x%x\n", scb->hscb->tag,
- scb->flags);
- goto bus_reset;
- }
- /* Send the abort to the active SCB */
- ahc_outb(ahc, MSG_LEN, 1);
- ahc_outb(ahc, MSG_OUT,
- (active_scb->hscb->control & TAG_ENB) == 0 ?
- MSG_ABORT : MSG_ABORT_TAG);
- ahc_outb(ahc, SCSISIGO, bus_state|ATNO);
- sc_print_addr(active_scb->xs->sc_link);
- printf("abort message in message buffer\n");
- active_scb->flags |= SCB_ABORT|SCB_RECOVERY_SCB;
- if (active_scb != scb) {
- untimeout(ahc_timeout,
- (caddr_t)active_scb,
- active_scb->xs->timeout_ch);
- /* Give scb a new lease on life */
- scb->xs->timeout_ch =
- timeout(ahc_timeout, (caddr_t)scb,
- (scb->xs->timeout * hz) / 1000);
- }
- active_scb->xs->timeout_ch =
- timeout(ahc_timeout, active_scb, 2 * hz);
- unpause_sequencer(ahc, /*unpause_always*/TRUE);
- } else {
- int disconnected;
- u_int8_t hscb_index;
- u_int8_t linked_next;
-
- disconnected = FALSE;
- hscb_index = ahc_find_scb(ahc, scb);
- if (hscb_index == SCB_LIST_NULL) {
- disconnected = TRUE;
- linked_next = (scb->hscb->datalen >> 24)
- & 0xFF;
- } else {
- ahc_outb(ahc, SCBPTR, hscb_index);
- if (ahc_inb(ahc, SCB_CONTROL) & DISCONNECTED)
- disconnected = TRUE;
- linked_next = ahc_inb(ahc, SCB_LINKED_NEXT);
- }
-
- if (disconnected) {
- /*
- * Simply set the ABORT_SCB control bit
- * and preserve the linked next pointer
- */
- scb->hscb->control |= ABORT_SCB|MK_MESSAGE;
- scb->hscb->datalen &= ~0xFF000000;
- scb->hscb->datalen |= linked_next << 24;
- if ((ahc->flags & AHC_PAGESCBS) == 0)
- scb->hscb->control &= ~DISCONNECTED;
- scb->flags |= SCB_QUEUED_ABORT
- | SCB_ABORT|SCB_RECOVERY_SCB;
- if (hscb_index != SCB_LIST_NULL) {
- u_int8_t scb_control;
-
- scb_control = ahc_inb(ahc, SCB_CONTROL);
- ahc_outb(ahc, SCB_CONTROL,
- scb_control | MK_MESSAGE
- | ABORT_SCB);
- }
- /*
- * Actually re-queue this SCB in case we can
- * select the device before it reconnects. If
- * the transaction we want to abort is not
- * tagged, unbusy it first so that we don't
- * get held back from sending the command.
- */
- if ((scb->hscb->control & TAG_ENB) == 0) {
- int target;
- int lun;
-
- target = scb->xs->sc_link->target;
- lun = scb->xs->sc_link->lun;
- ahc_search_qinfifo(ahc, target,
- channel,
- lun,
- SCB_LIST_NULL,
- 0, 0,
- /*requeue*/TRUE);
- }
- sc_print_addr(scb->xs->sc_link);
- printf("Queueing an Abort SCB\n");
- STAILQ_INSERT_HEAD(&ahc->waiting_scbs, scb,
- links);
- scb->flags |= SCB_WAITINGQ;
- scb->xs->timeout_ch =
- timeout(ahc_timeout, (caddr_t)scb,
- (2000 * hz) / 1000);
- ahc_outb(ahc, SCBPTR, saved_scbptr);
- /*
- * ahc_run_waiting_queue may unpause us
- * so do this last.
- */
- ahc_run_waiting_queue(ahc);
- /*
- * If we are using AAP, ahc_run_waiting_queue
- * will not unpause us, so ensure we are
- * unpaused.
- */
- unpause_sequencer(ahc, /*unpause_always*/FALSE);
- } else {
- /* Go "immediatly" to the bus reset */
- sc_print_addr(scb->xs->sc_link);
- printf("SCB %d: Immediate reset. "
- "Flags = 0x%x\n", scb->hscb->tag,
- scb->flags);
- goto bus_reset;
- }
- }
- }
- splx(s);
-}
-
-/*
- * Look through the SCB array of the card and attempt to find the
- * hardware SCB that corresponds to the passed in SCB. Return
- * SCB_LIST_NULL if unsuccessful. This routine assumes that the
- * card is already paused.
- */
-static u_int8_t
-ahc_find_scb(ahc, scb)
- struct ahc_softc *ahc;
- struct scb *scb;
-{
- u_int8_t saved_scbptr;
- u_int8_t curindex;
-
- saved_scbptr = ahc_inb(ahc, SCBPTR);
- for (curindex = 0; curindex < ahc->scb_data->maxhscbs; curindex++) {
- ahc_outb(ahc, SCBPTR, curindex);
- if (ahc_inb(ahc, SCB_TAG) == scb->hscb->tag)
- break;
- }
- ahc_outb(ahc, SCBPTR, saved_scbptr);
- if (curindex >= ahc->scb_data->maxhscbs)
- curindex = SCB_LIST_NULL;
-
- return curindex;
-}
-
-static int
-ahc_search_qinfifo(ahc, target, channel, lun, tag, flags, xs_error, requeue)
- struct ahc_softc *ahc;
- int target;
- char channel;
- int lun;
- u_int8_t tag;
- u_int32_t flags;
- u_int32_t xs_error;
- int requeue;
-{
- u_int8_t saved_queue[AHC_SCB_MAX];
- int queued = ahc_inb(ahc, QINCNT) & ahc->qcntmask;
- int i;
- int found;
- struct scb *scbp;
- STAILQ_HEAD(, scb) removed_scbs;
-
- found = 0;
- STAILQ_INIT(&removed_scbs);
- for (i = 0; i < (queued - found); i++) {
- saved_queue[i] = ahc_inb(ahc, QINFIFO);
- scbp = ahc->scb_data->scbarray[saved_queue[i]];
- if (ahc_match_scb(scbp, target, channel, lun, tag)) {
- /*
- * We found an scb that needs to be removed.
- */
- if (requeue) {
- STAILQ_INSERT_HEAD(&removed_scbs, scbp, links);
- } else {
- scbp->flags |= flags;
- scbp->flags &= ~SCB_ACTIVE;
- scbp->xs->error = xs_error;
- }
- i--;
- found++;
- }
- }
- /* Now put the saved scbs back. */
- for (queued = 0; queued < i; queued++)
- ahc_outb(ahc, QINFIFO, saved_queue[queued]);
-
- if (requeue) {
- while ((scbp = removed_scbs.stqh_first) != NULL) {
- STAILQ_REMOVE_HEAD(&removed_scbs, links);
- STAILQ_INSERT_HEAD(&ahc->waiting_scbs, scbp, links);
- scbp->flags |= SCB_WAITINGQ;
- }
- }
-
- return found;
-}
-
-
-/*
- * The device at the given target/channel has been reset. Abort
- * all active and queued scbs for that target/channel.
- */
-static int
-ahc_reset_device(ahc, target, channel, lun, tag, xs_error)
- struct ahc_softc *ahc;
- int target;
- char channel;
- int lun;
- u_int8_t tag;
- u_int32_t xs_error;
-{
- struct scb *scbp;
- u_int8_t active_scb;
- int i;
- int found;
-
- /* restore this when we're done */
- active_scb = ahc_inb(ahc, SCBPTR);
-
- /*
- * Deal with the busy target and linked next issues.
- */
- {
- int min_target, max_target;
- u_int8_t busy_scbid;
-
- /* Make all targets 'relative' to bus A */
- if (target == ALL_TARGETS) {
- switch (channel) {
- case 'A':
- min_target = 0;
- max_target = ahc->type & AHC_WIDE ? 15 : 7;
- break;
- case 'B':
- min_target = 8;
- max_target = 15;
- break;
- case ALL_CHANNELS:
- min_target = 0;
- max_target = ahc->type & (AHC_WIDE|AHC_TWIN)
- ? 15 : 7;
- break;
- default:
- /* Shutup warning */
- min_target = 0;
- max_target = 0;
- panic("ahc_reset_device: Bogus Channel");
- /* NOTREACHED */
- }
- } else {
- min_target = max_target
- = target + (channel == 'B' ? 8 : 0);
- }
-
- for (i = min_target; i <= max_target; i++) {
- busy_scbid = ahc_index_busy_target(ahc, i, 'A',
- /*unbusy*/FALSE);
- if (busy_scbid < ahc->scb_data->numscbs) {
- struct scb *busy_scb;
- struct scb *next_scb;
- u_int8_t next_scbid;
-
- busy_scb = ahc->scb_data->scbarray[busy_scbid];
-
- next_scbid = busy_scb->hscb->datalen >> 24;
-
- if (next_scbid == SCB_LIST_NULL) {
- busy_scbid = ahc_find_scb(ahc,
- busy_scb);
-
- if (busy_scbid != SCB_LIST_NULL) {
- ahc_outb(ahc, SCBPTR,
- busy_scbid);
- next_scbid = ahc_inb(ahc,
- SCB_LINKED_NEXT);
- }
- }
-
- if (ahc_match_scb(busy_scb, target, channel,
- lun, tag)) {
- ahc_index_busy_target(ahc, i, 'A',
- /*unbusy*/TRUE);
- }
-
- if (next_scbid != SCB_LIST_NULL) {
- next_scb = ahc->scb_data->scbarray[next_scbid];
- if (ahc_match_scb(next_scb, target,
- channel, lun, tag))
- continue;
- /* Requeue for later processing */
- STAILQ_INSERT_HEAD(&ahc->waiting_scbs,
- next_scb, links);
- next_scb->flags |= SCB_WAITINGQ;
- }
- }
- }
- }
- /*
- * Remove any entries from the Queue-In FIFO.
- */
- found = ahc_search_qinfifo(ahc, target, channel, lun, tag,
- SCB_ABORTED|SCB_QUEUED_FOR_DONE, xs_error,
- /*requeue*/FALSE);
-
- /*
- * Search waiting for selection list.
- */
- {
- u_int8_t next, prev;
-
- next = ahc_inb(ahc, WAITING_SCBH); /* Start at head of list. */
- prev = SCB_LIST_NULL;
-
- while (next != SCB_LIST_NULL) {
- u_int8_t scb_index;
-
- ahc_outb(ahc, SCBPTR, next);
- scb_index = ahc_inb(ahc, SCB_TAG);
- if (scb_index >= ahc->scb_data->numscbs) {
- panic("Waiting List inconsistency. "
- "SCB index == %d, yet numscbs == %d.",
- scb_index, ahc->scb_data->numscbs);
- }
- scbp = ahc->scb_data->scbarray[scb_index];
- if (ahc_match_scb(scbp, target, channel, lun, tag)) {
- u_int8_t linked_next;
-
- next = ahc_abort_wscb(ahc, scbp, next, prev,
- xs_error);
- linked_next = ahc_inb(ahc, SCB_LINKED_NEXT);
- if (linked_next != SCB_LIST_NULL) {
- struct scb *next_scb;
-
- /*
- * Re-queue the waiting SCB via the
- * waiting list.
- */
- next_scb =
- ahc->scb_data->scbarray[linked_next];
- if (!ahc_match_scb(next_scb, target,
- channel, lun, tag)) {
- STAILQ_INSERT_HEAD(&ahc->waiting_scbs,
- next_scb,
- links);
- next_scb->flags |= SCB_WAITINGQ;
- }
- }
- found++;
- } else {
- prev = next;
- next = ahc_inb(ahc, SCB_NEXT);
- }
- }
- }
- /*
- * Go through the disconnected list and remove any entries we
- * have queued for completion, 0'ing their control byte too.
- */
- {
- u_int8_t next, prev;
-
- next = ahc_inb(ahc, DISCONNECTED_SCBH);
- prev = SCB_LIST_NULL;
-
- while (next != SCB_LIST_NULL) {
- u_int8_t scb_index;
-
- ahc_outb(ahc, SCBPTR, next);
- scb_index = ahc_inb(ahc, SCB_TAG);
- if (scb_index >= ahc->scb_data->numscbs) {
- panic("Disconnected List inconsistency. "
- "SCB index == %d, yet numscbs == %d.",
- scb_index, ahc->scb_data->numscbs);
- }
- scbp = ahc->scb_data->scbarray[scb_index];
- if (ahc_match_scb(scbp, target, channel, lun, tag)) {
- next = ahc_rem_scb_from_disc_list(ahc, next);
- } else {
- prev = next;
- next = ahc_inb(ahc, SCB_NEXT);
- }
- }
- }
- /*
- * Go through the hardware SCB array looking for commands that
- * were active but not on any list.
- */
- for(i = 0; i < ahc->scb_data->maxhscbs; i++) {
- u_int8_t scbid;
-
- ahc_outb(ahc, SCBPTR, i);
- scbid = ahc_inb(ahc, SCB_TAG);
- if (scbid < ahc->scb_data->numscbs) {
- scbp = ahc->scb_data->scbarray[scbid];
- if (ahc_match_scb(scbp, target, channel, lun, tag)) {
- ahc_add_curscb_to_free_list(ahc);
- }
- }
- }
- /*
- * Go through the entire SCB array now and look for
- * commands for this target that are still active. These
- * are other tagged commands that were disconnected when
- * the reset occured or untagged commands that were linked
- * to the command that preceeded it.
- */
- for (i = 0; i < ahc->scb_data->numscbs; i++) {
- scbp = ahc->scb_data->scbarray[i];
- if ((scbp->flags & SCB_ACTIVE) != 0
- && ahc_match_scb(scbp, target, channel, lun, tag)) {
- scbp->flags |= SCB_ABORTED|SCB_QUEUED_FOR_DONE;
- scbp->flags &= ~SCB_ACTIVE;
- scbp->xs->error = xs_error;
- found++;
-
- if ((scbp->flags & SCB_WAITINGQ) != 0) {
- STAILQ_REMOVE(&ahc->waiting_scbs, scbp, scb,
- links);
- scbp->flags &= ~SCB_WAITINGQ;
- }
- }
- }
- ahc_outb(ahc, SCBPTR, active_scb);
- return found;
-}
-
-static u_int8_t
-ahc_rem_scb_from_disc_list(ahc, scbptr)
- struct ahc_softc *ahc;
- u_int8_t scbptr;
-{
- u_int8_t next;
- u_int8_t prev;
-
- ahc_outb(ahc, SCBPTR, scbptr);
- next = ahc_inb(ahc, SCB_NEXT);
- prev = ahc_inb(ahc, SCB_PREV);
-
- ahc_outb(ahc, SCB_CONTROL, 0);
-
- ahc_add_curscb_to_free_list(ahc);
-
- if (prev != SCB_LIST_NULL) {
- ahc_outb(ahc, SCBPTR, prev);
- ahc_outb(ahc, SCB_NEXT, next);
- } else
- ahc_outb(ahc, DISCONNECTED_SCBH, next);
-
- if (next != SCB_LIST_NULL) {
- ahc_outb(ahc, SCBPTR, next);
- ahc_outb(ahc, SCB_PREV, prev);
- }
- return next;
-}
-
-static void
-ahc_add_curscb_to_free_list(ahc)
- struct ahc_softc *ahc;
-{
- /* Invalidate the tag so that ahc_find_scb doesn't think it's active */
- ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL);
-
- ahc_outb(ahc, SCB_NEXT, ahc_inb(ahc, FREE_SCBH));
- ahc_outb(ahc, FREE_SCBH, ahc_inb(ahc, SCBPTR));
-}
-
-/*
- * Manipulate the waiting for selection list and return the
- * scb that follows the one that we remove.
- */
-static u_char
-ahc_abort_wscb (ahc, scbp, scbpos, prev, xs_error)
- struct ahc_softc *ahc;
- struct scb *scbp;
- u_int8_t scbpos;
- u_int8_t prev;
- u_int32_t xs_error;
-{
- u_int8_t curscb, next;
- /*
- * Select the SCB we want to abort and
- * pull the next pointer out of it.
- */
- curscb = ahc_inb(ahc, SCBPTR);
- ahc_outb(ahc, SCBPTR, scbpos);
- next = ahc_inb(ahc, SCB_NEXT);
-
- /* Clear the necessary fields */
- ahc_outb(ahc, SCB_CONTROL, 0);
-
- ahc_add_curscb_to_free_list(ahc);
-
- /* update the waiting list */
- if (prev == SCB_LIST_NULL)
- /* First in the list */
- ahc_outb(ahc, WAITING_SCBH, next);
- else {
- /*
- * Select the scb that pointed to us
- * and update its next pointer.
- */
- ahc_outb(ahc, SCBPTR, prev);
- ahc_outb(ahc, SCB_NEXT, next);
- }
-
- /*
- * Point us back at the original scb position
- * and inform the SCSI system that the command
- * has been aborted.
- */
- ahc_outb(ahc, SCBPTR, curscb);
- scbp->flags |= SCB_ABORTED|SCB_QUEUED_FOR_DONE;
- scbp->flags &= ~SCB_ACTIVE;
- scbp->xs->error = xs_error;
- return next;
-}
-
-static u_int8_t
-ahc_index_busy_target(ahc, target, channel, unbusy)
- struct ahc_softc *ahc;
- int target;
- char channel;
- int unbusy;
-{
- u_int8_t active_scb;
- u_int8_t info_scb;
- u_int8_t busy_scbid;
- u_int32_t scb_offset;
-
- info_scb = target / 4;
- if (channel == 'B')
- info_scb += 2;
- active_scb = ahc_inb(ahc, SCBPTR);
- ahc_outb(ahc, SCBPTR, info_scb);
- scb_offset = SCB_BUSYTARGETS + (target & 0x03);
- busy_scbid = ahc_inb(ahc, scb_offset);
- if (unbusy)
- ahc_outb(ahc, scb_offset, SCB_LIST_NULL);
- ahc_outb(ahc, SCBPTR, active_scb);
- return busy_scbid;
-}
-
-static void
-ahc_busy_target(ahc, target, channel, scbid)
- struct ahc_softc *ahc;
- int target;
- char channel;
- u_int8_t scbid;
-{
- u_int8_t active_scb;
- u_int8_t info_scb;
- u_int32_t scb_offset;
-
- info_scb = target / 4;
- if (channel == 'B')
- info_scb += 2;
- active_scb = ahc_inb(ahc, SCBPTR);
- ahc_outb(ahc, SCBPTR, info_scb);
- scb_offset = SCB_BUSYTARGETS + (target & 0x03);
- ahc_outb(ahc, scb_offset, scbid);
- ahc_outb(ahc, SCBPTR, active_scb);
- return;
-}
-
-static void
-ahc_clear_intstat(ahc)
- struct ahc_softc *ahc;
-{
- /* Clear any interrupt conditions this may have caused */
- ahc_outb(ahc, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO);
- ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI
- |CLRBUSFREE|CLRSCSIPERR|CLRPHASECHG|
- CLRREQINIT);
- ahc_outb(ahc, CLRINT, CLRSCSIINT);
-}
-
-static void
-ahc_reset_current_bus(ahc)
- struct ahc_softc *ahc;
-{
- u_int8_t scsiseq;
-
- ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENSCSIRST);
- scsiseq = ahc_inb(ahc, SCSISEQ);
- ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO);
-
- DELAY(AHC_BUSRESET_DELAY);
- /* Turn off the bus reset */
- ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO);
-
- ahc_clear_intstat(ahc);
-
- /* Re-enable reset interrupts */
- ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) | ENSCSIRST);
-}
-
-static int
-ahc_reset_channel(ahc, channel, xs_error, initiate_reset)
- struct ahc_softc *ahc;
- char channel;
- u_int32_t xs_error;
- int initiate_reset;
-{
- u_int32_t offset, offset_max;
- int found;
- u_int8_t sblkctl;
- char cur_channel;
-
- pause_sequencer(ahc);
- /*
- * Clean up all the state information for the
- * pending transactions on this bus.
- */
- found = ahc_reset_device(ahc, ALL_TARGETS, channel, ALL_LUNS,
- SCB_LIST_NULL, xs_error);
- if (channel == 'B') {
- ahc->needsdtr |= (ahc->needsdtr_orig & 0xff00);
- ahc->sdtrpending &= 0x00ff;
- ahc->orderedtag &= 0x00ff;
- offset = TARG_SCRATCH + 8;
- offset_max = TARG_SCRATCH + 16;
- } else if (ahc->type & AHC_WIDE){
- ahc->needsdtr = ahc->needsdtr_orig;
- ahc->needwdtr = ahc->needwdtr_orig;
- ahc->orderedtag = 0;
- ahc->sdtrpending = 0;
- ahc->wdtrpending = 0;
- offset = TARG_SCRATCH;
- offset_max = TARG_SCRATCH + 16;
- } else {
- ahc->needsdtr |= (ahc->needsdtr_orig & 0x00ff);
- ahc->sdtrpending &= 0xff00;
- ahc->orderedtag &= 0xff00;
- offset = TARG_SCRATCH;
- offset_max = TARG_SCRATCH + 8;
- }
-
- for (; offset < offset_max; offset++) {
- /*
- * Revert to async/narrow transfers
- * until we renegotiate.
- */
- u_int8_t targ_scratch;
-
- targ_scratch = ahc_inb(ahc, offset);
- targ_scratch &= SXFR;
- ahc_outb(ahc, offset, targ_scratch);
- }
-
- /*
- * Reset the bus if we are initiating this reset and
- * restart/unpause the sequencer
- */
- sblkctl = ahc_inb(ahc, SBLKCTL);
- cur_channel = (sblkctl & SELBUSB) ? 'B' : 'A';
- if (cur_channel != channel) {
- /* Case 1: Command for another bus is active
- * Stealthily reset the other bus without
- * upsetting the current bus.
- */
- ahc_outb(ahc, SBLKCTL, sblkctl ^ SELBUSB);
- ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
- if (initiate_reset)
- ahc_reset_current_bus(ahc);
- ahc_outb(ahc, SCSISEQ, 0);
- ahc_clear_intstat(ahc);
- ahc_outb(ahc, SBLKCTL, sblkctl);
- unpause_sequencer(ahc, /*unpause_always*/FALSE);
- } else {
- /* Case 2: A command from this bus is active or we're idle */
- ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
- if (initiate_reset)
- ahc_reset_current_bus(ahc);
- ahc_outb(ahc, SCSISEQ, 0);
- ahc_clear_intstat(ahc);
- restart_sequencer(ahc);
- }
- /*
- * Untimeout our scbs now in case we have to delay our done
- * processing.
- */
- ahc_untimeout_done_queue(ahc);
- ahc_run_done_queue(ahc);
- return found;
-}
-
-static void
-ahc_run_done_queue(ahc)
- struct ahc_softc *ahc;
-{
- int i;
- struct scb *scbp;
-
- for (i = 0; i < ahc->scb_data->numscbs; i++) {
- scbp = ahc->scb_data->scbarray[i];
- if (scbp->flags & SCB_QUEUED_FOR_DONE)
- ahc_done(ahc, scbp);
- }
-}
-
-static void
-ahc_untimeout_done_queue(ahc)
- struct ahc_softc *ahc;
-{
- int i;
- struct scb *scbp;
-
- for (i = 0; i < ahc->scb_data->numscbs; i++) {
- scbp = ahc->scb_data->scbarray[i];
- if (scbp->flags & SCB_QUEUED_FOR_DONE)
- untimeout(ahc_timeout, (caddr_t)scbp,
- scbp->xs->timeout_ch);
- }
-}
-
-static int
-ahc_match_scb (scb, target, channel, lun, tag)
- struct scb *scb;
- int target;
- char channel;
- int lun;
- u_int8_t tag;
-{
- int targ = (scb->hscb->tcl >> 4) & 0x0f;
- char chan = (scb->hscb->tcl & SELBUSB) ? 'B' : 'A';
- int slun = scb->hscb->tcl & 0x07;
- int match;
-
- match = ((chan == channel) || (channel == ALL_CHANNELS));
- if (match != 0)
- match = ((targ == target) || (target == ALL_TARGETS));
- if (match != 0)
- match = ((lun == slun) || (lun == ALL_LUNS));
- if (match != 0)
- match = ((tag == scb->hscb->tag) || (tag == SCB_LIST_NULL));
-
- return match;
-}
-
-static void
-ahc_construct_sdtr(ahc, start_byte, period, offset)
- struct ahc_softc *ahc;
- int start_byte;
- u_int8_t period;
- u_int8_t offset;
-{
- ahc_outb(ahc, MSG_OUT + start_byte, MSG_EXTENDED);
- ahc_outb(ahc, MSG_OUT + 1 + start_byte, MSG_EXT_SDTR_LEN);
- ahc_outb(ahc, MSG_OUT + 2 + start_byte, MSG_EXT_SDTR);
- ahc_outb(ahc, MSG_OUT + 3 + start_byte, period);
- ahc_outb(ahc, MSG_OUT + 4 + start_byte, offset);
- ahc_outb(ahc, MSG_LEN, start_byte + 5);
-}
-
-static void
-ahc_construct_wdtr(ahc, start_byte, bus_width)
- struct ahc_softc *ahc;
- int start_byte;
- u_int8_t bus_width;
-{
- ahc_outb(ahc, MSG_OUT + start_byte, MSG_EXTENDED);
- ahc_outb(ahc, MSG_OUT + 1 + start_byte, MSG_EXT_WDTR_LEN);
- ahc_outb(ahc, MSG_OUT + 2 + start_byte, MSG_EXT_WDTR);
- ahc_outb(ahc, MSG_OUT + 3 + start_byte, bus_width);
- ahc_outb(ahc, MSG_LEN, start_byte + 4);
-}
-
-static void
-ahc_calc_residual(scb)
- struct scb *scb;
-{
- struct scsi_xfer *xs;
- struct hardware_scb *hscb;
- int resid_sgs;
-
- xs = scb->xs;
- hscb = scb->hscb;
-
- /*
- * If the disconnected flag is still set, this is bogus
- * residual information left over from a sequencer
- * pagin/pageout, so ignore this case.
- */
- if ((scb->hscb->control & DISCONNECTED) == 0
- && (scb->flags & SCB_SENSE) == 0) {
- /*
- * Remainder of the SG where the transfer
- * stopped.
- */
- xs->resid = (hscb->residual_data_count[2] <<16) |
- (hscb->residual_data_count[1] <<8) |
- (hscb->residual_data_count[0]);
-
- /*
- * Add up the contents of all residual
- * SG segments that are after the SG where
- * the transfer stopped.
- */
- resid_sgs = scb->hscb->residual_SG_segment_count - 1;
- while (resid_sgs > 0) {
- int sg;
-
- sg = scb->sg_count - resid_sgs;
- xs->resid += scb->ahc_dma[sg].len;
- resid_sgs--;
- }
-#if defined(__FreeBSD__)
- xs->flags |= SCSI_RESID_VALID;
-#elif defined(__NetBSD__)
- /* XXX - Update to do this right */
-#endif
- }
-
- /*
- * Clean out the residual information in this SCB for its
- * next consumer.
- */
- hscb->residual_data_count[2] = 0;
- hscb->residual_data_count[1] = 0;
- hscb->residual_data_count[0] = 0;
- hscb->residual_SG_segment_count = 0;
-
-#ifdef AHC_DEBUG
- if (ahc_debug & AHC_SHOWMISC) {
- sc_print_addr(xs->sc_link);
- printf("Handled Residual of %ld bytes\n" ,xs->resid);
- }
-#endif
-}
diff --git a/sys/i386/scsi/aic7xxx.h b/sys/i386/scsi/aic7xxx.h
deleted file mode 100644
index 1794cec..0000000
--- a/sys/i386/scsi/aic7xxx.h
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * Interface to the generic driver for the aic7xxx based adaptec
- * SCSI controllers. This is used to implement product specific
- * probe and attach routines.
- *
- * Copyright (c) 1994-1997 Justin Gibbs.
- * 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,
- * without modification, immediately at the beginning of the file.
- * 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. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * Where this Software is combined with software released under the terms of
- * the GNU Public License ("GPL") and the terms of the GPL would require the
- * combined work to also be released under the terms of the GPL, the terms
- * and conditions of this License will apply in addition to those of the
- * GPL with the exception of any terms or conditions of this License that
- * conflict with, or are expressly prohibited by, the GPL.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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: aic7xxx.h,v 1.42 1997/08/13 17:02:47 gibbs Exp $
- */
-
-#ifndef _AIC7XXX_H_
-#define _AIC7XXX_H_
-
-#if defined(__FreeBSD__)
-#include "ahc.h" /* for NAHC from config */
-#include "opt_aic7xxx.h" /* for config options */
-#endif
-
-#if defined(__NetBSD__)
-/*
- * convert FreeBSD's <sys/queue.h> symbols to NetBSD's
- */
-#define STAILQ_ENTRY SIMPLEQ_ENTRY
-#define STAILQ_HEAD SIMPLEQ_HEAD
-#define STAILQ_INIT SIMPLEQ_INIT
-#define STAILQ_INSERT_HEAD SIMPLEQ_INSERT_HEAD
-#define STAILQ_INSERT_TAIL SIMPLEQ_INSERT_TAIL
-#define STAILQ_REMOVE_HEAD(head, field) \
- SIMPLEQ_REMOVE_HEAD(head, (head)->sqh_first, field)
-#define stqh_first sqh_first
-#define stqe_next sqe_next
-#endif
-
-#define AHC_NSEG 32 /* The number of dma segments supported.
- * AHC_NSEG can be maxed out at 256 entries,
- * but the kernel will never need to transfer
- * such a large (1MB) request. To reduce the
- * driver's memory consumption, we reduce the
- * max to 32. 16 would work if all transfers
- * are paged alined since the kernel will only
- * generate at most a 64k transfer, but to
- * handle non-page aligned transfers, you need
- * 17, so we round to the next power of two
- * to make allocating SG space easy and
- * efficient.
- */
-
-#define AHC_SCB_MAX 255 /*
- * Up to 255 SCBs on some types of aic7xxx
- * based boards. The aic7870 have 16 internal
- * SCBs, but external SRAM bumps this to 255.
- * The aic7770 family have only 4, and the
- * aic7850 has only 3.
- */
-
-
-typedef u_int32_t physaddr;
-#if defined(__FreeBSD__)
-extern u_long ahc_unit;
-#endif
-
-struct ahc_dma_seg {
- physaddr addr;
- u_int32_t len;
-};
-
-typedef enum {
- AHC_NONE = 0x0000,
- AHC_ULTRA = 0x0001, /* Supports 20MHz Transfers */
- AHC_WIDE = 0x0002, /* Wide Channel */
- AHC_TWIN = 0x0008, /* Twin Channel */
- AHC_AIC7770 = 0x0010,
- AHC_AIC7850 = 0x0020,
- AHC_AIC7860 = 0x0021, /* ULTRA version of the aic7850 */
- AHC_AIC7870 = 0x0040,
- AHC_AIC7880 = 0x0041,
- AHC_AIC78X0 = 0x0060, /* PCI Based Controller */
- AHC_274 = 0x0110, /* EISA Based Controller */
- AHC_284 = 0x0210, /* VL/ISA Based Controller */
- AHC_294AU = 0x0421, /* aic7860 based '2940' */
- AHC_294 = 0x0440, /* PCI Based Controller */
- AHC_294U = 0x0441, /* ULTRA PCI Based Controller */
- AHC_394 = 0x0840, /* Twin Channel PCI Controller */
- AHC_394U = 0x0841, /* ULTRA, Twin Channel PCI Controller */
- AHC_398 = 0x1040, /* Multi Channel PCI RAID Controller */
- AHC_398U = 0x1041, /* ULTRA, Multi Channel PCI
- * RAID Controller
- */
- AHC_39X = 0x1800 /* Multi Channel PCI Adapter */
-}ahc_type;
-
-typedef enum {
- AHC_FNONE = 0x00,
- AHC_INIT = 0x01,
- AHC_RUNNING = 0x02,
- AHC_PAGESCBS = 0x04, /* Enable SCB paging */
- AHC_CHANNEL_B_PRIMARY = 0x08, /*
- * On twin channel adapters, probe
- * channel B first since it is the
- * primary bus.
- */
- AHC_USEDEFAULTS = 0x10, /*
- * For cards without an seeprom
- * or a BIOS to initialize the chip's
- * SRAM, we use the default target
- * settings.
- */
- AHC_CHNLB = 0x20, /*
- * Second controller on 3940/398X
- * Also encodes the offset in the
- * SEEPROM for CHNLB info (32)
- */
- AHC_CHNLC = 0x40 /*
- * Third controller on 3985
- * Also encodes the offset in the
- * SEEPROM for CHNLC info (64)
- */
-} ahc_flag;
-
-typedef enum {
- SCB_FREE = 0x0000,
- SCB_ACTIVE = 0x0001,
- SCB_ABORTED = 0x0002,
- SCB_DEVICE_RESET = 0x0004,
- SCB_SENSE = 0x0008,
- SCB_TIMEDOUT = 0x0010,
- SCB_QUEUED_FOR_DONE = 0x0020,
- SCB_RECOVERY_SCB = 0x0040,
- SCB_WAITINGQ = 0x0080,
- SCB_ASSIGNEDQ = 0x0100,
- SCB_SENTORDEREDTAG = 0x0200,
- SCB_MSGOUT_SDTR = 0x0400,
- SCB_MSGOUT_WDTR = 0x0800,
- SCB_ABORT = 0x1000,
- SCB_QUEUED_ABORT = 0x2000
-} scb_flag;
-
-/*
- * The driver keeps up to MAX_SCB scb structures per card in memory. The SCB
- * consists of a "hardware SCB" mirroring the fields availible on the card
- * and additional information the kernel stores for each transaction.
- */
-struct hardware_scb {
-/*0*/ u_int8_t control;
-/*1*/ u_int8_t tcl; /* 4/1/3 bits */
-/*2*/ u_int8_t status;
-/*3*/ u_int8_t SG_segment_count;
-/*4*/ physaddr SG_list_pointer;
-/*8*/ u_int8_t residual_SG_segment_count;
-/*9*/ u_int8_t residual_data_count[3];
-/*12*/ physaddr data;
-/*16*/ u_int32_t datalen; /* Really only three bits, but its
- * faster to treat it as a long on
- * a quad boundary.
- */
-/*20*/ physaddr cmdpointer;
-/*24*/ u_int8_t cmdlen;
-/*25*/ u_int8_t tag; /* Index into our kernel SCB array.
- * Also used as the tag for tagged I/O
- */
-#define SCB_PIO_TRANSFER_SIZE 26 /* amount we need to upload/download
- * via PIO to initialize a transaction.
- */
-/*26*/ u_int8_t next; /* Used for threading SCBs in the
- * "Waiting for Selection" and
- * "Disconnected SCB" lists down
- * in the sequencer.
- */
-/*27*/ u_int8_t prev;
-
-/*28*/ u_int32_t pad; /*
- * Unused by the kernel, but we require
- * the padding so that the array of
- * hardware SCBs is alligned on 32 byte
- * boundaries so the sequencer can
- * index them easily.
- */
-};
-
-struct scb {
- struct hardware_scb *hscb;
- STAILQ_ENTRY(scb) links; /* for chaining */
- struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
- scb_flag flags;
- struct ahc_dma_seg *ahc_dma;/* Pointer to SG segments */
- struct scsi_sense sense_cmd;
- u_int8_t sg_count;/* How full ahc_dma_seg is */
- u_int8_t position;/* Position in card's scbarray */
-};
-
-struct scb_data {
- struct hardware_scb *hscbs; /* Array of hardware SCBs */
- struct scb *scbarray[AHC_SCB_MAX]; /* Array of kernel SCBs */
- STAILQ_HEAD(, scb) free_scbs; /*
- * Pool of SCBs ready to be assigned
- * commands to execute.
- */
- u_int8_t numscbs;
- u_int8_t maxhscbs; /* Number of SCBs on the card */
- u_int8_t maxscbs; /*
- * Max SCBs we allocate total including
- * any that will force us to page SCBs
- */
-};
-
-struct ahc_busreset_args {
- struct ahc_softc *ahc;
- char bus;
-};
-
-struct ahc_softc {
-#if defined(__FreeBSD__)
- int unit;
-#elif defined(__NetBSD__)
- struct device sc_dev;
- void *sc_ih;
- bus_chipset_tag_t sc_bc;
- bus_io_handle_t sc_ioh;
-#endif
- ahc_type type;
- ahc_flag flags;
-#if defined(__FreeBSD__)
- u_int32_t baseport;
-#endif
- volatile u_int8_t *maddr;
- struct scb_data *scb_data;
- struct scsi_link sc_link;
- struct scsi_link sc_link_b; /* Second bus for Twin channel cards */
- STAILQ_HEAD(, scb) waiting_scbs;/*
- * SCBs waiting ready to go but
- * waiting for space in the QINFIFO.
- */
- STAILQ_HEAD(, scb) cmplete_scbs;/*
- * SCBs out of the QOUTFIFO, waiting
- * to be ahc_done'd.
- */
- u_int8_t activescbs;
- u_int8_t cmdoutcnt;
- u_int16_t needsdtr_orig; /* Targets we initiate sync neg with */
- u_int16_t needwdtr_orig; /* Targets we initiate wide neg with */
- u_int16_t needsdtr; /* Current list of negotiated targets */
- u_int16_t needwdtr; /* Current list of negotiated targets */
- u_int16_t sdtrpending; /* Pending SDTR to these targets */
- u_int16_t wdtrpending; /* Pending WDTR to these targets */
- u_int16_t tagenable; /* Targets that can handle tags */
- u_int16_t orderedtag; /* Targets to use ordered tag on */
- u_int16_t discenable; /* Targets allowed to disconnect */
- u_int8_t our_id; /* our scsi id */
- u_int8_t our_id_b; /* B channel scsi id */
- u_int8_t qcntmask; /*
- * Mask of valid registers in the
- * Q*CNT registers.
- */
- u_int8_t qfullcount; /*
- * The maximum number of entries
- * storable in the Q*FIFOs.
- */
- u_int8_t curqincnt; /*
- * The current value we "think" the
- * QINCNT has. The reason it is
- * "think" is that this is a cached
- * value that is only updated when
- * curqincount == qfullcount to reduce
- * the amount of accesses made to the
- * card.
- */
- u_int8_t unpause;
- u_int8_t pause;
- u_int8_t in_timeout;
-};
-
-struct full_ahc_softc {
- struct ahc_softc softc;
- struct scb_data scb_data_storage;
-};
-
-/* #define AHC_DEBUG */
-#ifdef AHC_DEBUG
-/* Different debugging levels used when AHC_DEBUG is defined */
-#define AHC_SHOWMISC 0x0001
-#define AHC_SHOWCMDS 0x0002
-#define AHC_SHOWSCBS 0x0004
-#define AHC_SHOWABORTS 0x0008
-#define AHC_SHOWSENSE 0x0010
-#define AHC_SHOWSCBCNT 0x0020
-
-extern int ahc_debug; /* Initialized in i386/scsi/aic7xxx.c */
-#endif
-
-#if defined(__FreeBSD__)
-char *ahc_name __P((struct ahc_softc *ahc));
-
-struct ahc_softc *ahc_alloc __P((int unit, u_int32_t io_base,
- vm_offset_t maddr, ahc_type type,
- ahc_flag flags, struct scb_data *scb_data));
-#elif defined(__NetBSD__)
-
-#define ahc_name(ahc) (ahc)->sc_dev.dv_xname
-
-void ahc_construct __P((struct ahc_softc *ahc, bus_chipset_tag_t bc, bus_io_handle_t ioh, ahc_type type, ahc_flag flags));
-#endif
-void ahc_reset __P((struct ahc_softc *ahc));
-void ahc_free __P((struct ahc_softc *));
-int ahc_init __P((struct ahc_softc *));
-int ahc_attach __P((struct ahc_softc *));
-#if defined(__FreeBSD__)
-void ahc_intr __P((void *arg));
-#elif defined(__NetBSD__)
-int ahc_intr __P((void *arg));
-#endif
-
-#if defined(__FreeBSD__)
-static __inline u_int8_t ahc_inb __P((struct ahc_softc *ahc, u_int32_t port));
-static __inline void ahc_outb __P((struct ahc_softc *ahc, u_int32_t port,
- u_int8_t val));
-static __inline void ahc_outsb __P((struct ahc_softc *ahc, u_int32_t port,
- u_int8_t *valp, size_t size));
-
-static __inline u_int8_t
-ahc_inb(ahc, port)
- struct ahc_softc *ahc;
- u_int32_t port;
-{
- if (ahc->maddr != NULL)
- return ahc->maddr[port];
- else
- return inb(ahc->baseport + port);
-}
-
-static __inline void
-ahc_outb(ahc, port, val)
- struct ahc_softc *ahc;
- u_int32_t port;
- u_int8_t val;
-{
- if (ahc->maddr != NULL)
- ahc->maddr[port] = val;
- else
- outb(ahc->baseport + port, val);
-}
-
-static __inline void
-ahc_outsb(ahc, port, valp, size)
- struct ahc_softc *ahc;
- u_int32_t port;
- u_int8_t *valp;
- size_t size;
-{
- if (ahc->maddr != NULL) {
- __asm __volatile("
- cld;
- 1: lodsb;
- movb %%al,(%0);
- loop 1b" :
- :
- "r" ((ahc)->maddr + (port)),
- "S" ((valp)), "c" ((size)) :
- "%esi", "%ecx", "%eax");
- } else
- outsb(ahc->baseport + port, valp, size);
-}
-#elif defined(__NetBSD__)
-#define ahc_inb(ahc, port) \
- bus_io_read_1((ahc)->sc_bc, (ahc)->sc_ioh, port)
-#define ahc_outb(ahc, port, val) \
- bus_io_write_1((ahc)->sc_bc, (ahc)->sc_ioh, port, val)
-#define ahc_outsb(ahc, port, valp, size) \
- bus_io_write_multi_1((ahc)->sc_bc, (ahc)->sc_ioh, port, valp, size)
-#endif
-
-#endif /* _AIC7XXX_H_ */
diff --git a/sys/i386/scsi/bt.c b/sys/i386/scsi/bt.c
deleted file mode 100644
index d3d0ec0..0000000
--- a/sys/i386/scsi/bt.c
+++ /dev/null
@@ -1,1583 +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.
- *
- * $Id: bt.c,v 1.16 1998/02/20 13:37:37 bde Exp $
- */
-
-/*
- * Bulogic/Bustek 32 bit Addressing Mode SCSI driver.
- *
- * NOTE: 1. Some bt5xx card can NOT handle 32 bit addressing mode.
- * 2. OLD bt445s Revision A,B,C,D(nowired) + any firmware version
- * has broken busmaster for handling 32 bit addressing on H/W bus
- * side.
- *
- * 3. Extended probing still needs confirmation from our user base, due
- * to several H/W and firmware dependencies. If you have a problem
- * with extended probing, please contact 'amurai@spec.co.jp'
- *
- * amurai@spec.co.jp 94/6/16
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-
-#include <sys/malloc.h>
-#include <sys/buf.h>
-#include <sys/kernel.h>
-#include <sys/sysctl.h>
-
-#include <machine/clock.h>
-#include <machine/stdarg.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-
-#include <i386/scsi/btreg.h>
-
-struct bt_data *btdata[NBT];
-
-/*
- * I/O Port Interface
- */
-
-#define BT_BASE bt->bt_base
-#define BT_CTRL_STAT_PORT (BT_BASE + 0x0) /* control & status */
-/* ReadOps WriteOps */
-#define BT_HRST 0x80 /* Hardware reset */
-#define BT_SRST 0x40 /* Software reset */
-#define BT_IRST 0x20 /* Interrupt reset */
-#define BT_SCRST 0x10 /* SCSI bus reset */
-#define BT_STST 0x80 /* Self test in Progress */
-#define BT_DIAGF 0x40 /* Diagnostic Failure */
-#define BT_INIT 0x20 /* Mbx Init required */
-#define BT_IDLE 0x10 /* Host Adapter Idle */
-#define BT_CDF 0x08 /* cmd/data out port full */
-#define BT_DF 0x04 /* Data in port full */
-#define BT_INVDCMD 0x01 /* Invalid command */
-#define BT_STAT_MASK \
- (BT_STST | BT_DIAGF | BT_INIT | BT_IDLE | BT_CDF | BT_DF | BT_INVDCMD)
-
-#define BT_CMD_DATA_PORT (BT_BASE + 0x1) /* cmds and datas */
-/* ReadOps WriteOps */
-#define BT_NOP 0x00 /* No operation */
-#define BT_MBX_INIT 0x01 /* Mbx initialization */
-#define BT_START_SCSI 0x02 /* start scsi command */
-#define BT_START_BIOS 0x03 /* start bios command */
-#define BT_INQUIRE 0x04 /* Adapter Inquiry */
-#define BT_MBO_INTR_EN 0x05 /* Enable MBO available intr */
-#define BT_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
-#define BT_BUS_ON_TIME_SET 0x07 /* set bus-on time */
-#define BT_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
-#define BT_SPEED_SET 0x09 /* set transfer speed */
-#define BT_DEV_GET 0x0a /* return installed devices */
-#define BT_CONF_GET 0x0b /* return configuration data */
-#define BT_TARGET_EN 0x0c /* enable target mode */
-#define BT_SETUP_GET 0x0d /* return setup data */
-#define BT_WRITE_CH2 0x1a /* write channel 2 buffer */
-#define BT_READ_CH2 0x1b /* read channel 2 buffer */
-#define BT_WRITE_FIFO 0x1c /* write fifo buffer */
-#define BT_READ_FIFO 0x1d /* read fifo buffer */
-#define BT_ECHO 0x1e /* Echo command data */
-#define BT_MBX_INIT_EXTENDED 0x81 /* Mbx initialization */
-#define BT_INQUIRE_REV_THIRD 0x84 /* Get FirmWare version #3 */
-#define BT_INQUIRE_REV_FOURTH 0x85 /* Get FirmWare version #4 */
-#define BT_INQUIRE_EXTENDED 0x8D /* Adapter Setup Inquiry */
-/* The following commands appeared at FirmWare 3.31 */
-#define BT_ROUND_ROBIN 0x8f /* Enable/Disable round robin */
-#define BT_STRICT_ROUND_ROBIN 0x00 /* Parameter for strict mode */
-#define BT_AGRES_ROUND_ROBIN 0x01 /* Parameter for back compat */
-
-#define BT_INTR_PORT (BT_BASE + 0x2) /* Intr. stat */
-/* ReadOps WriteOps */
-#define BT_ANY_INTR 0x80 /* Any interrupt */
-#define BT_SCRD 0x08 /* SCSI reset detected */
-#define BT_HACC 0x04 /* Command complete */
-#define BT_MBOA 0x02 /* MBX out empty */
-#define BT_MBIF 0x01 /* MBX in full */
-
-struct bt_cmd_buf {
- u_char byte[16];
-};
-
-
-#define CCB_HASH_SHIFT 9 /* only hash on multiples of 512 */
-#define CCB_HASH(x) ((((long int)(x))>>CCB_HASH_SHIFT) % CCB_HASH_SIZE)
-
-#define bt_nextmbx( wmb, mbx, mbio ) \
- if ( (wmb) == &((mbx)->mbio[BT_MBX_SIZE - 1 ]) ) \
- (wmb) = &((mbx)->mbio[0]); \
- else \
- (wmb)++;
-
-struct bt_boardID {
- u_char board_type;
- u_char custom_feture;
- char firm_revision;
- u_char firm_version;
-};
-
-struct bt_setup {
- u_char sync_neg:1;
- u_char parity:1;
- u_char :6;
- u_char speed;
- u_char bus_on;
- u_char bus_off;
- u_char num_mbx;
- u_char mbx[3]; /* for backwards compatibility */
- struct {
- u_char offset:4;
- u_char period:3;
- u_char valid:1;
- } sync[8];
- u_char disc_sts;
-};
-
-struct bt_config {
- u_char chan;
-#define BUSDMA 0x00
-#define CHAN0 0x01
-#define CHAN5 0x20
-#define CHAN6 0x40
-#define CHAN7 0x80
- u_char intr;
-#define INT9 0x01
-#define INT10 0x02
-#define INT11 0x04
-#define INT12 0x08
-#define INT14 0x20
-#define INT15 0x40
- u_char scsi_dev:3; /* XXX What about Wide Controllers? */
- u_char :5;
-};
-
-
-
-/*
- * Determine 32bit address/Data firmware functionality from the bus type
- * Note: bt742a/747[s|d]/757/946/445s will return 'E'
- * bt542b/545s/545d will return 'A'
- * 94/05/18 amurai@spec.co.jp
- */
-struct bt_ext_info {
- u_char bus_type; /* Host adapter bus type */
-#define BT_BUS_TYPE_24bit 'A' /* PC/AT 24 bit address bus type */
-#define BT_BUS_TYPE_32bit 'E' /* EISA/VLB/PCI 32 bit address type */
-#define BT_BUS_TYPE_MCA 'M' /* Micro chanel? */
- u_char bios_addr; /* Bios Address-Not used */
- u_short max_seg; /* Max segment List */
- u_char num_mbx; /* Number of mailbox */
- int32_t mbx_base; /* mailbox base address */
- struct {
- u_char resv1:1; /* ??? */
- u_char force:1; /* ON: force sync */
- u_char maxsync:1; /* ON: 10MB/s , OFF: 5MB/s */
- u_char resv2:2; /* ??? */
- u_char sync:1; /* ON: Sync, OFF: async ONLY!! */
- u_char resv3:2; /* ??? */
- } s;
- u_char firmid[3]; /* Firmware ver. & rev. w/o last char */
-};
-
-#define BT_GET_BOARD_INFO 0x8b /* Get H/W ID and Revision */
-struct bt_board_info {
- u_char id[4]; /* i.e bt742a -> '7','4','2','A' */
- u_char ver[2]; /* i.e Board Revision 'H' -> 'H', 0x00 */
-};
-
-#define BT_GET_SYNC_VALUE 0x8c /* Get Synchronous Value */
-struct bt_sync_value {
- u_char value[8]; /* Synchrnous value (value * 10 nsec) */
-};
-
-
-#define KVTOPHYS(x) vtophys(x)
-#define PAGESIZ 4096
-#define INVALIDATE_CACHE {asm volatile( ".byte 0x0F ;.byte 0x08" ); }
-
-/***********debug values *************/
-#define BT_SHOWCCBS 0x01
-#define BT_SHOWINTS 0x02
-#define BT_SHOWCMDS 0x04
-#define BT_SHOWMISC 0x08
-static int bt_debug = 0;
-SYSCTL_INT(_debug, OID_AUTO, bt_debug, CTLFLAG_RW, &bt_debug, 0, "");
-
-static u_int32_t bt_adapter_info __P((int unit));
-static struct bt_ccb *
- bt_ccb_phys_kv __P((struct bt_data *bt, physaddr ccb_phys));
-static int bt_cmd __P((struct bt_data *bt, int icnt, int ocnt, int wait,
- u_char *retval, u_char opcode, ...));
-static void bt_done __P((struct bt_data *bt, struct bt_ccb *ccb));
-static void bt_free_ccb __P((struct bt_data *bt, struct bt_ccb *ccb,
- int flags));
-static struct bt_ccb *
- bt_get_ccb __P((struct bt_data *bt, int flags));
-static void bt_inquire_setup_information __P((struct bt_data *bt,
- struct bt_ext_info *info));
-static void btminphys __P((struct buf *bp));
-static int bt_poll __P((struct bt_data *bt, struct scsi_xfer *xs,
- struct bt_ccb *ccb));
-#ifdef UTEST
-static void bt_print_active_ccbs __P((int unit));
-static void bt_print_ccb __P((struct bt_ccb *ccb));
-#endif
-static int32_t bt_scsi_cmd __P((struct scsi_xfer *xs));
-static BT_MBO * bt_send_mbo __P((struct bt_data *bt, int flags, int cmd,
- struct bt_ccb *ccb));
-static timeout_t
- bt_timeout;
-
-u_long bt_unit = 0;
-static int btprobing = 1;
-
-/*
- * XXX
- * Do our own re-probe protection until a configuration
- * manager can do it for us. This ensures that we don't
- * reprobe a card already found by the EISA or PCI probes.
- */
-struct bt_found
-{
- u_long port;
- char probed;
-};
-
-static struct bt_found found[] =
-{
- { 0x330, 0 },
- { 0x334, 0 },
- { 0x230, 0 },
- { 0x234, 0 },
- { 0x130, 0 },
- { 0x134, 0 }
-};
-
-static struct scsi_adapter bt_switch =
-{
- bt_scsi_cmd,
- btminphys,
- 0,
- 0,
- bt_adapter_info,
- "bt",
- { 0, 0 }
-};
-
-/* the below structure is so we have a default dev struct for out link struct */
-static struct scsi_device bt_dev =
-{
- NULL, /* Use default error handler */
- NULL, /* have a queue, served by this */
- NULL, /* have no async handler */
- NULL, /* Use default 'done' routine */
- "bt",
- 0,
- { 0, 0 }
-};
-
-#define BT_RESET_TIMEOUT 1000
-
-/*
- * bt_cmd(bt, icnt, ocnt, wait, retval, opcode, ...)
- *
- * Activate Adapter command
- * icnt: number of args (outbound bytes written after opcode)
- * ocnt: number of expected returned bytes
- * wait: number of seconds to wait for response
- * retval: buffer where to place returned bytes
- * opcode: opcode BT_NOP, BT_MBX_INIT, BT_START_SCSI ...
- * ...: parameters to the command specified by opcode
- *
- * Performs an adapter command through the ports. Not to be confused with a
- * scsi command, which is read in via the dma; one of the adapter commands
- * tells it to read in a scsi command.
- */
-static int
-#ifdef __STDC__
-bt_cmd(struct bt_data *bt, int icnt, int ocnt, int wait, u_char *retval,
- u_char opcode, ...)
-#else
-bt_cmd(bt, icnt, ocnt, wait, retval, opcode, va_alist)
- struct bt_data *bt;
- int icnt, ocnt, wait;
- u_char *retval;
- u_char opcode;
- va_dcl
-#endif
-{
- va_list ap;
- u_char data;
- u_char oc;
- int i;
- int sts;
-
- /*
- * multiply the wait argument by a big constant
- * zero defaults to 1
- */
- if (wait)
- wait *= 100000;
- else
- wait = 100000;
- /*
- * Wait for the adapter to go idle, unless it's one of
- * the commands which don't need this
- */
- if (opcode != BT_MBX_INIT && opcode != BT_START_SCSI) {
- i = 100000; /* 1 sec? */
- while (--i) {
- sts = inb(BT_CTRL_STAT_PORT);
- if (sts & BT_IDLE) {
- break;
- }
- DELAY(10);
- }
- if (i == 0) {
- if(!btprobing)
- printf("bt%d: bt_cmd, host not idle(0x%x)\n",
- bt->unit, sts);
- return (ENXIO);
- }
- }
- /*
- * Now that it is idle, if we expect output, preflush the
- * queue feeding to us.
- */
- if (ocnt) {
- while ((inb(BT_CTRL_STAT_PORT)) & BT_DF)
- inb(BT_CMD_DATA_PORT);
- }
- /*
- * Output the command and the number of arguments given
- * for each byte, first check the port is empty.
- */
- va_start(ap, opcode);
- /* test icnt >= 0, to include the command in data sent */
- for (data = opcode; icnt >= 0; icnt--, data = (u_char)va_arg(ap, int)) {
- sts = inb(BT_CTRL_STAT_PORT);
- for (i = wait; i; i--) {
- sts = inb(BT_CTRL_STAT_PORT);
- if (!(sts & BT_CDF))
- break;
- DELAY(10);
- }
- if (i == 0) {
- if(!btprobing)
- printf("bt%d: bt_cmd, cmd/data port full\n",
- bt->unit);
- outb(BT_CTRL_STAT_PORT, BT_SRST);
- return (ENXIO);
- }
- outb(BT_CMD_DATA_PORT, data);
- }
- va_end(ap);
- /*
- * If we expect input, loop that many times, each time,
- * looking for the data register to have valid data
- */
- while (ocnt--) {
- sts = inb(BT_CTRL_STAT_PORT);
- for (i = wait; i; i--) {
- sts = inb(BT_CTRL_STAT_PORT);
- if (sts & BT_DF)
- break;
- DELAY(10);
- }
- if (i == 0) {
- if(!btprobing)
- printf("bt%d: bt_cmd, cmd/data port empty %d\n",
- bt->unit, ocnt);
- return (ENXIO);
- }
- oc = inb(BT_CMD_DATA_PORT);
- if (retval)
- *retval++ = oc;
- }
- /*
- * Wait for the board to report a finised instruction
- */
- i = 100000; /* 1 sec? */
- while (--i) {
- sts = inb(BT_INTR_PORT);
- if (sts & BT_HACC) {
- break;
- }
- DELAY(10);
- }
- if (i == 0) {
- if(!btprobing)
- printf("bt%d: bt_cmd, host not finished(0x%x)\n",
- bt->unit, sts);
- return (ENXIO);
- }
- outb(BT_CTRL_STAT_PORT, BT_IRST);
- return (0);
-}
-
-struct bt_data *
-bt_alloc(unit, iobase)
- int unit;
- u_long iobase;
-{
- struct bt_data *bt;
- int i;
-
- if (unit >= NBT) {
- printf("bt: unit number (%d) too high\n", unit);
- return NULL;
- }
-
- /*
- * Allocate a storage area for us
- */
- if (btdata[unit]) {
- printf("bt%d: memory already allocated\n", unit);
- return NULL;
- }
-
- /*
- * Ensure that we haven't already been probed
- */
- for (i=0; i < sizeof(found)/sizeof(struct bt_found); i++) {
- if (found[i].port == iobase) {
- if (found[i].probed)
- return NULL;
- else {
- found[i].probed = 1;
- break;
- }
- }
- }
-
- bt = malloc(sizeof(struct bt_data), M_DEVBUF, M_NOWAIT);
- if (!bt) {
- printf("bt%d: cannot malloc!\n", unit);
- return NULL;
- }
- bzero(bt, sizeof(struct bt_data));
- btdata[unit] = bt;
- bt->unit = unit;
- bt->bt_base = iobase;
-
- return(bt);
-}
-
-void
-bt_free(bt)
- struct bt_data *bt;
-{
- btdata[bt->unit] = NULL;
- free(bt, M_DEVBUF);
- return;
-}
-
-
-int
-bt_attach(bt)
- struct bt_data *bt;
-{
- struct scsibus_data *scbus;
-
- btprobing = 0;
- /*
- * fill in the prototype scsi_link.
- */
- bt->sc_link.adapter_unit = bt->unit;
- bt->sc_link.adapter_targ = bt->bt_scsi_dev;
- bt->sc_link.adapter_softc = bt;
- bt->sc_link.adapter = &bt_switch;
- bt->sc_link.device = &bt_dev;
- bt->sc_link.flags = bt->bt_bounce ? SDEV_BOUNCE : 0;
-
- /*
- * Prepare the scsibus_data area for the upperlevel
- * scsi code.
- */
- scbus = scsi_alloc_bus();
- /* XXX scbus->magtarg should be adjusted for Wide cards */
- if(!scbus)
- return 0;
- scbus->adapter_link = &bt->sc_link;
-
- /*
- * ask the adapter what subunits are present
- */
- scsi_attachdevs(scbus);
- return 1;
-}
-
-/*
- * Return some information to the caller about the adapter and its
- * capabilities.
- */
-static u_int32_t
-bt_adapter_info(unit)
- int unit;
-{
- return (2); /* 2 outstanding requests at a time per device */
-}
-
-/*
- * Catch an interrupt from the adaptor
- */
-void
-bt_intr(arg)
- void *arg;
-{
- BT_MBI *wmbi;
- struct bt_mbx *wmbx;
- struct bt_ccb *ccb;
- unsigned char stat;
- int i, wait;
- int found = 0;
- struct bt_data *bt;
-
- bt = (struct bt_data *)arg;
-
-#ifdef UTEST
- printf("bt_intr ");
-#endif
- /*
- * First acknowlege the interrupt, Then if it's
- * not telling about a completed operation
- * just return.
- */
- stat = inb(BT_INTR_PORT);
- if((stat & BT_STAT_MASK) == 0) {
- /* Shared interrupt */
- return;
- }
-
- /* Mail Box out empty ? */
- if (stat & BT_MBOA) {
- printf("bt%d: Available Free mbo post\n", bt->unit);
- /* Disable MBO available interrupt */
- outb(BT_CMD_DATA_PORT, BT_MBO_INTR_EN);
- wait = 100000; /* 1 sec enough? */
- for (i = wait; i; i--) {
- if (!(inb(BT_CTRL_STAT_PORT) & BT_CDF))
- break;
- DELAY(10);
- }
- if (i == 0) {
- printf("bt%d: bt_intr, cmd/data port full\n", bt->unit);
- outb(BT_CTRL_STAT_PORT, BT_SRST);
- return;
- }
- outb(BT_CMD_DATA_PORT, 0x00); /* Disable */
- wakeup((caddr_t)&bt->bt_mbx);
- outb(BT_CTRL_STAT_PORT, BT_IRST);
- return;
- }
- if (!(stat & BT_MBIF)) {
- outb(BT_CTRL_STAT_PORT, BT_IRST);
- return;
- }
- /*
- * If it IS then process the competed operation
- */
- wmbx = &bt->bt_mbx;
- wmbi = wmbx->tmbi;
- AGAIN:
- while (wmbi->stat != BT_MBI_FREE) {
- ccb = bt_ccb_phys_kv(bt, (wmbi->ccb_addr));
- if (!ccb) {
- wmbi->stat = BT_MBI_FREE;
- printf("bt: BAD CCB ADDR!\n");
- continue;
- }
- found++;
- if ((stat = wmbi->stat) != BT_MBI_OK) {
- switch (stat) {
- case BT_MBI_ABORT:
-#ifdef UTEST
- if (bt_debug & BT_SHOWMISC)
- printf("abort ");
-#endif
- ccb->host_stat = BT_ABORTED;
- break;
-
- case BT_MBI_UNKNOWN:
- ccb = (struct bt_ccb *) 0;
-#ifdef UTEST
- if (bt_debug & BT_SHOWMISC)
- printf("unknown ccb for abort");
-#endif
- break;
-
- case BT_MBI_ERROR:
- break;
-
- default:
- panic("Impossible mbxi status");
-
- }
-#ifdef UTEST
- if ((bt_debug & BT_SHOWCMDS) && ccb) {
- u_char *cp;
- cp = ccb->scsi_cmd;
- printf("op=%x %x %x %x %x %x\n",
- cp[0], cp[1], cp[2],
- cp[3], cp[4], cp[5]);
- printf("stat %x for mbi addr = 0x%08x\n"
- ,wmbi->stat, wmbi);
- printf("addr = 0x%x\n", ccb);
- }
-#endif
- }
- wmbi->stat = BT_MBI_FREE;
- if (ccb) {
- untimeout(bt_timeout, (caddr_t)ccb,
- ccb->xfer->timeout_ch);
- bt_done(bt, ccb);
- }
- /* Set the IN mail Box pointer for next */ bt_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
- for (i = 0; i < BT_MBX_SIZE; i++) {
- if (wmbi->stat != BT_MBI_FREE) {
- found++;
- break;
- }
- bt_nextmbx(wmbi, wmbx, mbi);
- }
- if (!found) {
-#ifdef DEBUG
- printf(
- "bt%d: mbi at %p should be found, stat=%02x..resync\n",
- bt->unit, wmbi, stat);
-#endif
- } else {
- found = 0;
- goto AGAIN;
- }
- }
- wmbx->tmbi = wmbi;
- outb(BT_CTRL_STAT_PORT, BT_IRST);
-}
-
-/*
- * A ccb is put onto the free list.
- */
-static void
-bt_free_ccb(bt, ccb, flags)
- struct bt_data *bt;
- struct bt_ccb *ccb;
- int flags;
-{
- unsigned int opri;
-
- opri = splbio();
-
- ccb->next = bt->bt_ccb_free;
- bt->bt_ccb_free = ccb;
- ccb->flags = CCB_FREE;
- /*
- * If there were none, wake anybody waiting for one to come free,
- * starting with queued entries.
- */
- if (!ccb->next) {
- wakeup((caddr_t)&bt->bt_ccb_free);
- }
-
- splx(opri);
-}
-
-/*
- * Get a free ccb
- *
- * If there are none, see if we can allocate a new one. If so, put it in
- * the hash table too otherwise either return an error or sleep.
- */
-static struct bt_ccb *
-bt_get_ccb(bt, flags)
- struct bt_data *bt;
- int flags;
-{
- unsigned opri;
- struct bt_ccb *ccbp;
- int hashnum;
-
- opri = splbio();
- /*
- * If we can and have to, sleep waiting for one to come free
- * but only if we can't allocate a new one.
- */
- while (!(ccbp = bt->bt_ccb_free)) {
- if (bt->numccbs < BT_CCB_MAX) {
- if (ccbp = (struct bt_ccb *) malloc(sizeof(struct bt_ccb),
- M_TEMP,
- M_NOWAIT)) {
- bzero(ccbp, sizeof(struct bt_ccb));
- bt->numccbs++;
- ccbp->flags = CCB_ACTIVE;
- /*
- * put in the phystokv hash table
- * Never gets taken out.
- */
- ccbp->hashkey = KVTOPHYS(ccbp);
- hashnum = CCB_HASH(ccbp->hashkey);
- ccbp->nexthash = bt->ccbhash[hashnum];
- bt->ccbhash[hashnum] = ccbp;
- } else {
- printf("bt%d: Can't malloc CCB\n", bt->unit);
- }
- goto gottit;
- } else {
- if (!(flags & SCSI_NOSLEEP)) {
- tsleep((caddr_t)&bt->bt_ccb_free, PRIBIO,
- "btccb", 0);
- continue;
- }
- break;
- }
- }
- if (ccbp) {
- /* Get CCB from from free list */
- bt->bt_ccb_free = ccbp->next;
- ccbp->flags = CCB_ACTIVE;
- }
- gottit:
- splx(opri);
-
- return (ccbp);
-}
-
-/*
- * given a physical address, find the ccb that
- * it corresponds to:
- */
-static struct bt_ccb *
-bt_ccb_phys_kv(bt, ccb_phys)
- struct bt_data *bt;
- physaddr ccb_phys;
-{
- int hashnum = CCB_HASH(ccb_phys);
- struct bt_ccb *ccbp = bt->ccbhash[hashnum];
-
- while (ccbp) {
- if (ccbp->hashkey == ccb_phys)
- break;
- ccbp = ccbp->nexthash;
- }
- return ccbp;
-}
-
-/*
- * Get a MBO and then Send it
- */
-static BT_MBO *
-bt_send_mbo(bt, flags, cmd, ccb)
- struct bt_data *bt;
- int flags;
- int cmd;
- struct bt_ccb *ccb;
-{
- unsigned opri;
- BT_MBO *wmbo; /* Mail Box Out pointer */
- struct bt_mbx *wmbx; /* Mail Box pointer specified unit */
- int i, wait;
-
- wmbx = &bt->bt_mbx;
-
- opri = splbio();
-
- /* Get the Target OUT mail Box pointer and move to Next */
- wmbo = wmbx->tmbo;
- wmbx->tmbo = (wmbo == &(wmbx->mbo[BT_MBX_SIZE - 1]) ?
- &(wmbx->mbo[0]) : wmbo + 1);
-
- /*
- * Check the outmail box is free or not.
- * Note: Under the normal operation, it shuld NOT happen to wait.
- */
- while (wmbo->cmd != BT_MBO_FREE) {
- wait = 100000; /* 1 sec enough? */
- /* Enable MBO available interrupt */
- outb(BT_CMD_DATA_PORT, BT_MBO_INTR_EN);
- for (i = wait; i; i--) {
- if (!(inb(BT_CTRL_STAT_PORT) & BT_CDF))
- break;
- DELAY(10);
- }
- if (i == 0) {
- printf("bt%d: bt_send_mbo, cmd/data port full\n", bt->unit);
- outb(BT_CTRL_STAT_PORT, BT_SRST);
- return ((BT_MBO *) 0);
- }
- outb(BT_CMD_DATA_PORT, 0x01); /* Enable */
- tsleep((caddr_t)wmbx, PRIBIO, "btsend", 0);
- /* XXX */ /*can't do this! */
- /* May be servicing an int */
- }
- /* Link CCB to the Mail Box */
- wmbo->ccb_addr = KVTOPHYS(ccb);
- ccb->mbx = wmbo;
- wmbo->cmd = cmd;
-
- /* Send it! */
- outb(BT_CMD_DATA_PORT, BT_START_SCSI);
-
- splx(opri);
-
- return (wmbo);
-}
-
-/*
- * We have a ccb which has been processed by the
- * adaptor, now we look to see how the operation
- * went. Wake up the owner if waiting
- */
-static void
-bt_done(bt, ccb)
- struct bt_data *bt;
- struct bt_ccb *ccb;
-{
- struct scsi_sense_data *s1, *s2;
- struct scsi_xfer *xs = ccb->xfer;
-
- SC_DEBUG(xs->sc_link, SDEV_DB2, ("bt_done\n"));
- /*
- * Otherwise, put the results of the operation
- * into the xfer and call whoever started it
- */
- if ((ccb->host_stat != BT_OK || ccb->target_stat != SCSI_OK)
- && (!(xs->flags & SCSI_ERR_OK))) {
-
- s1 = &(ccb->scsi_sense);
- s2 = &(xs->sense);
-
- if (ccb->host_stat) {
- switch (ccb->host_stat) {
- case BT_ABORTED: /* No response */
- SC_DEBUG(xs->sc_link, SDEV_DB3,
- ("timeout reported back\n"));
- xs->error = XS_TIMEOUT;
- break;
- case BT_SEL_TIMEOUT:
- SC_DEBUG(xs->sc_link, SDEV_DB3,
- ("selection timeout reported back\n"));
- xs->error = XS_SELTIMEOUT;
- break;
- default: /* Other scsi protocol messes */
- xs->error = XS_DRIVER_STUFFUP;
- SC_DEBUG(xs->sc_link, SDEV_DB3,
- ("unexpected host_stat: %x\n",
- ccb->host_stat));
- }
- } else {
- switch (ccb->target_stat) {
- case 0x02:
- *s2 = *s1;
- xs->error = XS_SENSE;
- break;
- case 0x08:
- xs->error = XS_BUSY;
- break;
- default:
- SC_DEBUG(xs->sc_link, SDEV_DB3,
- ("unexpected target_stat: %x\n",
- ccb->target_stat));
- xs->error = XS_DRIVER_STUFFUP;
- }
- }
- } else { /* All went correctly OR errors expected */
- xs->resid = 0;
- }
- xs->flags |= ITSDONE;
- bt_free_ccb(bt, ccb, xs->flags);
- scsi_done(xs);
-}
-
-/*
- * Start the board, ready for normal operation
- */
-int
-bt_init(bt)
- struct bt_data* bt;
-{
- unsigned char ad[4];
- volatile int i, sts;
- struct bt_config conf;
- struct bt_ext_info info;
- struct bt_board_info binfo;
-
- /*
- * reset board, If it doesn't respond, assume
- * that it's not there.. good for the probe
- */
-
- outb(BT_CTRL_STAT_PORT, BT_HRST | BT_SRST);
-
- DELAY(10000);
-
- for (i = BT_RESET_TIMEOUT; i; i--) {
- sts = inb(BT_CTRL_STAT_PORT);
- if (sts == (BT_IDLE | BT_INIT))
- break;
- DELAY(1000);
- }
- if (i == 0) {
-#ifdef UTEST
- printf("bt_init: No answer from board\n");
-#endif
- return (ENXIO);
- }
-
- DELAY(10000);
-
- /*
- * Displaying Board ID and Hardware Revision
- * 94/05/18 amurai@spec.co.jp
- */
- i = bt_cmd(bt, 1, sizeof(binfo),0,
- (u_char *)&binfo,BT_GET_BOARD_INFO,sizeof(binfo));
- if(i)
- return i;
- printf("bt%d: Bt%c%c%c%c/%c%d-", bt->unit,
- binfo.id[0],
- binfo.id[1],
- binfo.id[2],
- binfo.id[3],
- binfo.ver[0],
- (unsigned) binfo.ver[1]
- );
-
- /*
- * Make sure board has a capability of 32bit addressing.
- * and Firmware also need a capability of 32bit addressing pointer
- * in Extended mailbox and ccb structure.
- * 94/05/18 amurai@spec.co.jp
- */
- bt_cmd(bt, 1, sizeof(info),0, (u_char *)&info, BT_INQUIRE_EXTENDED,
- sizeof(info));
- switch (info.bus_type) {
- case BT_BUS_TYPE_24bit: /* PC/AT 24 bit address bus */
- printf("ISA(24bit) bus\n");
- break;
- case BT_BUS_TYPE_32bit: /* EISA/VLB/PCI 32 bit bus */
- printf("(32bit) bus\n");
- break;
- case BT_BUS_TYPE_MCA: /* forget it right now */
- printf("MCA bus architecture...");
- printf("giving up\n");
- return (ENXIO);
- break;
- default:
- printf("Unknown state...");
- printf("giving up\n");
- return (ENXIO);
- break;
- }
-
- if ( binfo.id[0] == '4' && binfo.id[1] == '4' && binfo.id[2] == '5' &&
- binfo.id[3] == 'S' ) {
- printf("bt%d: Your card cannot DMA above 16MB boundary. Bounce buffering enabled.\n", bt->unit);
- bt->bt_bounce++;
- } else if ( binfo.id[0] == '5' ) {
- printf("bt%d: This driver is designed for using 32 bit addressing\n"
- "bt%d: mode firmware and EISA/PCI/VLB bus architectures\n"
- "bt%d: Bounce-buffering will be used (and is necessary)\n"
- "bt%d: if you have more than 16MBytes memory.\n",
- bt->unit,
- bt->unit,
- bt->unit,
- bt->unit);
- bt->bt_bounce++;
- } else if ( info.bus_type == BT_BUS_TYPE_24bit ) {
- printf("bt%d: Your board should report a 32bit bus architecture type..\n"
- "bt%d: The firmware on your board may have a problem with over\n"
- "bt%d: 16MBytes memory handling with this driver.\n",
- bt->unit,
- bt->unit,
- bt->unit);
- bt->bt_bounce++;
- }
-
- /*
- * Assume we have a board at this stage
- * setup dma channel from jumpers and save int
- * level
- */
- printf("bt%d: reading board settings, ", bt->unit);
-
- bt_cmd(bt, 0, sizeof(conf), 0, (u_char *)&conf, BT_CONF_GET);
- switch (conf.chan) {
- case BUSDMA:
- bt->bt_dma = -1;
- break;
- case CHAN0:
- outb(0x0b, 0x0c);
- outb(0x0a, 0x00);
- bt->bt_dma = 0;
- break;
- case CHAN5:
- outb(0xd6, 0xc1);
- outb(0xd4, 0x01);
- bt->bt_dma = 5;
- break;
- case CHAN6:
- outb(0xd6, 0xc2);
- outb(0xd4, 0x02);
- bt->bt_dma = 6;
- break;
- case CHAN7:
- outb(0xd6, 0xc3);
- outb(0xd4, 0x03);
- bt->bt_dma = 7;
- break;
- default:
- printf("illegal dma setting %x\n", conf.chan);
- return (EIO);
- }
- if (bt->bt_dma == -1)
- printf("busmastering, ");
- else
- printf("dma=%d, ", bt->bt_dma);
-
- switch (conf.intr) {
- case INT9:
- bt->bt_int = 9;
- break;
- case INT10:
- bt->bt_int = 10;
- break;
- case INT11:
- bt->bt_int = 11;
- break;
- case INT12:
- bt->bt_int = 12;
- break;
- case INT14:
- bt->bt_int = 14;
- break;
- case INT15:
- bt->bt_int = 15;
- break;
- default:
- printf("illegal int setting\n");
- return (EIO);
- }
- printf("int=%d\n", bt->bt_int);
-
- /* who are we on the scsi bus */
- bt->bt_scsi_dev = conf.scsi_dev;
- /*
- * Initialize mail box
- */
- *((physaddr *) ad) = KVTOPHYS(&bt->bt_mbx);
- bt_cmd(bt, 5, 0, 0, 0, BT_MBX_INIT_EXTENDED
- ,BT_MBX_SIZE
- ,ad[0]
- ,ad[1]
- ,ad[2]
- ,ad[3]);
-
- /*
- * Set Pointer chain null for just in case
- * Link the ccb's into a free-list W/O mbox
- * Initialize mail box status to free
- */
- if (bt->bt_ccb_free != (struct bt_ccb *) 0) {
- printf("bt%d: bt_ccb_free is NOT initialized but init here\n",
- bt->unit);
- bt->bt_ccb_free = (struct bt_ccb *) 0;
- }
- for (i = 0; i < BT_MBX_SIZE; i++) {
- bt->bt_mbx.mbo[i].cmd = BT_MBO_FREE;
- bt->bt_mbx.mbi[i].stat = BT_MBI_FREE;
- }
- /*
- * Set up initial mail box for round-robin operation.
- */
- bt->bt_mbx.tmbo = &bt->bt_mbx.mbo[0];
- bt->bt_mbx.tmbi = &bt->bt_mbx.mbi[0];
- bt_inquire_setup_information(bt, &info);
-
-
- /*
- * Note that we are going and return (to probe)
- */
- return 0;
-}
-
-static void
-bt_inquire_setup_information(bt, info)
- struct bt_data* bt;
- struct bt_ext_info *info;
-{
- struct bt_setup setup;
- struct bt_sync_value sync;
- char dummy[8];
- char sub_ver[3];
- struct bt_boardID bID;
- int i;
-
- /* Inquire Installed Devices */
- bzero( &dummy[0], sizeof(dummy) );
- bt_cmd(bt, 0, sizeof(dummy), 100, &dummy[0], BT_DEV_GET);
-
- /*
- * If board has a capbility of Syncrhonouse mode,
- * Get a SCSI Synchronous value
- */
-
- if (info->s.force) { /* Assume fast sync capability */
- info->s.sync = 1; /* It's appear at 4.25? version */
- info->s.maxsync = 1;
- }
- if ( info->s.sync ) {
- bt_cmd(bt, 1, sizeof(sync), 100,
- (u_char *)&sync,BT_GET_SYNC_VALUE,sizeof(sync));
- }
-
- /*
- * Inquire Board ID to board for firmware version
- */
- bt_cmd(bt, 0, sizeof(bID), 0, (u_char *)&bID, BT_INQUIRE);
- bt_cmd(bt, 0, 1, 0, &sub_ver[0], BT_INQUIRE_REV_THIRD );
- i = ((int)(bID.firm_revision-'0')) * 10 + (int)(bID.firm_version-'0');
- if ( i >= 33 ) {
- bt_cmd(bt, 0, 1, 0, &sub_ver[1], BT_INQUIRE_REV_FOURTH );
- } else {
- /*
- * Below rev 3.3 firmware has a problem for issuing
- * the BT_INQUIRE_REV_FOURTH command.
- */
- sub_ver[1]='\0';
- }
- sub_ver[2]='\0';
- if (sub_ver[1]==' ')
- sub_ver[1]='\0';
- printf("bt%d: version %c.%c%s, ",
- bt->unit, bID.firm_revision, bID.firm_version, sub_ver );
-
- /*
- * Obtain setup information from board.
- */
- bt_cmd(bt, 1, sizeof(setup), 0, (u_char *)&setup, BT_SETUP_GET,
- sizeof(setup));
-
- if (setup.sync_neg && info->s.sync ) {
- if ( info->s.maxsync ) {
- printf("fast sync, "); /* Max 10MB/s */
- } else {
- printf("sync, "); /* Max 5MB/s */
- }
- } else {
- if ( info->s.sync ) {
- printf("async, "); /* Never try by board */
- } else {
- printf("async only, "); /* Doesn't has a capability on board */
- }
- }
- if (setup.parity) {
- printf("parity, ");
- } else {
- printf("no parity, ");
- }
- printf("%d mbxs, %d ccbs\n", setup.num_mbx, BT_CCB_MAX);
-
- /*
- * Displayi SCSI negotiation value by each target.
- * amurai@spec.co.jp
- */
- for (i = 0; i < 8; i++) {
- if (!setup.sync[i].valid )
- continue;
- if ( (!setup.sync[i].offset && !setup.sync[i].period)
- || !info->s.sync ) {
- printf("bt%d: targ %d async\n", bt->unit, i);
- } else {
- printf("bt%d: targ %d sync rate=%2d.%02dMB/s(%dns), offset=%02d\n",
- bt->unit, i,
- 100 / sync.value[i],
- (100 % sync.value[i]) * 100 / sync.value[i],
- sync.value[i] * 10,
- setup.sync[i].offset );
- }
- }
-
- /*
- * Enable round-robin scheme - appeared at firmware rev. 3.31
- * Below rev 3.XX firmware has a problem for issuing
- * BT_ROUND_ROBIN command amurai@spec.co.jp
- */
- if ( bID.firm_revision >= '3' ) {
- printf("bt%d: Using Strict Round robin scheme\n", bt->unit);
- bt_cmd(bt, 1, 0, 0, 0, BT_ROUND_ROBIN, BT_STRICT_ROUND_ROBIN);
- } else {
- printf("bt%d: Not using Strict Round robin scheme\n", bt->unit);
- }
-
-}
-
-#ifndef min
-#define min(x,y) (x < y ? x : y)
-#endif /* min */
-
-static void
-btminphys(bp)
- struct buf *bp;
-{
- if (bp->b_bcount > ((BT_NSEG - 1) * PAGESIZ)) {
- bp->b_bcount = ((BT_NSEG - 1) * PAGESIZ);
- }
-}
-
-/*
- * start a scsi operation given the command and the data address. Also needs
- * the unit, target and lu.
- */
-static int32_t
-bt_scsi_cmd(xs)
- struct scsi_xfer *xs;
-{
- struct bt_ccb *ccb;
- struct bt_scat_gath *sg;
- int seg; /* scatter gather seg being worked on */
- int thiskv;
- physaddr thisphys, nextphys;
- int bytes_this_seg, bytes_this_page, datalen, flags;
- struct bt_data *bt;
-
- bt = (struct bt_data *)xs->sc_link->adapter_softc;
-
- SC_DEBUG(xs->sc_link, SDEV_DB2, ("bt_scsi_cmd\n"));
- /*
- * get a ccb (mbox-out) to use. If the transfer
- * is from a buf (possibly from interrupt time)
- * then we can't allow it to sleep
- */
- flags = xs->flags;
- if (flags & ITSDONE) {
- printf("bt%d: Already done?\n", bt->unit);
- xs->flags &= ~ITSDONE;
- }
- if (!(flags & INUSE)) {
- printf("bt%d: Not in use?\n", bt->unit);
- xs->flags |= INUSE;
- }
- if (!(ccb = bt_get_ccb(bt, flags))) {
- xs->error = XS_DRIVER_STUFFUP;
- return (TRY_AGAIN_LATER);
- }
- SC_DEBUG(xs->sc_link, SDEV_DB3,
- ("start ccb(%p)\n", ccb));
- /*
- * Put all the arguments for the xfer in the ccb
- */
- ccb->xfer = xs;
- if (flags & SCSI_RESET) {
- ccb->opcode = BT_RESET_CCB;
- } else {
- /* can't use S/G if zero length */
- ccb->opcode = (xs->datalen ?
- BT_INIT_SCAT_GATH_CCB
- : BT_INITIATOR_CCB);
- }
- ccb->target = xs->sc_link->target;
- ccb->data_out = 0;
- ccb->data_in = 0;
- ccb->lun = xs->sc_link->lun;
- ccb->scsi_cmd_length = xs->cmdlen;
- ccb->sense_ptr = KVTOPHYS(&(ccb->scsi_sense));
- ccb->req_sense_length = sizeof(ccb->scsi_sense);
-
- if ((xs->datalen) && (!(flags & SCSI_RESET))) { /* can use S/G only if not zero length */
- ccb->data_addr = KVTOPHYS(ccb->scat_gath);
- sg = ccb->scat_gath;
- seg = 0;
-#ifdef TFS
- if (flags & SCSI_DATA_UIO) {
- struct iovec *iovp;
-
- iovp = ((struct uio *) xs->data)->uio_iov;
- datalen = ((struct uio *) xs->data)->uio_iovcnt;
- xs->datalen = 0;
- while ((datalen) && (seg < BT_NSEG)) {
- sg->seg_addr = (physaddr) iovp->iov_base;
- xs->datalen += sg->seg_len = iovp->iov_len;
- SC_DEBUGN(xs->sc_link, SDEV_DB4, ("(0x%x@0x%x)"
- ,iovp->iov_len, iovp->iov_base));
- sg++;
- iovp++;
- seg++;
- datalen--;
- }
- } else
-#endif /* TFS */
- {
- /*
- * Set up the scatter gather block
- */
-
- SC_DEBUG(xs->sc_link, SDEV_DB4,
- ("%ld @%p:- ", xs->datalen, xs->data));
- datalen = xs->datalen;
- thiskv = (int) xs->data;
- thisphys = KVTOPHYS(thiskv);
-
- while ((datalen) && (seg < BT_NSEG)) {
- bytes_this_seg = 0;
-
- /* put in the base address */
- sg->seg_addr = thisphys;
-
- SC_DEBUGN(xs->sc_link, SDEV_DB4,
- ("0x%lx", thisphys));
-
- /* do it at least once */
- nextphys = thisphys;
- while ((datalen) && (thisphys == nextphys))
- /*
- * This page is contiguous (physically) with
- * the the last, just extend the length
- */
- {
- /* how far to the end of the page */
- nextphys = (thisphys & (~(PAGESIZ - 1)))
- + PAGESIZ;
- bytes_this_page = nextphys - thisphys;
- /**** or the data ****/
- bytes_this_page = min(bytes_this_page
- ,datalen);
- bytes_this_seg += bytes_this_page;
- datalen -= bytes_this_page;
-
- /* get more ready for the next page */
- thiskv = (thiskv & (~(PAGESIZ - 1)))
- + PAGESIZ;
- if (datalen)
- thisphys = KVTOPHYS(thiskv);
- }
- /*
- * next page isn't contiguous, finish the seg
- */
- SC_DEBUGN(xs->sc_link, SDEV_DB4,
- ("(0x%x)", bytes_this_seg));
- sg->seg_len = bytes_this_seg;
- sg++;
- seg++;
- }
- }
- /* end of iov/kv decision */
- ccb->data_length = seg * sizeof(struct bt_scat_gath);
- SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n"));
- if (datalen) {
- /*
- * there's still data, must have run out of segs!
- */
- printf("bt%d: bt_scsi_cmd, more than %d DMA segs\n",
- bt->unit, BT_NSEG);
- xs->error = XS_DRIVER_STUFFUP;
- bt_free_ccb(bt, ccb, flags);
- return (HAD_ERROR);
- }
- } else { /* No data xfer, use non S/G values */
- ccb->data_addr = (physaddr) 0;
- ccb->data_length = 0;
- }
- ccb->link_id = 0;
- ccb->link_addr = (physaddr) 0;
- /*
- * Put the scsi command in the ccb and start it
- */
- if (!(flags & SCSI_RESET)) {
- bcopy(xs->cmd, ccb->scsi_cmd, ccb->scsi_cmd_length);
- }
- if (bt_send_mbo(bt, flags, BT_MBO_START, ccb) == (BT_MBO *) 0) {
- xs->error = XS_DRIVER_STUFFUP;
- bt_free_ccb(bt, ccb, flags);
- return (TRY_AGAIN_LATER);
- }
- /*
- * Usually return SUCCESSFULLY QUEUED
- */
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_sent\n"));
- if (!(flags & SCSI_NOMASK)) {
- xs->timeout_ch = timeout(bt_timeout, (caddr_t)ccb,
- (xs->timeout * hz) / 1000);
- return (SUCCESSFULLY_QUEUED);
- }
- /*
- * If we can't use interrupts, poll on completion
- */
- return (bt_poll(bt, xs, ccb));
-}
-
-/*
- * Poll a particular unit, looking for a particular xs
- */
-static int
-bt_poll(bt, xs, ccb)
- struct bt_data* bt;
- struct scsi_xfer *xs;
- struct bt_ccb *ccb;
-{
- int count = xs->timeout;
- u_char stat;
-
- /* timeouts are in msec, so we loop in 1000 usec cycles */
- while (count) {
- /*
- * If we had interrupts enabled, would we
- * have got an interrupt?
- */
- stat = inb(BT_INTR_PORT);
- if (stat & BT_ANY_INTR) {
- bt_intr((void *)bt);
- }
- if (xs->flags & ITSDONE) {
- break;
- }
- DELAY(1000); /* only happens in boot so ok */
- count--;
- }
- if (count == 0) {
- /*
- * We timed out, so call the timeout handler manually,
- * accounting for the fact that the clock is not running yet
- * by taking out the clock queue entry it makes.
- */
- bt_timeout(ccb);
-
- /*
- * because we are polling, take out the timeout entry
- * bt_timeout made
- */
- untimeout(bt_timeout, (caddr_t)ccb, ccb->xfer->timeout_ch);
- count = 2000;
- while (count) {
- /*
- * Once again, wait for the int bit
- */
- stat = inb(BT_INTR_PORT);
- if (stat & BT_ANY_INTR) {
- bt_intr((void *)bt);
- }
- if (xs->flags & ITSDONE) {
- break;
- }
- DELAY(1000); /* only happens in boot so ok */
- count--;
- }
- if (count == 0) {
- /*
- * We timed out again... This is bad. Notice that
- * this time there is no clock queue entry to remove.
- */
- bt_timeout(ccb);
- }
- }
- if (xs->error)
- return (HAD_ERROR);
- return (COMPLETE);
-}
-
-static void
-bt_timeout(void *arg1)
-{
- struct bt_ccb * ccb = (struct bt_ccb *)arg1;
- int unit;
- struct bt_data *bt;
- int s = splbio();
-
- /*
- * A timeout routine in kernel DONOT unlink
- * Entry chains when time outed....So infinity Loop..
- * 94/04/20 amurai@spec.co.jp
- */
- untimeout(bt_timeout, (caddr_t)ccb, ccb->xfer->timeout_ch);
-
- unit = ccb->xfer->sc_link->adapter_unit;
- bt = btdata[unit];
-
-#ifdef UTEST
- bt_print_active_ccbs(bt);
-#endif
-
- /*
- * If the ccb's mbx is not free, then the board has gone Far East?
- */
- if (bt_ccb_phys_kv(bt, ccb->mbx->ccb_addr) == ccb &&
- ccb->mbx->cmd != BT_MBO_FREE) {
- printf("bt%d: not taking commands!\n", unit);
- Debugger("bt742a");
- }
- /*
- * If it has been through before, then
- * a previous abort has failed, don't
- * try abort again
- */
- if (ccb->flags == CCB_ABORTED) {
- /*
- * abort timed out
- */
- printf("bt%d: Abort Operation has timed out\n", unit);
- ccb->xfer->retries = 0; /* I MEAN IT ! */
- ccb->host_stat = BT_ABORTED;
- bt_done(bt, ccb);
- } else {
- /* abort the operation that has timed out */
- printf("bt%d: Try to abort\n", unit);
- bt_send_mbo(bt, ~SCSI_NOMASK, BT_MBO_ABORT, ccb);
- /* 2 secs for the abort */
- ccb->flags = CCB_ABORTED;
- ccb->xfer->timeout_ch = timeout(bt_timeout, (caddr_t)ccb,
- 2 * hz);
- }
- splx(s);
-}
-
-#ifdef UTEST
-static void
-bt_print_ccb(ccb)
- struct bt_ccb *ccb;
-{
- printf("ccb:%x op:%x cmdlen:%d senlen:%d\n"
- ,ccb
- ,ccb->opcode
- ,ccb->scsi_cmd_length
- ,ccb->req_sense_length);
- printf(" datlen:%d hstat:%x tstat:%x flags:%x\n"
- ,ccb->data_length
- ,ccb->host_stat
- ,ccb->target_stat
- ,ccb->flags);
-}
-
-static void
-bt_print_active_ccbs(bt)
- struct bt_data *bt;
-{
- struct bt_ccb *ccb;
- int i = 0;
-
- while (i < CCB_HASH_SIZE) {
- ccb = bt->ccbhash[i];
- while (ccb) {
- if (ccb->flags != CCB_FREE)
- bt_print_ccb(ccb);
- ccb = ccb->nexthash;
- }
- i++;
- }
-}
-#endif /*UTEST */
diff --git a/sys/i386/scsi/btreg.h b/sys/i386/scsi/btreg.h
deleted file mode 100644
index 8475fa5..0000000
--- a/sys/i386/scsi/btreg.h
+++ /dev/null
@@ -1,149 +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
- * organizations 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: btreg.h,v 1.6 1997/02/22 09:38:43 peter Exp $
- */
-
-#ifndef _BTREG_H_
-#define _BTREG_H_
-
-#include "bt.h"
-
-/*
- * Mail box defs etc.
- * these could be bigger but we need the bt_data to fit on a single page..
- */
-
-#define BT_MBX_SIZE 32 /* mail box size (MAX 255 MBxs) */
- /* don't need that many really */
-#define BT_CCB_MAX 32 /* store up to 32CCBs at any one time */
- /* in bt742a H/W ( Not MAX ? ) */
-#define CCB_HASH_SIZE 32 /* when we have a physical addr. for */
- /* a ccb and need to find the ccb in */
- /* space, look it up in the hash table */
-#define BT_NSEG 33 /*
- * Number of SG segments per command
- * Max of 2048???
- */
-
-typedef unsigned long int physaddr;
-
-struct bt_scat_gath {
- unsigned long seg_len;
- physaddr seg_addr;
-};
-
-typedef struct bt_mbx_out {
- physaddr ccb_addr;
- unsigned char dummy[3];
- unsigned char cmd;
-} BT_MBO;
-
-typedef struct bt_mbx_in {
- physaddr ccb_addr;
- unsigned char btstat;
- unsigned char sdstat;
- unsigned char dummy;
- unsigned char stat;
-} BT_MBI;
-
-struct bt_mbx {
- BT_MBO mbo[BT_MBX_SIZE];
-#define BT_MBO_FREE 0x0 /* MBO intry is free */
-#define BT_MBO_START 0x1 /* MBO activate entry */
-#define BT_MBO_ABORT 0x2 /* MBO abort entry */
- BT_MBI mbi[BT_MBX_SIZE];
-#define BT_MBI_FREE 0x0 /* MBI entry is free */
-#define BT_MBI_OK 0x1 /* completed without error */
-#define BT_MBI_ABORT 0x2 /* aborted ccb */
-#define BT_MBI_UNKNOWN 0x3 /* Tried to abort invalid CCB */
-#define BT_MBI_ERROR 0x4 /* Completed with error */
- BT_MBO *tmbo; /* Target Mail Box out */
- BT_MBI *tmbi; /* Target Mail Box in */
-};
-
-
-struct bt_ccb {
- unsigned char opcode;
-#define BT_INITIATOR_CCB 0x00 /* SCSI Initiator CCB */
-#define BT_TARGET_CCB 0x01 /* SCSI Target CCB */
-#define BT_INIT_SCAT_GATH_CCB 0x02 /* SCSI Initiator w/sg */
-#define BT_RESET_CCB 0x81 /* SCSI Bus reset */
- unsigned :3, data_in:1, data_out:1,:3;
- unsigned char scsi_cmd_length;
- unsigned char req_sense_length;
- unsigned long data_length;
- physaddr data_addr;
- unsigned char dummy[2];
- unsigned char host_stat;
-#define BT_OK 0x00 /* cmd ok */
-#define BT_LINK_OK 0x0a /* Link cmd ok */
-#define BT_LINK_IT 0x0b /* Link cmd ok + int */
-#define BT_SEL_TIMEOUT 0x11 /* Selection time out */
-#define BT_OVER_UNDER 0x12 /* Data over/under run */
-#define BT_BUS_FREE 0x13 /* Bus dropped at unexpected time */
-#define BT_INV_BUS 0x14 /* Invalid bus phase/sequence */
-#define BT_BAD_MBO 0x15 /* Incorrect MBO cmd */
-#define BT_BAD_CCB 0x16 /* Incorrect ccb opcode */
-#define BT_BAD_LINK 0x17 /* Not same values of LUN for links */
-#define BT_INV_TARGET 0x18 /* Invalid target direction */
-#define BT_CCB_DUP 0x19 /* Duplicate CCB received */
-#define BT_INV_CCB 0x1a /* Invalid CCB or segment list */
-#define BT_ABORTED 42 /* pseudo value from driver */
- unsigned char target_stat;
- unsigned char target;
- unsigned char lun;
- unsigned char scsi_cmd[12]; /* 12 bytes (bytes only) */
- unsigned char dummy2[1];
- unsigned char link_id;
- physaddr link_addr;
- physaddr sense_ptr;
- struct scsi_sense_data scsi_sense;
- struct bt_scat_gath scat_gath[BT_NSEG];
- struct bt_ccb *next;
- struct scsi_xfer *xfer; /* the scsi_xfer for this cmd */
- struct bt_mbx_out *mbx; /* pointer to mail box */
- int flags;
-#define CCB_FREE 0
-#define CCB_ACTIVE 1
-#define CCB_ABORTED 2
- struct bt_ccb *nexthash; /* if two hash the same */
- physaddr hashkey; /*physaddr of this ccb */
-};
-
-struct bt_data {
- int bt_base; /* base port for each board */
- struct bt_mbx bt_mbx; /* all our mailboxes */
- struct bt_ccb *bt_ccb_free; /* list of free CCBs */
- struct bt_ccb *ccbhash[CCB_HASH_SIZE]; /* phys to kv hash */
- int bt_int; /* int. read off board */
- int bt_dma; /* DMA channel read of board */
- int bt_scsi_dev; /* adapters scsi id */
- int numccbs; /* how many we have malloc'd */
- int bt_bounce; /* should we bounce? */
- int unit; /* The zero in bt0 */
- struct scsi_link sc_link; /* prototype for devs */
-};
-
-extern struct bt_data *btdata[NBT];
-
-extern u_long bt_unit;
-
-struct bt_data *bt_alloc __P((int unit, u_long iobase));
-void bt_free __P((struct bt_data *bt));
-void bt_intr __P((void *arg));
-int bt_init __P((struct bt_data *bt));
-int bt_attach __P((struct bt_data *bt));
-
-#endif /* _BT_H_ */
diff --git a/sys/pci/aic7870.c b/sys/pci/aic7870.c
deleted file mode 100644
index 0445576..0000000
--- a/sys/pci/aic7870.c
+++ /dev/null
@@ -1,997 +0,0 @@
-/*
- * Product specific probe and attach routines for:
- * 3940, 2940, aic7880, aic7870, aic7860 and aic7850 SCSI controllers
- *
- * Copyright (c) 1995-1997 Justin Gibbs.
- * 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,
- * without modification, immediately at the beginning of the file.
- * 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. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * Where this Software is combined with software released under the terms of
- * the GNU Public License ("GPL") and the terms of the GPL would require the
- * combined work to also be released under the terms of the GPL, the terms
- * and conditions of this License will apply in addition to those of the
- * GPL with the exception of any terms or conditions of this License that
- * conflict with, or are expressly prohibited by, the GPL.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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: aic7870.c,v 1.55 1998/07/06 18:38:57 gibbs Exp $
- */
-
-#if defined(__FreeBSD__)
-#include "pci.h"
-#endif
-#if NPCI > 0 || defined(__NetBSD__)
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/queue.h>
-#if defined(__NetBSD__)
-#include <sys/device.h>
-#include <machine/bus.h>
-#include <machine/intr.h>
-#endif /* defined(__NetBSD__) */
-
-#include <scsi/scsiconf.h>
-
-#if defined(__FreeBSD__)
-
-#include <pci/pcireg.h>
-#include <pci/pcivar.h>
-
-#include <machine/clock.h>
-
-#include <i386/scsi/aic7xxx.h>
-#include <i386/scsi/93cx6.h>
-
-#include "aic7xxx_reg.h"
-
-#define PCI_BASEADR0 PCI_MAP_REG_START /* I/O Address */
-#define PCI_BASEADR1 PCI_MAP_REG_START + 4 /* Mem I/O Address */
-
-#elif defined(__NetBSD__)
-
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcivar.h>
-
-#include <dev/ic/aic7xxxreg.h>
-#include <dev/ic/aic7xxxvar.h>
-#include <dev/ic/smc93cx6var.h>
-
-#define bootverbose 1
-#define PCI_BASEADR0 PCI_MAPREG_START /* I/O Address */
-#define PCI_BASEADR1 PCI_MAPREG_START + 4 /* Mem I/O Address */
-
-#endif /* defined(__NetBSD__) */
-
-#define PCI_DEVICE_ID_ADAPTEC_398XU 0x83789004ul
-#define PCI_DEVICE_ID_ADAPTEC_3940U 0x82789004ul
-#define PCI_DEVICE_ID_ADAPTEC_2944U 0x84789004ul
-#define PCI_DEVICE_ID_ADAPTEC_2940U 0x81789004ul
-#define PCI_DEVICE_ID_ADAPTEC_2940AU 0x61789004ul
-#define PCI_DEVICE_ID_ADAPTEC_398X 0x73789004ul
-#define PCI_DEVICE_ID_ADAPTEC_3940 0x72789004ul
-#define PCI_DEVICE_ID_ADAPTEC_2944 0x74789004ul
-#define PCI_DEVICE_ID_ADAPTEC_2940 0x71789004ul
-#define PCI_DEVICE_ID_ADAPTEC_AIC7880 0x80789004ul
-#define PCI_DEVICE_ID_ADAPTEC_AIC7870 0x70789004ul
-#define PCI_DEVICE_ID_ADAPTEC_AIC7860 0x60789004ul
-#define PCI_DEVICE_ID_ADAPTEC_AIC7855 0x55789004ul
-#define PCI_DEVICE_ID_ADAPTEC_AIC7850 0x50789004ul
-#define PCI_DEVICE_ID_ADAPTEC_AIC7810 0x10789004ul
-
-#define DEVCONFIG 0x40
-#define MPORTMODE 0x00000400ul /* aic7870 only */
-#define RAMPSM 0x00000200ul /* aic7870 only */
-#define VOLSENSE 0x00000100ul
-#define SCBRAMSEL 0x00000080ul
-#define MRDCEN 0x00000040ul
-#define EXTSCBTIME 0x00000020ul /* aic7870 only */
-#define EXTSCBPEN 0x00000010ul /* aic7870 only */
-#define BERREN 0x00000008ul
-#define DACEN 0x00000004ul
-#define STPWLEVEL 0x00000002ul
-#define DIFACTNEGEN 0x00000001ul /* aic7870 only */
-
-#define CSIZE_LATTIME 0x0c
-#define CACHESIZE 0x0000003ful /* only 5 bits */
-#define LATTIME 0x0000ff00ul
-
-/*
- * Define the format of the aic78X0 SEEPROM registers (16 bits).
- */
-
-struct seeprom_config {
-
-/*
- * SCSI ID Configuration Flags
- */
-#define CFXFER 0x0007 /* synchronous transfer rate */
-#define CFSYNCH 0x0008 /* enable synchronous transfer */
-#define CFDISC 0x0010 /* enable disconnection */
-#define CFWIDEB 0x0020 /* wide bus device */
-/* UNUSED 0x00C0 */
-#define CFSTART 0x0100 /* send start unit SCSI command */
-#define CFINCBIOS 0x0200 /* include in BIOS scan */
-#define CFRNFOUND 0x0400 /* report even if not found */
-/* UNUSED 0xf800 */
- u_int16_t device_flags[16]; /* words 0-15 */
-
-/*
- * BIOS Control Bits
- */
-#define CFSUPREM 0x0001 /* support all removeable drives */
-#define CFSUPREMB 0x0002 /* support removeable drives for boot only */
-#define CFBIOSEN 0x0004 /* BIOS enabled */
-/* UNUSED 0x0008 */
-#define CFSM2DRV 0x0010 /* support more than two drives */
-/* UNUSED 0x0060 */
-#define CFEXTEND 0x0080 /* extended translation enabled */
-/* UNUSED 0xff00 */
- u_int16_t bios_control; /* word 16 */
-
-/*
- * Host Adapter Control Bits
- */
-#define CFAUTOTERM 0x0001 /* Perform Auto termination */
-#define CFULTRAEN 0x0002 /* Ultra SCSI speed enable */
-#define CFSTERM 0x0004 /* SCSI low byte termination */
-#define CFWSTERM 0x0008 /* SCSI high byte termination */
-#define CFSPARITY 0x0010 /* SCSI parity */
-/* UNUSED 0x0020 */
-#define CFRESETB 0x0040 /* reset SCSI bus at boot */
-/* UNUSED 0xff80 */
- u_int16_t adapter_control; /* word 17 */
-
-/*
- * Bus Release, Host Adapter ID
- */
-#define CFSCSIID 0x000f /* host adapter SCSI ID */
-/* UNUSED 0x00f0 */
-#define CFBRTIME 0xff00 /* bus release time */
- u_int16_t brtime_id; /* word 18 */
-
-/*
- * Maximum targets
- */
-#define CFMAXTARG 0x00ff /* maximum targets */
-/* UNUSED 0xff00 */
- u_int16_t max_targets; /* word 19 */
-
- u_int16_t res_1[11]; /* words 20-30 */
- u_int16_t checksum; /* word 31 */
-};
-
-static void load_seeprom __P((struct ahc_softc *ahc, u_int8_t *sxfrctl1));
-static int acquire_seeprom __P((struct seeprom_descriptor *sd));
-static void release_seeprom __P((struct seeprom_descriptor *sd));
-static void write_brdctl __P((struct ahc_softc *ahc, u_int8_t value));
-static u_int8_t read_brdctl __P((struct ahc_softc *ahc));
-
-static int aic3940_count;
-static int aic398X_count;
-static struct ahc_softc *first_398X;
-
-#if defined(__FreeBSD__)
-
-static char* aic7870_probe __P((pcici_t tag, pcidi_t type));
-static void aic7870_attach __P((pcici_t config_id, int unit));
-
-static struct pci_device ahc_pci_driver = {
- "ahc",
- aic7870_probe,
- aic7870_attach,
- &ahc_unit,
- NULL
-};
-
-DATA_SET (pcidevice_set, ahc_pci_driver);
-
-static char*
-aic7870_probe (pcici_t tag, pcidi_t type)
-{
- switch (type) {
- case PCI_DEVICE_ID_ADAPTEC_398XU:
- return ("Adaptec 398X Ultra SCSI RAID adapter");
- break;
- case PCI_DEVICE_ID_ADAPTEC_3940U:
- return ("Adaptec 3940 Ultra SCSI host adapter");
- break;
- case PCI_DEVICE_ID_ADAPTEC_398X:
- return ("Adaptec 398X SCSI RAID adapter");
- break;
- case PCI_DEVICE_ID_ADAPTEC_3940:
- return ("Adaptec 3940 SCSI host adapter");
- break;
- case PCI_DEVICE_ID_ADAPTEC_2944U:
- return ("Adaptec 2944 Ultra SCSI host adapter");
- break;
- case PCI_DEVICE_ID_ADAPTEC_2940U:
- return ("Adaptec 2940 Ultra SCSI host adapter");
- break;
- case PCI_DEVICE_ID_ADAPTEC_2944:
- return ("Adaptec 2944 SCSI host adapter");
- break;
- case PCI_DEVICE_ID_ADAPTEC_2940:
- return ("Adaptec 2940 SCSI host adapter");
- break;
- case PCI_DEVICE_ID_ADAPTEC_2940AU:
- return ("Adaptec 2940A Ultra SCSI host adapter");
- break;
- case PCI_DEVICE_ID_ADAPTEC_AIC7880:
- return ("Adaptec aic7880 Ultra SCSI host adapter");
- break;
- case PCI_DEVICE_ID_ADAPTEC_AIC7870:
- return ("Adaptec aic7870 SCSI host adapter");
- break;
- case PCI_DEVICE_ID_ADAPTEC_AIC7860:
- return ("Adaptec aic7860 SCSI host adapter");
- break;
- case PCI_DEVICE_ID_ADAPTEC_AIC7855:
- return ("Adaptec aic7855 SCSI host adapter");
- break;
- case PCI_DEVICE_ID_ADAPTEC_AIC7850:
- return ("Adaptec aic7850 SCSI host adapter");
- break;
- case PCI_DEVICE_ID_ADAPTEC_AIC7810:
- return ("Adaptec aic7810 RAID memory controller");
- break;
- default:
- break;
- }
- return (0);
-
-}
-
-#elif defined(__NetBSD__)
-
-int ahc_pci_probe __P((struct device *, void *, void *));
-void ahc_pci_attach __P((struct device *, struct device *, void *));
-
-struct cfattach ahc_pci_ca = {
- sizeof(struct ahc_softc), ahc_pci_probe, ahc_pci_attach
-};
-
-int
-ahc_pci_probe(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- struct pci_attach_args *pa = aux;
-
- switch (pa->pa_id) {
- case PCI_DEVICE_ID_ADAPTEC_398XU:
- case PCI_DEVICE_ID_ADAPTEC_3940U:
- case PCI_DEVICE_ID_ADAPTEC_2944U:
- case PCI_DEVICE_ID_ADAPTEC_2940U:
- case PCI_DEVICE_ID_ADAPTEC_2940AU:
- case PCI_DEVICE_ID_ADAPTEC_398X:
- case PCI_DEVICE_ID_ADAPTEC_3940:
- case PCI_DEVICE_ID_ADAPTEC_2944:
- case PCI_DEVICE_ID_ADAPTEC_2940:
- case PCI_DEVICE_ID_ADAPTEC_AIC7880:
- case PCI_DEVICE_ID_ADAPTEC_AIC7870:
- case PCI_DEVICE_ID_ADAPTEC_AIC7860:
- case PCI_DEVICE_ID_ADAPTEC_AIC7855:
- case PCI_DEVICE_ID_ADAPTEC_AIC7850:
- case PCI_DEVICE_ID_ADAPTEC_AIC7810:
- return 1;
- }
- return 0;
-}
-#endif /* defined(__NetBSD__) */
-
-#if defined(__FreeBSD__)
-static void
-aic7870_attach(config_id, unit)
- pcici_t config_id;
- int unit;
-#elif defined(__NetBSD__)
-void
-ahc_pci_attach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-#endif
-{
-#if defined(__FreeBSD__)
- u_int16_t io_port;
- struct ahc_softc *ahc;
-#elif defined(__NetBSD__)
- struct pci_attach_args *pa = aux;
- struct ahc_softc *ahc = (void *)self;
- int unit = ahc->sc_dev.dv_unit;
- bus_io_addr_t iobase;
- bus_io_size_t iosize;
- bus_io_handle_t ioh;
- pci_intr_handle_t ih;
- const char *intrstr;
-#endif
- u_int32_t id;
- u_int32_t command;
- struct scb_data *shared_scb_data;
- int opri;
- ahc_type ahc_t = AHC_NONE;
- ahc_flag ahc_f = AHC_FNONE;
- vm_offset_t vaddr;
- vm_offset_t paddr;
- u_int8_t ultra_enb = 0;
- u_int8_t our_id = 0;
- u_int8_t sxfrctl1;
-
- shared_scb_data = NULL;
- vaddr = NULL;
- paddr = NULL;
-#if defined(__FreeBSD__)
- io_port = 0;
- command = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG);
-#ifdef AHC_ALLOW_MEMIO
- if ((command & PCI_COMMAND_MEM_ENABLE) == 0
- || (pci_map_mem(config_id, PCI_BASEADR1, &vaddr, &paddr)) == 0)
-#endif
- if ((command & PCI_COMMAND_IO_ENABLE) == 0
- || (pci_map_port(config_id, PCI_BASEADR0, &io_port)) == 0)
- return;
-#elif defined(__NetBSD__)
- /* XXX Memory mapped I/O?? */
- if (bus_io_map(pa->pa_bc, iobase, iosize, &ioh))
- if (pci_io_find(pa->pa_pc, pa->pa_tag, PCI_BASEADR0, &iobase,
- &iosize))
- return;
-#endif
-
-#if defined(__FreeBSD__)
- switch ((id = pci_conf_read(config_id, PCI_ID_REG))) {
-#elif defined(__NetBSD__)
- switch (id = pa->pa_id) {
-#endif
- case PCI_DEVICE_ID_ADAPTEC_398XU:
- case PCI_DEVICE_ID_ADAPTEC_398X:
- if (id == PCI_DEVICE_ID_ADAPTEC_398XU)
- ahc_t = AHC_398U;
- else
- ahc_t = AHC_398;
- switch (aic398X_count) {
- case 0:
- break;
- case 1:
- ahc_f |= AHC_CHNLB;
- break;
- case 2:
- ahc_f |= AHC_CHNLC;
- break;
- default:
- break;
- }
- aic398X_count++;
- if (first_398X != NULL)
-#ifdef AHC_SHARE_SCBS
- shared_scb_data = first_398X->scb_data;
-#endif
- if (aic398X_count == 3) {
- /*
- * This is the last device on this RAID
- * controller, so reset our counts.
- * XXX This won't work for the multiple 3980
- * controllers since they have only 2 channels,
- * but I'm not even sure if Adaptec actually
- * went through with their plans to produce
- * this controller.
- */
- aic398X_count = 0;
- first_398X = NULL;
- }
- break;
- case PCI_DEVICE_ID_ADAPTEC_3940U:
- case PCI_DEVICE_ID_ADAPTEC_3940:
- if (id == PCI_DEVICE_ID_ADAPTEC_3940U)
- ahc_t = AHC_394U;
- else
- ahc_t = AHC_394;
- if ((aic3940_count & 0x01) != 0)
- /* Odd count implies second channel */
- ahc_f |= AHC_CHNLB;
- aic3940_count++;
- break;
- case PCI_DEVICE_ID_ADAPTEC_2944U:
- case PCI_DEVICE_ID_ADAPTEC_2940U:
- ahc_t = AHC_294U;
- break;
- case PCI_DEVICE_ID_ADAPTEC_2944:
- case PCI_DEVICE_ID_ADAPTEC_2940:
- ahc_t = AHC_294;
- break;
- case PCI_DEVICE_ID_ADAPTEC_2940AU:
- ahc_t = AHC_294AU;
- break;
- case PCI_DEVICE_ID_ADAPTEC_AIC7880:
- ahc_t = AHC_AIC7880;
- break;
- case PCI_DEVICE_ID_ADAPTEC_AIC7870:
- ahc_t = AHC_AIC7870;
- break;
- case PCI_DEVICE_ID_ADAPTEC_AIC7860:
- ahc_t = AHC_AIC7860;
- break;
- case PCI_DEVICE_ID_ADAPTEC_AIC7855:
- case PCI_DEVICE_ID_ADAPTEC_AIC7850:
- ahc_t = AHC_AIC7850;
- break;
- case PCI_DEVICE_ID_ADAPTEC_AIC7810:
- printf("RAID functionality unsupported\n");
- return;
- default:
- break;
- }
-
- /* On all PCI adapters, we allow SCB paging */
- ahc_f |= AHC_PAGESCBS;
-#if defined(__FreeBSD__)
- if ((ahc = ahc_alloc(unit, io_port, vaddr, ahc_t, ahc_f,
- shared_scb_data)) == NULL)
- return; /* XXX PCI code should take return status */
-#else
- ahc_construct(ahc, pa->pa_bc, ioh, ahc_t, ahc_f);
-#endif
-
- /* Remeber how the card was setup in case there is no SEEPROM */
- our_id = ahc_inb(ahc, SCSIID) & OID;
- if (ahc_t & AHC_ULTRA)
- ultra_enb = ahc_inb(ahc, SXFRCTL0) & FAST20;
- sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN;
-
-#if defined(__NetBSD__)
- printf("\n");
-#endif
- ahc_reset(ahc);
-
-#ifdef AHC_SHARE_SCBS
- if (ahc_t & AHC_AIC7870) {
-#if defined(__FreeBSD__)
- u_int32_t devconfig = pci_conf_read(config_id, DEVCONFIG);
-#elif defined(__NetBSD__)
- u_int32_t devconfig =
- pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG);
-#endif
- if (devconfig & (RAMPSM)) {
- /* XXX Assume 9bit SRAM and enable parity checking */
- devconfig |= EXTSCBPEN;
-
- /* XXX Assume fast SRAM and only enable 2 cycle
- * access if we are sharing the SRAM across mutiple
- * adapters (398X adapter).
- */
- if ((devconfig & MPORTMODE) == 0)
- /* Multi-user mode */
- devconfig |= EXTSCBTIME;
-
- devconfig &= ~SCBRAMSEL;
-#if defined(__FreeBSD__)
- pci_conf_write(config_id, DEVCONFIG, devconfig);
-#elif defined(__NetBSD__)
- pci_conf_write(pa->pa_pc, pa->pa_tag,
- DEVCONFIG, devconfig);
-#endif
- }
- }
-#endif
-
-#if defined(__FreeBSD__)
- if (!(pci_map_int(config_id, ahc_intr, (void *)ahc, &bio_imask))) {
- ahc_free(ahc);
- return;
- }
-#elif defined(__NetBSD__)
-
- if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
- pa->pa_intrline, &ih)) {
- printf("%s: couldn't map interrupt\n", ahc->sc_dev.dv_xname);
- ahc_free(ahc);
- return;
- }
- intrstr = pci_intr_string(pa->pa_pc, ih);
-#ifdef __OpenBSD__
- ahc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, ahc_intr, ahc,
- ahc->sc_dev.dv_xname);
-#else
- ahc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, ahc_intr, ahc);
-#endif
- if (ahc->sc_ih == NULL) {
- printf("%s: couldn't establish interrupt",
- ahc->sc_dev.dv_xname);
- if (intrstr != NULL)
- printf(" at %s", intrstr);
- printf("\n");
- ahc_free(ahc);
- return;
- }
- if (intrstr != NULL)
- printf("%s: interrupting at %s\n", ahc->sc_dev.dv_xname,
- intrstr);
-#endif
- /*
- * Protect ourself from spurrious interrupts during
- * intialization.
- */
- opri = splbio();
-
- /*
- * Do aic7880/aic7870/aic7860/aic7850 specific initialization
- */
- {
- u_int8_t sblkctl;
- char *id_string;
-
- switch(ahc->type) {
- case AHC_398U:
- case AHC_394U:
- case AHC_294U:
- case AHC_AIC7880:
- id_string = "aic7880 ";
- load_seeprom(ahc, &sxfrctl1);
- break;
- case AHC_398:
- case AHC_394:
- case AHC_294:
- case AHC_AIC7870:
- id_string = "aic7870 ";
- load_seeprom(ahc, &sxfrctl1);
- break;
- case AHC_294AU:
- case AHC_AIC7860:
- id_string = "aic7860 ";
- load_seeprom(ahc, &sxfrctl1);
- break;
- case AHC_AIC7850:
- id_string = "aic7850 ";
- /*
- * Use defaults, if the chip wasn't initialized by
- * a BIOS.
- */
- ahc->flags |= AHC_USEDEFAULTS;
- break;
- default:
- printf("ahc: Unknown controller type. Ignoring.\n");
- ahc_free(ahc);
- splx(opri);
- return;
- }
-
- /*
- * Take the LED out of diagnostic mode
- */
- sblkctl = ahc_inb(ahc, SBLKCTL);
- ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON)));
-
- /*
- * I don't know where this is set in the SEEPROM or by the
- * BIOS, so we default to 100%.
- */
- ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100);
-
- if (ahc->flags & AHC_USEDEFAULTS) {
- /*
- * PCI Adapter default setup
- * Should only be used if the adapter does not have
- * an SEEPROM.
- */
- /* See if someone else set us up already */
- u_int32_t i;
- for (i = TARG_SCRATCH; i < 0x60; i++) {
- if (ahc_inb(ahc, i) != 0x00)
- break;
- }
- if (i == TARG_SCRATCH) {
- /*
- * Try looking for all ones. You can get
- * either.
- */
- for (i = TARG_SCRATCH; i < 0x60; i++) {
- if (ahc_inb(ahc, i) != 0xff)
- break;
- }
- }
- if ((i != 0x60) && (our_id != 0)) {
- printf("%s: Using left over BIOS settings\n",
- ahc_name(ahc));
- ahc->flags &= ~AHC_USEDEFAULTS;
- } else {
- /*
- * Assume only one connector and always turn
- * on termination.
- */
- our_id = 0x07;
- sxfrctl1 = STPWEN;
- }
- ahc_outb(ahc, SCSICONF,
- (our_id & 0x07)|ENSPCHK|RESET_SCSI);
- /* In case we are a wide card */
- ahc_outb(ahc, SCSICONF + 1, our_id);
-
- if (ultra_enb == 0
- && (ahc->flags & AHC_USEDEFAULTS) == 0) {
- /*
- * If there wasn't a BIOS or the board
- * wasn't in this mode to begin with,
- * turn off ultra.
- */
- ahc->type &= ~AHC_ULTRA;
- }
- }
-
- printf("%s: %s", ahc_name(ahc), id_string);
- }
-
- /*
- * Put our termination setting into sxfrctl1 now so that the
- * generic initialization can see it.
- */
- sxfrctl1 |= ahc_inb(ahc, SXFRCTL1);
- ahc_outb(ahc, SXFRCTL1, sxfrctl1);
-
- if (ahc_init(ahc)){
- ahc_free(ahc);
- splx(opri);
- return; /* XXX PCI code should take return status */
- }
-
- if ((ahc->type & AHC_398) == AHC_398) {
- /* Only set this once we've successfully probed */
- if (shared_scb_data == NULL)
- first_398X = ahc;
- }
- splx(opri);
-
- ahc_attach(ahc);
-}
-
-/*
- * Read the SEEPROM. Return 0 on failure
- */
-void
-load_seeprom(ahc, sxfrctl1)
- struct ahc_softc *ahc;
- u_int8_t *sxfrctl1;
-{
- struct seeprom_descriptor sd;
- struct seeprom_config sc;
- u_int16_t *scarray = (u_int16_t *)&sc;
- u_int8_t scsi_conf;
- u_int8_t host_id;
- int have_seeprom;
-
-#if defined(__FreeBSD__)
- sd.sd_maddr = ahc->maddr;
- if (sd.sd_maddr != NULL)
- sd.sd_maddr += SEECTL;
- sd.sd_iobase = ahc->baseport;
- if (sd.sd_iobase != 0)
- sd.sd_iobase += SEECTL;
-#elif defined(__NetBSD__)
- sd.sd_bc = ahc->sc_bc;
- sd.sd_ioh = ahc->sc_ioh;
- sd.sd_offset = SEECTL;
-#endif
- /*
- * For some multi-channel devices, the c46 is simply too
- * small to work. For the other controller types, we can
- * get our information from either SEEPROM type. Set the
- * type to start our probe with accordingly.
- */
- if ((ahc->type & AHC_398) == AHC_398)
- sd.sd_chip = C56_66;
- else
- sd.sd_chip = C46;
- sd.sd_MS = SEEMS;
- sd.sd_RDY = SEERDY;
- sd.sd_CS = SEECS;
- sd.sd_CK = SEECK;
- sd.sd_DO = SEEDO;
- sd.sd_DI = SEEDI;
-
- have_seeprom = acquire_seeprom(&sd);
- if (have_seeprom) {
- if (bootverbose)
- printf("%s: Reading SEEPROM...", ahc_name(ahc));
-
- for (;;) {
- u_int start_addr;
-
- start_addr = ahc->flags & (AHC_CHNLB|AHC_CHNLC);
-
- have_seeprom = read_seeprom(&sd, (u_int16_t *)&sc,
- start_addr, sizeof(sc)/2);
-
- if (have_seeprom) {
- /* Check checksum */
- int i;
- int maxaddr;
- u_int16_t *scarray;
- u_int16_t checksum;
-
- maxaddr = (sizeof(sc)/2) - 1;
- checksum = 0;
- scarray = (u_int16_t *)&sc;
-
- for (i = 0; i < maxaddr; i++)
- checksum = checksum + scarray[i];
- if (checksum == 0 || checksum != sc.checksum) {
- if (bootverbose && sd.sd_chip == C56_66)
- printf ("checksum error\n");
- have_seeprom = 0;
- } else {
- if (bootverbose)
- printf("done.\n");
- break;
- }
- }
-
- if (sd.sd_chip == C56_66)
- break;
- sd.sd_chip = C56_66;
- }
- }
- release_seeprom(&sd);
- if (!have_seeprom) {
- if (bootverbose)
- printf("\n%s: No SEEPROM available\n", ahc_name(ahc));
- ahc->flags |= AHC_USEDEFAULTS;
- } else {
- /*
- * Put the data we've collected down into SRAM
- * where ahc_init will find it.
- */
- int i;
- int max_targ = sc.max_targets & CFMAXTARG;
-
- for (i = 0; i < max_targ; i++){
- u_char target_settings;
- target_settings = (sc.device_flags[i] & CFXFER) << 4;
- if (sc.device_flags[i] & CFSYNCH)
- target_settings |= SOFS;
- if (sc.device_flags[i] & CFWIDEB)
- target_settings |= WIDEXFER;
- if (sc.device_flags[i] & CFDISC)
- ahc->discenable |= (0x01 << i);
- ahc_outb(ahc, TARG_SCRATCH+i, target_settings);
- }
- ahc_outb(ahc, DISC_DSB, ~(ahc->discenable & 0xff));
- ahc_outb(ahc, DISC_DSB + 1, ~((ahc->discenable >> 8) & 0xff));
-
- host_id = sc.brtime_id & CFSCSIID;
-
- scsi_conf = (host_id & 0x7);
- if (sc.adapter_control & CFSPARITY)
- scsi_conf |= ENSPCHK;
- if (sc.adapter_control & CFRESETB)
- scsi_conf |= RESET_SCSI;
-
- /*
- * Update the settings in sxfrctl1 to match the
- *termination settings
- */
- *sxfrctl1 = 0;
- if (sc.adapter_control & CFAUTOTERM) {
- /* Play around with the memory port */
- have_seeprom = acquire_seeprom(&sd);
- if (have_seeprom) {
- u_int8_t brdctl;
- u_int8_t seectl;
- int internal50_present;
- int internal68_present;
- int external68_present;
- int eprom_present;
- int high_on;
- int low_on;
-
- seectl = sd.sd_CS|sd.sd_MS;
- SEEPROM_OUTB(&sd, seectl);
- /*
- * First read the status of our cables.
- * Set the rom bank to 0 since the
- * bank setting serves as a multiplexor
- * for the cable detection logic.
- * BRDDAT5 controls the bank switch.
- */
- write_brdctl(ahc, 0);
-
- /*
- * Now read the state of the internal
- * connectors. BRDDAT6 is INT50 and
- * BRDDAT7 is INT68.
- */
- brdctl = read_brdctl(ahc);
- internal50_present = !(brdctl & BRDDAT6);
- internal68_present = !(brdctl & BRDDAT7)
- && (max_targ > 8);
- if (bootverbose) {
- printf("internal50 cable %s present\n"
- "internal68 cable %s present\n"
- "brdctl == 0x%x\n",
- internal50_present ? "is":"not",
- internal68_present ? "is":"not",
- brdctl);
- }
-
- /*
- * Set the rom bank to 1 and determine
- * the other signals.
- */
- write_brdctl(ahc, BRDDAT5);
-
- /*
- * Now read the state of the external
- * connectors. BRDDAT6 is EXT68 and
- * BRDDAT7 is EPROMPS.
- */
- brdctl = read_brdctl(ahc);
- external68_present = !(brdctl & BRDDAT6);
- eprom_present = brdctl & BRDDAT7;
- if (bootverbose) {
- printf("external cable %s present\n"
- "eprom %s present\n"
- "brdctl == 0x%x\n",
- external68_present ? "is":"not",
- eprom_present ? "is" : "not",
- brdctl);
- }
-
- /*
- * Now set the termination based on what
- * we found. BRDDAT6 controls wide
- * termination enable.
- */
- high_on = FALSE;
- low_on = FALSE;
- if ((max_targ > 8)
- && ((external68_present == 0)
- || (internal68_present == 0)))
- high_on = TRUE;
-
- if (((internal50_present ? 1 : 0)
- + (internal68_present ? 1 : 0)
- + (external68_present ? 1 : 0)) <= 1)
- low_on = TRUE;
-
- if ((internal50_present != 0)
- && (internal68_present != 0)
- && (external68_present != 0)) {
- printf("Illegal cable configuration!!. "
- "Only two connectors on the "
- "adapter may be used at a "
- "time!");
- }
-
- if (high_on == TRUE)
- write_brdctl(ahc, BRDDAT6);
- else
- write_brdctl(ahc, 0);
-
- if (low_on == TRUE)
- *sxfrctl1 |= STPWEN;
-
- if (bootverbose) {
- printf("low byte termination %s, "
- "high byte termination %s\n",
- low_on ? "enabled":"disabled",
- high_on ? "enabled":"disabled");
- }
- }
- release_seeprom(&sd);
- } else {
- if (sc.adapter_control & CFSTERM)
- *sxfrctl1 |= STPWEN;
- have_seeprom = acquire_seeprom(&sd);
- if (have_seeprom) {
- SEEPROM_OUTB(&sd, sd.sd_CS|sd.sd_MS);
- if (sc.adapter_control & CFWSTERM)
- write_brdctl(ahc, BRDDAT6);
- else
- write_brdctl(ahc, 0);
- release_seeprom(&sd);
- } else
- printf("Unabled to configure high byte "
- "termination!\n");
-
- if (bootverbose) {
- printf("low byte termination %s, "
- "high byte termination %s\n",
- sc.adapter_control & CFSTERM ?
- "enabled":"disabled",
- sc.adapter_control & CFWSTERM ?
- "enabled":"disabled");
- }
- }
-
- if (ahc->type & AHC_ULTRA) {
- /* Should we enable Ultra mode? */
- if (!(sc.adapter_control & CFULTRAEN))
- /* Treat us as a non-ultra card */
- ahc->type &= ~AHC_ULTRA;
- }
- /* Set the host ID */
- ahc_outb(ahc, SCSICONF, scsi_conf);
- /* In case we are a wide card */
- ahc_outb(ahc, SCSICONF + 1, host_id);
- }
-}
-
-static int
-acquire_seeprom(sd)
- struct seeprom_descriptor *sd;
-{
- int wait;
-
- /*
- * Request access of the memory port. When access is
- * granted, SEERDY will go high. We use a 1 second
- * timeout which should be near 1 second more than
- * is needed. Reason: after the chip reset, there
- * should be no contention.
- */
- SEEPROM_OUTB(sd, sd->sd_MS);
- wait = 1000; /* 1 second timeout in msec */
- while (--wait && ((SEEPROM_INB(sd) & sd->sd_RDY) == 0)) {
- DELAY (1000); /* delay 1 msec */
- }
- if ((SEEPROM_INB(sd) & sd->sd_RDY) == 0) {
- SEEPROM_OUTB(sd, 0);
- return (0);
- }
- return(1);
-}
-
-static void
-release_seeprom(sd)
- struct seeprom_descriptor *sd;
-{
- /* Release access to the memory port and the serial EEPROM. */
- SEEPROM_OUTB(sd, 0);
-}
-
-static void
-write_brdctl(ahc, value)
- struct ahc_softc *ahc;
- u_int8_t value;
-{
- u_int8_t brdctl;
-
- brdctl = BRDCS|BRDSTB;
- ahc_outb(ahc, BRDCTL, brdctl);
- brdctl |= value;
- ahc_outb(ahc, BRDCTL, brdctl);
- brdctl &= ~BRDSTB;
- ahc_outb(ahc, BRDCTL, brdctl);
- brdctl &= ~BRDCS;
- ahc_outb(ahc, BRDCTL, brdctl);
-}
-
-static u_int8_t
-read_brdctl(ahc)
- struct ahc_softc *ahc;
-{
- ahc_outb(ahc, BRDCTL, BRDRW|BRDCS);
- return ahc_inb(ahc, BRDCTL);
-}
-
-#endif /* NPCI > 0 */
diff --git a/sys/pci/bt9xx.c b/sys/pci/bt9xx.c
deleted file mode 100644
index e50116e..0000000
--- a/sys/pci/bt9xx.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Product specific probe and attach routines for:
- * Buslogic BT946 and BT956 SCSI controllers
- *
- * Copyright (c) 1995 Justin T. Gibbs
- * 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 immediately at the beginning of the file, without modification,
- * 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. Absolutely no warranty of function or purpose is made by the author
- * Justin T. Gibbs.
- * 4. Modifications may be freely made to this file if the above conditions
- * are met.
- *
- * $Id: bt9xx.c,v 1.10 1997/02/22 09:44:00 peter Exp $
- */
-
-#include "pci.h"
-#if NPCI > 0
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <scsi/scsiconf.h>
-#include <pci/pcireg.h>
-#include <pci/pcivar.h>
-#include <i386/scsi/btreg.h>
-
-/* XXX Need more device IDs */
-#define PCI_DEVICE_ID_BUSLOGIC_946 0x1040104Bul
-#define PCI_DEVICE_ID_BUSLOGIC_946_OLD 0x0140104Bul
-
-static char* bt_pci_probe __P((pcici_t tag, pcidi_t type));
-static void bt_pci_attach __P((pcici_t config_id, int unit));
-
-static struct pci_device bt_pci_driver = {
- "bt",
- bt_pci_probe,
- bt_pci_attach,
- &bt_unit,
- NULL
-};
-
-DATA_SET (pcidevice_set, bt_pci_driver);
-
-static char*
-bt_pci_probe (pcici_t tag, pcidi_t type)
-{
- switch(type) {
- case PCI_DEVICE_ID_BUSLOGIC_946_OLD:
- case PCI_DEVICE_ID_BUSLOGIC_946:
- return ("Buslogic 946 SCSI host adapter");
- break;
- default:
- break;
- }
- return (0);
-
-}
-
-static void
-bt_pci_attach(config_id, unit)
- pcici_t config_id;
- int unit;
-{
- u_char reg;
- u_long io_port;
- unsigned opri = 0;
- struct bt_data *bt;
-
- for(reg = PCI_MAP_REG_START; reg < PCI_MAP_REG_END; reg+=4) {
- io_port = pci_conf_read(config_id, reg);
- if ((io_port&~7)==0) continue;
- if(io_port & PCI_MAP_IO) {
- io_port &= ~PCI_MAP_IO;
- break;
- }
- }
- if(reg == PCI_MAP_REG_END)
- return;
-
- if(!(bt = bt_alloc(unit, io_port)))
- return; /* XXX PCI code should take return status */
-
- if(!(pci_map_int(config_id, bt_intr, (void *)bt, &bio_imask))) {
- bt_free(bt);
- return;
- }
- /*
- * Protect ourself from spurrious interrupts during
- * intialization and attach. We should really rely
- * on interrupts during attach, but we don't have
- * access to our interrupts during ISA probes, so until
- * that changes, we mask our interrupts during attach
- * too.
- */
- opri = splbio();
-
- if(bt_init(bt)){
- bt_free(bt);
- splx(opri);
- return; /* XXX PCI code should take return status */
- }
-
- bt_attach(bt);
-
- splx(opri);
- return;
-}
-
-#endif /* NPCI > 0 */
diff --git a/sys/scsi/README b/sys/scsi/README
deleted file mode 100644
index b9a626a..0000000
--- a/sys/scsi/README
+++ /dev/null
@@ -1,203 +0,0 @@
-WARNING: This file was not fully updated by dufault@hda.com when
-changing the configuration. See the end for new notes.
-
-This release consists of the following files
-(relative to the base of the source tree )
-
-share/man/man4/scsi.4 <-useful general info
-share/man/man4/uk.4
-share/man/man4/su.4
-share/man/man4/ch.4
-share/man/man4/cd.4
-share/man/man4/sd.4
-share/man/man4/st.4 <--READ THIS IF YOU USE TAPES!
-sbin/scsi/procargs.c
-sbin/scsi/scsi.c
-sbin/scsi/scsi.1
-sbin/scsi/Makefile
-sbin/st/Makefile
-sbin/st/st.1
-sbin/st/st.c
-sys/sys/chio.h
-sys/sys/cdio.h
-sys/sys/mtio.h
-sys/sys/scsiio.h
-sys/i386/conf/EXAMPLE
-sys/i386/isa/ultra14f.c <-runs 14f and 34f
-sys/i386/isa/ultra_all.c.beta <-beta version, runs 14f,24f and 34f
-sys/i386/isa/bt742a.c
-sys/i386/isa/aha1742.c
-sys/i386/isa/aha1542.c
-sys/scsi/syspatches
-sys/scsi/syspatches/conf.c
-sys/scsi/syspatches/user_scsi.diffs
-sys/scsi/syspatches/MAKEDEV.diff
-sys/scsi/syspatches/isa.c.patch
-sys/scsi/syspatches/README
-sys/scsi/uk.c
-sys/scsi/su.c
-sys/scsi/st.c
-sys/scsi/sd.c
-sys/scsi/ch.c
-sys/scsi/cd.c
-sys/scsi/scsi_ioctl.c
-sys/scsi/scsi_base.c
-sys/scsi/scsiconf.c
-sys/scsi/scsi_tape.h
-sys/scsi/scsi_disk.h
-sys/scsi/scsi_changer.h
-sys/scsi/scsi_cd.h
-sys/scsi/scsi_all.h
-sys/scsi/scsi_debug.h
-sys/scsi/scsiconf.h
-sys/scsi/README <--this file
-
-notice sys/scsi/sg.c and sys/sys/sgio.h have been removed
-
-
-----------------------------------------------------------------
-This scsi system is designed to allow the re-use of top end drivers
-such as disk and tape drivers, with different scsi adapters.
-
-As of writing this document, There are top end drivers working for:
-----------------------------------------------------------------
-generic scsi disk
-generic scsi tape
-cd-rom (plays music under the xcplayer (?) program)
-AEG Character recognition devices *
-Calera Character recognition devices *
-Generic scsi-II scanners *
-Exabyte tape changer device.
-GENERIC SCSI DEVICES (user generated scsi commands)
-----------------------------------------------------------------
-
-
-There are also working bottom end drivers for:
-----------------------------------------------------------------
-adaptec 1542 (and 1742 in 1542 mode)
-bustec 742a (apparently works for VESA version (445S?))(and 747?)
-adaptec 174x (note NOT 27xx)
-Ultrastore 14f (works for 34f (VESA version))
-Ultrastore 24f RSN (Beta version included here)
-----------------------------------------------------------------
-
-
-################## Using the scsi system ##################
-------------minor numbers---------------
-This scsi system does not allocate minor numbers to devices depending
-on their SCSI IDs is any way. A devices minor number is dependant
-on the order in which it was found.
-e.g. the first tape found will become st0 (minor number 0)
- the second found will become st1 (minor number 16)
- the third will become st2 (minor 32)
- etc.
-
-These devices could be on the same scsi bus or different scsi busses.
-That would not change their minor numbers.
-
-THE EXCEPTION TO THIS IS IN THE GENERIC SCSI DRIVER. in which case
-the following mapping applies:
-
-BB TTT LLL B= scsi bus number, T = target number, L = LUN.
-
-It is possible to run two different TYPES of scsi adapters at the
-same time and have st0 on one and st1 on another. (for example)
-
-There is a scheme supported in which scsi devices can be 'wired in' even
-if they are not present or powered on at probe time. (see scsiconf.c)
-In addition, the scsi(1) command allows the operator ask for a
-reprobe at any time. Newly found devices will be configured in. Any
-device that does not map to a known device type is attached to the
-'unknown' (uk) driver.
-
-
---------------making devices------------
-A changed version of /dev/MAKEDEV is supplied that
-can be used to make devices sd[01234] and st[01234]
-
-e.g.
-cd /dev
-sh MAKEDEV sd0 sd1 sd2 st0 st1 cd0
-
-see st(1) and st(4) for info on tape devices.
-
---------------file layout-------------------
-Originally I had all scsi definitions in one file: scsi.h
-I have since moved definitions of commands so that all
-definitions needed for a particular type of device are
-found together in the include file of that name.
-This approximatly follows the layout of their definition
-in the SCSI-2 spec.
-As such they are:
-
-scsi_all.h general commands for all devices --- CHAPTER 7
-scsi-disk.h commands relevant to disk --- CHAPTER 8
-scsi-tape.h commands for scsi tapes --- CHAPTER 9
-scsi-cd.h commands for cd-roms (and audio) --- CHAPTER 13
-scsi-changer.h commands medium changer devices --- CHAPTER 16
-
----------ioctl definitions-------------
-User accessable structures (e.g. ioctl definitions) have been
-placed in sys/cdio, sys/sgio and sys/chio (based after sys/mtio for
-the ioctls for mag tapes (including st).
-General scsi ioctls are found in sys/scsiio.h.
-
------------cd-rom-----------------
-The cd rom driver ha been tested by a number of people and
-grefen@convex.com has completed the audio play
-functions.
-(xcdplayer was available from the 'from_ref' directory on agate)
-
-At this time it is possible audio play is broken on cdroms and I will
-be unable to fix it until I get one to test.
-***IMPORTANT***
-Cdrom audio is only suported at all for cdroms that use SCSI2 audio
-definitions.
-
--------------media changer---------------
-Once again courtesy of grefen@convex.com (in germany)
-I have not tested this but he assures me it's ready for testing.
-If anyone has an exabyte tape changer or similar,
-contact the author for information regarding the control interface
-and program.
-
-WARNING: This has not been tested for a LONG TIME!
-
-
----------recent changes-----------
-Removed all bitfields from machine independent sections to make
-it possible for them to be used on big-endian architectures.
-
-Removed scsi specific timeouts in favour of system timeout handling.
-
-Many structures (getting more all the time) now dynamically allocated.
-
-Addition of code in the tape driver to recognise models of drive that
-have particular problems so they can be handled specially.
-
-many bug-fixes and cleanups.
-
----------even more recent changes:--------
-
-rewrote almost the entire thing..
-
-
-
-------Mon Oct 11 22:20:25 WST 1993------
-
-Code is now all KNF (or close to it).
-
-A new structure has been introduced..
-Called scsi_link, one of these exists for every bus/target/lun
-that has a driver attached to it.
-It has links to the adapter and to the driver, as well as status
-information of global interest. (e.g. if the device is in use).
-The use of this new structure has allowed the compaction of a
-lot of duplicated code into a single copy (now in scsi_base.c)
-and makes more simple the USER level scsi implimentation.
-
-------Tue Feb 28 07:43:17 EST 1995-----
-dufault@hda.com: Redid configuration to support wired devices.
-All driver entries now get bounced directly into the routines in
-"scsi_driver" via a set of functions generated by the SCSI_ENTRIES macro
-in scsi_conf.h. This lets us put the common code in a single place.
diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c
deleted file mode 100644
index 750746f..0000000
--- a/sys/scsi/cd.c
+++ /dev/null
@@ -1,1419 +0,0 @@
-/*
- * Written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- *
- * $Id: cd.c,v 1.98 1998/08/17 19:09:36 bde Exp $
- */
-
-#include "opt_bounce.h"
-#include "opt_devfs.h"
-#include "opt_scsi.h"
-
-#define SPLCD splbio
-#define ESUCCESS 0
-#include <sys/param.h>
-#include <sys/dkbad.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/buf.h>
-#include <sys/cdio.h>
-#include <sys/disklabel.h>
-#include <sys/diskslice.h>
-#include <sys/dkstat.h>
-#include <sys/kernel.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-
-#include <scsi/scsi_all.h>
-#include <scsi/scsi_cd.h>
-#include <scsi/scsi_disk.h> /* rw_big and start_stop come from there */
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-#include "ioconf.h"
-
-static errval cd_get_parms __P((int, int));
-static u_int32_t cd_size __P((int unit, int flags));
-static d_strategy_t cdstrategy1;
-static errval cd_get_mode __P((u_int32_t, struct cd_mode_data *, u_int32_t));
-static errval cd_set_mode __P((u_int32_t unit, struct cd_mode_data *));
-static errval cd_read_toc __P((u_int32_t, u_int32_t, u_int32_t, struct cd_toc_entry *,
- u_int32_t));
-
-static errval cd_pause __P((u_int32_t, u_int32_t));
-static errval cd_reset __P((u_int32_t));
-static errval cd_play_msf __P((u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t));
-static errval cd_play __P((u_int32_t, u_int32_t, u_int32_t));
-#ifdef notyet
-static errval cd_play_big __P((u_int32_t unit, u_int32_t blk, u_int32_t len));
-#endif
-static errval cd_play_tracks __P((u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t));
-static errval cd_read_subchannel __P((u_int32_t, u_int32_t, u_int32_t, int, struct cd_sub_channel_info *, u_int32_t));
-
-static d_open_t cdopen;
-static d_read_t cdread;
-static d_close_t cdclose;
-static d_ioctl_t cdioctl;
-static d_strategy_t cdstrategy;
-
-#define CDEV_MAJOR 15
-#define BDEV_MAJOR 6
-static struct cdevsw cd_cdevsw = {
- cdopen, cdclose, cdread, nowrite,
- cdioctl, nostop, nullreset, nodevtotty,
- seltrue, nommap, cdstrategy, "cd",
- NULL, -1, nodump, nopsize,
- D_DISK, 0, -1 };
-
-static int32_t cdstrats, cdqueues;
-
-#define CDUNIT(dev) dkunit(dev)
-
-/* XXX introduce a dkmodunit() macro for this. */
-#define CDSETUNIT(DEV, U) \
- makedev(major(DEV), dkmakeminor((U), dkslice(DEV), dkpart(DEV)))
-
-#define CDOUTSTANDING 2
-#define CDRETRIES 1
-#define LEADOUT 0xaa /* leadout toc entry */
-
-#define PARTITION(dev) dkpart(dev)
-
-static void cdstart(u_int32_t unit, u_int32_t flags);
-
-struct scsi_data {
- u_int32_t flags;
-#define CDINIT 0x04 /* device has been init'd */
- struct cd_parms {
- u_int32_t blksize;
- u_long disksize; /* total number sectors */
- } params;
- struct diskslices *dk_slices; /* virtual drives */
- struct buf_queue_head buf_queue;
- int dkunit;
-#ifdef DEVFS
- void *b_devfs_token;
- void *c_devfs_token;
- void *ctl_devfs_token;
-#endif
-};
-
-static int cdunit(dev_t dev) { return CDUNIT(dev); }
-static dev_t cdsetunit(dev_t dev, int unit) { return CDSETUNIT(dev, unit); }
-
-static errval cd_open(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-static errval cd_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag,
- struct proc *p, struct scsi_link *sc_link);
-static errval cd_close(dev_t dev, int flag, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-static void cd_strategy(struct buf *bp, struct scsi_link *sc_link);
-
-SCSI_DEVICE_ENTRIES(cd)
-
-static struct scsi_device cd_switch =
-{
- NULL, /* use default error handler */
- cdstart, /* we have a queue, which is started by this */
- NULL, /* we do not have an async handler */
- NULL, /* use default 'done' routine */
- "cd", /* we are to be refered to by this name */
- 0, /* no device specific flags */
- {0, 0},
- 0, /* Link flags */
- cdattach,
- "CD-ROM",
- cdopen,
- sizeof(struct scsi_data),
- T_READONLY,
- cdunit,
- cdsetunit,
- cd_open,
- cd_ioctl,
- cd_close,
- cd_strategy,
-};
-
-#define CD_STOP 0
-#define CD_START 1
-#define CD_EJECT -2
-
-static __inline void
-cd_registerdev(int unit)
-{
- if(dk_ndrive < DK_NDRIVE) {
- sprintf(dk_names[dk_ndrive], "cd%d", unit);
- dk_wpms[dk_ndrive] = (150*1024/2);
- SCSI_DATA(&cd_switch, unit)->dkunit = dk_ndrive++;
- } else {
- SCSI_DATA(&cd_switch, unit)->dkunit = -1;
- }
-}
-
-/*
- * The routine called by the low level scsi routine when it discovers
- * A device suitable for this driver
- */
-static int
-cdattach(struct scsi_link *sc_link)
-{
- u_int32_t unit;
- struct cd_parms *dp;
- struct scsi_data *cd = sc_link->sd;
-#ifdef DEVFS
- int mynor;
-#endif
-
- unit = sc_link->dev_unit;
- dp = &(cd->params);
-
- bufq_init(&cd->buf_queue);
- if (sc_link->opennings > CDOUTSTANDING)
- sc_link->opennings = CDOUTSTANDING;
- /*
- * Use the subdriver to request information regarding
- * the drive. We cannot use interrupts yet, so the
- * request must specify this.
- *
- * XXX dufault@hda.com:
- * Need to handle this better in the case of no record. Rather than
- * a state driven sense handler I think we should make it so that
- * the command can get the sense back so that it can selectively log
- * errors.
- */
- if (sc_link->quirks & CD_Q_NO_TOUCH) {
- dp->disksize = 0;
- } else {
- cd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
- }
- if (dp->disksize) {
- printf("cd present [%lu x %lu byte records]",
- cd->params.disksize, (u_long)cd->params.blksize);
- } else {
- printf("can't get the size");
- }
-
- cd->flags |= CDINIT;
- cd_registerdev(unit);
-#ifdef DEVFS
- mynor = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART);
- cd->b_devfs_token = devfs_add_devswf(&cd_cdevsw, mynor, DV_BLK,
- UID_ROOT, GID_OPERATOR, 0640,
- "cd%d", unit);
- cd->c_devfs_token = devfs_add_devswf(&cd_cdevsw, mynor, DV_CHR,
- UID_ROOT, GID_OPERATOR, 0640,
- "rcd%d", unit);
- mynor = dkmakeminor(unit, 0, 0); /* XXX */
- cd->ctl_devfs_token = devfs_add_devswf(&cd_cdevsw,
- mynor | SCSI_CONTROL_MASK,
- DV_CHR,
- UID_ROOT, GID_WHEEL, 0600,
- "rcd%d.ctl", unit);
-#endif
-
- return 0;
-}
-
-/*
- * open the device. Make sure the partition info is a up-to-date as can be.
- */
-static errval
-cd_open(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link)
-{
- errval errcode = 0;
- u_int32_t unit;
- struct disklabel label;
- struct scsi_data *cd;
- int n;
-
- unit = CDUNIT(dev);
-
- cd = sc_link->sd;
- /*
- * Make sure the device has been initialised
- */
- if ((cd == NULL) || (!(cd->flags & CDINIT)))
- return (ENXIO);
-
- SC_DEBUG(sc_link, SDEV_DB1,
- ("cd_open: dev=0x%lx (unit %lu,partition %d)\n",
- (u_long)dev, (u_long)unit, PARTITION(dev)));
- /*
- * Check that it is still responding and ok.
- * if the media has been changed this will result in a
- * "unit attention" error which the error code will
- * disregard because the SDEV_OPEN flag is not yet set.
- * Makes sure that we know it if the media has been changed..
- */
- scsi_test_unit_ready(sc_link, SCSI_SILENT);
-
- /*
- * If it's been invalidated, then forget the label.
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED) && cd->dk_slices != NULL) {
- /*
- * If somebody still has it open, then forbid re-entry.
- */
- if (dsisopen(cd->dk_slices)) {
- SC_DEBUG(sc_link, SDEV_DB2,
- ("unit attn, but openparts?\n"));
- return (ENXIO);
- }
-
- dsgone(&cd->dk_slices);
- }
-
- /*
- * Start the drive, and take notice of error returns.
- * Some (arguably broken) drives go crazy on this attempt, we can
- * handle it.
- */
- if ((sc_link->quirks & CD_Q_NO_START) == 0) {
- scsi_start_unit(sc_link, CD_START);
- SC_DEBUG(sc_link, SDEV_DB3, ("'start' attempted "));
- }
- sc_link->flags |= SDEV_OPEN; /* unit attn errors are now errors */
-
- /*
- * Some drives take a long time to become ready after a disk swap
- * and report 'Not Ready' rather than 'Unit in the Process of Getting
- * Ready' while doing so; attempts to mount during this period will
- * return ENXIO. Give them some time to come up.
- */
- for (n = 0; scsi_test_unit_ready(sc_link, SCSI_SILENT) && n != 12; n++)
- tsleep(cd, PRIBIO | PCATCH, "cdrdy", hz);
-
- /* If still not ready, give up */
- if (scsi_test_unit_ready(sc_link, SCSI_SILENT) != 0) {
- SC_DEBUG(sc_link, SDEV_DB3, ("not ready\n"));
- errcode = ENXIO;
- goto bad;
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("Device present\n"));
- scsi_prevent(sc_link, PR_PREVENT, SCSI_SILENT);
- /*
- * Load the physical device parameters
- */
- if (cd_get_parms(unit, 0)) {
- errcode = ENXIO;
- goto bad;
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
-
- /*
- * Build prototype label for whole disk.
- * Should put manufacturer and model in d_typename and d_packname.
- * Should take information about different data tracks from the
- * TOC and put it in the partition table.
- */
- bzero(&label, sizeof label);
- label.d_type = DTYPE_SCSI;
- strncpy(label.d_typename, "scsi cd_rom", sizeof(label.d_typename));
- label.d_secsize = cd->params.blksize;
- label.d_secperunit = cd->params.disksize;
- label.d_flags = D_REMOVABLE;
- /*
- * Make partition 'a' cover the whole disk. This is a temporary
- * compatibility hack. The 'a' partition should not exist, so
- * the slice code won't create it. The slice code will make
- * partition (RAW_PART + 'a') cover the whole disk and fill in
- * some more defaults.
- */
- label.d_partitions[0].p_size = label.d_secperunit;
- label.d_partitions[0].p_fstype = FS_OTHER;
-
- /* Initialize slice tables. */
- errcode = dsopen("cd", dev, fmt, DSO_NOLABELS | DSO_ONESLICE,
- &cd->dk_slices, &label, cdstrategy1,
- (ds_setgeom_t *)NULL, &cd_cdevsw);
- if (errcode != 0)
- goto bad;
- SC_DEBUG(sc_link, SDEV_DB3, ("Slice tables initialized "));
-
- SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));
- sc_link->flags |= SDEV_MEDIA_LOADED;
- return 0;
-
- bad:
- /*
- * if we would have been the only open
- * then leave things back as they were
- */
- if (!dsisopen(cd->dk_slices)) {
- sc_link->flags &= ~SDEV_OPEN;
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
- }
- return (errcode);
-}
-
-/*
- * close the device.. only called if we are the LAST
- * occurence of an open device
- */
-static errval
-cd_close(dev_t dev, int flag, int fmt, struct proc *p,
- struct scsi_link *sc_link)
-{
- struct scsi_data *cd;
-
- cd = sc_link->sd;
- SC_DEBUG(sc_link, SDEV_DB2, ("cd%d: closing part %d\n",
- CDUNIT(dev), PARTITION(dev)));
- dsclose(dev, fmt, cd->dk_slices);
- if (!dsisopen(cd->dk_slices)) {
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
- sc_link->flags &= ~SDEV_OPEN;
- }
- return (0);
-}
-
-
-static int
-cdread(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(cdstrategy, NULL, dev, 1, minphys, uio));
-}
-
-/*
- * Actually translate the requested transfer into one the physical driver can
- * understand. The transfer is described by a buf and will include only one
- * physical transfer.
- */
-static void
-cd_strategy(struct buf *bp, struct scsi_link *sc_link)
-{
- u_int32_t opri;
- u_int32_t unit = CDUNIT((bp->b_dev));
- struct scsi_data *cd = sc_link->sd;
-
- cdstrats++;
- /*
- * If the device has been made invalid, error out
- * maybe the media changed
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- bp->b_error = EIO;
- goto bad;
- }
- /*
- * can't ever write to a CD
- */
- if ((bp->b_flags & B_READ) == 0) {
- bp->b_error = EROFS;
- goto bad;
- }
-
- /*
- * Do bounds checking, adjust transfer, and set b_pblkno.
- */
- if (dscheck(bp, cd->dk_slices) <= 0)
- goto done;
-
- opri = SPLCD();
-
- /*
- * Use a bounce buffer if necessary
- */
-#ifdef BOUNCE_BUFFERS
- if (sc_link->flags & SDEV_BOUNCE)
- vm_bounce_alloc(bp);
-#endif
-
- /*
- * Place it in the queue of disk activities for this disk
- */
- bufq_insert_tail(&cd->buf_queue, bp);
-
- /*
- * Tell the device to get going on the transfer if it's
- * not doing anything, otherwise just wait for completion
- */
- cdstart(unit, 0);
-
- splx(opri);
- return;
- bad:
- bp->b_flags |= B_ERROR;
- done:
-
- /*
- * Correctly set the buf to indicate a completed xfer
- */
- bp->b_resid = bp->b_bcount;
- biodone(bp);
- return;
-}
-
-static void
-cdstrategy1(struct buf *bp)
-{
- /*
- * XXX - do something to make cdstrategy() but not this block while
- * we're doing dsinit() and dsioctl().
- */
- cdstrategy(bp);
-}
-
-/*
- * cdstart looks to see if there is a buf waiting for the device
- * and that the device is not already busy. If both are true,
- * It deques the buf and creates a scsi command to perform the
- * transfer in the buf. The transfer request will call scsi_done
- * on completion, which will in turn call this routine again
- * so that the next queued transfer is performed.
- * The bufs are queued by the strategy routine (cdstrategy)
- *
- * This routine is also called after other non-queued requests
- * have been made of the scsi driver, to ensure that the queue
- * continues to be drained.
- *
- * must be called at the correct (highish) spl level
- * cdstart() is called at SPLCD from cdstrategy and scsi_done
- */
-static void
-cdstart(unit, flags)
- u_int32_t unit;
- u_int32_t flags;
-{
- register struct buf *bp = 0;
- struct scsi_rw_big cmd;
- u_int32_t blkno, nblk;
- struct scsi_link *sc_link = SCSI_LINK(&cd_switch, unit);
- struct scsi_data *cd = sc_link->sd;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("cdstart%lu ", (u_long)unit));
- /*
- * See if there is a buf to do and we are not already
- * doing one
- */
- if (!sc_link->opennings) {
- return; /* no room for us, unit already underway */
- }
- if (sc_link->flags & SDEV_WAITING) { /* is room, but a special waits */
- return; /* give the special that's waiting a chance to run */
- }
-
- bp = bufq_first(&cd->buf_queue);
- if (bp == NULL) { /* yes, an assign */
- return;
- }
- bufq_remove(&cd->buf_queue, bp);
-
- /*
- * Should reject all queued entries if SDEV_MEDIA_LOADED is not true.
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- goto bad; /* no I/O.. media changed or something */
- }
- /*
- * We have a buf, now we should make a command
- */
- blkno = bp->b_pblkno;
- nblk = bp->b_bcount / cd->params.blksize;
-
- /*
- * Fill out the scsi command
- */
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = READ_BIG;
- cmd.addr_3 = (blkno & 0xff000000UL) >> 24;
- cmd.addr_2 = (blkno & 0xff0000) >> 16;
- cmd.addr_1 = (blkno & 0xff00) >> 8;
- cmd.addr_0 = blkno & 0xff;
- cmd.length2 = (nblk & 0xff00) >> 8;
- cmd.length1 = (nblk & 0xff);
-
- /*
- * Call the routine that chats with the adapter.
- * Note: we cannot sleep as we may be an interrupt
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- (u_char *) bp->b_data,
- bp->b_bcount,
- CDRETRIES,
- 30000,
- bp,
- flags | ((bp->b_flags & B_READ) ?
- SCSI_DATA_IN : SCSI_DATA_OUT))
- != SUCCESSFULLY_QUEUED) {
- bad:
- printf("cd%lu: oops not queued\n", (u_long)unit);
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- biodone(bp);
- return;
- }
- cdqueues++;
- if(cd->dkunit >= 0) {
- dk_xfer[cd->dkunit]++;
- dk_seek[cd->dkunit]++; /* don't know */
- dk_wds[cd->dkunit] += bp->b_bcount >> 6;
- }
-}
-
-/*
- * Perform special action on behalf of the user.
- * Knows about the internals of this device
- */
-static errval
-cd_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p,
- struct scsi_link *sc_link)
-{
- errval error;
- u_int32_t unit;
- register struct scsi_data *cd;
-
- /*
- * Find the device that the user is talking about
- */
- cd = sc_link->sd;
- SC_DEBUG(sc_link, SDEV_DB2, ("cdioctl 0x%lx ", cmd));
-
- /*
- * If the device is not valid.. abandon ship
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED))
- return (EIO);
-
- if (cmd == DIOCSBAD)
- return (EINVAL); /* XXX */
-#if 0
- /* Wait until we have exclusive access to the device. */
- /* XXX this is how sd does it. How did we work without this? */
- error = scsi_device_lock(sc_link);
- if (error)
- return error;
-#endif
- error = dsioctl("cd", dev, cmd, addr, flag, &cd->dk_slices,
- cdstrategy1, (ds_setgeom_t *)NULL);
- scsi_device_unlock(sc_link);
- if (error != ENOIOCTL)
- return (error);
- if (PARTITION(dev) != RAW_PART)
- return (ENOTTY);
- error = 0;
- unit = CDUNIT(dev);
- switch (cmd) {
- case CDIOCPLAYTRACKS:
- {
- struct ioc_play_track *args
- = (struct ioc_play_track *) addr;
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.flags &= ~CD_PA_SOTC;
- data.page.audio.flags |= CD_PA_IMMED;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- if (sc_link->quirks & CD_Q_BCD_TRACKS) {
- args->start_track = bin2bcd(args->start_track);
- args->end_track = bin2bcd(args->end_track);
- }
- return (cd_play_tracks(unit
- ,args->start_track
- ,args->start_index
- ,args->end_track
- ,args->end_index
- ));
- }
- break;
- case CDIOCPLAYMSF:
- {
- struct ioc_play_msf *args
- = (struct ioc_play_msf *) addr;
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.flags &= ~CD_PA_SOTC;
- data.page.audio.flags |= CD_PA_IMMED;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- return (cd_play_msf(unit
- ,args->start_m
- ,args->start_s
- ,args->start_f
- ,args->end_m
- ,args->end_s
- ,args->end_f
- ));
- }
- break;
- case CDIOCPLAYBLOCKS:
- {
- struct ioc_play_blocks *args
- = (struct ioc_play_blocks *) addr;
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.flags &= ~CD_PA_SOTC;
- data.page.audio.flags |= CD_PA_IMMED;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- return (cd_play(unit, args->blk, args->len));
-
- }
- break;
- case CDIOCREADSUBCHANNEL:
- {
- struct ioc_read_subchannel *args
- = (struct ioc_read_subchannel *) addr;
- struct cd_sub_channel_info data;
- u_int32_t len = args->data_len;
- if (len > sizeof(data) ||
- len < sizeof(struct cd_sub_channel_header)) {
- error = EINVAL;
- break;
- }
- if (sc_link->quirks & CD_Q_BCD_TRACKS)
- args->track = bin2bcd(args->track);
- error = cd_read_subchannel(unit, args->address_format,
- args->data_format, args->track, &data, len);
- if (error)
- break;
- if (sc_link->quirks & CD_Q_BCD_TRACKS)
- data.what.track_info.track_number =
- bcd2bin(data.what.track_info.track_number);
- len = min(len, ((data.header.data_len[0] << 8) +
- data.header.data_len[1] +
- sizeof(struct cd_sub_channel_header)));
- if (copyout(&data, args->data, len) != 0) {
- error = EFAULT;
- }
- }
- break;
- case CDIOREADTOCHEADER:
- {
- struct ioc_toc_header th;
- error = cd_read_toc(unit, 0, 0,
- (struct cd_toc_entry *)&th, sizeof th);
- if (error)
- break;
- if (sc_link->quirks & CD_Q_BCD_TRACKS) {
- /* we are going to have to convert the BCD
- * encoding on the cd to what is expected
- */
- th.starting_track = bcd2bin(th.starting_track);
- th.ending_track = bcd2bin(th.ending_track);
- }
- NTOHS(th.len);
- bcopy(&th, addr, sizeof th);
- }
- break;
- case CDIOREADTOCENTRYS:
- {
- struct {
- struct ioc_toc_header header;
- struct cd_toc_entry entries[100];
- } data;
- struct {
- struct ioc_toc_header header;
- struct cd_toc_entry entry;
- } lead;
- struct ioc_read_toc_entry *te =
- (struct ioc_read_toc_entry *) addr;
- struct ioc_toc_header *th;
- u_int32_t len, readlen, idx, num;
- u_int32_t starting_track = te->starting_track;
-
- if ( te->data_len < sizeof(struct cd_toc_entry)
- || (te->data_len % sizeof(struct cd_toc_entry)) != 0
- || te->address_format != CD_MSF_FORMAT
- && te->address_format != CD_LBA_FORMAT
- ) {
- error = EINVAL;
- break;
- }
-
- th = &data.header;
- error = cd_read_toc(unit, 0, 0,
- (struct cd_toc_entry *)th, sizeof (*th));
- if (error)
- break;
-
- if (sc_link->quirks & CD_Q_BCD_TRACKS) {
- /* we are going to have to convert the BCD
- * encoding on the cd to what is expected
- */
- th->starting_track =
- bcd2bin(th->starting_track);
- th->ending_track = bcd2bin(th->ending_track);
- }
-
- if (starting_track == 0)
- starting_track = th->starting_track;
- else if (starting_track == LEADOUT)
- starting_track = th->ending_track + 1;
- else if (starting_track < th->starting_track ||
- starting_track > th->ending_track + 1) {
- error = EINVAL;
- break;
- }
-
- /* calculate reading length without leadout entry */
- readlen = (th->ending_track - starting_track + 1) *
- sizeof(struct cd_toc_entry);
-
- /* and with leadout entry */
- len = readlen + sizeof(struct cd_toc_entry);
- if (te->data_len < len) {
- len = te->data_len;
- if (readlen > len)
- readlen = len;
- }
- if (len > sizeof(data.entries)) {
- error = EINVAL;
- break;
- }
- num = len / sizeof(struct cd_toc_entry);
-
- if (readlen > 0) {
- error = cd_read_toc(unit, te->address_format,
- starting_track,
- (struct cd_toc_entry *)&data,
- readlen + sizeof (*th));
- if (error)
- break;
- }
-
- /* make leadout entry if needed */
- idx = starting_track + num - 1;
- if (sc_link->quirks & CD_Q_BCD_TRACKS)
- th->ending_track = bcd2bin(th->ending_track);
- if (idx == th->ending_track + 1) {
- error = cd_read_toc(unit, te->address_format,
- LEADOUT,
- (struct cd_toc_entry *)&lead,
- sizeof(lead));
- if (error)
- break;
- data.entries[idx - starting_track] = lead.entry;
- }
-
- if (sc_link->quirks & CD_Q_BCD_TRACKS) {
- for (idx = 0; idx < num - 1; idx++) {
- data.entries[idx].track =
- bcd2bin(data.entries[idx].track);
- }
- }
-
- error = copyout(data.entries, te->data, len);
- }
- break;
- case CDIOREADTOCENTRY:
- {
- struct {
- struct ioc_toc_header header;
- struct cd_toc_entry entry;
- } data;
- struct ioc_read_toc_single_entry *te =
- (struct ioc_read_toc_single_entry *) addr;
- struct ioc_toc_header *th;
- u_int32_t track;
-
- if (te->address_format != CD_MSF_FORMAT
- && te->address_format != CD_LBA_FORMAT) {
- error = EINVAL;
- break;
- }
-
- th = &data.header;
- error = cd_read_toc(unit, 0, 0,
- (struct cd_toc_entry *)th, sizeof (*th));
- if (error)
- break;
-
- if (sc_link->quirks & CD_Q_BCD_TRACKS) {
- /* we are going to have to convert the BCD
- * encoding on the cd to what is expected
- */
- th->starting_track =
- bcd2bin(th->starting_track);
- th->ending_track = bcd2bin(th->ending_track);
- }
-
- track = te->track;
- if (track == 0)
- track = th->starting_track;
- else if (track == LEADOUT)
- /* OK */;
- else if (track < th->starting_track ||
- track > th->ending_track + 1) {
- error = EINVAL;
- break;
- }
-
- error = cd_read_toc(unit, te->address_format,
- track,
- (struct cd_toc_entry *)&data,
- sizeof data);
- if (error)
- break;
-
- if (sc_link->quirks & CD_Q_BCD_TRACKS)
- data.entry.track = bcd2bin(data.entry.track);
-
- bcopy(&data.entry, &te->entry,
- sizeof(struct cd_toc_entry));
- }
- break;
- case CDIOCSETPATCH:
- {
- struct ioc_patch *arg = (struct ioc_patch *) addr;
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.port[LEFT_PORT].channels = arg->patch[0];
- data.page.audio.port[RIGHT_PORT].channels = arg->patch[1];
- data.page.audio.port[2].channels = arg->patch[2];
- data.page.audio.port[3].channels = arg->patch[3];
- error = cd_set_mode(unit, &data);
- if (error)
- break; /* eh? */
- }
- break;
- case CDIOCGETVOL:
- {
- struct ioc_vol *arg = (struct ioc_vol *) addr;
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- arg->vol[LEFT_PORT] = data.page.audio.port[LEFT_PORT].volume;
- arg->vol[RIGHT_PORT] = data.page.audio.port[RIGHT_PORT].volume;
- arg->vol[2] = data.page.audio.port[2].volume;
- arg->vol[3] = data.page.audio.port[3].volume;
- }
- break;
- case CDIOCSETVOL:
- {
- struct ioc_vol *arg = (struct ioc_vol *) addr;
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.port[LEFT_PORT].channels = CHANNEL_0;
- data.page.audio.port[LEFT_PORT].volume = arg->vol[LEFT_PORT];
- data.page.audio.port[RIGHT_PORT].channels = CHANNEL_1;
- data.page.audio.port[RIGHT_PORT].volume = arg->vol[RIGHT_PORT];
- data.page.audio.port[2].volume = arg->vol[2];
- data.page.audio.port[3].volume = arg->vol[3];
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- }
- break;
- case CDIOCSETMONO:
- {
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL | RIGHT_CHANNEL;
- data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL | RIGHT_CHANNEL;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- }
- break;
- case CDIOCSETSTEREO:
- {
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
- data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- }
- break;
- case CDIOCSETMUTE:
- {
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.port[LEFT_PORT].channels = 0;
- data.page.audio.port[RIGHT_PORT].channels = 0;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- }
- break;
- case CDIOCSETLEFT:
- {
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.port[LEFT_PORT].channels = LEFT_CHANNEL;
- data.page.audio.port[RIGHT_PORT].channels = LEFT_CHANNEL;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- }
- break;
- case CDIOCSETRIGHT:
- {
- struct cd_mode_data data;
- error = cd_get_mode(unit, &data, AUDIO_PAGE);
- if (error)
- break;
- data.page.audio.port[LEFT_PORT].channels = RIGHT_CHANNEL;
- data.page.audio.port[RIGHT_PORT].channels = RIGHT_CHANNEL;
- data.page.audio.port[2].channels = 0;
- data.page.audio.port[3].channels = 0;
- error = cd_set_mode(unit, &data);
- if (error)
- break;
- }
- break;
- case CDIOCRESUME:
- error = cd_pause(unit, 1);
- break;
- case CDIOCPAUSE:
- error = cd_pause(unit, 0);
- break;
- case CDIOCSTART:
- error = scsi_start_unit(sc_link, 0);
- break;
- case CDIOCSTOP:
- error = scsi_stop_unit(sc_link, 0, 0);
- break;
- case CDIOCEJECT:
- error = scsi_stop_unit(sc_link, 1, 0);
- break;
- case CDIOCALLOW:
- error = scsi_prevent(sc_link, PR_ALLOW, 0);
- break;
- case CDIOCPREVENT:
- error = scsi_prevent(sc_link, PR_PREVENT, 0);
- break;
- case CDIOCSETDEBUG:
- sc_link->flags |= (SDEV_DB1 | SDEV_DB2);
- break;
- case CDIOCCLRDEBUG:
- sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2);
- break;
- case CDIOCRESET:
- return (cd_reset(unit));
- break;
- default:
- error = scsi_do_ioctl(dev, cmd, addr, flag, p, sc_link);
- break;
- }
- return (error);
-}
-
-/*
- * Find out from the device what its capacity is
- */
-static u_int32_t
-cd_size(unit, flags)
- int unit;
- int flags;
-{
- struct scsi_read_cd_cap_data rdcap;
- struct scsi_read_cd_capacity scsi_cmd;
- u_int32_t size;
- u_int32_t blksize;
- struct scsi_link *sc_link = SCSI_LINK(&cd_switch, unit);
- struct scsi_data *cd = sc_link->sd;
-
- /*
- * make up a scsi command and ask the scsi driver to do
- * it for you.
- */
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = READ_CD_CAPACITY;
-
- /*
- * If the command works, interpret the result as a 4 byte
- * number of blocks and a blocksize
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) & rdcap,
- sizeof(rdcap),
- CDRETRIES,
- 20000, /* might be a disk-changer */
- NULL,
- SCSI_DATA_IN | flags) != 0) {
- return (0);
- } else {
- size = rdcap.addr_0 + 1;
- size += rdcap.addr_1 << 8;
- size += rdcap.addr_2 << 16;
- size += rdcap.addr_3 << 24;
- blksize = rdcap.length_0;
- blksize += rdcap.length_1 << 8;
- blksize += rdcap.length_2 << 16;
- blksize += rdcap.length_3 << 24;
- }
- if (blksize < 512)
- blksize = 2048; /* some drives lie ! */
- if (size < 100)
- size = 400000; /* ditto */
- SC_DEBUG(sc_link, SDEV_DB3, ("cd%d: %lu %lu byte blocks\n",
- unit, (u_long)size, (u_long)blksize));
- cd->params.disksize = size;
- cd->params.blksize = blksize;
- return (size);
-}
-
-/*
- * Get the requested page into the buffer given
- */
-static errval
-cd_get_mode(unit, data, page)
- u_int32_t unit;
- struct cd_mode_data *data;
- u_int32_t page;
-{
- struct scsi_mode_sense scsi_cmd;
- errval retval;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- bzero(data, sizeof(*data));
- scsi_cmd.op_code = MODE_SENSE;
- scsi_cmd.page = page;
- scsi_cmd.length = sizeof(*data) & 0xff;
- retval = scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) data,
- sizeof(*data),
- CDRETRIES,
- 20000, /* should be immed */
- NULL,
- SCSI_DATA_IN);
- return (retval);
-}
-
-/*
- * Get the requested page into the buffer given
- */
-static errval
-cd_set_mode(unit, data)
- u_int32_t unit;
- struct cd_mode_data *data;
-{
- struct scsi_mode_select scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SELECT;
- scsi_cmd.byte2 |= SMS_PF;
- scsi_cmd.length = sizeof(*data) & 0xff;
- data->header.data_length = 0;
- /*
- * SONY drives do not allow a mode select with a medium_type
- * value that has just been returned by a mode sense; use a
- * medium_type of 0 (Default) instead.
- */
- data->header.medium_type = 0;
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) data,
- sizeof(*data),
- CDRETRIES,
- 20000, /* should be immed */
- NULL,
- SCSI_DATA_OUT));
-}
-
-/*
- * Get scsi driver to send a "start playing" command
- */
-static errval
-cd_play(unit, blk, len)
- u_int32_t unit, blk, len;
-{
- struct scsi_play scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = PLAY;
- scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff;
- scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff;
- scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff;
- scsi_cmd.blk_addr[3] = blk & 0xff;
- scsi_cmd.xfer_len[0] = (len >> 8) & 0xff;
- scsi_cmd.xfer_len[1] = len & 0xff;
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- CDRETRIES,
- 200000, /* should be immed */
- NULL,
- 0));
-}
-
-#ifdef notyet
-/*
- * Get scsi driver to send a "start playing" command
- */
-static errval
-cd_play_big(unit, blk, len)
- u_int32_t unit, blk, len;
-{
- struct scsi_play_big scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = PLAY_BIG;
- scsi_cmd.blk_addr[0] = (blk >> 24) & 0xff;
- scsi_cmd.blk_addr[1] = (blk >> 16) & 0xff;
- scsi_cmd.blk_addr[2] = (blk >> 8) & 0xff;
- scsi_cmd.blk_addr[3] = blk & 0xff;
- scsi_cmd.xfer_len[0] = (len >> 24) & 0xff;
- scsi_cmd.xfer_len[1] = (len >> 16) & 0xff;
- scsi_cmd.xfer_len[2] = (len >> 8) & 0xff;
- scsi_cmd.xfer_len[3] = len & 0xff;
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- CDRETRIES,
- 20000, /* should be immed */
- NULL,
- 0));
-}
-#endif
-
-/*
- * Get scsi driver to send a "start playing" command
- */
-static errval
-cd_play_tracks(unit, strack, sindex, etrack, eindex)
- u_int32_t unit, strack, sindex, etrack, eindex;
-{
- struct scsi_play_track scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = PLAY_TRACK;
- scsi_cmd.start_track = strack;
- scsi_cmd.start_index = sindex;
- scsi_cmd.end_track = etrack;
- scsi_cmd.end_index = eindex;
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- CDRETRIES,
- 20000, /* should be immed */
- NULL,
- 0));
-}
-
-/*
- * Get scsi driver to send a "play msf" command
- */
-static errval
-cd_play_msf(unit, startm, starts, startf, endm, ends, endf)
- u_int32_t unit, startm, starts, startf, endm, ends, endf;
-{
- struct scsi_play_msf scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = PLAY_MSF;
- scsi_cmd.start_m = startm;
- scsi_cmd.start_s = starts;
- scsi_cmd.start_f = startf;
- scsi_cmd.end_m = endm;
- scsi_cmd.end_s = ends;
- scsi_cmd.end_f = endf;
-
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- CDRETRIES,
- 2000,
- NULL,
- 0));
-}
-
-/*
- * Get scsi driver to send a "start up" command
- */
-static errval
-cd_pause(unit, go)
- u_int32_t unit, go;
-{
- struct scsi_pause scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = PAUSE;
- scsi_cmd.resume = go;
-
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- CDRETRIES,
- 2000,
- NULL,
- 0));
-}
-
-/*
- * Get scsi driver to send a "RESET" command
- */
-static errval
-cd_reset(unit)
- u_int32_t unit;
-{
- return scsi_reset_target(SCSI_LINK(&cd_switch, unit));
-}
-
-/*
- * Read subchannel
- */
-static errval
-cd_read_subchannel(unit, mode, format, track, data, len)
- u_int32_t unit, mode, format;
- int track;
- struct cd_sub_channel_info *data;
- u_int32_t len;
-{
- struct scsi_read_subchannel scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
-
- scsi_cmd.op_code = READ_SUBCHANNEL;
- if (mode == CD_MSF_FORMAT)
- scsi_cmd.byte2 |= CD_MSF;
- scsi_cmd.byte3 = SRS_SUBQ;
- scsi_cmd.subchan_format = format;
- scsi_cmd.track = track;
- scsi_cmd.data_len[0] = (len) >> 8;
- scsi_cmd.data_len[1] = (len) & 0xff;
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(struct scsi_read_subchannel),
- (u_char *) data,
- len,
- CDRETRIES,
- 5000,
- NULL,
- SCSI_DATA_IN));
-}
-
-/*
- * Read table of contents
- */
-static errval
-cd_read_toc(unit, mode, start, data, len)
- u_int32_t unit, mode, start;
- struct cd_toc_entry *data;
- u_int32_t len;
-{
- struct scsi_read_toc scsi_cmd;
- u_int32_t ntoc;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- /*if(len!=sizeof(struct ioc_toc_header))
- * ntoc=((len)-sizeof(struct ioc_toc_header))/sizeof(struct cd_toc_entry);
- * else */
- ntoc = len;
-
- scsi_cmd.op_code = READ_TOC;
- if (mode == CD_MSF_FORMAT)
- scsi_cmd.byte2 |= CD_MSF;
- scsi_cmd.from_track = start;
- scsi_cmd.data_len[0] = (ntoc) >> 8;
- scsi_cmd.data_len[1] = (ntoc) & 0xff;
- return (scsi_scsi_cmd(SCSI_LINK(&cd_switch, unit),
- (struct scsi_generic *) &scsi_cmd,
- sizeof(struct scsi_read_toc),
- (u_char *) data,
- len,
- CDRETRIES,
- 5000,
- NULL,
- SCSI_DATA_IN));
-}
-
-#define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
-
-/*
- * Get the scsi driver to send a full inquiry to the device and use the
- * results to fill out the disk parameter structure.
- */
-static errval
-cd_get_parms(unit, flags)
- int unit;
- int flags;
-{
- struct scsi_link *sc_link = SCSI_LINK(&cd_switch, unit);
-
- /*
- * First check if we have it all loaded
- */
- if (sc_link->flags & SDEV_MEDIA_LOADED)
- return (0);
- /*
- * give a number of sectors so that sec * trks * cyls
- * is <= disk_size
- */
- if (cd_size(unit, flags)) {
- sc_link->flags |= SDEV_MEDIA_LOADED;
- return (0);
- } else {
- return (ENXIO);
- }
-}
-
-static cd_devsw_installed = 0;
-
-static void cd_drvinit(void *unused)
-{
-
- if( ! cd_devsw_installed ) {
- cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &cd_cdevsw);
- cd_devsw_installed = 1;
- }
-}
-
-SYSINIT(cddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,cd_drvinit,NULL)
-
-
diff --git a/sys/scsi/ch.c b/sys/scsi/ch.c
deleted file mode 100644
index 9b970fb..0000000
--- a/sys/scsi/ch.c
+++ /dev/null
@@ -1,750 +0,0 @@
-/*
- * Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
- * All rights reserved.
- *
- * Partially based on an autochanger driver written by Stefan Grefen
- * and on an autochanger driver written by the Systems Programming Group
- * at the University of Utah Computer Science Department.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgements:
- * This product includes software developed by Jason R. Thorpe
- * for And Communications, http://www.and.com/
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: ch.c,v 1.47 1998/06/17 14:13:13 bde Exp $
- */
-
-#include "opt_devfs.h"
-#include "opt_bounce.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/chio.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-#ifdef BOUNCE_BUFFERS
-#include <sys/buf.h>
-#endif
-
-#include <scsi/scsi_changer.h>
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_driver.h>
-
-#include "ioconf.h"
-
-#define CHRETRIES 2
-#define CHUNIT(x) (minor((x)))
-#define CHSETUNIT(x, y) makedev(major(x), y)
-
-struct ch_softc {
- /*
- * Human-readable external name. FreeBSD doesn't have a
- * generic hook for this, so we make it look NetBSD-like. See
- * comment in chattach().
- */
- struct {
- char dv_xname[16];
- } sc_dev;
-
- /*
- * Pointer back to the scsi_link. See comment in chattach().
- */
- struct scsi_link *sc_link;
-
- int sc_picker; /* current picker */
-
- /*
- * The following information is obtained from the
- * element address assignment page.
- */
- int sc_firsts[4]; /* firsts, indexed by CHET_* */
- int sc_counts[4]; /* counts, indexed by CHET_* */
-
- /*
- * The following mask defines the legal combinations
- * of elements for the MOVE MEDIUM command.
- */
- u_int8_t sc_movemask[4];
-
- /*
- * As above, but for EXCHANGE MEDIUM.
- */
- u_int8_t sc_exchangemask[4];
-
- int flags; /* misc. info */
-#ifdef DEVFS
- void *c_devfs_token;
- void *ctl_devfs_token;
-#endif
-};
-
-/* sc_flags */
-#define CHF_ROTATE 0x01 /* picker can rotate */
-
-static d_open_t chopen;
-static d_close_t chclose;
-static d_ioctl_t chioctl;
-
-#define CDEV_MAJOR 17
-static struct cdevsw ch_cdevsw =
- { chopen, chclose, noread, nowrite, /*17*/
- chioctl, nostop, nullreset, nodevtotty,/* ch */
- seltrue, nommap, nostrat, "ch", NULL, -1 };
-
-/*
- * SCSI glue.
- */
-
-/*
- * Under FreeBSD, this macro sets up a bunch of trampoline
- * functions that indirect through the SCSI subsystem.
- */
-SCSI_DEVICE_ENTRIES(ch)
-
-static int chunit __P((dev_t));
-static dev_t chsetunit __P((dev_t, int));
-
-/* So, like, why not "int"? */
-static errval ch_devopen __P((dev_t, int, int, struct proc *,
- struct scsi_link *));
-static errval ch_devioctl __P((dev_t, u_long, caddr_t, int, struct proc *,
- struct scsi_link *));
-static errval ch_devclose __P((dev_t, int, int, struct proc *,
- struct scsi_link *));
-
-static struct scsi_device ch_switch = {
- NULL, /* (*err_handler) */
- NULL, /* (*start) */
- NULL, /* (*async) */
- NULL, /* (*done) */
- "ch", /* name */
- 0, /* flags */
- { 0, 0 }, /* spare[2] */
- 0, /* link_flags */
- chattach, /* (*attach) */
- "Medium-Changer", /* desc */
- chopen, /* (*open) */
- sizeof(struct ch_softc), /* sizeof_scsi_data */
- T_CHANGER, /* type */
- chunit, /* (*getunit) */
- chsetunit, /* (*setunit) */
- ch_devopen, /* (*dev_open) */
- ch_devioctl, /* (*dev_ioctl) */
- ch_devclose, /* (*dev_close) */
-};
-
-static int ch_move __P((struct ch_softc *, struct changer_move *));
-static int ch_exchange __P((struct ch_softc *, struct changer_exchange *));
-static int ch_position __P((struct ch_softc *, struct changer_position *));
-static int ch_usergetelemstatus __P((struct ch_softc *, int, u_int8_t *));
-static int ch_getelemstatus __P((struct ch_softc *, int, int, caddr_t, size_t));
-static int ch_get_params __P((struct ch_softc *, int));
-
-static errval
-chattach(link)
- struct scsi_link *link;
-{
- struct ch_softc *sc = (struct ch_softc *)(link->sd);
- u_int32_t unit = link->dev_unit;
-
- /*
- * FreeBSD doesn't have any common way of carrying
- * around a device's external name (i.e. <name><unit>),
- * so emulate the structure used by NetBSD to keep the
- * diffs lower.
- */
- bzero(sc->sc_dev.dv_xname, sizeof(sc->sc_dev.dv_xname));
- sprintf(sc->sc_dev.dv_xname, "%s%d", ch_switch.name, unit);
-
- /*
- * FreeBSD gets "softc" info for a device from the
- * scsi_link argument passed to indirect entry point functions.
- * NetBSD get scsi_link info from softcs that are
- * obtained from indexes passed to direct entry point functions.
- * We emulate the NetBSD behavior here to keep the diffs
- * lower.
- */
- sc->sc_link = link;
-
- /*
- * Get information about the device. Note we can't use
- * interrupts yet.
- */
- if (ch_get_params(sc, SCSI_NOSLEEP|SCSI_NOMASK))
- printf("offline");
- else {
- printf("%d slot%s, %d drive%s, %d picker%s",
- sc->sc_counts[CHET_ST], (sc->sc_counts[CHET_ST] > 1) ?
- "s" : "",
- sc->sc_counts[CHET_DT], (sc->sc_counts[CHET_DT] > 1) ?
- "s" : "",
- sc->sc_counts[CHET_MT], (sc->sc_counts[CHET_MT] > 1) ?
- "s" : "");
- if (sc->sc_counts[CHET_IE])
- printf(", %d portal%s", sc->sc_counts[CHET_IE],
- (sc->sc_counts[CHET_IE] > 1) ? "s" : "");
- if (bootverbose) {
- printf("\n"); /* This will probably look ugly ... bummer. */
- printf("%s: move mask: 0x%x 0x%x 0x%x 0x%x\n",
- sc->sc_dev.dv_xname,
- sc->sc_movemask[CHET_MT], sc->sc_movemask[CHET_ST],
- sc->sc_movemask[CHET_IE], sc->sc_movemask[CHET_DT]);
- printf("%s: exchange mask: 0x%x 0x%x 0x%x 0x%x\n",
- sc->sc_dev.dv_xname,
- sc->sc_exchangemask[CHET_MT], sc->sc_exchangemask[CHET_ST],
- sc->sc_exchangemask[CHET_IE], sc->sc_exchangemask[CHET_DT]);
- }
- }
-
- /* Default the current picker. */
- sc->sc_picker = sc->sc_firsts[CHET_MT];
-
-#ifdef DEVFS
- sc->c_devfs_token = devfs_add_devswf(&ch_cdevsw, unit << 4, DV_CHR,
- UID_ROOT, GID_OPERATOR, 0600,
- "ch%d", unit);
- sc->ctl_devfs_token = devfs_add_devswf(&ch_cdevsw,
- (unit << 4) | SCSI_CONTROL_MASK,
- DV_CHR,
- UID_ROOT, GID_OPERATOR, 0600,
- "ch%d.ctl", unit);
-#endif
- return (0);
-}
-
-static errval
-ch_devopen(dev, flags, fmt, p, link)
- dev_t dev;
- int flags, fmt;
- struct proc *p;
- struct scsi_link *link;
-{
- struct ch_softc *sc = (struct ch_softc *)(link->sd);
- errval error = 0;
- int unit;
-
- unit = CHUNIT(dev);
-
- /*
- * Only allow one open at a time.
- */
- if (link->flags & SDEV_OPEN)
- return (EBUSY);
-
- link->flags |= SDEV_OPEN;
-
- /*
- * Absorb any unit attention errors. Ignore "not ready"
- * since this might occur if e.g. a tape isn't actually
- * loaded in the drive.
- */
- (void)scsi_test_unit_ready(link, SCSI_SILENT);
-
- /*
- * Make sure our parameters are up to date.
- */
- if (error = ch_get_params(sc, 0))
- goto bad;
-
- return (0);
-
- bad:
- link->flags &= ~SDEV_OPEN;
- return (error);
-}
-
-static errval
-ch_devclose(dev, flags, fmt, p, link)
- dev_t dev;
- int flags, fmt;
- struct proc *p;
- struct scsi_link *link;
-{
-
- link->flags &= ~SDEV_OPEN;
- return (0);
-}
-
-static errval
-ch_devioctl(dev, cmd, data, flags, p, link)
- dev_t dev;
- u_long cmd;
- caddr_t data;
- int flags;
- struct proc *p;
- struct scsi_link *link;
-{
- struct ch_softc *sc = (struct ch_softc *)(link->sd);
- caddr_t elemdata;
- int error = 0;
-
- switch (cmd) {
- case CHIOMOVE:
- error = ch_move(sc, (struct changer_move *)data);
- break;
-
- case CHIOEXCHANGE:
- error = ch_exchange(sc, (struct changer_exchange *)data);
- break;
-
- case CHIOPOSITION:
- error = ch_position(sc, (struct changer_position *)data);
- break;
-
- case CHIOGPICKER:
- *(int *)data = sc->sc_picker - sc->sc_firsts[CHET_MT];
- break;
-
- case CHIOSPICKER: {
- int new_picker = *(int *)data;
-
- if (new_picker > (sc->sc_counts[CHET_MT] - 1))
- return (EINVAL);
- sc->sc_picker = sc->sc_firsts[CHET_MT] + new_picker;
- break; }
-
- case CHIOGPARAMS: {
- struct changer_params *cp = (struct changer_params *)data;
-
- cp->cp_curpicker = sc->sc_picker - sc->sc_firsts[CHET_MT];
- cp->cp_npickers = sc->sc_counts[CHET_MT];
- cp->cp_nslots = sc->sc_counts[CHET_ST];
- cp->cp_nportals = sc->sc_counts[CHET_IE];
- cp->cp_ndrives = sc->sc_counts[CHET_DT];
- break; }
-
- case CHIOGSTATUS: {
- struct changer_element_status *ces =
- (struct changer_element_status *)data;
-
- error = ch_usergetelemstatus(sc, ces->ces_type, ces->ces_data);
- break; }
-
- /* Implement prevent/allow? */
-
- default:
- error = scsi_do_ioctl(dev, cmd, data, flags, p, link);
- break;
- }
-
- return (error);
-}
-
-static int
-ch_move(sc, cm)
- struct ch_softc *sc;
- struct changer_move *cm;
-{
- struct scsi_move_medium cmd;
- u_int16_t fromelem, toelem;
-
- /*
- * Check arguments.
- */
- if ((cm->cm_fromtype > CHET_DT) || (cm->cm_totype > CHET_DT))
- return (EINVAL);
- if ((cm->cm_fromunit > (sc->sc_counts[cm->cm_fromtype] - 1)) ||
- (cm->cm_tounit > (sc->sc_counts[cm->cm_totype] - 1)))
- return (ENODEV);
-
- /*
- * Check the request against the changer's capabilities.
- */
- if ((sc->sc_movemask[cm->cm_fromtype] & (1 << cm->cm_totype)) == 0)
- return (EINVAL);
-
- /*
- * Calculate the source and destination elements.
- */
- fromelem = sc->sc_firsts[cm->cm_fromtype] + cm->cm_fromunit;
- toelem = sc->sc_firsts[cm->cm_totype] + cm->cm_tounit;
-
- /*
- * Build the SCSI command.
- */
- bzero(&cmd, sizeof(cmd));
- cmd.opcode = MOVE_MEDIUM;
- scsi_uto2b(sc->sc_picker, cmd.tea);
- scsi_uto2b(fromelem, cmd.src);
- scsi_uto2b(toelem, cmd.dst);
- if (cm->cm_flags & CM_INVERT)
- cmd.flags |= MOVE_MEDIUM_INVERT;
-
- /*
- * Send command to changer.
- */
- return (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
- sizeof(cmd), NULL, 0, CHRETRIES, 100000, NULL, 0));
-}
-
-static int
-ch_exchange(sc, ce)
- struct ch_softc *sc;
- struct changer_exchange *ce;
-{
- struct scsi_exchange_medium cmd;
- u_int16_t src, dst1, dst2;
-
- /*
- * Check arguments.
- */
- if ((ce->ce_srctype > CHET_DT) || (ce->ce_fdsttype > CHET_DT) ||
- (ce->ce_sdsttype > CHET_DT))
- return (EINVAL);
- if ((ce->ce_srcunit > (sc->sc_counts[ce->ce_srctype] - 1)) ||
- (ce->ce_fdstunit > (sc->sc_counts[ce->ce_fdsttype] - 1)) ||
- (ce->ce_sdstunit > (sc->sc_counts[ce->ce_sdsttype] - 1)))
- return (ENODEV);
-
- /*
- * Check the request against the changer's capabilities.
- */
- if (((sc->sc_exchangemask[ce->ce_srctype] &
- (1 << ce->ce_fdsttype)) == 0) ||
- ((sc->sc_exchangemask[ce->ce_fdsttype] &
- (1 << ce->ce_sdsttype)) == 0))
- return (EINVAL);
-
- /*
- * Calculate the source and destination elements.
- */
- src = sc->sc_firsts[ce->ce_srctype] + ce->ce_srcunit;
- dst1 = sc->sc_firsts[ce->ce_fdsttype] + ce->ce_fdstunit;
- dst2 = sc->sc_firsts[ce->ce_sdsttype] + ce->ce_sdstunit;
-
- /*
- * Build the SCSI command.
- */
- bzero(&cmd, sizeof(cmd));
- cmd.opcode = EXCHANGE_MEDIUM;
- scsi_uto2b(sc->sc_picker, cmd.tea);
- scsi_uto2b(src, cmd.src);
- scsi_uto2b(dst1, cmd.fdst);
- scsi_uto2b(dst2, cmd.sdst);
- if (ce->ce_flags & CE_INVERT1)
- cmd.flags |= EXCHANGE_MEDIUM_INV1;
- if (ce->ce_flags & CE_INVERT2)
- cmd.flags |= EXCHANGE_MEDIUM_INV2;
-
- /*
- * Send command to changer.
- */
- return (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
- sizeof(cmd), NULL, 0, CHRETRIES, 100000, NULL, 0));
-}
-
-static int
-ch_position(sc, cp)
- struct ch_softc *sc;
- struct changer_position *cp;
-{
- struct scsi_position_to_element cmd;
- u_int16_t dst;
-
- /*
- * Check arguments.
- */
- if (cp->cp_type > CHET_DT)
- return (EINVAL);
- if (cp->cp_unit > (sc->sc_counts[cp->cp_type] - 1))
- return (ENODEV);
-
- /*
- * Calculate the destination element.
- */
- dst = sc->sc_firsts[cp->cp_type] + cp->cp_unit;
-
- /*
- * Build the SCSI command.
- */
- bzero(&cmd, sizeof(cmd));
- cmd.opcode = POSITION_TO_ELEMENT;
- scsi_uto2b(sc->sc_picker, cmd.tea);
- scsi_uto2b(dst, cmd.dst);
- if (cp->cp_flags & CP_INVERT)
- cmd.flags |= POSITION_TO_ELEMENT_INVERT;
-
- /*
- * Send command to changer.
- */
- return (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
- sizeof(cmd), NULL, 0, CHRETRIES, 100000, NULL, 0));
-}
-
-/*
- * Perform a READ ELEMENT STATUS on behalf of the user, and return to
- * the user only the data the user is interested in (i.e. an array of
- * flags bytes).
- */
-static int
-ch_usergetelemstatus(sc, chet, uptr)
- struct ch_softc *sc;
- int chet;
- u_int8_t *uptr;
-{
- struct read_element_status_header *st_hdr;
- struct read_element_status_page_header *pg_hdr;
- struct read_element_status_descriptor *desc;
- caddr_t data = NULL;
-#ifdef BOUNCE_BUFFERS
- int datasize = 0;
-#endif
- size_t size, desclen;
- int avail, i, error = 0;
- u_int8_t *user_data = NULL;
-
- /*
- * If there are no elements of the requested type in the changer,
- * the request is invalid.
- */
- if (sc->sc_counts[chet] == 0)
- return (EINVAL);
-
- /*
- * Request one descriptor for the given element type. This
- * is used to determine the size of the descriptor so that
- * we can allocate enough storage for all of them. We assume
- * that the first one can fit into 1k.
- */
-#ifdef BOUNCE_BUFFERS
- data = (caddr_t)vm_bounce_kva_alloc(btoc(1024));
- if (!data)
- return (ENOMEM);
- datasize = 1024;
-#else
- data = (caddr_t)malloc(1024, M_DEVBUF, M_WAITOK);
-#endif
- if (error = ch_getelemstatus(sc, sc->sc_firsts[chet], 1, data, 1024))
- goto done;
-
- st_hdr = (struct read_element_status_header *)data;
- pg_hdr = (struct read_element_status_page_header *)((char *)st_hdr +
- sizeof(struct read_element_status_header));
- desclen = scsi_2btou(pg_hdr->edl);
-
- size = sizeof(struct read_element_status_header) +
- sizeof(struct read_element_status_page_header) +
- (desclen * sc->sc_counts[chet]);
-
- /*
- * Reallocate storage for descriptors and get them from the
- * device.
- */
-#ifdef BOUNCE_BUFFERS
- vm_bounce_kva_alloc_free((vm_offset_t)data, btoc(datasize));
- data = (caddr_t)vm_bounce_kva_alloc(btoc(size));
- if (!data) {
- error = ENOMEM;
- goto done;
- }
- datasize = size;
-#else
- free(data, M_DEVBUF);
- data = (caddr_t)malloc(size, M_DEVBUF, M_WAITOK);
-#endif
- if (error = ch_getelemstatus(sc, sc->sc_firsts[chet],
- sc->sc_counts[chet], data, size))
- goto done;
-
- /*
- * Fill in the user status array.
- */
- st_hdr = (struct read_element_status_header *)data;
- avail = scsi_2btou(st_hdr->count);
- if (avail != sc->sc_counts[chet])
- printf("%s: warning, READ ELEMENT STATUS avail != count\n",
- sc->sc_dev.dv_xname);
-
- user_data = (u_int8_t *)malloc(avail, M_DEVBUF, M_WAITOK);
-
- desc = (struct read_element_status_descriptor *)((char *)data +
- sizeof(struct read_element_status_header) +
- sizeof(struct read_element_status_page_header));
- for (i = 0; i < avail; ++i) {
- user_data[i] = desc->flags1;
- desc = (struct read_element_status_descriptor *)
- ((char *)desc + desclen);
- }
-
- /* Copy flags array out to userspace. */
- error = copyout(user_data, uptr, avail);
-
- done:
-#ifdef BOUNCE_BUFFERS
- if (data != NULL)
- vm_bounce_kva_alloc_free((vm_offset_t)data, btoc(datasize));
-#else
- if (data != NULL)
- free(data, M_DEVBUF);
-#endif
- if (user_data != NULL)
- free(user_data, M_DEVBUF);
- return (error);
-}
-
-static int
-ch_getelemstatus(sc, first, count, data, datalen)
- struct ch_softc *sc;
- int first, count;
- caddr_t data;
- size_t datalen;
-{
- struct scsi_read_element_status cmd;
-
- /*
- * Build SCSI command.
- */
- bzero(&cmd, sizeof(cmd));
- cmd.opcode = READ_ELEMENT_STATUS;
- scsi_uto2b(first, cmd.sea);
- scsi_uto2b(count, cmd.count);
- scsi_uto3b(datalen, cmd.len);
-
- /*
- * Send command to changer.
- */
- return (scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
- sizeof(cmd), (u_char *)data, datalen, CHRETRIES, 100000, NULL, SCSI_DATA_IN));
-}
-
-
-/*
- * Ask the device about itself and fill in the parameters in our
- * softc.
- */
-static int
-ch_get_params(sc, scsiflags)
- struct ch_softc *sc;
- int scsiflags;
-{
- struct scsi_mode_sense cmd;
- struct scsi_mode_sense_data {
- struct scsi_mode_header header;
- union {
- struct page_element_address_assignment ea;
- struct page_transport_geometry_parameters tg;
- struct page_device_capabilities cap;
- } pages;
- } sense_data;
- int error, from;
- u_int8_t *moves, *exchanges;
-
- /*
- * Grab info from the element address assignment page.
- */
- bzero(&cmd, sizeof(cmd));
- bzero(&sense_data, sizeof(sense_data));
- cmd.op_code = MODE_SENSE;
- cmd.byte2 |= 0x08; /* disable block descriptors */
- cmd.page = 0x1d;
- cmd.length = (sizeof(sense_data) & 0xff);
- error = scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
- sizeof(cmd), (u_char *)&sense_data, sizeof(sense_data), CHRETRIES,
- 6000, NULL, scsiflags | SCSI_DATA_IN);
- if (error) {
- printf("%s: could not sense element address page\n",
- sc->sc_dev.dv_xname);
- return (error);
- }
-
- sc->sc_firsts[CHET_MT] = scsi_2btou(sense_data.pages.ea.mtea);
- sc->sc_counts[CHET_MT] = scsi_2btou(sense_data.pages.ea.nmte);
- sc->sc_firsts[CHET_ST] = scsi_2btou(sense_data.pages.ea.fsea);
- sc->sc_counts[CHET_ST] = scsi_2btou(sense_data.pages.ea.nse);
- sc->sc_firsts[CHET_IE] = scsi_2btou(sense_data.pages.ea.fieea);
- sc->sc_counts[CHET_IE] = scsi_2btou(sense_data.pages.ea.niee);
- sc->sc_firsts[CHET_DT] = scsi_2btou(sense_data.pages.ea.fdtea);
- sc->sc_counts[CHET_DT] = scsi_2btou(sense_data.pages.ea.ndte);
-
- /* XXX ask for page trasport geom */
-
- /*
- * Grab info from the capabilities page.
- */
- bzero(&cmd, sizeof(cmd));
- bzero(&sense_data, sizeof(sense_data));
- cmd.op_code = MODE_SENSE;
- cmd.byte2 |= 0x08; /* disable block descriptors */
- cmd.page = 0x1f;
- cmd.length = (sizeof(sense_data) & 0xff);
- error = scsi_scsi_cmd(sc->sc_link, (struct scsi_generic *)&cmd,
- sizeof(cmd), (u_char *)&sense_data, sizeof(sense_data), CHRETRIES,
- 6000, NULL, scsiflags | SCSI_DATA_IN);
- if (error) {
- printf("%s: could not sense capabilities page\n",
- sc->sc_dev.dv_xname);
- return (error);
- }
-
- bzero(sc->sc_movemask, sizeof(sc->sc_movemask));
- bzero(sc->sc_exchangemask, sizeof(sc->sc_exchangemask));
- moves = &sense_data.pages.cap.move_from_mt;
- exchanges = &sense_data.pages.cap.exchange_with_mt;
- for (from = CHET_MT; from <= CHET_DT; ++from) {
- sc->sc_movemask[from] = moves[from];
- sc->sc_exchangemask[from] = exchanges[from];
- }
-
- sc->sc_link->flags |= SDEV_MEDIA_LOADED;
- return (0);
-}
-
-static int
-chunit(dev)
- dev_t dev;
-{
-
- return (CHUNIT(dev));
-}
-
-static dev_t
-chsetunit(dev, unit)
- dev_t dev;
- int unit;
-{
-
- return (CHSETUNIT(dev, unit));
-}
-
-
-static ch_devsw_installed = 0;
-
-static void
-ch_drvinit(void *unused)
-{
- dev_t dev;
-
- if( ! ch_devsw_installed ) {
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev,&ch_cdevsw, NULL);
- ch_devsw_installed = 1;
- }
-}
-
-SYSINIT(chdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ch_drvinit,NULL)
diff --git a/sys/scsi/od.c b/sys/scsi/od.c
deleted file mode 100644
index 5943b50..0000000
--- a/sys/scsi/od.c
+++ /dev/null
@@ -1,966 +0,0 @@
-/*
- * Copyright (c) 1995,1996 Shunsuke Akiyama. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Shunsuke Akiyama.
- * 4. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY Shunsuke Akiyama AND CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL Shunsuke Akiyama OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * $Id: od.c,v 1.45 1998/07/30 15:16:05 bde Exp $
- */
-
-/*
- * Compile option defines:
- */
-
-/*
- * If drive returns sense key as 0x02 with vendor specific additional
- * sense code (ASC) and additional sense code qualifier (ASCQ), or
- * illegal ASC and ASCQ. This cause an error (NOT READY) and retrying.
- * To suppress this, uncomment following.
- * Or put "options OD_BOGUS_NOT_READY" entry into your kernel
- * configuration file.
- *
-#define OD_BOGUS_NOT_READY
- */
-
-/*
- * For an automatic spindown, try this. Again, preferrably as an
- * option in your config file.
- * WARNING! Use at your own risk. Joerg's ancient SONY SMO drive
- * groks it fine, while Shunsuke's Fujitsu chokes on it and times
- * out.
-#define OD_AUTO_TURNOFF
- */
-
-#include "opt_bounce.h"
-#include "opt_devfs.h"
-#include "opt_scsi.h"
-#include "opt_od.h"
-
-#define SPLOD splbio
-#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/dkbad.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/buf.h>
-#include <sys/cdio.h>
-#include <sys/dkstat.h>
-#include <sys/disklabel.h>
-#include <sys/diskslice.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-#include <scsi/scsi_disk.h>
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-#include "ioconf.h"
-
-static u_int32_t odstrats, odqueues;
-
-#define SECSIZE 512 /* default sector size */
-#define ODOUTSTANDING 4
-#define OD_RETRIES 4
-
-#define PARTITION(dev) dkpart(dev)
-#define ODUNIT(dev) dkunit(dev)
-
-/* XXX introduce a dkmodunit() macro for this. */
-#define ODSETUNIT(DEV, U) \
- makedev(major(DEV), dkmakeminor((U), dkslice(DEV), dkpart(DEV)))
-
-struct scsi_data {
- u_int32_t flags;
-#define ODINIT 0x04 /* device has been init'd */
- struct disk_parms {
- u_char heads; /* Number of heads */
- u_int16_t cyls; /* Number of cylinders (fictitious) */
- u_int16_t sectors; /* Number of sectors/track */
- u_int16_t secsiz; /* Number of bytes/sector */
- u_int32_t disksize; /* total number sectors */
- u_int16_t rpm; /* medium rotation rate */
- } params;
- struct diskslices *dk_slices; /* virtual drives */
- struct buf_queue_head buf_queue;
- int dkunit; /* disk stats unit number */
-#ifdef DEVFS
- /* Eventually move all these to common disk struct. */
- void *b_devfs_token;
- void *c_devfs_token;
- void *ctl_devfs_token;
-#endif
-};
-
-static errval od_get_parms __P((int unit, int flags));
-#ifdef notyet
-static errval od_reassign_blocks __P((int unit, int block));
-#endif
-static u_int32_t od_size __P((int unit, int flags));
-static int od_sense_handler __P((struct scsi_xfer *));
-static void odstart __P((u_int32_t, u_int32_t));
-static void odstrategy1 __P((struct buf *));
-
-static dev_t odsetunit(dev_t dev, int unit) { return ODSETUNIT(dev, unit); }
-static int odunit(dev_t dev) { return ODUNIT(dev); }
-
-static errval od_open __P((dev_t dev, int mode, int fmt, struct proc *p,
- struct scsi_link *sc_link));
-static errval od_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag,
- struct proc *p, struct scsi_link *sc_link);
-static errval od_close __P((dev_t dev, int fflag, int fmt, struct proc *p,
- struct scsi_link *sc_link));
-static void od_strategy(struct buf *bp, struct scsi_link *sc_link);
-
-static d_open_t odopen;
-static d_read_t odread;
-static d_write_t odwrite;
-static d_close_t odclose;
-static d_ioctl_t odioctl;
-static d_strategy_t odstrategy;
-
-#define CDEV_MAJOR 70
-#define BDEV_MAJOR 20
-static struct cdevsw od_cdevsw = {
- odopen, odclose, odread, odwrite,
- odioctl, nostop, nullreset, nodevtotty,
- seltrue, nommap, odstrategy, "od",
- NULL, -1, nodump, nopsize,
- D_DISK, 0, -1 };
-
-/*
- * Actually include the interface routines
- */
-SCSI_DEVICE_ENTRIES(od)
-
-static struct scsi_device od_switch =
-{
- od_sense_handler,
- odstart, /* have a queue, served by this */
- NULL, /* have no async handler */
- NULL, /* Use default 'done' routine */
- "od",
- 0,
- {0, 0},
- 0, /* Link flags */
- odattach,
- "Optical",
- odopen,
- sizeof(struct scsi_data),
- T_OPTICAL,
- odunit,
- odsetunit,
- od_open,
- od_ioctl,
- od_close,
- od_strategy,
-};
-
-static __inline void
-od_registerdev(int unit)
-{
- if(dk_ndrive < DK_NDRIVE) {
- sprintf(dk_names[dk_ndrive], "od%d", unit);
- dk_wpms[dk_ndrive] = (4*1024*1024/2); /* 4MB/sec */
- SCSI_DATA(&od_switch, unit)->dkunit = dk_ndrive++;
- } else {
- SCSI_DATA(&od_switch, unit)->dkunit = -1;
- }
-}
-
-
-/*
- * The routine called by the low level scsi routine when it discovers
- * a device suitable for this driver.
- */
-static errval
-odattach(struct scsi_link *sc_link)
-{
- u_int32_t unit;
- struct disk_parms *dp;
-#ifdef DEVFS
- int mynor;
-#endif
-
- struct scsi_data *od = sc_link->sd;
-
- unit = sc_link->dev_unit;
-
- dp = &(od->params);
-
- if (sc_link->opennings > ODOUTSTANDING)
- sc_link->opennings = ODOUTSTANDING;
-
- bufq_init(&od->buf_queue);
- /*
- * Use the subdriver to request information regarding
- * the drive. We cannot use interrupts yet, so the
- * request must specify this.
- */
- scsi_start_unit(sc_link, SCSI_NOSLEEP | SCSI_NOMASK
- | SCSI_ERR_OK | SCSI_SILENT);
- od_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
- /*
- * if we don't have actual parameters, assume 512 bytes/sec
- * (could happen on removable media - MOD)
- * -- this avoids the division below from falling over
- */
- if(dp->secsiz == 0) dp->secsiz = SECSIZE;
- if (dp->disksize != 0) {
- printf("%luMB (%lu %u byte sectors)",
- (u_long)(dp->disksize / ((1024L * 1024L) / dp->secsiz)),
- (u_long)dp->disksize, dp->secsiz);
- } else {
- printf("od not present");
- }
-
-#ifndef SCSI_REPORT_GEOMETRY
- if ( (sc_link->flags & SDEV_BOOTVERBOSE) )
-#endif
- {
- sc_print_addr(sc_link);
- printf("with approximate %d cyls, %d heads, and %d sectors/track",
- dp->cyls, dp->heads, dp->sectors);
- }
-#ifdef OD_AUTO_TURNOFF
- scsi_stop_unit(sc_link, 0, SCSI_ERR_OK | SCSI_SILENT);
-#endif /* OD_AUTO_TURNOFF */
-
- od->flags |= ODINIT;
- od_registerdev(unit);
-
-#ifdef DEVFS
- mynor = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART);
- od->b_devfs_token = devfs_add_devswf(&od_cdevsw, mynor, DV_BLK,
- UID_ROOT, GID_OPERATOR, 0640,
- "od%d", unit);
- od->c_devfs_token = devfs_add_devswf(&od_cdevsw, mynor, DV_CHR,
- UID_ROOT, GID_OPERATOR, 0640,
- "rod%d", unit);
- mynor = dkmakeminor(unit, 0, 0); /* XXX */
- od->ctl_devfs_token = devfs_add_devswf(&od_cdevsw,
- mynor | SCSI_CONTROL_MASK,
- DV_CHR,
- UID_ROOT, GID_WHEEL, 0600,
- "rod%d.ctl", unit);
-#endif
-
- return 0;
-}
-
-/*
- * open the device. Make sure the partition info is a up-to-date as can be.
- */
-static errval
-od_open(dev, mode, fmt, p, sc_link)
- dev_t dev;
- int mode;
- int fmt;
- struct proc *p;
- struct scsi_link *sc_link;
-{
- errval errcode = 0;
- u_int32_t unit;
- struct disklabel label;
- struct scsi_data *od;
-
- unit = ODUNIT(dev);
- od = sc_link->sd;
-
- /*
- * Make sure the disk has been initialized
- * At some point in the future, get the scsi driver
- * to look for a new device if we are not initted
- */
- if ((!od) || (!(od->flags & ODINIT))) {
- return ENXIO;
- }
-
- SC_DEBUG(sc_link, SDEV_DB1,
- ("od_open: dev=0x%lx (unit %lu, partition %d)\n",
- (u_long)dev, (u_long)unit, PARTITION(dev)));
-
- /*
- * Try to start the drive, and try to clear "Unit Attention"
- * condition, when media had been changed before.
- * This operation also clears the SDEV_MEDIA_LOADED flag in its
- * error handling routine.
- */
- scsi_start_unit(sc_link, SCSI_SILENT);
- scsi_prevent(sc_link, PR_PREVENT, SCSI_ERR_OK | SCSI_SILENT);
-
- /*
- * Make sure the drive is ready.
- */
- scsi_test_unit_ready(sc_link, 0);
-
- SC_DEBUG(sc_link, SDEV_DB3, ("'start' attempted "));
-
- sc_link->flags |= SDEV_OPEN; /* unit attn becomes an err now */
- /*
- * If it's been invalidated, then forget the label.
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- /*
- * If somebody still has it open, then forbid re-entry.
- */
- if (dsisopen(od->dk_slices)) {
- errcode = ENXIO;
- goto bad;
- }
-
- if (od->dk_slices != NULL)
- dsgone(&od->dk_slices);
- }
-
- /*
- * This time actually take notice of error returns
- */
- if (scsi_test_unit_ready(sc_link, SCSI_SILENT) != 0) {
- SC_DEBUG(sc_link, SDEV_DB3, ("not ready\n"));
- errcode = ENXIO;
- goto bad;
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("device present\n"));
-
- /*
- * Load the physical device parameters
- */
- errcode = od_get_parms(unit, 0); /* sets SDEV_MEDIA_LOADED */
- if (errcode) {
- goto bad;
- }
- switch (od->params.secsiz) {
- case SECSIZE :
- case 1024 :
- case 2048 :
- break;
- default :
- printf("od%lu: Can't deal with %u bytes logical blocks\n",
- (u_long)unit, od->params.secsiz);
- Debugger("od");
- errcode = ENXIO;
- goto bad;
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("params loaded "));
-
- /* Build label for whole disk. */
- bzero(&label, sizeof label);
- label.d_type = DTYPE_SCSI;
- label.d_secsize = od->params.secsiz;
- label.d_nsectors = od->params.sectors;
- label.d_ntracks = od->params.heads;
- label.d_ncylinders = od->params.cyls;
- label.d_secpercyl = od->params.heads * od->params.sectors;
- label.d_rpm = od->params.rpm; /* maybe wrong */
- if (label.d_secpercyl == 0)
- label.d_secpercyl = 64*32;
- /* XXX as long as it's not 0
- * - readdisklabel divides by it (?)
- */
- label.d_secperunit = od->params.disksize;
-
- /* Initialize slice tables. */
- errcode = dsopen("od", dev, fmt, 0, &od->dk_slices, &label, odstrategy1,
- (ds_setgeom_t *)NULL, &od_cdevsw);
- if (errcode != 0)
- goto bad;
- SC_DEBUG(sc_link, SDEV_DB3, ("Slice tables initialized "));
-
- SC_DEBUG(sc_link, SDEV_DB3, ("open %lu %lu\n",
- (u_long)odstrats, (u_long)odqueues));
-
- return 0;
-
-bad:
- if (!dsisopen(od->dk_slices)) {
- scsi_prevent(sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT);
-#ifdef OD_AUTO_TURNOFF
- scsi_stop_unit(sc_link, 0, SCSI_ERR_OK | SCSI_SILENT);
-#endif /* OD_AUTO_TURNOFF */
- sc_link->flags &= ~SDEV_OPEN;
- }
- return errcode;
-}
-
-/*
- * close the device.. only called if we are the LAST occurence of an open
- * device. Convenient now but usually a pain.
- */
-static errval
-od_close(dev, fflag, fmt, p, sc_link)
- dev_t dev;
- int fflag;
- int fmt;
- struct proc *p;
- struct scsi_link *sc_link;
-{
- struct scsi_data *od;
-
- od = sc_link->sd;
- dsclose(dev, fmt, od->dk_slices);
- if (!dsisopen(od->dk_slices)) {
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT | SCSI_ERR_OK);
-#ifdef OD_AUTO_TURNOFF
- scsi_stop_unit(sc_link, 0, SCSI_ERR_OK | SCSI_SILENT);
-#endif /* OD_AUTO_TURNOFF */
- sc_link->flags &= ~SDEV_OPEN;
- }
- return 0;
-}
-
-static int
-odread(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(odstrategy, NULL, dev, 1, minphys, uio));
-}
-
-static int
-odwrite(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(odstrategy, NULL, dev, 0, minphys, uio));
-}
-
-/*
- * Actually translate the requested transfer into one the physical driver
- * can understand. The transfer is described by a buf and will include
- * only one physical transfer.
- */
-static void
-od_strategy(struct buf *bp, struct scsi_link *sc_link)
-{
- u_int32_t opri;
- struct scsi_data *od;
- u_int32_t unit;
-
- odstrats++;
- unit = ODUNIT((bp->b_dev));
- od = sc_link->sd;
-
- /*
- * If the device has been made invalid, error out
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- bp->b_error = EIO;
- goto bad;
- }
-
- /*
- * Do bounds checking, adjust transfer, and set b_pblkno.
- */
- if (dscheck(bp, od->dk_slices) <= 0)
- goto done; /* XXX check b_resid */
-
- opri = SPLOD();
-
- /*
- * Use a bounce buffer if necessary
- */
-#ifdef BOUNCE_BUFFERS
- if (sc_link->flags & SDEV_BOUNCE)
- vm_bounce_alloc(bp);
-#endif
-
- /*
- * Place it in the queue of disk activities for this disk
- */
- bufq_insert_tail(&od->buf_queue, bp);
-
- /*
- * Tell the device to get going on the transfer if it's
- * not doing anything, otherwise just wait for completion
- */
- odstart(unit, 0);
-
- splx(opri);
- return /*0*/;
-bad:
- bp->b_flags |= B_ERROR;
-done:
-
- /*
- * Correctly set the buf to indicate a completed xfer
- */
- bp->b_resid = bp->b_bcount;
- biodone(bp);
- return /*0*/;
-}
-
-static void
-odstrategy1(struct buf *bp)
-{
- /*
- * XXX - do something to make odstrategy() but not this block while
- * we're doing dsinit() and dsioctl().
- */
- odstrategy(bp);
-}
-
-/*
- * odstart looks to see if there is a buf waiting for the device
- * and that the device is not already busy. If both are true,
- * It dequeues the buf and creates a scsi command to perform the
- * transfer in the buf. The transfer request will call scsi_done
- * on completion, which will in turn call this routine again
- * so that the next queued transfer is performed.
- * The bufs are queued by the strategy routine (odstrategy)
- *
- * This routine is also called after other non-queued requests
- * have been made of the scsi driver, to ensure that the queue
- * continues to be drained.
- *
- * must be called at the correct (highish) spl level
- * odstart() is called at SPLOD from odstrategy and scsi_done
- */
-static void
-odstart(u_int32_t unit, u_int32_t flags)
-{
- register struct scsi_link *sc_link = SCSI_LINK(&od_switch, unit);
- register struct scsi_data *od = sc_link->sd;
- struct buf *bp = 0;
- struct scsi_rw_big cmd;
- u_int32_t blkno, nblk;
- u_int32_t secsize;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("odstart "));
- /*
- * Check if the device has room for another command
- */
- while (sc_link->opennings) {
-
- /*
- * there is excess capacity, but a special waits
- * It'll need the adapter as soon as we clear out of the
- * way and let it run (user level wait).
- */
- if (sc_link->flags & SDEV_WAITING) {
- return;
- }
- /*
- * See if there is a buf with work for us to do..
- */
- bp = bufq_first(&od->buf_queue);
- if (bp == NULL) { /* yes, an assign */
- return;
- }
- bufq_remove(&od->buf_queue, bp);
-
- /*
- * If the device has become invalid, abort all the
- * reads and writes until all files have been closed and
- * re-openned
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- goto bad;
- }
- /*
- * We have a buf, now we know we are going to go through
- * With this thing..
- */
- secsize = od->params.secsiz;
- blkno = bp->b_pblkno;
- if (bp->b_bcount & (secsize - 1))
- {
- goto bad;
- }
- nblk = bp->b_bcount / secsize;
-
- /*
- * Fill out the scsi command
- */
- cmd.op_code = (bp->b_flags & B_READ)
- ? READ_BIG : WRITE_BIG;
- scsi_uto4b(blkno, &cmd.addr_3);
- scsi_uto2b(nblk, &cmd.length2);
- cmd.byte2 = cmd.reserved = cmd.control = 0;
- /*
- * Call the routine that chats with the adapter.
- * Note: we cannot sleep as we may be an interrupt
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- (u_char *) bp->b_data,
- bp->b_bcount,
- OD_RETRIES,
- 100000,
- bp,
- flags | ((bp->b_flags & B_READ) ?
- SCSI_DATA_IN : SCSI_DATA_OUT))
- == SUCCESSFULLY_QUEUED) {
- odqueues++;
- if(od->dkunit >= 0) {
- dk_xfer[od->dkunit]++;
- dk_seek[od->dkunit]++; /* don't know */
- dk_wds[od->dkunit] += bp->b_bcount >> 6;
- }
- } else {
-bad:
- printf("od%lu: oops not queued\n", (u_long)unit);
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- biodone(bp);
- }
- }
-}
-
-/*
- * Perform special action on behalf of the user
- * Knows about the internals of this device
- */
-static errval
-od_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p,
- struct scsi_link *sc_link)
-{
- /* struct od_cmd_buf *args; */
- errval error;
- struct scsi_data *od;
-
- /*
- * Find the device that the user is talking about
- */
- od = sc_link->sd;
- SC_DEBUG(sc_link, SDEV_DB1, ("odioctl (0x%lx)", cmd));
-
- /*
- * If the device is not valid.. abandon ship
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED))
- return EIO;
-
- switch (cmd) {
- case DIOCSBAD:
- error = EINVAL;
- break;
- case CDIOCEJECT:
- error = scsi_stop_unit(sc_link, 1, 0);
- sc_link->flags &= ~SDEV_MEDIA_LOADED;
- break;
- case CDIOCALLOW:
- error = scsi_prevent(sc_link, PR_ALLOW, 0);
- break;
- case CDIOCPREVENT:
- error = scsi_prevent(sc_link, PR_PREVENT, 0);
- break;
- default:
- error = dsioctl("od", dev, cmd, addr, flag, &od->dk_slices,
- odstrategy1, (ds_setgeom_t *)NULL);
- if (error == ENOIOCTL) {
- if (PARTITION(dev) != RAW_PART) {
- error = ENOTTY;
- } else {
- error = scsi_do_ioctl(dev, cmd, addr,
- flag, p, sc_link);
- }
- }
- break;
- }
- return error;
-}
-
-/*
- * Find out from the device what its capacity is
- */
-static u_int32_t
-od_size(unit, flags)
- int unit, flags;
-{
- struct scsi_read_cap_data rdcap;
- struct scsi_read_capacity rdcap_cmd;
- struct scsi_link *sc_link = SCSI_LINK(&od_switch, unit);
- struct scsi_data *od = sc_link->sd;
- struct scsi_mode_sense mdsense_cmd;
- struct scsi_mode_sense_data {
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- union disk_pages pages;
- } scsi_sense;
-
- /*
- * make up a scsi command and ask the scsi driver to do
- * it for you.
- */
- bzero(&rdcap_cmd, sizeof(rdcap_cmd));
- rdcap_cmd.op_code = READ_CAPACITY;
-
- /*
- * If the command works, interpret the result as a 4 byte
- * number of blocks
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &rdcap_cmd,
- sizeof(rdcap_cmd),
- (u_char *) & rdcap,
- sizeof(rdcap),
- OD_RETRIES,
- 10000,
- NULL,
- flags | SCSI_DATA_IN) != 0) {
- return 0;
- } else {
- od->params.disksize = scsi_4btou(&rdcap.addr_3) + 1;
- od->params.secsiz = scsi_4btou(&rdcap.length_3);
- }
-
- /*
- * do a "mode sense page 4" (rigid disk drive geometry)
- */
- bzero(&mdsense_cmd, sizeof(mdsense_cmd));
- mdsense_cmd.op_code = MODE_SENSE;
- mdsense_cmd.page = 4;
- mdsense_cmd.length = 0x20;
- /*
- * If the command worked, use the results to fill out
- * the parameter structure
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &mdsense_cmd,
- sizeof(mdsense_cmd),
- (u_char *) & scsi_sense,
- sizeof(scsi_sense),
- OD_RETRIES,
- 10000,
- NULL,
- flags | SCSI_SILENT | SCSI_DATA_IN) != 0) {
-
- /* default to a fictitious geometry */
- od->params.heads = 64;
- } else {
- SC_DEBUG(sc_link, SDEV_DB3,
- ("%lu cyls, %d heads, %lu rpm\n",
- (u_long)scsi_3btou(&scsi_sense.pages.rigid_geometry.ncyl_2),
- scsi_sense.pages.rigid_geometry.nheads,
- (u_long)scsi_2btou(
- &scsi_sense.pages.rigid_geometry.medium_rot_rate_1)));
-
- od->params.heads = scsi_sense.pages.rigid_geometry.nheads;
- if (od->params.heads == 0)
- od->params.heads = 64; /* fictitious */
- od->params.rpm =
- scsi_2btou(&scsi_sense.pages.rigid_geometry.medium_rot_rate_1);
- }
-
- /*
- * do a "mode sense page 3" (format device)
- */
- bzero(&mdsense_cmd, sizeof(mdsense_cmd));
- mdsense_cmd.op_code = MODE_SENSE;
- mdsense_cmd.page = 3;
- mdsense_cmd.length = 0x20;
- /*
- * If the command worked, use the results to fill out
- * the parameter structure
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &mdsense_cmd,
- sizeof(mdsense_cmd),
- (u_char *) & scsi_sense,
- sizeof(scsi_sense),
- OD_RETRIES,
- 10000,
- NULL,
- flags | SCSI_SILENT | SCSI_DATA_IN) != 0) {
-
- /* default to a fictitious geometry */
- od->params.sectors = 32;
- } else {
- SC_DEBUG(sc_link, SDEV_DB3,
- ("%d secs\n",
- scsi_2btou(&scsi_sense.pages.disk_format.ph_sec_t_1)));
-
- od->params.sectors =
- scsi_2btou(&scsi_sense.pages.disk_format.ph_sec_t_1);
- if (od->params.sectors == 0)
- od->params.sectors = 32; /* fictitious */
- }
-
- return od->params.disksize;
-}
-
-#ifdef notyet
-/*
- * Tell the device to map out a defective block
- */
-static errval
-od_reassign_blocks(unit, block)
- int unit, block;
-{
- struct scsi_reassign_blocks scsi_cmd;
- struct scsi_reassign_blocks_data rbdata;
- struct scsi_link *sc_link = SCSI_LINK(&od_switch, unit);
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- bzero(&rbdata, sizeof(rbdata));
- scsi_cmd.op_code = REASSIGN_BLOCKS;
-
- rbdata.length_msb = 0;
- rbdata.length_lsb = sizeof(rbdata.defect_descriptor[0]);
- scsi_uto4b(block, &rbdata.defect_descriptor[0].dlbaddr_3);
-
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) & rbdata,
- sizeof(rbdata),
- OD_RETRIES,
- 20000,
- NULL,
- SCSI_DATA_OUT);
-}
-#endif
-
-/*
- * Get the scsi driver to send a full inquiry to the
- * device and use the results to fill out the disk
- * parameter structure.
- */
-static errval
-od_get_parms(unit, flags)
- int unit, flags;
-{
- struct scsi_link *sc_link = SCSI_LINK(&od_switch, unit);
- struct scsi_data *od = sc_link->sd;
- struct disk_parms *disk_parms = &od->params;
- u_int32_t sectors;
- errval retval;
-
- /*
- * First check if we have it all loaded
- */
- if (sc_link->flags & SDEV_MEDIA_LOADED)
- return 0;
-
- /*
- * Use fictitious geometry, this depends on the size of medium.
- */
- sectors = od_size(unit, flags);
- /* od_size() sets secsiz, disksize, sectors, and heads */
-
- /* fictitious number of cylinders, so that C*H*S <= total */
- if (disk_parms->sectors != 0 && disk_parms->heads != 0) {
- disk_parms->cyls =
- sectors / (disk_parms->sectors * disk_parms->heads);
- } else {
- disk_parms->cyls = 0;
- }
-
- if (sectors != 0) {
- sc_link->flags |= SDEV_MEDIA_LOADED;
- retval = 0;
- } else {
- retval = ENXIO;
- }
- return retval;
-}
-
-/*
- * sense handler: Called to determine what to do when the
- * device returns a CHECK CONDITION.
- */
-
-static int
-od_sense_handler(struct scsi_xfer *xs)
-{
- struct scsi_sense_data *sense;
- struct scsi_sense_extended *ext;
- int asc, ascq;
-
- sense = &(xs->sense);
- ext = (struct scsi_sense_extended *)&(sense->ext.extended);
-
- /* I don't know what the heck to do with a deferred error,
- * so I'll just kick it back to the caller.
- */
- if ((sense->error_code & SSD_ERRCODE) == 0x71)
- return SCSIRET_CONTINUE;
-
-#ifdef OD_BOGUS_NOT_READY
- if (((sense->error_code & SSD_ERRCODE) == 0x70) &&
- ((sense->ext.extended.flags & SSD_KEY) == 0x02))
- /* No point in retrying Not Ready */
- return SCSIRET_CONTINUE;
-#endif
-
- if (((sense->error_code & SSD_ERRCODE) == 0x70) &&
- ((sense->ext.extended.flags & SSD_KEY) == 0x04))
- /* No point in retrying Hardware Failure */
- return SCSIRET_CONTINUE;
-
- if (((sense->error_code & SSD_ERRCODE) == 0x70) &&
- ((sense->ext.extended.flags & SSD_KEY) == 0x05))
- /* No point in retrying Illegal Requests */
- return SCSIRET_CONTINUE;
-
- asc = (ext->extra_len >= 5) ? ext->add_sense_code : 0;
- ascq = (ext->extra_len >= 6) ? ext->add_sense_code_qual : 0;
-
- if (asc == 0x11 || asc == 0x30 || asc == 0x31 || asc == 0x53
- || asc == 0x5a) {
- /* Unrecovered errors */
- return SCSIRET_CONTINUE;
- }
- if (asc == 0x21 && ascq == 0) {
- /* Logical block address out of range */
- return SCSIRET_CONTINUE;
- }
- if (asc == 0x27 && ascq == 0) {
- /* Write protected */
- return SCSIRET_CONTINUE;
- }
- if (asc == 0x28 && ascq == 0) {
- /* Not ready to ready transition */
- /* (medium may have changed) */
- return SCSIRET_CONTINUE;
- }
- if (asc == 0x3a && ascq == 0) {
- /* Medium not present */
- return SCSIRET_CONTINUE;
- }
-
- /* Retry all disk errors.
- */
- scsi_sense_print(xs);
- if (xs->retries)
- printf(", retries:%d\n", xs->retries);
- else
- printf(", FAILURE\n");
-
- return SCSIRET_DO_RETRY;
-}
-
-static od_devsw_installed = 0;
-
-static void od_drvinit(void *unused)
-{
-
- if( ! od_devsw_installed ) {
- cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &od_cdevsw);
- od_devsw_installed = 1;
- }
-}
-
-SYSINIT(oddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,od_drvinit,NULL)
diff --git a/sys/scsi/pt.c b/sys/scsi/pt.c
deleted file mode 100644
index c2a2a18..0000000
--- a/sys/scsi/pt.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * pt: Processor Type driver.
- *
- * Copyright (C) 1995, HD Associates, Inc.
- * PO Box 276
- * Pepperell, MA 01463
- * 508 433 5266
- * dufault@hda.com
- *
- * This code is contributed to the University of California at Berkeley:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: pt.c,v 1.29 1998/07/04 22:30:24 julian Exp $
- */
-
-#include "opt_bounce.h"
-#include "opt_devfs.h"
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-#include "ioconf.h"
-
-struct scsi_data {
- struct buf_queue_head buf_queue;
-#ifdef DEVFS
- void *devfs_data_tok;
- void *devfs_ctl_tok;
-#endif
-};
-
-static d_open_t ptopen;
-static d_read_t ptread;
-static d_write_t ptwrite;
-static d_close_t ptclose;
-static d_ioctl_t ptioctl;
-static d_strategy_t ptstrategy;
-
-#define CDEV_MAJOR 61
-static struct cdevsw pt_cdevsw =
- { ptopen, ptclose, ptread, ptwrite, /*61*/
- ptioctl, nostop, nullreset, nodevtotty,/* pt */
- seltrue, nommap, ptstrategy, "pt", NULL, -1 };
-
-SCSI_DEVICE_ENTRIES(pt)
-
-static void ptstart(u_int32_t unit, u_int32_t flags);
-static void pt_strategy(struct buf *bp, struct scsi_link *sc_link);
-static int pt_sense(struct scsi_xfer *scsi_xfer);
-
-static struct scsi_device pt_switch =
-{
- pt_sense,
- ptstart, /* we have a queue, and this is how we service it */
- NULL,
- NULL,
- "pt",
- 0,
- {0, 0},
- SDEV_ONCE_ONLY, /* Only one open allowed */
- ptattach,
- "Processor",
- ptopen,
- sizeof(struct scsi_data),
- T_PROCESSOR,
- 0,
- 0,
- 0,
- 0,
- 0,
- pt_strategy,
-};
-
-static errval
-ptattach(struct scsi_link *sc_link)
-{
- struct scsi_data *pt = sc_link->sd;
-
- bufq_init(&pt->buf_queue);
-
-#ifdef DEVFS
- pt->devfs_data_tok = devfs_add_devswf(&pt_cdevsw,
- sc_link->dev_unit,
- DV_CHR,
- UID_ROOT, GID_WHEEL, 0600,
- "pt%d", sc_link->dev_unit);
- pt->devfs_ctl_tok = devfs_add_devswf(&pt_cdevsw,
- sc_link->dev_unit | SCSI_CONTROL_MASK,
- DV_CHR,
- UID_ROOT, GID_WHEEL, 0600,
- "pt%d.ctl", sc_link->dev_unit);
-#endif
- return 0;
-}
-
-/*
- * ptstart looks to see if there is a buf waiting for the device
- * and that the device is not already busy. If both are true,
- * It dequeues the buf and creates a scsi command to perform the
- * transfer required. The transfer request will call scsi_done
- * on completion, which will in turn call this routine again
- * so that the next queued transfer is performed.
- * The bufs are queued by the strategy routine (ptstrategy)
- *
- * This routine is also called after other non-queued requests
- * have been made of the scsi driver, to ensure that the queue
- * continues to be drained.
- * ptstart() is called at splbio
- */
-static void
-ptstart(unit, flags)
- u_int32_t unit;
- u_int32_t flags;
-{
- struct scsi_link *sc_link = SCSI_LINK(&pt_switch, unit);
- struct scsi_data *pt = sc_link->sd;
- register struct buf *bp = 0;
- struct
- {
-#define PROCESSOR_SEND 0x0A
-#define PROCESSOR_RECEIVE 0x08
- u_char op_code;
- u_char byte2;
- u_char len[3];
- u_char control;
- } cmd;
-
-
- SC_DEBUG(sc_link, SDEV_DB2, ("ptstart "));
- /*
- * See if there is a buf to do and we are not already
- * doing one
- */
- while (sc_link->opennings != 0) {
-
- /* if a special awaits, let it proceed first */
- if (sc_link->flags & SDEV_WAITING) {
- sc_link->flags &= ~SDEV_WAITING;
- wakeup((caddr_t)sc_link);
- return;
- }
-
- bp = bufq_first(&pt->buf_queue);
- if (bp == NULL) { /* yes, an assign */
- return;
- }
- bufq_remove(&pt->buf_queue, bp);
-
- /*
- * Fill out the scsi command
- */
- bzero(&cmd, sizeof(cmd));
- if ((bp->b_flags & B_READ) == B_WRITE) {
- cmd.op_code = PROCESSOR_SEND;
- flags |= SCSI_DATA_OUT;
- } else {
- cmd.op_code = PROCESSOR_RECEIVE;
- flags |= SCSI_DATA_IN;
- }
-
- scsi_uto3b(bp->b_bcount, cmd.len);
- /*
- * go ask the adapter to do all this for us
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- (u_char *) bp->b_data,
- bp->b_bcount,
- 0,
- 10000,
- bp,
- flags) == SUCCESSFULLY_QUEUED) {
- } else {
- printf("pt%lu: oops not queued\n", (u_long)unit);
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- biodone(bp);
- }
- } /* go back and see if we can cram more work in.. */
-}
-
-static int
-ptread( dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(ptstrategy, NULL, dev, 1, minphys, uio));
-}
-
-static int
-ptwrite ( dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(ptstrategy, NULL, dev, 0, minphys, uio));
-}
-
-static void
-pt_strategy(struct buf *bp, struct scsi_link *sc_link)
-{
- unsigned char unit;
- u_int32_t opri;
- struct scsi_data *pt;
-
- unit = minor((bp->b_dev));
- pt = sc_link->sd;
-
- opri = splbio();
-
- /*
- * Use a bounce buffer if necessary
- */
-#ifdef BOUNCE_BUFFERS
- if (sc_link->flags & SDEV_BOUNCE)
- vm_bounce_alloc(bp);
-#endif
-
- /*
- * Place it in the queue of activities for this tape
- * at the end (a bit silly because we only have one user..
- * (but it could fork() ))
- */
- bufq_insert_tail(&pt->buf_queue, bp);
-
- /*
- * Tell the device to get going on the transfer if it's
- * not doing anything, otherwise just wait for completion
- * (All a bit silly if we're only allowing 1 open but..)
- */
- ptstart(unit, 0);
-
- splx(opri);
- return;
-}
-
-/*
- * sense handler: Called to determine what to do when the
- * device returns a CHECK CONDITION.
- *
- * For the processor type devices we try to handle the "info" field.
- */
-
-static int
-pt_sense(struct scsi_xfer *xs)
-{
- struct scsi_sense_data *sense = &(xs->sense);
- struct buf *bp;
-
- long resid;
-
- if ((sense->error_code & SSD_ERRCODE_VALID) == 0 ||
- (sense->ext.extended.flags & SSD_ILI) == 0) {
- return SCSIRET_CONTINUE; /* let the default handler handle it */
- }
-
- resid = ntohl(*((int32_t *) sense->ext.extended.info));
-
- bp = xs->bp;
-
- if (resid < 0) {
- /* It synthesized data in order to fill our request.
- * Move resid back to cover this.
- */
- xs->resid = -resid;
- xs->flags |= SCSI_RESID_VALID;
- return 0;
- }
- else {
- /* It wanted to send more data. We can't really do anything
- * about this.
- */
- return SCSIRET_CONTINUE;
- }
-}
-
-static pt_devsw_installed = 0;
-
-static void
-pt_drvinit(void *unused)
-{
- dev_t dev;
-
- if ( ! pt_devsw_installed ) {
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev,&pt_cdevsw, NULL);
- pt_devsw_installed = 1;
- }
-}
-
-SYSINIT(ptdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,pt_drvinit,NULL)
-
-
diff --git a/sys/scsi/scsi_all.h b/sys/scsi/scsi_all.h
deleted file mode 100644
index f12ac72..0000000
--- a/sys/scsi/scsi_all.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Largely written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- *
- * $Id: scsi_all.h,v 1.15 1997/02/22 09:44:27 peter Exp $
- */
-
-/*
- * SCSI general interface description
- */
-
-#ifndef _SCSI_SCSI_ALL_H
-#define _SCSI_SCSI_ALL_H 1
-/*
- * SCSI command format
- */
-
-/*
- * Define dome bits that are in ALL (or a lot of) scsi commands
- */
-#define SCSI_CTL_LINK 0x01
-#define SCSI_CTL_FLAG 0x02
-#define SCSI_CTL_VENDOR 0xC0
-#define SCSI_CMD_LUN 0xA0 /* these two should not be needed */
-#define SCSI_CMD_LUN_SHIFT 5 /* LUN in the cmd is no longer SCSI */
-
-
-struct scsi_generic
-{
- u_char opcode;
- u_char bytes[11];
-};
-
-struct scsi_test_unit_ready
-{
- u_char op_code;
- u_char byte2;
- u_char unused[3];
- u_char control;
-};
-
-struct scsi_send_diag
-{
- u_char op_code;
- u_char byte2;
-#define SSD_UOL 0x01
-#define SSD_DOL 0x02
-#define SSD_SELFTEST 0x04
-#define SSD_PF 0x10
- u_char unused[1];
- u_char paramlen[2];
- u_char control;
-};
-
-struct scsi_sense
-{
- u_char op_code;
- u_char byte2;
- u_char unused[2];
- u_char length;
- u_char control;
-};
-
-struct scsi_inquiry
-{
- u_char op_code;
- u_char byte2;
- u_char unused[2];
- u_char length;
- u_char control;
-};
-
-struct scsi_mode_sense
-{
- u_char op_code;
- u_char byte2;
-#define SMS_DBD 0x08
- u_char page;
-#define SMS_PAGE_CODE 0x3F
-#define SMS_PAGE_CTRL 0xC0
-#define SMS_PAGE_CTRL_CURRENT 0x00
-#define SMS_PAGE_CTRL_CHANGEABLE 0x40
-#define SMS_PAGE_CTRL_DEFAULT 0x80
-#define SMS_PAGE_CTRL_SAVED 0xC0
- u_char unused;
- u_char length;
- u_char control;
-};
-
-struct scsi_mode_sense_big
-{
- u_char op_code;
- u_char byte2; /* same bits as small version */
- u_char page; /* same bits as small version */
- u_char unused[4];
- u_char length[2];
- u_char control;
-};
-
-struct scsi_mode_select
-{
- u_char op_code;
- u_char byte2;
-#define SMS_SP 0x01
-#define SMS_PF 0x10
- u_char unused[2];
- u_char length;
- u_char control;
-};
-
-struct scsi_mode_select_big
-{
- u_char op_code;
- u_char byte2; /* same bits as small version */
- u_char unused[5];
- u_char length[2];
- u_char control;
-};
-
-struct scsi_reserve
-{
- u_char op_code;
- u_char byte2;
- u_char unused[2];
- u_char length;
- u_char control;
-};
-
-struct scsi_release
-{
- u_char op_code;
- u_char byte2;
- u_char unused[2];
- u_char length;
- u_char control;
-};
-
-struct scsi_prevent
-{
- u_char op_code;
- u_char byte2;
- u_char unused[2];
- u_char how;
- u_char control;
-};
-#define PR_PREVENT 0x01
-#define PR_ALLOW 0x00
-
-struct scsi_changedef
-{
- u_char op_code;
- u_char byte2;
- u_char unused1;
- u_char how;
- u_char unused[4];
- u_char datalen;
- u_char control;
-};
-#define SC_SCSI_1 0x01
-#define SC_SCSI_2 0x03
-
-/*
- * Opcodes
- */
-
-#define TEST_UNIT_READY 0x00
-#define REQUEST_SENSE 0x03
-#define INQUIRY 0x12
-#define MODE_SELECT 0x15
-#define MODE_SENSE 0x1a
-#define START_STOP 0x1b
-#define RESERVE 0x16
-#define RELEASE 0x17
-#define PREVENT_ALLOW 0x1e
-#define POSITION_TO_ELEMENT 0x2b
-#define CHANGE_DEFINITION 0x40
-#define MODE_SENSE_BIG 0x54
-#define MODE_SELECT_BIG 0x55
-#define MOVE_MEDIUM 0xa5
-#define READ_ELEMENT_STATUS 0xb8
-
-
-/*
- * sense data format
- */
-#define T_DIRECT 0
-#define T_SEQUENTIAL 1
-#define T_PRINTER 2
-#define T_PROCESSOR 3
-#define T_WORM 4
-#define T_READONLY 5
-#define T_SCANNER 6
-#define T_OPTICAL 7
-#define T_CHANGER 8
-#define T_COMM 9
-#define T_ASC0 10
-#define T_ASC1 11
-#define T_TARGET 12
-#define T_UNKNOWN 13
-#define T_NTYPES 14
-
-#define T_NODEVICE 0x1F
-
-#define T_REMOV 1
-#define T_FIXED 0
-
-struct scsi_inquiry_data
-{
- u_char device;
-#define SID_TYPE 0x1F
-#define SID_QUAL 0xE0
-#define SID_QUAL_LU_OK 0x00
-#define SID_QUAL_LU_OFFLINE 0x20
-#define SID_QUAL_RSVD 0x40
-#define SID_QUAL_BAD_LU 0x60
- u_char dev_qual2;
-#define SID_QUAL2 0x7F
-#define SID_REMOVABLE 0x80
- u_char version;
-#define SID_ANSII 0x07
-#define SID_ECMA 0x38
-#define SID_ISO 0xC0
- u_char response_format;
- u_char additional_length;
- u_char unused[2];
- u_char flags;
-#define SID_SftRe 0x01
-#define SID_CmdQue 0x02
-#define SID_Linked 0x08
-#define SID_Sync 0x10
-#define SID_WBus16 0x20
-#define SID_WBus32 0x40
-#define SID_RelAdr 0x80
- char vendor[8];
- char product[16];
- char revision[4];
- u_char extra[8];
-};
-
-
-struct scsi_sense_data
-{
-/* 1*/ u_char error_code; /* same bits as new version */
- union
- {
- struct
- {
-/* 2*/ u_char blockhi;
-/* 3*/ u_char blockmed;
-/* 4*/ u_char blocklow;
- } unextended;
- struct
- {
-/* 2*/ u_char segment;
-/* 3*/ u_char flags; /* same bits as new version */
-/* 7*/ u_char info[4];
-/* 8*/ u_char extra_len;
- /* allocate enough room to hold new stuff
- ( by increasing 16 to 24 below) */
-/*32*/ u_char extra_bytes[24];
- } extended;
- }ext;
-}; /* total of 32 bytes */
-
-struct scsi_sense_extended
-{
-/* 2*/ u_char segment;
-/* 3*/ u_char flags;
-#define SSD_KEY 0x0F
-#define SSD_ILI 0x20
-#define SSD_EOM 0x40
-#define SSD_FILEMARK 0x80
-/* 7*/ u_char info[4];
-/* 8*/ u_char extra_len;
-/*12*/ u_char cmd_spec_info[4];
-/*13*/ u_char add_sense_code;
-/*14*/ u_char add_sense_code_qual;
-/*15*/ u_char fru;
-/*16*/ u_char sense_key_spec_1;
-#define SSD_SCS_VALID 0x80
-/*17*/ u_char sense_key_spec_2;
-/*18*/ u_char sense_key_spec_3;
-/*32*/ u_char extra_bytes[14];
-};
-
-struct scsi_sense_data_new
-{
-/* 1*/ u_char error_code;
-#define SSD_ERRCODE 0x7F
-#define SSD_ERRCODE_VALID 0x80
- union
- {
- struct /* this is deprecated, the standard says "DON'T"*/
- {
-/* 2*/ u_char blockhi;
-/* 3*/ u_char blockmed;
-/* 4*/ u_char blocklow;
- } unextended;
-
- struct scsi_sense_extended extended;
- } ext;
-}; /* total of 32 bytes */
-
-struct blk_desc
-{
- u_char density;
- u_char nblocks[3];
- u_char reserved;
- u_char blklen[3];
-};
-
-struct scsi_mode_header
-{
- u_char data_length; /* Sense data length */
- u_char medium_type;
- u_char dev_spec;
- u_char blk_desc_len;
-};
-
-struct scsi_mode_header_big
-{
- u_char data_length[2]; /* Sense data length */
- u_char medium_type;
- u_char dev_spec;
- u_char unused[2];
- u_char blk_desc_len[2];
-};
-
-
-/*
- * Status Byte
- */
-#define SCSI_OK 0x00
-#define SCSI_CHECK 0x02
-#define SCSI_BUSY 0x08
-#define SCSI_INTERM 0x10
-#define SCSI_RSVD 0x18
-#define SCSI_QUEUE_FULL 0x28
-#endif /*_SCSI_SCSI_ALL_H*/
diff --git a/sys/scsi/scsi_base.c b/sys/scsi/scsi_base.c
deleted file mode 100644
index 67d01b8..0000000
--- a/sys/scsi/scsi_base.c
+++ /dev/null
@@ -1,1370 +0,0 @@
-/*
- * Written By Julian ELischer
- * Copyright julian Elischer 1993.
- * Permission is granted to use or redistribute this file in any way as long
- * as this notice remains. Julian Elischer does not guarantee that this file
- * is totally correct for any given task and users of this file must
- * accept responsibility for any damage that occurs from the application of this
- * file.
- *
- * Written by Julian Elischer (julian@dialix.oz.au)
- * $Id: scsi_base.c,v 1.57 1998/07/11 07:45:57 bde Exp $
- */
-
-#include "opt_bounce.h"
-#include "opt_scsi.h"
-
-#define SPLSD splbio
-#define ESUCCESS 0
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/malloc.h>
-#include <sys/proc.h>
-
-#include <machine/clock.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-
-#include <scsi/scsi_disk.h>
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-
-static errval sc_err1(struct scsi_xfer *);
-static errval scsi_interpret_sense(struct scsi_xfer *);
-static struct scsi_xfer *get_xs( struct scsi_link *sc_link, u_int32_t flags);
-static void free_xs(struct scsi_xfer *xs, struct scsi_link *sc_link,
- u_int32_t flags);
-#ifdef SCSIDEBUG
-static void show_mem(unsigned char *address, u_int32_t num);
-static void show_scsi_xs (struct scsi_xfer *);
-#endif
-
-#ifdef notyet
-static int scsi_sense_qualifiers (struct scsi_xfer *, int *, int *);
-#endif
-
-static struct scsi_xfer *next_free_xs;
-
-/*
- * Get a scsi transfer structure for the caller. Charge the structure
- * to the device that is referenced by the sc_link structure. If the
- * sc_link structure has no 'credits' then the device already has the
- * maximum number or outstanding operations under way. In this stage,
- * wait on the structure so that when one is freed, we are awoken again
- * If the SCSI_NOSLEEP flag is set, then do not wait, but rather, return
- * a NULL pointer, signifying that no slots were available
- * Note in the link structure, that we are waiting on it.
- */
-
-static struct scsi_xfer *
-get_xs(sc_link, flags)
- struct scsi_link *sc_link; /* who to charge the xs to */
- u_int32_t flags; /* if this call can sleep */
-{
- struct scsi_xfer *xs;
- u_int32_t s;
-
- SC_DEBUG(sc_link, SDEV_DB3, ("get_xs\n"));
- s = splbio();
- while (!sc_link->opennings) {
- SC_DEBUG(sc_link, SDEV_DB3, ("sleeping\n"));
- if (flags & SCSI_NOSLEEP) {
- splx(s);
- return 0;
- }
- sc_link->flags |= SDEV_WAITING;
- tsleep((caddr_t)sc_link, PRIBIO, "scsiget", 0);
- }
- sc_link->active++;
- sc_link->opennings--;
- if ( (xs = next_free_xs) ) {
- next_free_xs = xs->next;
- splx(s);
- } else {
- splx(s);
- SC_DEBUG(sc_link, SDEV_DB3, ("making\n"));
- xs = malloc(sizeof(*xs), M_TEMP,
- ((flags & SCSI_NOSLEEP) ? M_NOWAIT : M_WAITOK));
- if (xs == NULL) {
- sc_print_addr(sc_link);
- printf("cannot allocate scsi xs\n");
- return (NULL);
- }
- callout_handle_init(&xs->timeout_ch);
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("returning\n"));
- xs->sc_link = sc_link;
- return (xs);
-}
-
-/*
- * Given a scsi_xfer struct, and a device (referenced through sc_link)
- * return the struct to the free pool and credit the device with it
- * If another process is waiting for an xs, do a wakeup, let it proceed
- */
-static void
-free_xs(xs, sc_link, flags)
- struct scsi_xfer *xs;
- struct scsi_link *sc_link; /* who to credit for returning it */
- u_int32_t flags;
-{
- xs->next = next_free_xs;
- next_free_xs = xs;
-
- SC_DEBUG(sc_link, SDEV_DB3, ("free_xs\n"));
- /* if was 0 and someone waits, wake them up */
- sc_link->active--;
- if ((!sc_link->opennings++) && (sc_link->flags & SDEV_WAITING)) {
- sc_link->flags &= ~SDEV_WAITING;
- wakeup((caddr_t)sc_link); /* remember, it wakes them ALL up */
- } else {
- if (sc_link->device->start) {
- SC_DEBUG(sc_link, SDEV_DB2, ("calling private start()\n"));
- (*(sc_link->device->start)) (sc_link->dev_unit, flags);
- }
- }
-}
-
-/* XXX dufault: Replace "sd_size" with "scsi_read_capacity"
- * when bde is done with sd.c
- */
-/*
- * Find out from the device what its capacity is.
- */
-u_int32_t
-scsi_read_capacity(sc_link, blk_size, flags)
- struct scsi_link *sc_link;
- u_int32_t *blk_size;
- u_int32_t flags;
-{
- struct scsi_read_cap_data rdcap;
- struct scsi_read_capacity scsi_cmd;
- u_int32_t size;
-
- /*
- * make up a scsi command and ask the scsi driver to do
- * it for you.
- */
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = READ_CAPACITY;
-
- /*
- * If the command works, interpret the result as a 4 byte
- * number of blocks
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) & rdcap,
- sizeof(rdcap),
- 4,
- 5000000, /* WORMs tend to take a HUGE amount of time */
- NULL,
- flags | SCSI_DATA_IN) != 0) {
-
- sc_print_addr(sc_link);
- printf("could not get size\n");
- return (0);
- } else {
- size = scsi_4btou(&rdcap.addr_3) + 1;
- if (blk_size)
- *blk_size = scsi_4btou(&rdcap.length_3);
- }
- return (size);
-}
-
-errval
-scsi_reset_target(sc_link)
- struct scsi_link *sc_link;
-{
- return (scsi_scsi_cmd(sc_link,
- 0,
- 0,
- 0,
- 0,
- 1,
- 2000,
- NULL,
- SCSI_RESET));
-}
-
-errval
-scsi_target_mode(sc_link, on_off)
- struct scsi_link *sc_link;
- int on_off;
-{
- struct scsi_generic scsi_cmd;
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.opcode = SCSI_OP_TARGET;
- scsi_cmd.bytes[0] = (on_off) ? 1 : 0;
-
- return (scsi_scsi_cmd(sc_link,
- &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 1,
- 2000,
- NULL,
- SCSI_ESCAPE));
-}
-
-/*
- * Get scsi driver to send a "are you ready?" command
- */
-errval
-scsi_test_unit_ready(sc_link, flags)
- struct scsi_link *sc_link;
- u_int32_t flags;
-{
- struct scsi_test_unit_ready scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = TEST_UNIT_READY;
-
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 2,
- 100000,
- NULL,
- flags));
-}
-
-#ifdef SCSI_2_DEF
-/*
- * Do a scsi operation, asking a device to run as SCSI-II if it can.
- */
-errval
-scsi_change_def(sc_link, flags)
- struct scsi_link *sc_link;
- u_int32_t flags;
-{
- struct scsi_changedef scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = CHANGE_DEFINITION;
- scsi_cmd.how = SC_SCSI_2;
-
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 2,
- 100000,
- NULL,
- flags));
-}
-#endif /* SCSI_2_DEF */
-
-/*
- * Do a scsi operation asking a device what it is
- * Use the scsi_cmd routine in the switch table.
- */
-errval
-scsi_inquire(sc_link, inqbuf, flags)
- struct scsi_link *sc_link;
- struct scsi_inquiry_data *inqbuf;
- u_int32_t flags;
-{
- struct scsi_inquiry scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = INQUIRY;
- scsi_cmd.length = sizeof(struct scsi_inquiry_data);
-
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) inqbuf,
- sizeof(struct scsi_inquiry_data),
- 2,
- 100000,
- NULL,
- SCSI_DATA_IN | flags));
-}
-
-/*
- * Prevent or allow the user to remove the media
- */
-errval
-scsi_prevent(sc_link, type, flags)
- struct scsi_link *sc_link;
- u_int32_t type, flags;
-{
- struct scsi_prevent scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = PREVENT_ALLOW;
- scsi_cmd.how = type;
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 2,
- 5000,
- NULL,
- flags));
-}
-
-/*
- * Get scsi driver to send a "start up" command
- */
-errval
-scsi_start_unit(sc_link, flags)
- struct scsi_link *sc_link;
- u_int32_t flags;
-{
- struct scsi_start_stop scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = START_STOP;
- scsi_cmd.how = SSS_START;
-
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 2,
- 30000,
- NULL,
- flags));
-}
-
-/*
- * Get scsi driver to send a "stop" command
- */
-errval
-scsi_stop_unit(sc_link, eject, flags)
- struct scsi_link *sc_link;
- u_int32_t eject;
- u_int32_t flags;
-{
- struct scsi_start_stop scsi_cmd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = START_STOP;
- if (eject) {
- scsi_cmd.how = SSS_LOEJ;
- }
-
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 2,
- 10000,
- NULL,
- flags));
-}
-
-/*
- * This routine is called by the scsi interrupt when the transfer is complete.
- */
-void
-scsi_done(xs)
- struct scsi_xfer *xs;
-{
- struct scsi_link *sc_link = xs->sc_link;
- struct buf *bp = xs->bp;
- errval retval;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("scsi_done\n"));
-#ifdef SCSIDEBUG
- if (sc_link->flags & SDEV_DB1)
- {
- show_scsi_cmd(xs);
- }
-#endif /*SCSIDEBUG */
- /*
- * If it's a user level request, bypass all usual completion processing,
- * let the user work it out.. We take reponsibility for freeing the
- * xs when the user returns. (and restarting the device's queue).
- */
- if (xs->flags & SCSI_USER) {
- SC_DEBUG(sc_link, SDEV_DB3, ("calling user done()\n"));
- scsi_user_done(xs); /* to take a copy of the sense etc. */
- SC_DEBUG(sc_link, SDEV_DB3, ("returned from user done()\n "));
-
- free_xs(xs, sc_link, SCSI_NOSLEEP); /* restarts queue too */
- SC_DEBUG(sc_link, SDEV_DB3, ("returning to adapter\n"));
- return;
- }
- /*
- * If the device has its own done routine, call it first.
- * If it returns a legit error value, return that, otherwise
- * it wants us to continue with normal processing.
- */
-
- if (sc_link->device->done) {
- SC_DEBUG(sc_link, SDEV_DB2, ("calling private done()\n"));
- retval = (*sc_link->device->done) (xs);
- if (retval == -1) {
- free_xs(xs, sc_link, SCSI_NOSLEEP); /*XXX */
- return; /* it did it all, finish up */
- }
- /* XXX: This isn't used anywhere. Do you have plans for it,
- * Julian? (dufault@hda.com).
- * This allows a private 'done' handler to
- * resubmit the command if it wants to retry,
- * In this case the xs must NOT be freed. (julian)
- */
- if (retval == -2) {
- return; /* it did it all, finish up */
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("continuing with generic done()\n"));
- }
- if ((bp = xs->bp) == NULL) {
- /*
- * if it's a normal upper level request, then ask
- * the upper level code to handle error checking
- * rather than doing it here at interrupt time
- */
- wakeup((caddr_t)xs);
- return;
- }
- /*
- * Go and handle errors now.
- * If it returns SCSIRET_DO_RETRY then we should RETRY
- */
- if ((retval = sc_err1(xs)) == SCSIRET_DO_RETRY) {
- if ((*(sc_link->adapter->scsi_cmd)) (xs)
- == SUCCESSFULLY_QUEUED) { /* don't wake the job, ok? */
- return;
- }
- xs->flags |= ITSDONE;
- }
-
- free_xs(xs, sc_link, SCSI_NOSLEEP); /* does a start if needed */
- biodone(bp);
-}
-
-/*
- * ask the scsi driver to perform a command for us.
- * tell it where to read/write the data, and how
- * long the data is supposed to be. If we have a buf
- * to associate with the transfer, we need that too.
- */
-errval
-scsi_scsi_cmd(sc_link, scsi_cmd, cmdlen, data_addr, datalen,
- retries, timeout, bp, flags)
- struct scsi_link *sc_link;
- struct scsi_generic *scsi_cmd;
- u_int32_t cmdlen;
- u_char *data_addr;
- u_int32_t datalen;
- u_int32_t retries;
- u_int32_t timeout;
- struct buf *bp;
- u_int32_t flags;
-{
- struct scsi_xfer *xs;
- errval retval;
- u_int32_t s;
- struct proc *p = curproc;
- int iskstack = 0; /* 0 = "ok", 1 = copied from kernel stack */
-
- /*
- * Illegal command lengths will wedge host adapter software.
- * Reject zero length commands and assert all defined commands
- * are the correct length.
- */
- if ((flags & (SCSI_RESET | SCSI_ESCAPE)) == 0)
- {
- if (cmdlen == 0) {
- retval = EFAULT;
- goto bad_with_biodone;
- } else {
- static u_int8_t sizes[] = {6, 10, 10, 0, 0, 12, 0, 0 };
- u_int8_t size = sizes[((scsi_cmd->opcode) >> 5)];
- if (size && (size != cmdlen)) {
- retval = EIO;
- goto bad_with_biodone;
- }
- }
- }
-
- SC_DEBUG(sc_link, SDEV_DB2, ("scsi_cmd\n"));
-
- xs = get_xs(sc_link, flags);
- if (!xs) {
- retval = ENOMEM;
- goto bad_with_biodone;
- }
- /*
- * Fill out the scsi_xfer structure. We don't know whose context
- * the cmd is in, so copy it.
- */
- bcopy(scsi_cmd, &(xs->cmdstore), cmdlen);
- xs->flags = INUSE | flags;
- xs->sc_link = sc_link;
- xs->retries = retries;
- xs->timeout = timeout;
- xs->cmd = &xs->cmdstore;
- xs->cmdlen = cmdlen;
- xs->data = data_addr;
- xs->datalen = datalen;
- xs->resid = 0;
- xs->bp = bp;
-/*XXX*/ /*use constant not magic number */
- if (datalen && (caddr_t) data_addr < (caddr_t) KERNBASE) {
- /* XXX: should panic */
- printf("scsi_scsi_cmd(): data target is user space!\n");
-#ifdef SCSIDEBUG
- show_scsi_cmd(xs);
-#endif /* SCSIDEBUG */
- retval = EFAULT;
- goto bad;
- }
- /* XXX theoretically.. in !BOUNCE_BUFFERS, we can still get to all
- * process's kstack's, *BUT* we can swap a process. We really don't
- * need to take a fault in that situation. Besides, the permanent
- * KVM space will go away and only the current process will be
- * reachable once the kthreading is finished.
- */
- if (datalen && p != NULL &&
- (caddr_t)data_addr > (caddr_t)p->p_addr &&
- (caddr_t)data_addr < (caddr_t)p->p_addr + UPAGES * PAGE_SIZE)
- iskstack = 1;
- /* if we are doing a scsi command to/from per-proc kstack, copy it.. */
- if (iskstack) {
- if (bp) {
- printf("Data buffered space not in kernel context\n");
-#ifdef SCSIDEBUG
- show_scsi_cmd(xs);
-#endif /* SCSIDEBUG */
- retval = EFAULT;
- goto bad;
- }
-#ifdef BOUNCE_BUFFERS
- xs->data = (caddr_t) vm_bounce_kva_alloc(btoc(datalen));
-#else
- xs->data = malloc(datalen, M_TEMP, M_WAITOK);
-#endif
- /* I think waiting is ok *//*XXX */
- switch ((int)(flags & (SCSI_DATA_IN | SCSI_DATA_OUT))) {
- case 0:
- printf("No direction flags, assuming both\n");
-#ifdef SCSIDEBUG
- show_scsi_cmd(xs);
-#endif /* SCSIDEBUG */
- case SCSI_DATA_IN | SCSI_DATA_OUT: /* weird */
- case SCSI_DATA_OUT:
- bcopy(data_addr, xs->data, datalen);
- break;
- case SCSI_DATA_IN:
- bzero(xs->data, datalen);
- }
- }
-retry:
- xs->error = XS_NOERROR;
-#ifdef PARANOID
- if (datalen && ((caddr_t) xs->data < (caddr_t) KERNBASE)) {
- printf("It's still wrong!\n");
- }
-#endif /*PARANOID*/
-#ifdef SCSIDEBUG
- if (sc_link->flags & SDEV_DB3) show_scsi_xs(xs);
-#endif /* SCSIDEBUG */
- /*
- * Do the transfer. If we are polling we will return:
- * COMPLETE, Was poll, and scsi_done has been called
- * TRY_AGAIN_LATER, Adapter short resources, try again
- *
- * if under full steam (interrupts) it will return:
- * SUCCESSFULLY_QUEUED, will do a wakeup when complete
- * TRY_AGAIN_LATER, (as for polling)
- * After the wakeup, we must still check if it succeeded
- *
- * If we have a bp however, all the error proccessing
- * and the buffer code both expect us to return straight
- * to them, so as soon as the command is queued, return
- */
-
- retval = (*(sc_link->adapter->scsi_cmd)) (xs);
-
- switch (retval) {
- case SUCCESSFULLY_QUEUED:
- if (bp) {
- return 0; /* will sleep (or not) elsewhere */
- }
- s = splbio();
- while (!(xs->flags & ITSDONE)) {
- tsleep((caddr_t)xs, PRIBIO + 1, "scsicmd", 0);
- }
- splx(s);
- /* fall through to check success of completed command */
- case COMPLETE: /* Polling command completed ok */
-/*XXX*/ case HAD_ERROR: /* Polling command completed with error */
- SC_DEBUG(sc_link, SDEV_DB3, ("back in cmd()\n"));
- if ((retval = sc_err1(xs)) == SCSIRET_DO_RETRY)
- goto retry;
- break;
-
- case TRY_AGAIN_LATER: /* adapter resource shortage */
- SC_DEBUG(sc_link, SDEV_DB3, ("will try again \n"));
- /* should sleep 1 sec here */
- if (xs->retries--) {
- xs->flags &= ~ITSDONE;
- goto retry;
- }
- default:
- retval = EIO;
- }
- /*
- * If we had to copy the data out of the user's context,
- * then do the other half (copy it back or whatever)
- * and free the memory buffer
- */
- if (iskstack) {
- switch ((int)(flags & (SCSI_DATA_IN | SCSI_DATA_OUT))) {
- case 0:
- case SCSI_DATA_IN | SCSI_DATA_OUT: /* weird */
- case SCSI_DATA_IN:
- bcopy(xs->data, data_addr, datalen);
- break;
- }
-bad_with_alloc:
-#ifdef BOUNCE_BUFFERS
- vm_bounce_kva_alloc_free((vm_offset_t) xs->data,
- btoc(datalen));
-#else
- free(xs->data, M_TEMP);
-#endif
- }
- /*
- * we have finished with the xfer stuct, free it and
- * check if anyone else needs to be started up.
- */
-bad:
- s = splbio();
- free_xs(xs, sc_link, flags); /* includes the 'start' op */
- splx(s);
-bad_with_biodone:
- if (bp && retval) {
- bp->b_error = retval;
- bp->b_flags |= B_ERROR;
- biodone(bp);
- }
- return (retval);
-}
-
-static errval
-sc_done(struct scsi_xfer *xs, int code)
-{
- /*
- * If it has a buf, we might be working with
- * a request from the buffer cache or some other
- * piece of code that requires us to process
- * errors at interrupt time. We have probably
- * been called by scsi_done()
- */
- struct buf *bp;
-
- if (code == SCSIRET_DO_RETRY) {
- if (xs->retries--) {
- xs->error = XS_NOERROR;
- xs->flags &= ~ITSDONE;
- return SCSIRET_DO_RETRY;
- }
- code = EIO; /* Too many retries */
- }
-
- /*
- * an EOF condition results in a VALID resid..
- */
- if(xs->flags & SCSI_EOF) {
- xs->resid = xs->datalen;
- xs->flags |= SCSI_RESID_VALID;
- }
-
- bp = xs->bp;
- if (code != ESUCCESS) {
- if (bp) {
- bp->b_error = 0;
- bp->b_flags |= B_ERROR;
- bp->b_error = code;
- bp->b_resid = bp->b_bcount;
- SC_DEBUG(xs->sc_link, SDEV_DB3,
- ("scsi_interpret_sense (bp) returned %d\n", code));
- } else {
- SC_DEBUG(xs->sc_link, SDEV_DB3,
- ("scsi_interpret_sense (no bp) returned %d\n", code));
- }
- }
- else {
- if (bp) {
-
- bp->b_error = 0;
-
- /* XXX: We really shouldn't need this SCSI_RESID_VALID flag.
- * If we initialize it to 0 and only touch it if we have
- * a value then we can leave out the test.
- */
-
- if (xs->flags & SCSI_RESID_VALID) {
- bp->b_resid = xs->resid;
- bp->b_flags |= B_ERROR;
- } else {
- bp->b_resid = 0;
- }
- }
- }
-
- return code;
-}
-
-/*
- * submit a scsi command, given the command.. used for retries
- * and callable from timeout()
- */
-#ifdef NOTYET
-errval scsi_submit(xs)
- struct scsi_xfer *xs;
-{
- struct scsi_link *sc_link = xs->sc_link;
- int retval;
-
- retval = (*(sc_link->adapter->scsi_cmd)) (xs);
-
- return retval;
-}
-
-/*
- * Retry a scsi command, given the command, and a delay.
- */
-errval scsi_retry(xs,delay)
- struct scsi_xfer *xs;
- int delay;
-{
- if(delay)
- {
- timeout(((void())*)scsi_submit,xs,hz*delay);
- return(0);
- }
- else
- {
- return(scsi_submit(xs));
- }
-}
-#endif
-
-/*
- * handle checking for errors..
- * called at interrupt time from scsi_done() and
- * at user time from scsi_scsi_cmd(), depending on whether
- * there was a bp (basically, if there is a bp, there may be no
- * associated process at the time. (it could be an async operation))
- * lower level routines shouldn't know about xs->bp.. we are the lowest.
- */
-static errval
-sc_err1(xs)
- struct scsi_xfer *xs;
-{
- SC_DEBUG(xs->sc_link, SDEV_DB3, ("sc_err1,err = 0x%lx \n",
- (u_long)xs->error));
-
- switch ((int)xs->error) {
- case XS_SENSE:
- return sc_done(xs, scsi_interpret_sense(xs));
-
- case XS_NOERROR:
- return sc_done(xs, ESUCCESS);
-
- case XS_BUSY:
- /* should somehow arange for a 1 sec delay here (how?)[jre]
- * tsleep(&localvar, priority, "foo", hz);
- * that's how! [unknown]
- * no, we could be at interrupt context.. use
- * timeout(scsi_resubmit,xs,hz); [jre] (not implimenteed yet)
- */
- DELAY(1000);
- case XS_TIMEOUT:
- return sc_done(xs, SCSIRET_DO_RETRY);
-
- /* fall through */
- case XS_SELTIMEOUT:
- case XS_DRIVER_STUFFUP:
- return sc_done(xs, EIO);
-
- default:
- sc_print_addr(xs->sc_link);
- printf("unknown error category from scsi driver\n");
- return sc_done(xs, EIO);
- }
-}
-
-#ifdef notyet
-static int
-scsi_sense_qualifiers(xs, asc, ascq)
- struct scsi_xfer *xs;
- int *asc;
- int *ascq;
-{
- struct scsi_sense_data_new *sense;
- struct scsi_sense_extended *ext;
-
- sense = (struct scsi_sense_data_new *)&(xs->sense);
-
- ext = &(sense->ext.extended);
-
- if (ext->extra_len < 5)
- return 0;
-
- *asc = (ext->extra_len >= 5) ? ext->add_sense_code : 0;
- *ascq = (ext->extra_len >= 6) ? ext->add_sense_code_qual : 0;
-
- return 1;
-}
-
-#endif
-
-/*
- * scsi_sense_print will decode the sense data into human
- * readable form. Sense handlers can use this to generate
- * a report. This NOW DOES send the closing "\n".
- */
-void scsi_sense_print(xs)
- struct scsi_xfer *xs;
-{
- struct scsi_sense_data_new *sense;
- struct scsi_sense_extended *ext;
- u_int32_t key;
- u_int32_t info;
- int asc, ascq;
-
- /* This sense key text now matches what is in the SCSI spec
- * (Yes, even the capitals)
- * so that it is easier to look through the spec to find the
- * appropriate place.
- */
- static char *sense_key_text[] =
- {
- "NO SENSE", "RECOVERED ERROR",
- "NOT READY", "MEDIUM ERROR",
- "HARDWARE FAILURE", "ILLEGAL REQUEST",
- "UNIT ATTENTION", "DATA PROTECT",
- "BLANK CHECK", "Vendor Specific",
- "COPY ABORTED", "ABORTED COMMAND",
- "EQUAL", "VOLUME OVERFLOW",
- "MISCOMPARE", "RESERVED"
- };
-
- sc_print_start(xs->sc_link);
-
- sense = (struct scsi_sense_data_new *)&(xs->sense);
- ext = &(sense->ext.extended);
-
- key = ext->flags & SSD_KEY;
-
- switch (sense->error_code & SSD_ERRCODE) {
- case 0x71: /* deferred error */
- printf("Deferred Error: ");
-
- /* DROP THROUGH */
-
- case 0x70:
-
- printf("%s", sense_key_text[key]);
- info = (ext->info[0] << 24) | (ext->info[1] << 16)
- | (ext->info[2] << 8) | ext->info[3];
-
- if (sense->error_code & SSD_ERRCODE_VALID) {
-
- switch ((int)key) {
- case 0x2: /* NOT READY */
- case 0x5: /* ILLEGAL REQUEST */
- case 0x6: /* UNIT ATTENTION */
- case 0x7: /* DATA PROTECT */
- break;
- case 0x8: /* BLANK CHECK */
- printf(" req sz: %lu (decimal)", (u_long)info);
- break;
- default:
- if (info) {
- if (sense->ext.extended.flags & SSD_ILI) {
- printf(
- " ILI (length mismatch): %ld",
- (u_long)info);
- }
- else {
- printf(" info:%#lx",
- (u_long)info);
- }
- }
- }
- }
- else if (info)
- printf(" info?:%#lx", (u_long)info);
-
- if (ext->extra_len >= 4) {
- if (bcmp(ext->cmd_spec_info, "\0\0\0\0", 4)) {
- printf(" csi:%x,%x,%x,%x",
- ext->cmd_spec_info[0],
- ext->cmd_spec_info[1],
- ext->cmd_spec_info[2],
- ext->cmd_spec_info[3]);
- }
- }
-
- asc = (ext->extra_len >= 5) ? ext->add_sense_code : 0;
- ascq = (ext->extra_len >= 6) ? ext->add_sense_code_qual : 0;
-
- if (asc || ascq)
- {
- char *desc = scsi_sense_desc(asc, ascq);
- printf(" asc:%x,%x", asc, ascq);
-
- if (strlen(desc) > 40)
- sc_print_addr(xs->sc_link);;
-
- printf(" %s", desc);
- }
-
- if (ext->extra_len >= 7 && ext->fru) {
- printf(" field replaceable unit: %x", ext->fru);
- }
-
- if (ext->extra_len >= 10 &&
- (ext->sense_key_spec_1 & SSD_SCS_VALID)) {
- printf(" sks:%x,%x", ext->sense_key_spec_1,
- (ext->sense_key_spec_2 |
- ext->sense_key_spec_3));
- }
- break;
-
- /*
- * Not code 70, just report it
- */
- default:
- printf("error code %d",
- sense->error_code & SSD_ERRCODE);
- if (sense->error_code & SSD_ERRCODE_VALID) {
- printf(" at block no. %ld (decimal)",
- (((unsigned long)sense->ext.unextended.blockhi) << 16) +
- (((unsigned long)sense->ext.unextended.blockmed) << 8) +
- ((unsigned long)sense->ext.unextended.blocklow));
- }
- }
-
- printf("\n");
- sc_print_finish();
-}
-
-/*
- * Look at the returned sense and act on the error, determining
- * the unix error number to pass back. (0 = report no error)
- *
- * THIS IS THE DEFAULT SENSE HANDLER
- */
-static errval
-scsi_interpret_sense(xs)
- struct scsi_xfer *xs;
-{
- struct scsi_sense_data_new *sense;
- struct scsi_sense_extended *ext;
- struct scsi_link *sc_link = xs->sc_link;
- u_int32_t key;
- u_int32_t silent;
- errval errcode;
- int error_code, asc, ascq;
-
- /*
- * If the flags say errs are ok, then always return ok.
- * XXX: What if it is a deferred error?
- */
- if (xs->flags & SCSI_ERR_OK)
- return (ESUCCESS);
-
- sense = (struct scsi_sense_data_new *)&(xs->sense);
- ext = &(sense->ext.extended);
-#ifdef SCSIDEBUG
- if (sc_link->flags & SDEV_DB1) {
-
- u_int32_t count = 0;
- printf("code%x valid%x ",
- sense->error_code & SSD_ERRCODE,
- sense->error_code & SSD_ERRCODE_VALID ? 1 : 0);
- printf("seg%x key%x ili%x eom%x fmark%x\n",
- ext->segment,
- ext->flags & SSD_KEY,
- ext->flags & SSD_ILI ? 1 : 0,
- ext->flags & SSD_EOM ? 1 : 0,
- ext->flags & SSD_FILEMARK ? 1 : 0);
- printf("info: %x %x %x %x followed by %d extra bytes\n",
- ext->info[0],
- ext->info[1],
- ext->info[2],
- ext->info[3],
- ext->extra_len);
- printf("extra: ");
- while (count < ext->extra_len) {
- printf("%x ", ext->extra_bytes[count++]);
- }
- printf("\n");
- }
- #endif /*SCSIDEBUG */
- /*
- * If the device has its own sense handler, call it first.
- * If it returns a legit errno value, return that, otherwise
- * it should return either DO_RETRY or CONTINUE to either
- * request a retry or continue with default sense handling.
- */
- if (sc_link->device->err_handler) {
- SC_DEBUG(sc_link, SDEV_DB2,
- ("calling private err_handler()\n"));
- errcode = (*sc_link->device->err_handler) (xs);
-
- SC_DEBUG(sc_link, SDEV_DB2,
- ("private err_handler() returned %d\n",errcode));
- if (errcode >= 0) {
- SC_DEBUG(sc_link, SDEV_DB2,
- ("SCSI_EOF = %d\n",(xs->flags & SCSI_EOF)?1:0));
- SC_DEBUG(sc_link, SDEV_DB2,
- ("SCSI_RESID_VALID = %d\n",
- (xs->flags & SCSI_RESID_VALID)?1:0));
-
- if(xs->flags & SCSI_EOF) {
- xs->resid = xs->datalen;
- xs->flags |= SCSI_RESID_VALID;
- }
- return errcode; /* valid errno value */
- }
-
- switch(errcode) {
- case SCSIRET_DO_RETRY: /* Requested a retry */
- return errcode;
-
- case SCSIRET_CONTINUE: /* Continue with default sense processing */
- break;
-
- default:
- sc_print_addr(xs->sc_link);
- printf("unknown return code %d from sense handler.\n",
- errcode);
-
- return errcode;
- }
- }
-
- /* otherwise use the default */
- silent = xs->flags & SCSI_SILENT;
- key = ext->flags & SSD_KEY;
- error_code = sense->error_code & SSD_ERRCODE;
- asc = (ext->extra_len >= 5) ? ext->add_sense_code : 0;
- ascq = (ext->extra_len >= 6) ? ext->add_sense_code_qual : 0;
-
- /*
- * Retry while the device is returning a ``Logical unit
- * is in the process of becoming ready.'' (until it either
- * eventually yields an error, or finally succeeds).
- */
- if (error_code == 0x70 /* current error */ &&
- (int)key == 0x2 /* not ready */ &&
- asc == 4 && ascq == 1 /* logical unit i i t p o b r */)
- return (SCSIRET_DO_RETRY);
-
- if (!silent) {
- scsi_sense_print(xs);
- }
-
- switch (error_code) {
- case 0x71: /* deferred error */
- /* Print even if silent (not silent was already done)
- */
- if (silent) {
- scsi_sense_print(xs);
- }
-
- /* XXX:
- * This error doesn't relate to the command associated
- * with this request sense. A deferred error is an error
- * for a command that has already returned GOOD status (see 7.2.14.2).
- *
- * By my reading of that section, it looks like the current command
- * has been cancelled, we should now clean things up (hopefully
- * recovering any lost data) and then
- * retry the current command. There are two easy choices, both
- * wrong:
- * 1. Drop through (like we had been doing), thus treating this as
- * if the error were for the current command and return and stop
- * the current command.
- * 2. Issue a retry (like I made it do) thus hopefully recovering
- * the current transfer, and ignoring the fact that we've dropped
- * a command.
- *
- * These should probably be handled in a device specific
- * sense handler or punted back up to a user mode daemon
- */
- return SCSIRET_DO_RETRY;
-
- /*
- * If it's code 70, use the extended stuff and interpret the key
- */
- case 0x70:
-
- switch ((int)key) {
- case 0x0: /* NO SENSE */
- case 0x1: /* RECOVERED ERROR */
- case 0xc: /* EQUAL */
- if(xs->flags & SCSI_EOF) {
- xs->resid = xs->datalen;
- xs->flags |= SCSI_RESID_VALID;
- }
- return (ESUCCESS);
- case 0x2: /* NOT READY */
- sc_link->flags &= ~SDEV_MEDIA_LOADED;
- return (EBUSY);
- case 0x5: /* ILLEGAL REQUEST */
- return (EINVAL);
- case 0x6: /* UNIT ATTENTION */
- sc_link->flags &= ~SDEV_MEDIA_LOADED;
- if (sc_link->flags & SDEV_OPEN) {
- return (EIO);
- } else {
- return 0;
- }
- case 0x7: /* DATA PROTECT */
- return (EACCES);
- case 0xd: /* VOLUME OVERFLOW */
- return (ENOSPC);
- case 0x8: /* BLANK CHECK */
- xs->flags |= SCSI_EOF; /* force EOF on tape read */
- return (ESUCCESS);
- default:
- return (EIO);
- }
- /*
- * Not code 70, return EIO
- */
- default:
- return (EIO);
- }
-}
-
-/*
- * Utility routines often used in SCSI stuff
- */
-
-/*
- * convert a physical address to 3 bytes,
- * MSB at the lowest address,
- * LSB at the highest.
- */
-void
-scsi_uto3b(val, bytes)
- u_int32_t val;
- u_char *bytes;
-{
- *bytes++ = (val & 0xff0000) >> 16;
- *bytes++ = (val & 0xff00) >> 8;
- *bytes = val & 0xff;
-}
-
-u_int32_t
-scsi_3btou(bytes)
- u_char *bytes;
-{
- u_int32_t rc;
- rc = (*bytes++ << 16);
- rc += (*bytes++ << 8);
- rc += *bytes;
- return rc;
-}
-
-int32_t
-scsi_3btoi(bytes)
- u_char *bytes;
-{
- u_int32_t rc = scsi_3btou(bytes);
-
- if (rc & 0x00800000)
- rc |= 0xff000000;
-
- return (int32_t) rc;
-}
-
-void
-scsi_uto2b(val, bytes)
- u_int32_t val;
- u_char *bytes;
-{
- *bytes++ = (val & 0xff00) >> 8;
- *bytes = val & 0xff;
-}
-
-u_int32_t
-scsi_2btou(bytes)
- u_char *bytes;
-{
- u_int32_t rc;
- rc = (*bytes++ << 8);
- rc += *bytes;
- return rc;
-}
-
-void
-scsi_uto4b(val, bytes)
- u_int32_t val;
- u_char *bytes;
-{
- *bytes++ = (val & 0xff000000) >> 24;
- *bytes++ = (val & 0xff0000) >> 16;
- *bytes++ = (val & 0xff00) >> 8;
- *bytes = val & 0xff;
-}
-
-u_int32_t
-scsi_4btou(bytes)
- u_char *bytes;
-{
- u_int32_t rc;
- rc = (*bytes++ << 24);
- rc += (*bytes++ << 16);
- rc += (*bytes++ << 8);
- rc += *bytes;
- return rc;
-}
-
-static int sc_printing;
-
-void
-sc_print_init()
-{
- sc_printing++;
-}
-
-void
-sc_print_start(sc_link)
- struct scsi_link *sc_link;
-{
- sc_print_addr(sc_link);
- sc_printing++;
-}
-void
-sc_print_finish()
-{
- sc_printing--;
-}
-
-static void
-id_put(int id, char *after)
-{
- switch(id)
- {
- case SCCONF_UNSPEC:
- break;
-
- case SCCONF_ANY:
- printf("?");
- break;
-
- default:
- printf("%d", id);
- break;
- }
-
- printf("%s", after);
-}
-
-/*
- * sc_print_addr: Print out the scsi_link structure's address info.
- * This should handle any circumstance, even the transitory ones
- * during system configuration.
- */
-
-void
-sc_print_addr(sc_link)
- struct scsi_link *sc_link;
-{
- if (sc_printing)
- printf("\n");
-
- if (sc_link->device == 0) {
- printf("nodevice at ");
- }
- else if (strcmp(sc_link->device->name, "probe") != 0) {
- printf("%s", sc_link->device->name);
- id_put(sc_link->dev_unit, ": ");
- return;
- }
-
- printf("scbus");
- id_put(sc_link->scsibus, " ");
-
- printf("target ");
- id_put(sc_link->target, " ");
- printf("lun ");
- id_put(sc_link->lun, ": ");
-}
-
-#ifdef SCSIDEBUG
-/*
- * Given a scsi_xfer, dump the request, in all its glory
- */
-static void
-show_scsi_xs(xs)
- struct scsi_xfer *xs;
-{
- printf("xs(%p): ", (void *)xs);
- printf("flg(0x%lx)", (u_long)xs->flags);
- printf("sc_link(%p)", (void *)xs->sc_link);
- printf("retr(0x%x)", xs->retries);
- printf("timo(0x%lx)", (long)xs->timeout);
- printf("cmd(%p)", (void *)xs->cmd);
- printf("len(0x%lx)", (long)xs->cmdlen);
- printf("data(%p)", (void *)xs->data);
- printf("len(0x%lx)", (long)xs->datalen);
- printf("res(0x%lx)", (long)xs->resid);
- printf("err(0x%lx)", (long)xs->error);
- printf("bp(%p)", (void *)xs->bp);
- show_scsi_cmd(xs);
-}
-
-void
-show_scsi_cmd(struct scsi_xfer *xs)
-{
- u_char *b = (u_char *) xs->cmd;
- int i = 0;
-
- sc_print_addr(xs->sc_link);
- printf("command: ");
-
- if (!(xs->flags & SCSI_RESET)) {
- while (i < xs->cmdlen) {
- if (i)
- printf(",");
- printf("%x", b[i++]);
- }
- printf("-[%ld bytes]\n", (long)xs->datalen);
- if (xs->datalen)
- show_mem(xs->data, min(64, xs->datalen));
- } else {
- printf("-RESET-\n");
- }
-}
-
-static void
-show_mem(address, num)
- unsigned char *address;
- u_int32_t num;
-{
- u_int32_t y;
- printf("------------------------------");
- for (y = 0; y < num; y += 1) {
- if (!(y % 16))
- printf("\n%03ld: ", (long)y);
- printf("%02x ", *address++);
- }
- printf("\n------------------------------\n");
-}
-#endif /*SCSIDEBUG */
diff --git a/sys/scsi/scsi_cd.h b/sys/scsi/scsi_cd.h
deleted file mode 100644
index 26e366b..0000000
--- a/sys/scsi/scsi_cd.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- *
- * $Id: scsi_cd.h,v 1.10 1997/02/22 09:44:28 peter Exp $
- */
-#ifndef _SCSI_SCSI_CD_H
-#define _SCSI_SCSI_CD_H 1
-
-/*
- * Define two bits always in the same place in byte 2 (flag byte)
- */
-#define CD_RELADDR 0x01
-#define CD_MSF 0x02
-
-/*
- * SCSI command format
- */
-
-struct scsi_pause
-{
- u_char op_code;
- u_char byte2;
- u_char unused[6];
- u_char resume;
- u_char control;
-};
-#define PA_PAUSE 1
-#define PA_RESUME 0
-
-struct scsi_play_msf
-{
- u_char op_code;
- u_char byte2;
- u_char unused;
- u_char start_m;
- u_char start_s;
- u_char start_f;
- u_char end_m;
- u_char end_s;
- u_char end_f;
- u_char control;
-};
-
-struct scsi_play_track
-{
- u_char op_code;
- u_char byte2;
- u_char unused[2];
- u_char start_track;
- u_char start_index;
- u_char unused1;
- u_char end_track;
- u_char end_index;
- u_char control;
-};
-
-struct scsi_play
-{
- u_char op_code;
- u_char byte2;
- u_char blk_addr[4];
- u_char unused;
- u_char xfer_len[2];
- u_char control;
-};
-
-struct scsi_play_big
-{
- u_char op_code;
- u_char byte2; /* same as above */
- u_char blk_addr[4];
- u_char xfer_len[4];
- u_char unused;
- u_char control;
-};
-
-struct scsi_play_rel_big
-{
- u_char op_code;
- u_char byte2; /* same as above */
- u_char blk_addr[4];
- u_char xfer_len[4];
- u_char track;
- u_char control;
-};
-
-struct scsi_read_header
-{
- u_char op_code;
- u_char byte2;
- u_char blk_addr[4];
- u_char unused;
- u_char data_len[2];
- u_char control;
-};
-
-struct scsi_read_subchannel
-{
- u_char op_code;
- u_char byte2;
- u_char byte3;
-#define SRS_SUBQ 0x40
- u_char subchan_format;
- u_char unused[2];
- u_char track;
- u_char data_len[2];
- u_char control;
-};
-
-struct scsi_read_toc
-{
- u_char op_code;
- u_char byte2;
- u_char unused[4];
- u_char from_track;
- u_char data_len[2];
- u_char control;
-};
-
-struct scsi_read_cd_capacity
-{
- u_char op_code;
- u_char byte2;
- u_char addr_3; /* Most Significant */
- u_char addr_2;
- u_char addr_1;
- u_char addr_0; /* Least Significant */
- u_char unused[3];
- u_char control;
-};
-
-/*
- * Opcodes
- */
-
-#define READ_CD_CAPACITY 0x25 /* slightly different from disk */
-#define READ_SUBCHANNEL 0x42 /* cdrom read Subchannel */
-#define READ_TOC 0x43 /* cdrom read TOC */
-#define READ_HEADER 0x44 /* cdrom read header */
-#define PLAY 0x45 /* cdrom play 'play audio' mode */
-#define PLAY_MSF 0x47 /* cdrom play Min,Sec,Frames mode */
-#define PLAY_TRACK 0x48 /* cdrom play track/index mode */
-#define PLAY_TRACK_REL 0x49 /* cdrom play track/index mode */
-#define PAUSE 0x4b /* cdrom pause in 'play audio' mode */
-#define PLAY_BIG 0xa5 /* cdrom pause in 'play audio' mode */
-#define PLAY_TRACK_REL_BIG 0xa9 /* cdrom play track/index mode */
-
-
-
-struct scsi_read_cd_cap_data
-{
- u_char addr_3; /* Most significant */
- u_char addr_2;
- u_char addr_1;
- u_char addr_0; /* Least significant */
- u_char length_3; /* Most significant */
- u_char length_2;
- u_char length_1;
- u_char length_0; /* Least significant */
-};
-
-union cd_pages
-{
- struct audio_page
- {
- u_char page_code;
-#define CD_PAGE_CODE 0x3F
-#define AUDIO_PAGE 0x0e
-#define CD_PAGE_PS 0x80
- u_char param_len;
- u_char flags;
-#define CD_PA_SOTC 0x02
-#define CD_PA_IMMED 0x04
- u_char unused[2];
- u_char format_lba;
-#define CD_PA_FORMAT_LBA 0x0F
-#define CD_PA_APR_VALID 0x80
- u_char lb_per_sec[2];
- struct port_control
- {
- u_char channels;
-#define CHANNEL 0x0F
-#define CHANNEL_0 1
-#define CHANNEL_1 2
-#define CHANNEL_2 4
-#define CHANNEL_3 8
-#define LEFT_CHANNEL CHANNEL_0
-#define RIGHT_CHANNEL CHANNEL_1
- u_char volume;
- } port[4];
-#define LEFT_PORT 0
-#define RIGHT_PORT 1
- }audio;
-};
-
-struct cd_mode_data
-{
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- union cd_pages page;
-};
-#endif /*_SCSI_SCSI_CD_H*/
-
diff --git a/sys/scsi/scsi_changer.h b/sys/scsi/scsi_changer.h
deleted file mode 100644
index be24baf..0000000
--- a/sys/scsi/scsi_changer.h
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright (c) 1996 Jason R. Thorpe <thorpej@and.com>
- * All rights reserved.
- *
- * Partially based on an autochanger driver written by Stefan Grefen
- * and on an autochanger driver written by the Systems Programming Group
- * at the University of Utah Computer Science Department.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgements:
- * This product includes software developed by Jason R. Thorpe
- * for And Communications, http://www.and.com/
- * 4. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: scsi_changer.h,v 1.9 1997/02/22 09:44:29 peter Exp $
- */
-
-/*
- * SCSI changer interface description
- */
-
-/*
- * Partially derived from software written by Stefan Grefen
- * (grefen@goofy.zdv.uni-mainz.de soon grefen@convex.com)
- * based on the SCSI System by written Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- */
-
-#ifndef _SCSI_SCSI_CHANGER_H
-#define _SCSI_SCSI_CHANGER_H 1
-
-/*
- * SCSI command format
- */
-
-/*
- * Exchange the medium in the source element with the medium
- * located at the destination element.
- */
-struct scsi_exchange_medium {
- u_int8_t opcode;
-#define EXCHANGE_MEDIUM 0xa6
- u_int8_t byte2;
- u_int8_t tea[2]; /* transport element address */
- u_int8_t src[2]; /* source address */
- u_int8_t fdst[2]; /* first destination address */
- u_int8_t sdst[2]; /* second destination address */
- u_int8_t flags;
-#define EXCHANGE_MEDIUM_INV1 0x01
-#define EXCHANGE_MEDIUM_INV2 0x02
- u_int8_t control;
-};
-
-/*
- * Cause the medium changer to check all elements for medium and any
- * other status relevant to the element.
- */
-struct scsi_initialize_elememt_status {
- u_int8_t opcode;
-#define INITIALIZE_ELEMENT_STATUS 0x07
- u_int8_t byte2;
- u_int8_t reserved[3];
- u_int8_t control;
-};
-
-/*
- * Request the changer to move a unit of media from the source element
- * to the destination element.
- */
-struct scsi_move_medium {
- u_int8_t opcode;
-#define MOVE_MEDIUM 0xa5
- u_int8_t byte2;
- u_int8_t tea[2]; /* transport element address */
- u_int8_t src[2]; /* source element address */
- u_int8_t dst[2]; /* destination element address */
- u_int8_t reserved[2];
- u_int8_t flags;
-#define MOVE_MEDIUM_INVERT 0x01
- u_int8_t control;
-};
-
-/*
- * Position the specified transport element (picker) in front of
- * the destination element specified.
- */
-struct scsi_position_to_element {
- u_int8_t opcode;
-#define POSITION_TO_ELEMENT 0x2b
- u_int8_t byte2;
- u_int8_t tea[2]; /* transport element address */
- u_int8_t dst[2]; /* destination element address */
- u_int8_t reserved[2];
- u_int8_t flags;
-#define POSITION_TO_ELEMENT_INVERT 0x01
- u_int8_t control;
-};
-
-/*
- * Request that the changer report the status of its internal elements.
- */
-struct scsi_read_element_status {
- u_int8_t opcode;
-#define READ_ELEMENT_STATUS 0xb8
- u_int8_t byte2;
-#define READ_ELEMENT_STATUS_VOLTAG 0x10 /* report volume tag info */
- /* ...next 4 bits are an element type code... */
- u_int8_t sea[2]; /* starting element address */
- u_int8_t count[2]; /* number of elements */
- u_int8_t reserved0;
- u_int8_t len[3]; /* length of data buffer */
- u_int8_t reserved1;
- u_int8_t control;
-};
-
-struct scsi_request_volume_element_address {
- u_int8_t opcode;
-#define REQUEST_VOLUME_ELEMENT_ADDRESS 0xb5
- u_int8_t byte2;
-#define REQUEST_VOLUME_ELEMENT_ADDRESS_VOLTAG 0x10
- /* ...next 4 bits are an element type code... */
- u_int8_t eaddr[2]; /* element address */
- u_int8_t count[2]; /* number of elements */
- u_int8_t reserved0;
- u_int8_t len[3]; /* length of data buffer */
- u_int8_t reserved1;
- u_int8_t control;
-};
-
-/* XXX scsi_release */
-
-/*
- * Data returned by READ ELEMENT STATUS consists of an 8-byte header
- * followed by one or more read_element_status_pages.
- */
-struct read_element_status_header {
- u_int8_t fear[2]; /* first element address reported */
- u_int8_t count[2]; /* number of elements available */
- u_int8_t reserved;
- u_int8_t nbytes[3]; /* byte count of all pages */
-};
-
-struct read_element_status_page_header {
- u_int8_t type; /* element type code; see type codes below */
- u_int8_t flags;
-#define READ_ELEMENT_STATUS_AVOLTAG 0x40
-#define READ_ELEMENT_STATUS_PVOLTAG 0x80
- u_int8_t edl[2]; /* element descriptor length */
- u_int8_t reserved;
- u_int8_t nbytes[3]; /* byte count of all descriptors */
-};
-
-struct read_element_status_descriptor {
- u_int8_t eaddr[2]; /* element address */
- u_int8_t flags1;
-
-#define READ_ELEMENT_STATUS_FULL 0x01
-#define READ_ELEMENT_STATUS_IMPEXP 0x02
-#define READ_ELEMENT_STATUS_EXCEPT 0x04
-#define READ_ELEMENT_STATUS_ACCESS 0x08
-#define READ_ELEMENT_STATUS_EXENAB 0x10
-#define READ_ELEMENT_STATUS_INENAB 0x20
-
-#define READ_ELEMENT_STATUS_MT_MASK1 0x05
-#define READ_ELEMENT_STATUS_ST_MASK1 0x0c
-#define READ_ELEMENT_STATUS_IE_MASK1 0x3f
-#define READ_ELEMENT_STATUS_DT_MASK1 0x0c
-
- u_int8_t reserved0;
- u_int8_t sense_code;
- u_int8_t sense_qual;
-
- /*
- * dt_scsi_flags and dt_scsi_addr are valid only on data transport
- * elements. These bytes are undefined for all other element types.
- */
- u_int8_t dt_scsi_flags;
-
-#define READ_ELEMENT_STATUS_DT_LUNMASK 0x07
-#define READ_ELEMENT_STATUS_DT_LUVALID 0x10
-#define READ_ELEMENT_STATUS_DT_IDVALID 0x20
-#define READ_ELEMENT_STATUS_DT_NOTBUS 0x80
-
- u_int8_t dt_scsi_addr;
-
- u_int8_t reserved1;
-
- u_int8_t flags2;
-#define READ_ELEMENT_STATUS_INVERT 0x40
-#define READ_ELEMENT_STATUS_SVALID 0x80
- u_int8_t ssea[2]; /* source storage element address */
-
- /*
- * bytes 12-47: Primary volume tag information.
- * (field omitted if PVOLTAG = 0)
- *
- * bytes 48-83: Alternate volume tag information.
- * (field omitted if AVOLTAG = 0)
- *
- * bytes 84-87: Reserved (moved up if either of the above fields
- * are omitted)
- *
- * bytes 88-end: Vendor-specific: (moved up if either of the
- * above fields are missing)
- */
-};
-
-/* XXX add data returned by REQUEST VOLUME ELEMENT ADDRESS */
-
-/* Element type codes */
-#define ELEMENT_TYPE_MASK 0x0f /* Note: these aren't bits */
-#define ELEMENT_TYPE_ALL 0x00
-#define ELEMENT_TYPE_MT 0x01
-#define ELEMENT_TYPE_ST 0x02
-#define ELEMENT_TYPE_IE 0x03
-#define ELEMENT_TYPE_DT 0x04
-
-/*
- * XXX The following definitions should be common to all SCSI device types.
- */
-#define PGCODE_MASK 0x3f /* valid page number bits in pg_code */
-#define PGCODE_PS 0x80 /* indicates page is savable */
-
-/*
- * Device capabilities page.
- *
- * This page defines characteristics of the elemenet types in the
- * medium changer device.
- *
- * Note in the definitions below, the following abbreviations are
- * used:
- * MT Medium transport element (picker)
- * ST Storage transport element (slot)
- * IE Import/export element (portal)
- * DT Data tranfer element (tape/disk drive)
- */
-struct page_device_capabilities {
- u_int8_t pg_code; /* page code (0x1f) */
- u_int8_t pg_length; /* page length (0x12) */
-
- /*
- * The STOR_xx bits indicate that an element of a given
- * type may provide independent storage for a unit of
- * media. The top four bits of this value are reserved.
- */
- u_int8_t stor;
-#define STOR_MT 0x01
-#define STOR_ST 0x02
-#define STOR_IE 0x04
-#define STOR_DT 0x08
-
- u_int8_t reserved0;
-
- /*
- * The MOVE_TO_yy bits indicate the changer supports
- * moving a unit of medium from an element of a given type to an
- * element of type yy. This is used to determine if a given
- * MOVE MEDIUM command is legal. The top four bits of each
- * of these values are reserved.
- */
- u_int8_t move_from_mt;
- u_int8_t move_from_st;
- u_int8_t move_from_ie;
- u_int8_t move_from_dt;
-#define MOVE_TO_MT 0x01
-#define MOVE_TO_ST 0x02
-#define MOVE_TO_IE 0x04
-#define MOVE_TO_DT 0x08
-
- u_int8_t reserved1[2];
-
- /*
- * Similar to above, but for EXCHANGE MEDIUM.
- */
- u_int8_t exchange_with_mt;
- u_int8_t exchange_with_st;
- u_int8_t exchange_with_ie;
- u_int8_t exchange_with_dt;
-#define EXCHANGE_WITH_MT 0x01
-#define EXCHANGE_WITH_ST 0x02
-#define EXCHANGE_WITH_IE 0x04
-#define EXCHANGE_WITH_DT 0x08
-};
-
-/*
- * Medium changer elemement address assignment page.
- *
- * Some of these fields can be a little confusing, so an explanation
- * is in order.
- *
- * Each component within a a medium changer apparatus is called an
- * "element".
- *
- * The "medium transport element address" is the address of the first
- * picker (robotic arm). "Number of medium transport elements" tells
- * us how many pickers exist in the changer.
- *
- * The "first storage element address" is the address of the first
- * slot in the tape or disk magazine. "Number of storage elements" tells
- * us how many slots exist in the changer.
- *
- * The "first import/export element address" is the address of the first
- * medium portal accessible both by the medium changer and an outside
- * human operator. This is where the changer might deposit tapes destined
- * for some vault. The "number of import/export elements" tells us
- * not many of these portals exist in the changer. NOTE: this number may
- * be 0.
- *
- * The "first data transfer element address" is the address of the first
- * tape or disk drive in the changer. "Number of data transfer elements"
- * tells us how many drives exist in the changer.
- */
-struct page_element_address_assignment {
- u_int8_t pg_code; /* page code (0x1d) */
- u_int8_t pg_length; /* page length (0x12) */
-
- /* Medium transport element address */
- u_int8_t mtea[2];
-
- /* Number of medium transport elements */
- u_int8_t nmte[2];
-
- /* First storage element address */
- u_int8_t fsea[2];
-
- /* Number of storage elements */
- u_int8_t nse[2];
-
- /* First import/export element address */
- u_int8_t fieea[2];
-
- /* Number of import/export elements */
- u_int8_t niee[2];
-
- /* First data transfer element address */
- u_int8_t fdtea[2];
-
- /* Number of data trafer elements */
- u_int8_t ndte[2];
-
- u_int8_t reserved[2];
-};
-
-/*
- * Transport geometry parameters page.
- *
- * Defines whether each medium transport element is a member of a set of
- * elements that share a common robotics subsystem and whether the element
- * is capable of media rotation. One transport geometry descriptor is
- * transferred for each medium transport element, beginning with the first
- * medium transport element (other than the default transport element address
- * of 0).
- */
-struct page_transport_geometry_parameters {
- u_int8_t pg_code; /* page code (0x1e) */
- u_int8_t pg_length; /* page length; variable */
-
- /* Transport geometry descriptor(s) are here. */
-
- u_int8_t misc;
-#define CAN_ROTATE 0x01
-
- /* Member number in transport element set. */
- u_int8_t member;
-};
-
-#endif /* _SCSI_SCSI_CHANGER_H */
diff --git a/sys/scsi/scsi_debug.h b/sys/scsi/scsi_debug.h
deleted file mode 100644
index a362f5d..0000000
--- a/sys/scsi/scsi_debug.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Use
- * options SCSIDEBUG
- *
- * in the kernel config file to get these macros into effect.
- */
-
-/*
- * Written by Julian Elischer (julian@tfs.com)
- *
- * $Id$
- */
-#ifndef _SCSI_SCSI_DEBUG_H
-#define _SCSI_SCSI_DEBUG_H 1
-
-/*
- * These are the new debug bits. (Sat Oct 2 12:46:46 WST 1993)
- * the following DEBUG bits are defined to exist in the flags word of
- * the scsi_link structure.
- */
-#define SDEV_DB1 0x10 /* scsi commands, errors, data */
-#define SDEV_DB2 0x20 /* routine flow tracking */
-#define SDEV_DB3 0x40 /* internal to routine flows */
-#define SDEV_DB4 0x80 /* level 4 debugging for this dev */
-
-/* target and LUN we want to debug */
-#define DEBUGTARG 9 /*9 = dissable*/
-#define DEBUGLUN 0
-#define DEBUGLEVEL (SDEV_DB1|SDEV_DB2)
-
-/*
- * This is the usual debug macro for use with the above bits
- */
-#ifdef SCSIDEBUG
-#define SC_DEBUG(sc_link,Level,Printstuff) \
- if((sc_link)->flags & (Level)) \
- { \
- printf("%s%d(%s%d:%d:%d): ", \
- sc_link->device->name, \
- sc_link->dev_unit, \
- sc_link->adapter->name, \
- sc_link->adapter_unit, \
- sc_link->target, \
- sc_link->lun); \
- printf Printstuff; \
- }
-#define SC_DEBUGN(sc_link,Level,Printstuff) \
- if((sc_link)->flags & (Level)) \
- { \
- printf Printstuff; \
- }
-#else
-#define SC_DEBUG(A,B,C) /* not included */
-#define SC_DEBUGN(A,B,C) /* not included */
-#endif
-
-#endif /*_SCSI_SCSI_DEBUG_H*/
-/* END OF FILE */
-
diff --git a/sys/scsi/scsi_disk.h b/sys/scsi/scsi_disk.h
deleted file mode 100644
index a33e4e7..0000000
--- a/sys/scsi/scsi_disk.h
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * SCSI interface description
- */
-
-/*
- * Some lines of this file come from a file of the name "scsi.h"
- * distributed by OSF as part of mach2.5,
- * so the following disclaimer has been kept.
- *
- * Copyright 1990 by Open Software Foundation,
- * Grenoble, FRANCE
- *
- * All Rights Reserved
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appears in all copies and
- * that both the copyright notice and this permission notice appear in
- * supporting documentation, and that the name of OSF or Open Software
- * Foundation not be used in advertising or publicity pertaining to
- * distribution of the software without specific, written prior
- * permission.
- *
- * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
- * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
- * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * Largely written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- *
- * $Id$
- */
-
-/*
- * SCSI command format
- */
-
-#ifndef _SCSI_SCSI_DISK_H
-#define _SCSI_SCSI_DISK_H 1
-
-struct scsi_reassign_blocks
-{
- u_char op_code;
- u_char byte2;
- u_char unused[3];
- u_char control;
-};
-
-struct scsi_rw
-{
- u_char op_code;
- u_char addr_2; /* Most significant */
-#define SRW_TOPADDR 0x1F /* only 5 bits here */
- u_char addr_1;
- u_char addr_0; /* least significant */
- u_char length;
- u_char control;
-};
-
-struct scsi_rw_big
-{
- u_char op_code;
- u_char byte2;
-#define SRWB_RELADDR 0x01
- u_char addr_3; /* Most significant */
- u_char addr_2;
- u_char addr_1;
- u_char addr_0; /* least significant */
- u_char reserved;
- u_char length2;
- u_char length1;
- u_char control;
-};
-
-struct scsi_read_capacity
-{
- u_char op_code;
- u_char byte2;
- u_char addr_3; /* Most Significant */
- u_char addr_2;
- u_char addr_1;
- u_char addr_0; /* Least Significant */
- u_char unused[3];
- u_char control;
-};
-
-struct scsi_start_stop
-{
- u_char op_code;
- u_char byte2;
- u_char unused[2];
- u_char how;
-#define SSS_START 0x01
-#define SSS_LOEJ 0x02
- u_char control;
-};
-
-
-
-/*
- * Opcodes
- */
-
-#define REASSIGN_BLOCKS 0x07
-#define READ_COMMAND 0x08
-#define WRITE_COMMAND 0x0a
-#define MODE_SELECT 0x15
-#define MODE_SENSE 0x1a
-#define START_STOP 0x1b
-#define PREVENT_ALLOW 0x1e
-#define READ_CAPACITY 0x25
-#define READ_BIG 0x28
-#define WRITE_BIG 0x2a
-
-
-
-struct scsi_read_cap_data
-{
- u_char addr_3; /* Most significant */
- u_char addr_2;
- u_char addr_1;
- u_char addr_0; /* Least significant */
- u_char length_3; /* Most significant */
- u_char length_2;
- u_char length_1;
- u_char length_0; /* Least significant */
-};
-
-struct scsi_reassign_blocks_data
-{
- u_char reserved[2];
- u_char length_msb;
- u_char length_lsb;
- struct
- {
- u_char dlbaddr_3; /* defect logical block address (MSB) */
- u_char dlbaddr_2;
- u_char dlbaddr_1;
- u_char dlbaddr_0; /* defect logical block address (LSB) */
- } defect_descriptor[1];
-};
-
-union disk_pages /* this is the structure copied from osf */
-{
- struct page_disk_format {
- u_char pg_code; /* page code (should be 3) */
-#define DISK_PGCODE 0x3F /* only 6 bits valid */
- u_char pg_length; /* page length (should be 0x16) */
- u_char trk_z_1; /* tracks per zone (MSB) */
- u_char trk_z_0; /* tracks per zone (LSB) */
- u_char alt_sec_1; /* alternate sectors per zone (MSB) */
- u_char alt_sec_0; /* alternate sectors per zone (LSB) */
- u_char alt_trk_z_1; /* alternate tracks per zone (MSB) */
- u_char alt_trk_z_0; /* alternate tracks per zone (LSB) */
- u_char alt_trk_v_1; /* alternate tracks per volume (MSB) */
- u_char alt_trk_v_0; /* alternate tracks per volume (LSB) */
- u_char ph_sec_t_1; /* physical sectors per track (MSB) */
- u_char ph_sec_t_0; /* physical sectors per track (LSB) */
- u_char bytes_s_1; /* bytes per sector (MSB) */
- u_char bytes_s_0; /* bytes per sector (LSB) */
- u_char interleave_1;/* interleave (MSB) */
- u_char interleave_0;/* interleave (LSB) */
- u_char trk_skew_1; /* track skew factor (MSB) */
- u_char trk_skew_0; /* track skew factor (LSB) */
- u_char cyl_skew_1; /* cylinder skew (MSB) */
- u_char cyl_skew_0; /* cylinder skew (LSB) */
- u_char flags; /* various */
-#define DISK_FMT_SURF 0x10
-#define DISK_FMT_RMB 0x20
-#define DISK_FMT_HSEC 0x40
-#define DISK_FMT_SSEC 0x80
- u_char reserved21;
- u_char reserved22;
- u_char reserved23;
- } disk_format;
- struct page_rigid_geometry {
- u_char pg_code; /* page code (should be 4) */
- u_char pg_length; /* page length (should be 0x16) */
- u_char ncyl_2; /* number of cylinders (MSB) */
- u_char ncyl_1; /* number of cylinders */
- u_char ncyl_0; /* number of cylinders (LSB) */
- u_char nheads; /* number of heads */
- u_char st_cyl_wp_2; /* starting cyl., write precomp (MSB) */
- u_char st_cyl_wp_1; /* starting cyl., write precomp */
- u_char st_cyl_wp_0; /* starting cyl., write precomp (LSB) */
- u_char st_cyl_rwc_2;/* starting cyl., red. write cur (MSB)*/
- u_char st_cyl_rwc_1;/* starting cyl., red. write cur */
- u_char st_cyl_rwc_0;/* starting cyl., red. write cur (LSB)*/
- u_char driv_step_1; /* drive step rate (MSB) */
- u_char driv_step_0; /* drive step rate (LSB) */
- u_char land_zone_2; /* landing zone cylinder (MSB) */
- u_char land_zone_1; /* landing zone cylinder */
- u_char land_zone_0; /* landing zone cylinder (LSB) */
- u_char rpl; /* rotational position locking (2 bits) */
- u_char rot_offset; /* rotational offset */
- u_char reserved19;
- u_char medium_rot_rate_1; /* medium rotation rate (RPM) (MSB) */
- u_char medium_rot_rate_0; /* medium rotation rate (RPM) (LSB) */
- u_char reserved22;
- u_char reserved23;
- } rigid_geometry;
-} ;
-#endif /* _SCSI_SCSI_DISK_H*/
diff --git a/sys/scsi/scsi_driver.c b/sys/scsi/scsi_driver.c
deleted file mode 100644
index 69f2278..0000000
--- a/sys/scsi/scsi_driver.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 1995, HD Associates, Inc.
- * PO Box 276
- * Pepperell, MA 01463
- * 508 433 5266
- * dufault@hda.com
- *
- * This code is contributed to the University of California at Berkeley:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: scsi_driver.c,v 1.26 1997/09/02 20:06:34 bde Exp $
- *
- */
-
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-#define GETUNIT(DEVICE, DEV) \
- ((DEVICE)->getunit) ? (*(DEVICE)->getunit)((DEV)) \
- : (minor((DEV)) & ~SCSI_CONTROL_MASK)
-
-/* scsi_device_attach: Attach a SCSI device. This routine will
- * print out the device address, what it is, then call the type
- * attach function and when that returns print a newline. If the
- * type attach will make LOT's of noise it should print a leading
- * newline and then the address using sc_print_addr. See "sd.c".
- */
-int scsi_device_attach(struct scsi_link *sc_link)
-{
- errval errcode;
- dev_t dev;
- struct scsi_device *device = sc_link->device;
-
- if (bootverbose)
- sc_link->flags |= SDEV_BOOTVERBOSE;
-
- SC_DEBUG(sc_link, SDEV_DB2,
- ("%s%dattach: ", device->name, sc_link->dev_unit));
-
- /* Print _sane_ probe info! */
- printf("%s%d at scbus%d target %d lun %d\n",
- sc_link->device->name, sc_link->dev_unit,
- sc_link->scsibus, sc_link->target, sc_link->lun);
-#ifndef SCSIDEBUG
- scsi_print_info(sc_link);
-#endif
-
- printf("%s%d: %s ", device->name, sc_link->dev_unit, device->desc);
- /*
- * XXX some SCSI adapter drivers print out things while the
- * device-specific attach routine is running. The result is
- * something of a mess. This hack at least keeps it so each
- * line will begin with foodev0:.
- */
- sc_print_init();
-
- dev = scsi_dev_lookup(device->open);
-
- sc_link->dev = (device->setunit ?
- (*device->setunit)(dev, sc_link->dev_unit) :
- makedev(major(dev), sc_link->dev_unit) );
-
- errcode = (device->attach) ? (*(device->attach))(sc_link) : 0;
-
- printf("\n");
- sc_print_finish();
-
- if (errcode == 0)
- sc_link->flags |= device->link_flags;
-
- return errcode;
-}
-
-int
-scsi_open(dev_t dev, int flags, int fmt, struct proc *p,
-struct scsi_device *device)
-{
- errval errcode;
- u_int32_t unit;
- struct scsi_link *sc_link;
-
- if (device == 0)
- return ENXIO;
-
- unit = GETUNIT(device, dev);
- sc_link = SCSI_LINK(device, unit);
-
- /*
- * Check the unit is legal
- */
- if (sc_link == 0 || (sc_link->sd == 0 && !(sc_link->flags & SDEV_UK)))
- return ENXIO;
-
- /* If it is a "once only" device that is already open return EBUSY.
- */
- if ((sc_link->flags & SDEV_ONCE_ONLY) && (sc_link->flags & SDEV_IS_OPEN))
- return EBUSY;
-
- /* For the control device (user ioctl's only) don't call the open
- * entry.
- */
- if (SCSI_CONTROL(dev) || (device->dev_open == 0))
- {
- scsi_test_unit_ready(sc_link, SCSI_SILENT);
- errcode = 0;
- }
- else
- errcode = (*device->dev_open)(dev, flags, fmt, p, sc_link);
-
- if (!errcode ) sc_link->flags |= SDEV_IS_OPEN;
-
- SC_DEBUG(sc_link, SDEV_DB1, ("%sopen: dev=0x%lx (unit %lu) result %d\n",
- device->name, (u_long)dev, (u_long)unit, errcode));
-
- return errcode;
-}
-
-int
-scsi_close(dev_t dev, int flags, int fmt, struct proc *p,
-struct scsi_device *device)
-{
- errval errcode;
- struct scsi_link *sc_link = SCSI_LINK(device, GETUNIT(device, dev));
-
- SC_DEBUG(sc_link, SDEV_DB1, ("%sclose: Closing device\n", device->name));
-
- if (SCSI_CONTROL(dev) || (device->dev_close == 0))
- errcode = 0;
- else
- errcode = (*device->dev_close)(dev, flags, fmt, p, sc_link);
-
- sc_link->flags &= ~SDEV_IS_OPEN;
-
- return errcode;
-}
-
-int
-scsi_ioctl(dev_t dev, u_int32_t cmd, caddr_t arg, int flags, struct proc *p,
-struct scsi_device *device)
-{
- errval errcode;
- struct scsi_link *sc_link = SCSI_LINK(device, GETUNIT(device, dev));
-
- if (SCSI_CONTROL(dev) || (device->dev_ioctl == 0))
- errcode = scsi_do_ioctl(dev, cmd, arg, flags, p, sc_link);
- else
- errcode = (*device->dev_ioctl)(dev, cmd, arg, flags, p, sc_link);
-
- return errcode;
-}
-
-void
-scsi_minphys(struct buf *bp, struct scsi_device *device)
-{
- struct scsi_link *sc_link = SCSI_LINK(device, GETUNIT(device, bp->b_dev));
- (*sc_link->adapter->scsi_minphys)(bp);
-}
-
-void
-scsi_strategy(struct buf *bp, struct scsi_device *device)
-{
- u_int32_t unit = GETUNIT(device, bp->b_dev);
- struct scsi_link *sc_link = SCSI_LINK(device, unit);
-
- SC_DEBUG(sc_link, SDEV_DB2, ("\n%sstrategy ", device->name));
- SC_DEBUG(sc_link, SDEV_DB1, ("%ld bytes @ blk%ld\n",
- bp->b_bcount, (long)bp->b_blkno));
-
- if (SCSI_CONTROL(bp->b_dev) || (device->dev_strategy == 0))
- {
- bp->b_resid = bp->b_bcount;
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- biodone(bp);
- }
- else
- {
- bp->b_resid = 0;
- bp->b_error = 0;
-
- if (bp->b_bcount == 0)
- biodone(bp);
- else
- {
- (*sc_link->adapter->scsi_minphys)(bp);
- (*device->dev_strategy)(bp, sc_link);
- }
- }
-}
-
-int scsi_device_lock(struct scsi_link *sc_link)
-{
- int error;
- while (sc_link->flags & SDEV_XLOCK) {
- sc_link->flags |= SDEV_WANT;
- error = tsleep(&sc_link->flags, PRIBIO | PCATCH, "sdevlk",0);
- if (error)
- return error;
- }
- sc_link->flags |= SDEV_XLOCK;
- return 0;
-}
-
-void scsi_device_unlock(struct scsi_link *sc_link)
-{
- sc_link->flags &= ~SDEV_XLOCK;
- if (sc_link->flags & SDEV_WANT) {
- sc_link->flags &= ~SDEV_WANT;
- wakeup(&sc_link->flags);
- }
-}
diff --git a/sys/scsi/scsi_driver.h b/sys/scsi/scsi_driver.h
deleted file mode 100644
index 50f4851..0000000
--- a/sys/scsi/scsi_driver.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 1995, HD Associates, Inc.
- * PO Box 276
- * Pepperell, MA 01463
- * 508 433 5266
- * dufault@hda.com
- *
- * This code is contributed to the University of California at Berkeley:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: scsi_driver.h,v 1.12 1997/06/25 19:07:42 tegge Exp $
- *
- */
-#ifndef _SCSI__DRIVER_H_
-#define _SCSI__DRIVER_H_
-
-#ifdef KERNEL
-
-struct scsi_link;
-struct scsi_device;
-struct buf;
-struct proc;
-
-int scsi_device_attach __P((struct scsi_link *));
-int scsi_device_lock __P((struct scsi_link *));
-void scsi_device_unlock __P((struct scsi_link *));
-
-int scsi_open __P((dev_t, int, int, struct proc *, struct scsi_device *));
-int scsi_close __P((dev_t, int, int, struct proc *, struct scsi_device *));
-int scsi_ioctl __P((dev_t, u_int32_t, caddr_t, int, struct proc *,
- struct scsi_device *));
-void scsi_strategy __P((struct buf *, struct scsi_device *));
-void scsi_minphys __P((struct buf *, struct scsi_device *));
-
-#endif /* KERNEL */
-
-#endif /* _SCSI__DRIVER_H_ */
diff --git a/sys/scsi/scsi_generic.h b/sys/scsi/scsi_generic.h
deleted file mode 100644
index 2cd6f6c..0000000
--- a/sys/scsi/scsi_generic.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Contributed by HD Associates (contact: dufault@hda.com)
- * Copyright (c) 1992, 1993 HD Associates
- *
- * Berkeley style copyright. I've just snarfed it out of stdio.h:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * from: @(#)stdio.h 5.17 (Berkeley) 6/3/91
- * $Id$
- */
-
-/* generic SCSI header file. We use the same minor number format
- * as on SGI except that the flag bits aren't available because they
- * are used as the board index.
- *
- * The minor number format is:
- * FF UUU III (FFUU UIII)
- *
- * Where:
- * FF is the board index
- * UUU are the LUN
- * III is the SCSI ID (controller)
- */
-
-#ifndef _SCSI_GENERIC_H_
-#define _SCSI_GENERIC_H_
-
-#define G_SCSI_FLAG(DEV) (((DEV) & 0xC0) >> 6)
-#define G_SCSI_UNIT(DEV) G_SCSI_FLAG(DEV)
-#define G_SCSI_LUN(DEV) (((DEV) & 0x38) >> 3)
-#define G_SCSI_ID(DEV) ((DEV) & 0x7)
-
-#define G_SCSI_MINOR(FLAG, LUN, ID) \
- (((FLAG) << 6) | ((LUN) << 3) | (ID))
-
-#endif /* _SCSI_GENERIC_H_ */
diff --git a/sys/scsi/scsi_ioctl.c b/sys/scsi/scsi_ioctl.c
deleted file mode 100644
index c63de3a..0000000
--- a/sys/scsi/scsi_ioctl.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * Copyright (C) 1992, 1993, 1994, HD Associates, Inc.
- * PO Box 276
- * Pepperell, MA 01463
- * 508 433 5266
- * dufault@hda.com
- *
- * This code is contributed to the University of California at Berkeley:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *End copyright
- *
- * $Id: scsi_ioctl.c,v 1.31 1998/06/07 17:12:49 dfr Exp $
- *
- *
- */
-
-#include "opt_bounce.h"
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
-
-#define b_screq b_driver1 /* a patch in buf.h */
-#define b_sc_link b_driver2 /* a patch in buf.h */
-
-#include <sys/fcntl.h>
-#include <sys/proc.h>
-#include <sys/uio.h>
-
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <sys/scsiio.h>
-
-static void scsierr(struct buf *, int); /* XXX ??? */
-
-/*
- * We let the user interpret his own sense in the generic scsi world.
- * This routine is called at interrupt time if the SCSI_USER bit was set
- * in the flags passed to scsi_scsi_cmd(). No other completion processing
- * takes place, even if we are running over another device driver.
- * The lower level routines that call us here, will free the xs and restart
- * the device's queue if such exists.
- */
-#ifndef min
-#define min(A,B) ((A<B) ? A : B )
-#endif
-
-void scsi_user_done(xs)
-struct scsi_xfer *xs;
-{
-
- struct buf *bp;
- scsireq_t *screq;
-
- bp = xs->bp;
- if(!bp) { /* ALL user requests must have a buf */
- sc_print_addr(xs->sc_link);
- printf("User command with no buf\n");
- return ;
- }
- screq = bp->b_screq;
- if (!screq) { /* Is it one of ours? (the SCSI_USER bit says it is) */
- sc_print_addr(xs->sc_link);
- printf("User command with no request\n");
- return ;
- }
-
- SC_DEBUG(xs->sc_link,SDEV_DB2,("user-done\n"));
- screq->retsts = 0;
- screq->status = xs->status;
- switch((int)xs->error) {
- case XS_NOERROR:
- SC_DEBUG(xs->sc_link,SDEV_DB3,("no error\n"));
- if (xs->flags & SCSI_RESID_VALID)
- screq->datalen_used = xs->datalen - xs->resid;
- else
- screq->datalen_used = xs->datalen;
- screq->retsts = SCCMD_OK;
- break;
-
- case XS_SENSE:
- SC_DEBUG(xs->sc_link,SDEV_DB3,("have sense\n"));
- screq->senselen_used = min(sizeof(xs->sense),SENSEBUFLEN);
- bcopy(&xs->sense,screq->sense,screq->senselen);
- screq->retsts = SCCMD_SENSE;
- break;
-
- case XS_DRIVER_STUFFUP:
- sc_print_addr(xs->sc_link);
- printf("host adapter code inconsistency\n");
- screq->retsts = SCCMD_UNKNOWN;
- break;
-
- case XS_TIMEOUT:
- SC_DEBUG(xs->sc_link,SDEV_DB3,("timeout\n"));
- screq->retsts = SCCMD_TIMEOUT;
- break;
-
- case XS_BUSY:
- SC_DEBUG(xs->sc_link,SDEV_DB3,("busy\n"));
- screq->retsts = SCCMD_BUSY;
- break;
-
- default:
- sc_print_addr(xs->sc_link);
- printf("unknown error category from host adapter code\n");
- screq->retsts = SCCMD_UNKNOWN;
- break;
- }
- biodone(bp); /* we're waiting on it in scsistrategy() */
- return; /* it'll free the xs and restart any queue */
-}
-
-
-/* Pseudo strategy function
- * Called by scsi_do_ioctl() via physio/physstrat if there is to
- * be data transfered, and directly if there is no data transfer.
- *
- * Can't be used with block devices or raw_read/raw_write directly
- * from the cdevsw/bdevsw tables because they couldn't have added
- * the screq structure. [JRE]
- */
-static void
-scsistrategy(struct buf *bp)
-{
- errval err;
- struct scsi_link *sc_link = bp->b_sc_link;
- scsireq_t *screq;
- u_int32_t flags = 0;
- int s;
-
-
- if(!sc_link) {
- printf("user_strat: No link pointer\n");
- scsierr(bp,EINVAL);
- return;
- }
- SC_DEBUG(sc_link,SDEV_DB2,("user_strategy\n"));
- screq = bp->b_screq;
- if(!screq) {
- sc_print_addr(sc_link);
- printf("No request block\n");
- scsierr(bp,EINVAL);
- return;
- }
-
- /* We're in trouble if physio tried to break up the
- * transfer:
- */
- if (bp->b_bcount != screq->datalen) {
- sc_print_addr(sc_link);
- printf("physio split the request.. cannot proceed\n");
- scsierr(bp, EIO);
- return;
- }
-
- if (screq->timeout == 0) {
- scsierr(bp, EINVAL);
- return;
- }
-
- if (screq->cmdlen > sizeof(struct scsi_generic)) {
- sc_print_addr(sc_link);
- printf("cmdlen too big ");
- scsierr(bp, EFAULT);
- return;
- }
-
-
- if (screq->flags & SCCMD_READ)
- flags |= SCSI_DATA_IN;
-
- if (screq->flags & SCCMD_WRITE)
- flags |= SCSI_DATA_OUT;
-
- if (screq->flags & SCCMD_TARGET)
- flags |= SCSI_TARGET;
-
- if (screq->flags & SCCMD_ESCAPE)
- flags |= SCSI_ESCAPE;
-
-#ifdef BOUNCE_BUFFERS
- if (sc_link->flags & SDEV_BOUNCE)
- vm_bounce_alloc(bp);
-#endif
-
- err = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *)screq->cmd,
- screq->cmdlen,
- (u_char *)bp->b_data,
- screq->datalen,
- 0, /* user must do the retries *//* ignored */
- screq->timeout,
- bp,
- flags | SCSI_USER);
-
-
-
- /*because there is a bp, scsi_scsi_cmd will return immediatly*/
- if (err)
- {
- scsierr(bp, err);
- return;
- }
- SC_DEBUG(sc_link,SDEV_DB3,("about to sleep\n"));
- s = splbio();
- while(!(bp->b_flags & B_DONE))
- {
- tsleep((caddr_t)bp, PRIBIO, "scsistrat", 0);
- }
- splx(s);
- SC_DEBUG(sc_link,SDEV_DB3,("back from sleep\n"));
- return;
-}
-
-/*
- * Something (e.g. another driver) has called us
- * with an sc_link for a target/lun/adapter, and a scsi
- * specific ioctl to perform, better try.
- * If user-level type command, we must still be running
- * in the context of the calling process
- */
-errval scsi_do_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flags,
-struct proc *p, struct scsi_link *sc_link)
-{
- errval ret = 0;
-
- /* If we can't write the device we can't permit much:
- */
-
- if (cmd != SCIOCIDENTIFY && cmd != SCIOCGETDEVINFO&& !(flags & FWRITE))
- return EACCES;
-
- SC_DEBUG(sc_link,SDEV_DB2, ("scsi_do_ioctl(0x%lx)\n", cmd));
- switch(cmd)
- {
- case SCIOCCOMMAND:
- {
- /*
- * You won't believe this, but the arg copied in
- * from the user space, is on the kernel stack
- * for this process, so we can't write
- * to it at interrupt time..
- * we need to copy it in and out!
- * Make a static copy using malloc!
- */
- scsireq_t *screq2 = (scsireq_t *)addr;
- scsireq_t *screq = (scsireq_t *)addr;
- int rwflag = (screq->flags & SCCMD_READ) ? B_READ : B_WRITE;
- struct buf *bp;
- caddr_t d_addr;
- int len;
-
-#if 0 /* XXX dufault@hda.com: This looks too rev dependent. Do it always? */
- if((unsigned int)screq < (unsigned int)KERNBASE)
-#endif
- {
- screq = malloc(sizeof(scsireq_t),M_TEMP,M_WAITOK);
- bcopy(screq2,screq,sizeof(scsireq_t));
- }
- bp = malloc(sizeof (struct buf),M_TEMP,M_WAITOK);
- bzero(bp,sizeof(struct buf));
- d_addr = screq->databuf;
- bp->b_bcount = len = screq->datalen;
- bp->b_screq = screq;
- bp->b_sc_link = sc_link;
- if (len) {
- struct uio auio;
- struct iovec aiov;
- long cnt;
-
- aiov.iov_base = d_addr;
- aiov.iov_len = len;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
-
- auio.uio_resid = len;
- if (auio.uio_resid < 0)
- return (EINVAL);
-
- auio.uio_rw = (rwflag == B_READ) ? UIO_READ : UIO_WRITE;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_procp = curproc;
- cnt = len;
- ret = physio(scsistrategy, bp, dev, rwflag,
- minphys, &auio);
- } else {
- /* if no data, no need to translate it.. */
- bp->b_data = 0;
- bp->b_dev = dev;
- bp->b_flags |= B_BUSY;
-
- scsistrategy(bp);
- ret = bp->b_error;
- }
- free(bp,M_TEMP);
-#if 0 /* XXX dufault@hda.com: This looks too rev dependent. Do it always? */
- if((unsigned int)screq2 < (unsigned int)KERNBASE)
-#endif
- {
- bcopy(screq,screq2,sizeof(scsireq_t));
- free(screq,M_TEMP);
- }
- break;
- }
- case SCIOCDEBUG:
- {
- int level = *((int *)addr);
- SC_DEBUG(sc_link,SDEV_DB3,("debug set to %d\n",level));
- sc_link->flags &= ~SDEV_DBX; /*clear debug bits */
- if(level & 1) sc_link->flags |= SDEV_DB1;
- if(level & 2) sc_link->flags |= SDEV_DB2;
- if(level & 4) sc_link->flags |= SDEV_DB3;
- if(level & 8) sc_link->flags |= SDEV_DB4;
- ret = 0;
- break;
- }
- case SCIOCREPROBE:
- {
- struct scsi_addr *sca = (struct scsi_addr *) addr;
-
- ret = scsi_probe_busses(sca->scbus,sca->target,sca->lun);
- break;
- }
- case SCIOCRECONFIG:
- case SCIOCDECONFIG:
- ret = EINVAL;
- break;
-
- case SCIOCIDENTIFY:
- {
- struct scsi_addr *sca = (struct scsi_addr *) addr;
- sca->scbus = sc_link->scsibus;
- sca->target = sc_link->target;
- sca->lun = sc_link->lun;
- break;
- }
- case SCIOCGETDEVINFO:
- {
- struct scsi_devinfo *scd = (struct scsi_devinfo *)addr;
- struct scsi_link *scl;
- scl = scsi_link_get(scd->addr.scbus, scd->addr.target,
- scd->addr.lun);
- if (scl != 0) {
- scd->dev = scl->dev;
- /* XXX buffers better be big enough... */
- sprintf(scd->devname, "%s%d",
- scl->device->name, scl->dev_unit);
- sprintf(scd->adname, "%s%d:%d",
- scl->adapter->name, scl->adapter_unit,
- scl->adapter_bus);
- ret = 0;
- } else {
- ret = ENXIO;
- }
- break;
- }
-
- default:
- ret = ENOTTY;
- break;
- }
-
- return ret;
-}
-
-void
-scsierr(bp,err)
- struct buf *bp;
- int err;
-{
- bp->b_flags |= B_ERROR;
- bp->b_error = err;
- biodone(bp);
- return;
-}
-
diff --git a/sys/scsi/scsi_message.h b/sys/scsi/scsi_message.h
deleted file mode 100644
index 7163d49..0000000
--- a/sys/scsi/scsi_message.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Messages (1 byte) */ /* I/T (M)andatory or (O)ptional */
-#define MSG_CMDCOMPLETE 0x00 /* M/M */
-#define MSG_EXTENDED 0x01 /* O/O */
-#define MSG_SAVEDATAPOINTER 0x02 /* O/O */
-#define MSG_RESTOREPOINTERS 0x03 /* O/O */
-#define MSG_DISCONNECT 0x04 /* O/O */
-#define MSG_INITIATOR_DET_ERR 0x05 /* M/M */
-#define MSG_ABORT 0x06 /* O/M */
-#define MSG_MESSAGE_REJECT 0x07 /* M/M */
-#define MSG_NOOP 0x08 /* M/M */
-#define MSG_PARITY_ERROR 0x09 /* M/M */
-#define MSG_LINK_CMD_COMPLETE 0x0a /* O/O */
-#define MSG_LINK_CMD_COMPLETEF 0x0b /* O/O */
-#define MSG_BUS_DEV_RESET 0x0c /* O/M */
-#define MSG_ABORT_TAG 0x0d /* O/O */
-#define MSG_CLEAR_QUEUE 0x0e /* O/O */
-#define MSG_INIT_RECOVERY 0x0f /* O/O */
-#define MSG_REL_RECOVERY 0x10 /* O/O */
-#define MSG_TERM_IO_PROC 0x11 /* O/O */
-
-/* Messages (2 byte) */
-#define MSG_SIMPLE_Q_TAG 0x20 /* O/O */
-#define MSG_HEAD_OF_Q_TAG 0x21 /* O/O */
-#define MSG_ORDERED_Q_TAG 0x22 /* O/O */
-#define MSG_IGN_WIDE_RESIDUE 0x23 /* O/O */
-
-/* Identify message */ /* M/M */
-#define MSG_IDENTIFYFLAG 0x80
-#define MSG_IDENTIFY(lun, disc) (((disc) ? 0xc0 : MSG_IDENTIFYFLAG) | (lun))
-#define MSG_ISIDENTIFY(m) ((m) & MSG_IDENTIFYFLAG)
-
-/* Extended messages (opcode and length) */
-#define MSG_EXT_SDTR 0x01
-#define MSG_EXT_SDTR_LEN 0x03
-
-#define MSG_EXT_WDTR 0x03
-#define MSG_EXT_WDTR_LEN 0x02
diff --git a/sys/scsi/scsi_sense.c b/sys/scsi/scsi_sense.c
deleted file mode 100644
index 3dfc0ef..0000000
--- a/sys/scsi/scsi_sense.c
+++ /dev/null
@@ -1,309 +0,0 @@
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-
-#include <scsi/scsiconf.h>
-
-/* XXX There should be a way for a type driver to have its own
- * private senses and add them when it is added.
- */
-
-#if !defined(NO_SCSI_SENSE)
-
-#include "sd.h"
-#include "st.h"
-#define NSPRINT 0
-#include "pt.h"
-#include "worm.h"
-#include "cd.h"
-#define NSCAN 0
-#include "od.h"
-#include "ch.h"
-#define NCOMM 0
-
-static struct
-{
- u_char asc;
- u_char ascq;
- char *desc;
-} tab[] = {
-#if (NCH > 0)
- {0x28, 0x01, "Import or export element accessed" },
- {0x21, 0x01, "Invalid element address" },
- {0x3b, 0x0d, "Medium destination element full" },
- {0x3b, 0x0e, "Medium source element empty" },
-#endif
-#if (NOD > 0)
- {0x58, 0x00, "Generation does not exist" },
- {0x59, 0x00, "Updated block read" },
-#endif
-#if (NSCAN > 0)
- {0x2c, 0x02, "Invalid combination of windows specified" },
- {0x60, 0x00, "Lamp failure" },
- {0x61, 0x02, "Out of focus" },
- {0x3b, 0x0c, "Position past beginning of medium" },
- {0x3b, 0x0b, "Position past end of medium" },
- {0x3b, 0x0a, "Read past beginning of medium" },
- {0x3b, 0x09, "Read past end of medium" },
- {0x62, 0x00, "Scan head positioning error" },
- {0x2c, 0x01, "Too many windows specified" },
- {0x61, 0x01, "Unable to acquire video" },
- {0x61, 0x00, "Video acquisition error" },
-#endif
-#if (NCD > 0)
- {0x00, 0x11, "Audio play operation in progress" },
- {0x00, 0x12, "Audio play operation paused" },
- {0x00, 0x14, "Audio play operation stopped due to error" },
- {0x00, 0x13, "Audio play operation successfully completed" },
- {0x63, 0x00, "End of user area encountered on this track" },
- {0x64, 0x00, "Illegal mode for this track" },
- {0x00, 0x15, "No current audio status to return" },
- {0x18, 0x03, "Recovered data with CIRC" },
- {0x18, 0x04, "Recovered data with L-EC" },
- {0x57, 0x00, "Unable to recover table-of-contents" },
-#endif
-#if (NWORM > 0)||(NOD > 0)
- {0x11, 0x07, "Data resynchronization error" },
-#endif
-#if (NWORM > 0)||(NCD > 0)||(NOD > 0)
- {0x11, 0x06, "Circ unrecovered error" },
- {0x09, 0x02, "Focus servo failure" },
- {0x11, 0x05, "L-EC uncorrectable error" },
- {0x17, 0x04, "Recovered data with retries and/or CIRC applied" },
- {0x09, 0x03, "Spindle servo failure" },
- {0x09, 0x01, "Tracking servo failure" },
-#endif
-#if (NPT > 0)
- {0x54, 0x00, "SCSI to host system interface failure" },
- {0x55, 0x00, "System resource failure" },
-#endif
-#if (NSPRINT > 0)
- {0x3b, 0x07, "Failed to sense bottom-of-form" },
- {0x3b, 0x06, "Failed to sense top-of-form" },
- {0x3b, 0x05, "Paper jam" },
- {0x36, 0x00, "Ribbon, ink, or toner failure" },
- {0x3b, 0x04, "Slew failure" },
- {0x3b, 0x03, "Tape or electronic vertical forms unit not ready" },
-#endif
-#if (NST > 0)
- {0x14, 0x04, "Block sequence error" },
- {0x52, 0x00, "Cartridge fault" },
- {0x14, 0x03, "End-of-data not found" },
- {0x03, 0x02, "Excessive write errors" },
- {0x00, 0x01, "Filemark detected" },
- {0x14, 0x02, "Filemark or setmark not found" },
- {0x11, 0x08, "Incomplete block read" },
- {0x11, 0x09, "No gap found" },
- {0x03, 0x01, "No write current" },
- {0x2d, 0x00, "Overwrite error on update in place" },
- {0x50, 0x02, "Position error related to timing" },
- {0x3b, 0x08, "Reposition error" },
- {0x00, 0x03, "Setmark detected" },
- {0x33, 0x00, "Tape length error" },
- {0x3b, 0x01, "Tape position error at beginning-of-medium" },
- {0x3b, 0x02, "Tape position error at end-of-medium" },
- {0x53, 0x01, "Unload tape failure" },
- {0x50, 0x00, "Write append error" },
- {0x50, 0x01, "Write append position error" },
-#endif
-#if (NST > 0)||(NOD > 0)
- {0x51, 0x00, "Erase failure" },
-#endif
-#if (NST > 0)||(NSCAN > 0)
- {0x00, 0x04, "Beginning-of-partition/medium detected" },
- {0x00, 0x05, "End-of-data detected" },
- {0x00, 0x02, "End-of-partition/medium detected" },
- {0x0c, 0x00, "Write error" },
-#endif
-#if (NST > 0)||(NSPRINT > 0)
- {0x3b, 0x00, "Sequential positioning error" },
-#endif
-#if (NSD > 0)
- {0x41, 0x00, "Data path failure (should use 40 nn)" },
- {0x22, 0x00, "Illegal function (should use 20 00, 24 00, or 26 00)" },
- {0x42, 0x00, "Power-on or self-test failure (should use 40 nn)" },
- {0x40, 0x00, "Ram failure (should use 40 nn)" },
-#endif
-#if (NSD > 0)||(NOD > 0)
- {0x19, 0x00, "Defect list error" },
- {0x19, 0x03, "Defect list error in grown list" },
- {0x19, 0x02, "Defect list error in primary list" },
- {0x19, 0x01, "Defect list not available" },
- {0x1c, 0x00, "Defect list not found" },
- {0x1c, 0x02, "Grown defect list not found" },
- {0x1c, 0x01, "Primary defect list not found" },
- {0x5c, 0x00, "RPL status change" },
- {0x5c, 0x02, "Spindles not synchronized" },
- {0x5c, 0x01, "Spindles synchronized" },
-#endif
-#if (NSD > 0)||(NWORM > 0)||(NOD > 0)
- {0x13, 0x00, "Address mark not found for data field" },
- {0x12, 0x00, "Address mark not found for id field" },
- {0x16, 0x00, "Data synchronization mark error" },
- {0x32, 0x01, "Defect list update failure" },
- {0x10, 0x00, "Id CRC or ECC error" },
- {0x1d, 0x00, "Miscompare during verify operation" },
- {0x32, 0x00, "No defect spare location available" },
- {0x01, 0x00, "No index/sector signal" },
- {0x17, 0x06, "Recovered data without ECC - data auto-reallocated" },
- {0x17, 0x07, "Recovered data without ECC - recommend reassignment" },
- {0x17, 0x08, "Recovered data without ECC - recommend rewrite" },
- {0x1e, 0x00, "Recovered ID with ECC correction" },
- {0x11, 0x04, "Unrecovered read error - auto reallocate failed" },
- {0x11, 0x0b, "Unrecovered read error - recommend reassignment" },
- {0x11, 0x0c, "Unrecovered read error - recommend rewrite the data" },
- {0x0c, 0x02, "Write error - auto reallocation failed" },
- {0x0c, 0x01, "Write error recovered with auto reallocation" },
-#endif
-#if (NSD > 0)||(NWORM > 0)||(NCD > 0)||(NOD > 0)
- {0x18, 0x02, "Recovered data - data auto-reallocated" },
- {0x18, 0x05, "Recovered data - recommend reassignment" },
- {0x18, 0x06, "Recovered data - recommend rewrite" },
- {0x17, 0x05, "Recovered data using previous sector id" },
- {0x18, 0x01, "Recovered data with error correction & retries applied" },
-#endif
-#if (NSD > 0)||(NWORM > 0)||(NCD > 0)||(NOD > 0)||(NCH > 0)
- {0x06, 0x00, "No reference position found" },
- {0x02, 0x00, "No seek complete" },
-#endif
-#if (NSD > 0)||(NSPRINT > 0)||(NOD > 0)
- {0x31, 0x01, "Format command failed" },
-#endif
-#if (NSD > 0)||(NST > 0)
- {0x30, 0x03, "Cleaning cartridge installed" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NOD > 0)
- {0x11, 0x0a, "Miscorrected error" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NWORM > 0)||(NOD > 0)
- {0x31, 0x00, "Medium format corrupted" },
- {0x5a, 0x03, "Operator selected write permit" },
- {0x5a, 0x02, "Operator selected write protect" },
- {0x27, 0x00, "Write protected" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NWORM > 0)||(NSCAN > 0)||(NOD > 0)
- {0x11, 0x02, "Error too long to correct" },
- {0x11, 0x03, "Multiple read errors" },
- {0x11, 0x01, "Read retries exhausted" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NWORM > 0)||(NCD > 0)||(NOD > 0)
- {0x30, 0x02, "Cannot read medium - incompatible format" },
- {0x30, 0x01, "Cannot read medium - unknown format" },
- {0x15, 0x02, "Positioning error detected by read of medium" },
- {0x14, 0x01, "Record not found" },
- {0x18, 0x00, "Recovered data with error correction applied" },
- {0x17, 0x03, "Recovered data with negative head offset" },
- {0x17, 0x02, "Recovered data with positive head offset" },
- {0x09, 0x00, "Track following error" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NWORM > 0)||(NCD > 0)||(NOD > 0)||(NCH > 0)
- {0x30, 0x00, "Incompatible medium installed" },
- {0x21, 0x00, "Logical block address out of range" },
- {0x53, 0x02, "Medium removal prevented" },
- {0x5a, 0x01, "Operator medium removal request" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NWORM > 0)||(NCD > 0)||(NSCAN > 0)||(NOD > 0)
- {0x17, 0x00, "Recovered data with no error correction applied" },
- {0x17, 0x01, "Recovered data with retries" },
- {0x11, 0x00, "Unrecovered read error" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NSPRINT > 0)||(NOD > 0)
- {0x04, 0x04, "Logical unit not ready, format in progress" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NSPRINT > 0)||(NWORM > 0)||(NSCAN > 0)||(NOD > 0)
- {0x03, 0x00, "Peripheral device write fault" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NSPRINT > 0)||(NWORM > 0)||(NCD > 0)||(NSCAN > 0)||(NOD > 0)
- {0x14, 0x00, "Recorded entity not found" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NSPRINT > 0)||(NWORM > 0)||(NCD > 0)||(NSCAN > 0)||(NOD > 0)||(NCH > 0)
- {0x15, 0x01, "Mechanical positioning error" },
- {0x53, 0x00, "Media load or eject failed" },
- {0x3a, 0x00, "Medium not present" },
- {0x07, 0x00, "Multiple peripheral devices selected" },
- {0x15, 0x00, "Random positioning error" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NSPRINT > 0)||(NWORM > 0)||(NCD > 0)||(NSCAN > 0)||(NOD > 0)||(NCH > 0)||(ncomm > 0)
- {0x2a, 0x02, "Log parameters changed" },
- {0x08, 0x00, "Logical unit communication failure" },
- {0x08, 0x02, "Logical unit communication parity error" },
- {0x08, 0x01, "Logical unit communication time-out" },
- {0x2a, 0x01, "Mode parameters changed" },
- {0x2a, 0x00, "Parameters changed" },
- {0x37, 0x00, "Rounded parameter" },
- {0x39, 0x00, "Saving parameters not supported" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NSPRINT > 0)||(NPT > 0)||(NWORM > 0)||(NCD > 0)||(NSCAN > 0)||(NOD > 0)||(ncomm > 0)
- {0x2b, 0x00, "Copy cannot execute since host cannot disconnect" },
-#endif
-#if (NSD > 0)||(NST > 0)||(NSPRINT > 0)||(NPT > 0)||(NWORM > 0)||(NCD > 0)||(NSCAN > 0)||(NOD > 0)||(NCH > 0)
- {0x5b, 0x02, "Log counter at maximum" },
- {0x5b, 0x00, "Log exception" },
- {0x5b, 0x03, "Log list codes exhausted" },
- {0x5a, 0x00, "Operator request or state change input (unspecified)" },
- {0x5b, 0x01, "Threshold condition met" },
-#endif
- {0x3f, 0x02, "Changed operating definition" },
- {0x4a, 0x00, "Command phase error" },
- {0x2c, 0x00, "Command sequence error" },
- {0x2f, 0x00, "Commands cleared by another initiator" },
- {0x4b, 0x00, "Data phase error" },
-/* {0x40, 0xnn, "Diagnostic failure on component nn (80h-ffh)" }, */
- {0x0a, 0x00, "Error log overflow" },
- {0x00, 0x06, "I/O process terminated" },
- {0x48, 0x00, "Initiator detected error message received" },
- {0x3f, 0x03, "Inquiry data has changed" },
- {0x44, 0x00, "Internal target failure" },
- {0x3d, 0x00, "Invalid bits in identify message" },
- {0x20, 0x00, "Invalid command operation code" },
- {0x24, 0x00, "Invalid field in CDB" },
- {0x26, 0x00, "Invalid field in parameter list" },
- {0x49, 0x00, "Invalid message error" },
- {0x05, 0x00, "Logical unit does not respond to selection" },
- {0x4c, 0x00, "Logical unit failed self-configuration" },
- {0x3e, 0x00, "Logical unit has not self-configured yet" },
- {0x04, 0x01, "Logical unit is in process of becoming ready" },
- {0x04, 0x00, "Logical unit not ready, cause not reportable" },
- {0x04, 0x02, "Logical unit not ready, initializing command required" },
- {0x04, 0x03, "Logical unit not ready, manual intervention required" },
- {0x25, 0x00, "Logical unit not supported" },
- {0x43, 0x00, "Message error" },
- {0x3f, 0x01, "Microcode has been changed" },
- {0x00, 0x00, "No additional sense information" },
- {0x28, 0x00, "Not ready to ready transition, medium may have changed" },
- {0x4e, 0x00, "Overlapped commands attempted" },
- {0x1a, 0x00, "Parameter list length error" },
- {0x26, 0x01, "Parameter not supported" },
- {0x26, 0x02, "Parameter value invalid" },
- {0x29, 0x00, "Power on, reset, or bus device reset occurred" },
- {0x47, 0x00, "SCSI parity error" },
- {0x45, 0x00, "Select or reselect failure" },
- {0x1b, 0x00, "Synchronous data transfer error" },
- {0x3f, 0x00, "Target operating conditions have changed" },
- {0x26, 0x03, "Threshold parameters not supported" },
- {0x46, 0x00, "Unsuccessful soft reset" },
-};
-
-char *scsi_sense_desc(int asc, int ascq)
-{
- int i;
-
- if (asc >= 0x80 && asc <= 0xff)
- return "Vendor Specific ASC";
-
- if (ascq >= 0x80 && ascq <= 0xff)
- return "Vendor Specific ASCQ";
-
- for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++)
- if (tab[i].asc == asc && tab[i].ascq == ascq)
- return tab[i].desc;
-
- return "";
-}
-
-#else /* NO_SCSI_SENSE */
-char *scsi_sense_desc(int asc, int ascq)
-{
- return "";
-}
-#endif
diff --git a/sys/scsi/scsi_tape.h b/sys/scsi/scsi_tape.h
deleted file mode 100644
index 5b16574..0000000
--- a/sys/scsi/scsi_tape.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * SCSI tape interface description
- */
-
-/*
- * Written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- */
-
-/*
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- *
- * $Id$
- */
-#ifndef SCSI_SCSI_TAPE_H
-#define SCSI_SCSI_TAPE_H 1
-
-
-
-/*
- * SCSI command formats
- */
-
-
-struct scsi_rw_tape
-{
- u_char op_code;
- u_char byte2;
-#define SRWT_FIXED 0x01
- u_char len[3];
- u_char control;
-};
-
-struct scsi_space
-{
- u_char op_code;
- u_char byte2;
-#define SS_CODE 0x03
- u_char number[3];
- u_char control;
-};
-#define SP_BLKS 0
-#define SP_FILEMARKS 1
-#define SP_SEQ_FILEMARKS 2
-#define SP_EOM 3
-
-struct scsi_write_filemarks
-{
- u_char op_code;
- u_char byte2;
- u_char number[3];
- u_char control;
-};
-
-struct scsi_rewind
-{
- u_char op_code;
- u_char byte2;
-#define SR_IMMED 0x01
- u_char unused[3];
- u_char control;
-};
-
-/*
-** Tape erase - AKL: Andreas Klemm <andreas@knobel.gun.de>
-*/
-struct scsi_erase
-{
- u_char op_code;
- u_char byte2;
-#define SE_LONG 0x01 /*
- ** Archive Viper 2525 doesn't allow short
- ** erase, other tapes possibly don't allow
- ** that, too.
- */
-#define SE_IMMED 0x02
- u_char unused[3];
- u_char control;
-};
-
-struct scsi_load
-{
- u_char op_code;
- u_char byte2;
-#define SL_IMMED 0x01
- u_char unused[2];
- u_char how;
- u_char control;
-};
-#define LD_UNLOAD 0
-#define LD_LOAD 1
-#define LD_RETEN 2
-
-
-struct scsi_blk_limits
-{
- u_char op_code;
- u_char byte2;
- u_char unused[3];
- u_char control;
-};
-
-/*
- * Opcodes
- */
-
-#define REWIND 0x01
-#define READ_BLK_LIMITS 0x05
-#define READ_COMMAND_TAPE 0x08
-#define WRITE_COMMAND_TAPE 0x0a
-#define WRITE_FILEMARKS 0x10
-#define SPACE 0x11
-#define ERASE 0x19
-#define LOAD_UNLOAD 0x1b
-
-
-
-struct scsi_blk_limits_data
-{
- u_char reserved;
- u_char max_length_2; /* Most significant */
- u_char max_length_1;
- u_char max_length_0; /* Least significant */
- u_char min_length_1; /* Most significant */
- u_char min_length_0; /* Least significant */
-};
-
-/* defines for the device specific byte in the mode select/sense header */
-#define SMH_DSP_SPEED 0x0F
-#define SMH_DSP_BUFF_MODE 0x70
-#define SMH_DSP_BUFF_MODE_OFF 0x00
-#define SMH_DSP_BUFF_MODE_ON 0x10
-#define SMH_DSP_BUFF_MODE_MLTI 0x20
-#define SMH_DSP_WRITE_PROT 0x80
-
-/* A special for the CIPHER ST150S(old drive) */
-struct blk_desc_cipher
-{
- u_char density;
- u_char nblocks[3];
- u_char reserved;
- u_char blklen[3];
- u_char other;
-#define ST150_SEC 0x01 /* soft error count */
-#define SR150_AUI 0x02 /* autoload inhibit */
-};
-
-/*
- * This structure defines the various mode pages that tapes know about.
- */
-#define PAGE_HEADERLEN 2
-struct tape_pages
-{
- u_char pg_code; /* page code */
-#define ST_PAGE_CONFIGURATION 0x10
-#define ST_PAGE_MEDIUM_PART 0x11
-#define ST_PAGE_MEDIUM_PART2 0x12
-#define ST_PAGE_MEDIUM_PART3 0x13
-#define ST_PAGE_MEDIUM_PART4 0x14
-#define ST_P_CODE 0x3F /* page code */
-#define ST_P_PS 0x80 /* page savable */
- u_char pg_length; /* page length */
- union
- {
- struct
- {
- u_char active_format; /* active format for density*/
-#define ST_P_CAP 0x40 /* change active Partition */
-#define ST_P_CAF 0x20 /* change active format */
-#define ST_P_AF 0x1F /* active format */
- u_char active_partition; /* */
- u_char write_buffer_full_ratio; /* highwater writing*/
- u_char read_buffer_empty_ratio; /* lowwater reading*/
- u_char write_delay_high; /* # 100mSecs before flush*/
- u_char write_delay_low; /* of buffer to the media */
- u_char flags1; /* various single bit flags */
-#define ST_P_DBR 0x80 /* supports data-buffer recovery */
-#define ST_P_BIS 0x40 /* supports Block_ID */
-#define ST_P_RSmk 0x20 /* Reports setmarks during reads and spaces */
-#define ST_P_AVC 0x10 /* Supports Automatic Velocity Control */
-#define ST_P_SOCF 0x0C /* Stop On Consecutive Filemarks, */
-#define ST_P_RBO 0x02 /* Recoverd Buffered Data order, 1 = LIFO */
-#define ST_P_REW 0x01 /* Report Early Warning (see SEW) */
- u_char gap_size; /*I/B gap, 1=min 0=default */
- u_char flags2; /* various single bit flags */
-#define ST_P_EOD 0xE0 /* What is and EOD....*/
-#define ST_P_EOD_DEF 0x00 /* Drive's default */
-#define ST_P_EOD_FMT 0x20 /* define by format */
-#define ST_P_EOD_SOCF 0x40 /* define by SOCF (above) */
-#define ST_P_EEG 0x10 /* use EOD above */
-#define ST_P_SEW 0x04 /* Synchronise at Early warning.. flush buffers*/
- u_char early_warn_high;/* buf size at early warning */
- u_char early_warn_med; /* after early warning, only */
- u_char early_warn_low; /* buufer this much data */
- u_char data_compress_alg; /* 0 = off, 1 = default */
- u_char reserved; /* The standard says so */
- } configuration;
- struct
- {
-#define ST_MAXPARTS 16 /*for now*/
- u_char max_add_parts; /* that drive allows */
- u_char parts_defined; /* max min(ST_MAXPARTS,max_add_parts) */
- u_char flags;
-#define ST_P_FDP 0x80
-#define ST_P_SDP 0x40
-#define ST_P_IDP 0x20
-#define ST_P_PSUM 0x18 /* units of part defs.. */
-#define ST_P_PSUM_BYTES 0x0 /* units of part defs.. */
-#define ST_P_PSUM_KBYTES 0x08 /* units of part defs.. */
-#define ST_P_PSUM_MBYTES 0x10 /* units of part defs.. */
- u_char medium_format_recog;
-#define ST_P_REC_NONE 0x00
-#define ST_P_REC_FMT 0x01 /* can recognise format of new media */
-#define ST_P_REC_PART 0x02 /* can recognise partitions of new media */
-#define ST_P_REC_FMT_PART 0x03 /* can recognise format and parts */
- u_char reserved1;
- u_char reserved2;
- struct
- {
- u_char high;
- u_char low;
- }part[ST_MAXPARTS];
- } medium_partition;
- struct
- {
- struct
- {
- u_char high;
- u_char low;
- }part[ST_MAXPARTS];
- } medium_partition_extra;
- }pages;
-};
-
-
-#endif /*SCSI_SCSI_TAPE_H*/
diff --git a/sys/scsi/scsi_worm.h b/sys/scsi/scsi_worm.h
deleted file mode 100644
index 6f8fc61..0000000
--- a/sys/scsi/scsi_worm.h
+++ /dev/null
@@ -1,128 +0,0 @@
-#ifndef _SCSI_SCSI_WORM_H
-#define _SCSI_SCSI_WORM_H
-
-#define PAGE_HEADERLEN 2
-
-/*
- * Opcodes
- */
-
-#define REZERO_UNIT 0x01 /* re-init; XXX belongs to scsi_all? */
-#define SYNCHRONIZE_CACHE 0x35 /* flush write buffer, close wr chn */
-#define FIRST_WRITEABLE_ADDR 0xe2 /* return first available LBA */
-#define RESERVE_TRACK 0xe4 /* reserve a track for later write */
-#define READ_TRACK_INFORMATION 0xe5 /* get info for a particular track */
-#define WRITE_TRACK 0xe6 /* open the write channel */
-#define LOAD_UNLOAD 0xe7 /* resembles part of START_STOP */
-#define FIXATION 0xe9 /* write leadin/leadout */
-#define WRITE_SESSION 0xed /* guide to write a new session */
-#define READ_SESSION_INFO 0xee /* read leadin/leadout lengths */
-
-struct scsi_rezero_unit
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[3];
- u_char control;
-};
-
-struct scsi_synchronize_cache
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[7];
- u_char control;
-};
-
-/* struct scsi_first_writeable_address; */
-
-struct scsi_reserve_track
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[3];
- u_char reserve_length_3; /* MSB */
- u_char reserve_length_2;
- u_char reserve_length_1;
- u_char reserve_length_0; /* LSB */
- u_char control;
-};
-
-/* struct scsi_read_track_information; */
-
-struct scsi_write_track
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[3];
- u_char track_number; /* 0 means: use next available */
- u_char mode;
-#define WORM_TRACK_MODE_RAW 0x08
-#define WORM_TRACK_MODE_AUDIO 0x04
-#define WORM_TRACK_MODE_MODE1 0x01 /* also audio with preemphasis */
-#define WORM_TRACK_MODE_MODE2 0x02
- u_char transfer_length_1; /* number of blocks to transfer, MSB */
- u_char transfer_length_0; /* LSB */
- u_char control;
-#define WORM_TRACK_CONTROL_MIX 0x40 /* mixed mode blocks */
-};
-
-struct scsi_load_unload
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[6];
- u_char load;
-#define WORM_LOAD_MEDIUM 0x01
- u_char control;
-};
-
-struct scsi_fixation
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[6];
- u_char action;
-#define WORM_FIXATION_ONP 0x08 /* open next program area (new session) */
-#define WORM_TOC_TYPE_AUDIO 0x00
-#define WORM_TOC_TYPE_CDROM 0x01
-#define WORM_TOC_TYPE_CDROM_1 0x02 /* CD-ROM, first track mode 1 (?) */
-#define WORM_TOC_TYPE_CDROM_2 0x03 /* CD-ROM, first track mode 2 */
-#define WORM_TOC_TYPE_CDI 0x04
- u_char control;
-};
-
-struct scsi_write_session
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[4];
- u_char action; /* see scsi_fixation above */
-#define WORM_LOFP_MODE_MODE1 0x10
-#define WORM_LOFP_MODE_MODE2 0x20
- u_char transfer_length_2; /* number of blocks to transfer, MSB */
- u_char transfer_length_1; /* LSB */
- u_char control;
-};
-
-struct scsi_read_session_info
-{
- u_char op_code;
- u_char byte2;
- u_char reserved[6];
- u_char transfer_length;
- u_char control;
-};
-
-struct scsi_first_writable_address
-{
- u_char op_code;
- u_char byte2;
- u_char track_number;
- u_char mode;
- u_char reserved[4];
- u_char transfer_length;
- u_char control;
-};
-
-#endif /* _SCSI_SCSI_WORM_H */
diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c
deleted file mode 100644
index f805edc..0000000
--- a/sys/scsi/scsiconf.c
+++ /dev/null
@@ -1,1573 +0,0 @@
-/*
- * Written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- *
- * New configuration setup: dufault@hda.com
- *
- * $Id: scsiconf.c,v 1.107 1998/07/28 09:03:37 phk Exp $
- */
-
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/conf.h>
-#ifdef PC98
-#include <sys/device.h>
-#endif
-
-#include <machine/clock.h>
-
-#include "sd.h"
-#include "st.h"
-#include "cd.h"
-#include "ch.h"
-#include "od.h"
-#include "pt.h"
-#include "worm.h"
-
-#include "sctarg.h"
-
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-static struct extend_array *extend_new __P((void));
-static void extend_release __P((struct extend_array *ea, int index));
-static void *extend_set __P((struct extend_array *ea, int index, void *value));
-
-/*
- * XXX SCSI_DEVICE_ENTRIES() generates extern switches but it should
- * generate static switches except for this. Separate macros are
- * probably required for the extern and static parts.
- */
-extern struct scsi_device uk_switch;
-
-/***********************************************************************
- * Extensible arrays: Use a realloc like implementation to permit
- * the arrays to be extend. These are set up to be moved out
- * of this file if needed elsewhere.
- */
-struct extend_array
-{
- int nelem;
- void **ps;
-};
-
-static void make_readable __P((char *to, char *from, size_t n));
-static int match __P((char *pattern, char *name));
-static int scsi_bus_conf __P((struct scsi_link *sc_link_proto));
-
-static void *
-extend_alloc(size_t s)
-{
- void *p = malloc(s, M_DEVBUF, M_NOWAIT);
- if (!p)
- panic("extend_alloc: malloc failed.");
- return p;
-}
-
-static void
-extend_free(void *p) { free(p, M_DEVBUF); }
-
-/* EXTEND_CHUNK: Number of extend slots to allocate whenever we need a new
- * one.
- */
-#ifndef EXTEND_CHUNK
- #define EXTEND_CHUNK 8
-#endif
-
-static struct extend_array *
-extend_new(void)
-{
- struct extend_array *p = extend_alloc(sizeof(*p));
- if (p) {
- p->nelem = 0;
- p->ps = 0;
- }
-
- return p;
-}
-
-static void *
-extend_set(struct extend_array *ea, int index, void *value)
-{
- if (index >= ea->nelem) {
- void **space;
- space = extend_alloc(sizeof(void *) * (index + EXTEND_CHUNK));
- bzero(space, sizeof(void *) * (index + EXTEND_CHUNK));
-
- /* Make sure we have something to copy before we copy it */
- if (ea->nelem) {
- bcopy(ea->ps, space, sizeof(void *) * ea->nelem);
- extend_free(ea->ps);
- }
-
- ea->ps = space;
- ea->nelem = index + EXTEND_CHUNK;
- }
- if (ea->ps[index]) {
- printf("extend_set: entry %d already has storage.\n", index);
- return 0;
- }
- else
- ea->ps[index] = value;
-
- return value;
-}
-
-void *
-extend_get(struct extend_array *ea, int index)
-{
- if (ea == NULL || index >= ea->nelem || index < 0)
- return NULL;
- return ea->ps[index];
-}
-
-static void
-extend_release(struct extend_array *ea, int index)
-{
- void *p = extend_get(ea, index);
- if (p) {
- ea->ps[index] = 0;
- }
-}
-
-/***********************************************************************
- * This extend_array holds an array of "scsibus_data" pointers.
- * One of these is allocated and filled in for each scsi bus.
- * it holds pointers to allow the scsi bus to get to the driver
- * that is running each LUN on the bus
- * it also has a template entry which is the prototype struct
- * supplied by the adapter driver, this is used to initialise
- * the others, before they have the rest of the fields filled in
- */
-
-static struct extend_array *scbusses;
-
-/*
- * The structure of known drivers for autoconfiguration
- */
-struct scsidevs {
- u_int32_t type;
- u_int32_t driver; /* normally the same as type */
- boolean removable;
- char *manufacturer;
- char *model;
- char *version;
- char *devname;
- char flags; /* 1 show my comparisons during boot(debug) */
- u_int16_t quirks;
- void *devmodes;
-};
-
-#define SC_SHOWME 0x01
-#define SC_ONE_LU 0x00
-#define SC_MORE_LUS 0x02
-
-static struct scsidevs unknowndev =
- {
- T_UNKNOWN, T_UNKNOWN, 0, "*", "*", "*",
- "uk", SC_MORE_LUS
- };
-static st_modes mode_tandberg3600 =
- {
- {0, 0, 0}, /* minor 0,1,2,3 */
- {0, ST_Q_FORCE_VAR_MODE, QIC_525}, /* minor 4,5,6,7 */
- {0, 0, QIC_150}, /* minor 8,9,10,11 */
- {0, 0, QIC_120} /* minor 12,13,14,15 */
- };
-static st_modes mode_tandberg4200 =
- {
- {0, 0, 0}, /* minor 0,1,2,3 */
- {0, ST_Q_FORCE_VAR_MODE, 0}, /* minor 4,5,6,7 */
- {0, 0, QIC_150}, /* minor 8,9,10,11 */
- {0, 0, QIC_120} /* minor 12,13,14,15 */
- };
-static st_modes mode_archive2525 =
- {
- {0, ST_Q_SNS_HLP, 0}, /* minor 0,1,2,3 */
- {0, ST_Q_SNS_HLP, QIC_525}, /* minor 4,5,6,7 */
- {0, 0, QIC_150}, /* minor 8,9,10,11 */
- {0, 0, QIC_120} /* minor 12,13,14,15 */
- };
-static st_modes mode_archive150 =
- {
- {0, 0, 0}, /* minor 0,1,2,3 */
- {0, 0, QIC_150}, /* minor 4,5,6,7 */
- {0, 0, QIC_120}, /* minor 8,9,10,11 */
- {0, 0, QIC_24} /* minor 12,13,14,15 */
- };
-static st_modes mode_wangtek5525 =
- {
- {0, 0, 0}, /* minor 0,1,2,3 */
- {0, ST_Q_BLKSIZ, QIC_525}, /* minor 4,5,6,7 */
- {0, 0, QIC_150}, /* minor 8,9,10,11 */
- {0, 0, QIC_120} /* minor 12,13,14,15 */
- };
-static st_modes mode_wangdat1300 =
- {
- {0, 0, 0}, /* minor 0,1,2,3 */
- {512, ST_Q_FORCE_FIXED_MODE, DDS}, /* minor 4,5,6,7 */
- {1024, ST_Q_FORCE_FIXED_MODE, DDS}, /* minor 8,9,10,11 */
- {0, ST_Q_FORCE_VAR_MODE, DDS} /* minor 12,13,14,15 */
- };
-static st_modes mode_unktape =
- {
- {0, 0, 0}, /* minor 0,1,2,3 */
- {512, ST_Q_FORCE_FIXED_MODE, QIC_24}, /* minor 4,5,6,7 */
- {0, ST_Q_FORCE_VAR_MODE, HALFINCH_1600}, /* minor 8,9,10,11 */
- {0, ST_Q_FORCE_VAR_MODE, HALFINCH_6250} /* minor 12,13,14,15 */
- };
-
-static int worm_mode_philips = WORM_Q_PHILIPS;
-static int worm_mode_plasmon = WORM_Q_PLASMON;
-
-/***********************************************************************
- * A list of known devices and their "quirks". Matching is based
- * first on device type, then on the manufacturer, model, and revision
- * strings returned by the device. The returned strings are fixed lengths
- * of 8, 16 and 4 bytes respectively. In the matching pattern, a
- * question mark (?) matches any single character and a trailing
- * asterisk (*) matches remaining characters. For patterns shorter
- * than their respective fields, trailing spaces are implied.
- */
-
-static struct scsidevs knowndevs[] =
-{
-#if NOD > 0
- {
- T_OPTICAL, T_OPTICAL, T_REMOV, "MATSHITA", "PD-1 LF-1*", "*",
- "od", SC_MORE_LUS
- },
- {
- T_DIRECT, T_OPTICAL, T_REMOV, "SONY", "SMO-*", "*",
- "od", SC_MORE_LUS
- },
- {
- T_DIRECT, T_OPTICAL, T_REMOV, "MOST", "RMD-5200-S", "*",
- "od", SC_ONE_LU
- },
- {
- T_DIRECT, T_OPTICAL, T_REMOV, "RICOH", "RO-*", "*",
- "od", SC_ONE_LU
- },
-#endif /* NOD */
-#if NSD > 0
- {
- T_DIRECT, T_DIRECT, T_FIXED, "EMULEX", "MD21*" , "*",
- "sd", SC_MORE_LUS
- },
- {
- T_DIRECT, T_DIRECT, T_FIXED, "IFT", "*" , "*",
- "sd", SC_MORE_LUS
- },
-#endif /* NSD */
-#if NST > 0
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "TANDBERG", " TDC 3600", "*",
- "st", SC_ONE_LU, ST_Q_NEEDS_PAGE_0, mode_tandberg3600
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "TANDBERG", " TDC 42*", "*",
- "st", SC_ONE_LU, ST_Q_SNS_HLP|ST_Q_NO_1024, mode_tandberg4200
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "ARCHIVE", "VIPER 2525*", "-005",
- "st", SC_ONE_LU, 0, mode_archive2525
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "ARCHIVE", "VIPER 150 *", "*",
- "st", SC_ONE_LU, ST_Q_NEEDS_PAGE_0, mode_archive150
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "WANGTEK", "5525ES*", "*",
- "st", SC_ONE_LU, 0, mode_wangtek5525
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "WangDAT", "Model 1300", "*",
- "st", SC_ONE_LU, 0, mode_wangdat1300
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "DEC", "DLT2700", "*",
- "st", SC_MORE_LUS, 0
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "Quantum", "DLT*", "*",
- "st", SC_MORE_LUS, 0
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "SUN", "DLT*", "*",
- "st", SC_MORE_LUS, 0
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "HP", "C1553A*", "*",
- "st", SC_MORE_LUS, 0
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "HP", "C1557A", "*",
- "st", SC_MORE_LUS, 0
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "ARCHIVE", "Python 28849-*", "*",
- "st", SC_MORE_LUS, 0
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "ARCHIVE", "4586XX 28887-*", "*",
- "st", SC_MORE_LUS, 0
- },
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "SONY", "TSL-7000", "*",
- "st", SC_MORE_LUS, 0
- },
-#endif /* NST */
-#if NCH > 0
- /*
- * The <ARCHIVE, Python 28849-XXX, 4.98> is a SCSI changer device
- * with an Archive Python DAT drive built-in. The tape appears
- * at LUN 0 and the changer at LUN 1.
- * This entry should not be needed at all.
- */
- {
- T_CHANGER, T_CHANGER, T_REMOV, "ARCHIVE", "Python 28849-*", "*",
- "ch", SC_MORE_LUS
- },
- {
- T_CHANGER, T_CHANGER, T_REMOV, "ARCHIVE", "4586XX 28887-*", "*",
- "ch", SC_MORE_LUS
- },
- {
- T_CHANGER, T_CHANGER, T_REMOV, "SONY", "TSL-7000", "*",
- "ch", SC_MORE_LUS
- },
-#endif /* NCH */
-#if NCD > 0
-#ifndef UKTEST /* make cdroms unrecognised to test the uk driver */
- /*
- * CDU-8003A aka Apple CDROM-300.
- */
- {
- T_READONLY, T_READONLY, T_REMOV, "SONY", "CD-ROM CDU-8003A", "1.9a",
- "cd", SC_ONE_LU
- },
- {
- T_READONLY, T_READONLY, T_REMOV, "SONY", "CD-ROM CDU-8012", "3.1a",
- "cd", SC_ONE_LU
- },
- {
- T_READONLY, T_READONLY, T_REMOV, "PIONEER", "CD-ROM DRM-6??*" ,"*",
- "cd", SC_MORE_LUS, CD_Q_NO_TOUCH
- },
- {
- T_READONLY, T_READONLY, T_REMOV, "NRC", "MBR-7*" ,"*",
- "cd", SC_MORE_LUS
- },
- {
- T_READONLY, T_READONLY, T_REMOV, "CHINON", "CD-ROM CDS-535","*",
- "cd", SC_ONE_LU, CD_Q_BCD_TRACKS
- },
- /*
- * Note: My drive with v1.0 firmware "forgets" to generate scsi parity
- * when answering probes.. :-( EVIL!! You need to disable scsi parity
- * checking in order to find out that it answers to all 7 LUNS. :-(
- * -Peter
- */
- {
- T_READONLY, T_READONLY, T_REMOV, "NEC", "CD-ROM DRIVE:55","*",
- "cd", SC_ONE_LU
- },
- /*
- * Same with the OEM version of this drive (1.0 firmware).
- * -Paul
- */
- {
- T_READONLY, T_READONLY, T_REMOV, "NEC", "CD-ROM DRIVE:210","*",
- "cd", SC_ONE_LU
- },
- /*
- * Doobe-doo-be doooo
- * -Mary
- */
- {
- T_READONLY, T_READONLY, T_REMOV, "MEDIAVIS", "RENO CD-ROMX2A","*",
- "cd", SC_ONE_LU, CD_Q_NO_START
- },
- {
- T_READONLY, T_READONLY, T_REMOV, "NAKAMICH", "MJ-*" ,"*",
- "cd", SC_MORE_LUS
- },
- /* yet another changer */
- {
- T_READONLY, T_READONLY, T_REMOV, "REGAL", "CDC-4*" ,"*",
- "cd", SC_MORE_LUS
- },
- /* IODATA CD-C68E 6 CD changer */
- {
- T_READONLY, T_READONLY, T_REMOV, "IODATA", "CD-C68E" ,"*",
- "cd", SC_MORE_LUS
- },
-#endif /* !UKTEST */
-#endif /* NCD */
-#if NWORM > 0
- {
- T_READONLY, T_WORM, T_REMOV, "HP", "C4324/C4325", "*",
- "worm", SC_ONE_LU, 0, &worm_mode_philips
- },
- {
- T_READONLY, T_WORM, T_REMOV, "HP", "CD-Writer 6020", "*",
- "worm", SC_ONE_LU, 0, &worm_mode_philips
- },
- {
- /* That's the Philips drive, in case anybody wonders... */
- T_READONLY, T_WORM, T_REMOV, "IMS", "CDD2000*", "*",
- "worm", SC_ONE_LU, 0, &worm_mode_philips
- },
- {
- /* Here's another Philips drive... */
- T_READONLY, T_WORM, T_REMOV, "PHILIPS", "CDD2*", "*",
- "worm", SC_ONE_LU, 0, &worm_mode_philips
- },
- /*
- * The Plasmon's are dual-faced: they appear as T_WORM if the
- * drive is empty, or a CD-R medium is in the drive, and they
- * announce theirselves as T_READONLY if a CD-ROM (or fixated
- * CD-R) is there. We need both entries here, so the worm_mode
- * hook will be properly filled in.
- */
- {
- T_READONLY, T_WORM, T_REMOV, "PLASMON", "RF41*", "*",
- "worm", SC_ONE_LU, 0, &worm_mode_plasmon
- },
- {
- T_WORM, T_WORM, T_REMOV, "PLASMON", "RF41*", "*",
- "worm", SC_ONE_LU, 0, &worm_mode_plasmon
- },
-#endif /* NWORM */
-#if NPT > 0
- /*
- * Some of the Epson scanners erroneously respond to more than
- * one LUN.
- */
- {
- T_PROCESSOR, T_PROCESSOR, T_FIXED, "EPSON SC", "*", "*",
- "pt", SC_ONE_LU
- },
-#endif /* NPT */
-
- /*
- * Wildcard entries. Keep them down here below all device
- * specific entries, so the above ones can override the type
- * driver if necessary.
- */
-#if NOD > 0
- {
- T_OPTICAL, T_OPTICAL, T_REMOV, "*", "*", "*",
- "od", SC_ONE_LU
- },
-#endif /* NOD */
-#if NSD > 0
- {
- T_DIRECT, T_DIRECT, T_FIXED, "HP", "C372*", "*",
- "sd", SC_ONE_LU, SD_Q_NO_TAGS
- },
- {
- T_DIRECT, T_DIRECT, T_REMOV, "iomega", "jaz*", "*",
- "sd", SC_ONE_LU, SD_Q_NO_TAGS
- },
- {
- T_DIRECT, T_DIRECT, T_FIXED, "*", "*", "*",
- "sd", SC_ONE_LU
- },
- {
- T_DIRECT, T_DIRECT, T_REMOV, "*", "*", "*",
- "sd", SC_ONE_LU
- },
-#endif /* NSD */
-#if NST > 0
- {
- T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "*", "*", "*",
- "st", SC_ONE_LU, 0, mode_unktape
- },
-#endif /* NST */
-#if NCH > 0
- /*
- * Due to the way media changers are working, they are most
- * likely always on a different LUN than the transfer element
- * device. Thus, it should be safe to always probe all LUNs
- * on them.
- */
- {
- T_CHANGER, T_CHANGER, T_REMOV, "*", "*", "*",
- "ch", SC_MORE_LUS
- },
-#endif /* NCH */
-#if NCD > 0 && !defined(UKTEST)
- {
- T_READONLY, T_READONLY, T_REMOV, "*", "*", "*",
- "cd", SC_ONE_LU
- },
-#endif /* NCD */
-#if NWORM > 0
- {
- T_WORM, T_WORM, T_REMOV, "*", "*", "*",
- "worm", SC_ONE_LU
- },
-#endif /* NWORM */
- {
- 0
- }
-};
-
-/*
- * Declarations
- */
-static struct scsidevs *scsi_probedev __P((struct scsi_link *sc_link,
- boolean *maybe_more, int *type_p));
-static struct scsidevs *scsi_selectdev __P((u_int32_t qualifier, u_int32_t type,
- boolean remov, char *manu, char *model,
- char *rev));
-
-/* XXX dufault@hda.com
- * This scsi_device doesn't have the scsi_data_size.
- * This is used during probe.
- */
-static struct scsi_device probe_switch =
-{
- NULL,
- NULL,
- NULL,
- NULL,
- "probe",
-};
-
-static int free_bus; /* First bus not wired down */
-
-static struct scsi_device *device_list;
-static int next_free_type = T_NTYPES;
-
-/* Register new functions at the head of the list. That allows
- * you to replace a standard driver with a new one.
- *
- * You can't register the exact device (the same in memory structure)
- * more than once - the list links are part of the structure. That is
- * prevented.
- *
- * Custom devices should always be registered as type "-1". Then
- * the next available type number will be allocated for it.
- *
- * Be careful not to register a type as 0 unless you really mean to
- * replace the disk driver.
- *
- * This is usually called only by the "device_init" function generated
- * automatically in the SCSI_DEVICE_ENTRIES macro.
- */
-
-void
-scsi_device_register(struct scsi_device *sd)
-{
- /* Not only is it pointless to add the same device more than once
- * but it will also screw up the list.
- */
- struct scsi_device *is_there;
- for (is_there = device_list; is_there; is_there = is_there->next)
- if (is_there == sd)
- return;
-
- if (sd->type == -1)
- sd->type = next_free_type++;
-
- sd->next = device_list;
- device_list = sd;
-
- if (sd->links == 0)
- sd->links = extend_new();
-}
-
-static struct scsi_device *
-scsi_device_lookup(int type)
-{
- struct scsi_device *sd;
-
- for (sd = device_list; sd; sd = sd->next)
- if (sd->type == type)
- return sd;
-
- return &uk_switch;
-}
-
-static struct scsi_device *
-scsi_device_lookup_by_name(char *name)
-{
- struct scsi_device *sd;
-
- for (sd = device_list; sd; sd = sd->next)
- if (strcmp(sd->name, name) == 0)
- return sd;
-
- return &uk_switch;
-}
-
-/* Macro that lets us know something is specified.
- */
-#define IS_SPECIFIED(ARG) (ARG != SCCONF_UNSPEC && ARG != SCCONF_ANY)
-
-/* scsi_init: Do all the one time processing. This initializes the
- * type drivers and initializes the configuration.
- */
-static void
-scsi_init(void)
-{
- static int done = 0;
- if(!done) {
- int i;
-
- done = 1;
-
- scbusses = extend_new();
-
- /* First call all type initialization functions.
- */
- ukinit(); /* We always have the unknown device. */
-
- for (i = 0; scsi_tinit[i]; i++)
- (*scsi_tinit[i])();
-
- /* Lowest free bus for auto-configure is one
- * more than the first one not
- * specified in config:
- */
- for (i = 0; scsi_cinit[i].driver; i++)
- if (IS_SPECIFIED(scsi_cinit[i].scbus) &&
- free_bus <= scsi_cinit[i].scbus)
- free_bus = scsi_cinit[i].scbus + 1;
-
- /* Lowest free unit for each type for auto-configure is one
- * more than the first one not specified in the config file:
- */
- for (i = 0; scsi_dinit[i].name; i++) {
- struct scsi_device_config *sdc = scsi_dinit + i;
- struct scsi_device *sd =
- scsi_device_lookup_by_name(sdc->name);
-
- /* This is a little tricky: We don't want "sd 4" to match as
- * a wired down device, but we do want "sd 4 target 5" or
- * even "sd 4 scbus 1" to match.
- */
- if (IS_SPECIFIED(sdc->unit) &&
- (IS_SPECIFIED(sdc->target) || IS_SPECIFIED(sdc->cunit)) &&
- sd->free_unit <= sdc->unit)
- sd->free_unit = sdc->unit + 1;
- }
- }
-}
-
-/* scsi_bus_conf: Figure out which bus this is. If it is wired in config
- * use that. Otherwise use the next free one.
- */
-static int
-scsi_bus_conf(sc_link_proto)
- struct scsi_link *sc_link_proto;
-{
- int i;
- int bus;
-
- /* Which bus is this? Try to find a match in the "scsi_cinit"
- * table. If it isn't wired down auto-configure it at the
- * next available bus.
- */
-
- bus = SCCONF_UNSPEC;
- for (i = 0; scsi_cinit[i].driver; i++) {
- if (IS_SPECIFIED(scsi_cinit[i].scbus))
- {
- if (!strcmp(sc_link_proto->adapter->name, scsi_cinit[i].driver)
- &&(sc_link_proto->adapter_unit == scsi_cinit[i].unit))
- {
- if (IS_SPECIFIED(scsi_cinit[i].bus)) {
- if (sc_link_proto->adapter_bus==scsi_cinit[i].bus){
- bus = scsi_cinit[i].scbus;
- break;
- }
- }
- else if (sc_link_proto->adapter_bus == 0) {
- /* Backwards compatibility for single bus cards */
- bus = scsi_cinit[i].scbus;
- break;
- }
- else {
- printf("Ambiguous scbus configuration for %s%d "
- "bus %d, cannot wire down. The kernel "
- "config entry for scbus%d should specify "
- "a controller bus.\n"
- "Scbus will be assigned dynamically.\n",
- sc_link_proto->adapter->name,
- sc_link_proto->adapter_unit,
- sc_link_proto->adapter_bus,
- sc_link_proto->adapter_bus );
- break;
- }
- }
- }
- }
-
-
- if (bus == SCCONF_UNSPEC)
- bus = free_bus++;
- else if (bootverbose)
- printf("Choosing drivers for scbus configured at %d\n", bus);
-
- return bus;
-}
-
-/* scsi_assign_unit: Look through the structure generated by config.
- * See if there is a fixed assignment for this unit. If there isn't,
- * assign the next free unit.
- */
-static int
-scsi_assign_unit(struct scsi_link *sc_link)
-{
- int i;
- int found;
-#ifdef PC98
- struct cfdata cf;
- cf.cf_flags = 0;
-#endif
-
- found = 0;
- for (i = 0; scsi_dinit[i].name; i++) {
- if ((strcmp(sc_link->device->name, scsi_dinit[i].name) == 0) &&
- sc_link->target == scsi_dinit[i].target &&
- (
- (sc_link->lun == scsi_dinit[i].lun) ||
- (sc_link->lun == 0 && scsi_dinit[i].lun == SCCONF_UNSPEC)
- ) &&
- sc_link->scsibus == scsi_dinit[i].cunit) {
- sc_link->dev_unit = scsi_dinit[i].unit;
- found = 1;
-#ifdef PC98
- cf.cf_flags = scsi_dinit[i].flags;
-#endif
- if (bootverbose)
- printf("%s is configured at %d\n",
- sc_link->device->name, sc_link->dev_unit);
- break;
- }
- }
-
- if (!found)
- sc_link->dev_unit = sc_link->device->free_unit++;
-
-#ifdef PC98
- if (!found) {
- for (i = 0; scsi_dinit[i].name; i++) {
- if ((strcmp(sc_link->device->name, scsi_dinit[i].name) == 0) &&
- (scsi_dinit[i].target == SCCONF_UNSPEC))
- cf.cf_flags = scsi_dinit[i].flags;
- }
- }
- if (sc_link->adapter->open_target_lu)
- (*(sc_link->adapter->open_target_lu))(sc_link, &cf);
-#endif
-
- return sc_link->dev_unit;
-}
-
-
-#if NSCTARG > 0
-/* The SCSI target configuration is simpler. If an entry is present
- * we just return the bus, target and lun for that unit.
- */
-static void
-scsi_sctarg_lookup(char *name, int unit, int *target, int *lun, int *bus)
-{
- int i;
-
- *bus = SCCONF_UNSPEC;
- *target = SCCONF_UNSPEC;
- *lun = SCCONF_UNSPEC;
-
- for (i = 0; scsi_dinit[i].name; i++) {
- if ((strcmp(name, scsi_dinit[i].name) == 0) &&
- unit == scsi_dinit[i].unit)
- {
- *bus = scsi_dinit[i].cunit;
- *target = scsi_dinit[i].target;
- *lun = scsi_dinit[i].lun;
- }
- }
-}
-#endif /* NSCTARG > 0 */
-
-void
-scsi_configure_start(void)
-{
- scsi_init();
-}
-
-#if NSCTARG > 0
-static errval scsi_attach_sctarg __P((void));
-#endif
-
-void
-scsi_configure_finish(void)
-{
-
-#if NSCTARG > 0
- scsi_attach_sctarg();
-#endif
-
-}
-
-/*
- * scsi_attachdevs is the routine called by the adapter boards
- * to get all their devices configured in.
- */
-void
-scsi_attachdevs(scbus)
- struct scsibus_data *scbus;
-{
- int scsibus;
- struct scsi_link *sc_link_proto = scbus->adapter_link;
-
- if ( (scsibus = scsi_bus_conf(sc_link_proto)) == -1) {
- return;
- }
- /*
- * if the adapter didn't give us this, set a default
- * (compatibility with old adapter drivers)
- */
- if(!(sc_link_proto->opennings)) {
- sc_link_proto->opennings = 1;
- }
- sc_link_proto->scsibus = scsibus;
- /*
- * Allocate our target-lun space.
- */
- scbus->sc_link = (struct scsi_link *(*)[][8])malloc(
- sizeof(struct scsi_link *[scbus->maxtarg + 1][8]),
- M_TEMP, M_NOWAIT);
- if(scbus == 0 || scbus->sc_link == 0
- || extend_set(scbusses, scsibus, scbus) == 0) {
- panic("scsi_attachdevs: malloc");
- }
- bzero(scbus->sc_link, sizeof(struct scsi_link*[scbus->maxtarg + 1][8]));
-#if defined(SCSI_DELAY) && SCSI_DELAY > 2
- printf("%s%d: waiting for scsi devices to settle\n",
- sc_link_proto->adapter->name, sc_link_proto->adapter_unit);
-#else /* SCSI_DELAY > 2 */
-#undef SCSI_DELAY
-#define SCSI_DELAY 2
-#endif /* SCSI_DELAY */
- DELAY(1000000 * SCSI_DELAY);
- scsi_probe_bus(scsibus,-1,-1);
-}
-
-/*
- * Probe the requested scsi bus. It must be already set up.
- * -1 requests all set up scsi busses.
- * targ and lun optionally narrow the search if not -1
- */
-errval
-scsi_probe_busses(int bus, int targ, int lun)
-{
- if (bus == -1) {
- for(bus = 0; bus < scbusses->nelem; bus++) {
- scsi_probe_bus(bus, targ, lun);
- }
- return 0;
- } else {
- return scsi_probe_bus(bus, targ, lun);
- }
-}
-
-/* scsi_alloc_unit: Register a scsi_data pointer for a given
- * unit in a given scsi_device structure.
- *
- * XXX dufault@hda.com: I still don't like the way this reallocs stuff -
- * but at least now it is collected in one place instead of existing
- * in multiple type drivers. I'd like it better if we had it do a
- * second pass after it knew the sizes of everything and set up everything
- * at once.
- */
-static int
-scsi_alloc_unit(struct scsi_link *sc_link)
-{
- u_int32_t unit;
- struct scsi_data *sd;
- struct scsi_device *dsw;
-
- unit = sc_link->dev_unit;
- dsw = sc_link->device;
-
- /*
- * allocate the per unit data area
- */
- if (dsw->sizeof_scsi_data)
- {
- sd = malloc(dsw->sizeof_scsi_data, M_DEVBUF, M_NOWAIT);
- if (!sd) {
- printf("%s%lu: malloc failed for scsi_data\n",
- sc_link->device->name, (u_long)unit);
- return 0;
- }
- bzero(sd, dsw->sizeof_scsi_data);
- }
- else
- sd = 0;
-
- sc_link->sd = sd;
-
- if (extend_set(dsw->links, unit, (void *)sc_link) == 0) {
- printf("%s%lu: Can't store link pointer.\n",
- sc_link->device->name, (u_long)unit);
- free(sd, M_DEVBUF);
- return 0;
- }
-
- return 1;
-}
-
-static void
-scsi_free_unit(struct scsi_link *sc_link)
-{
- if (sc_link->sd)
- {
- free(sc_link->sd, M_DEVBUF);
- sc_link->sd = 0;
- }
- extend_release(sc_link->device->links, sc_link->dev_unit);
-}
-
-#if NSCTARG > 0
-
-/* XXX: It is a bug that the sc_link has this information
- * about the adapter in it. The sc_link should refer to
- * a structure that is host adpater specific. That will also
- * pull all knowledge of an sc_link out of the adapter drivers.
- */
-
-errval
-scsi_set_bus(int bus, struct scsi_link *sc_link)
-{
- struct scsi_link *ad_link;
- struct scsibus_data *scsibus_data;
-
- if (bus < 0 || bus > scbusses->nelem) {
- return ENXIO;
- }
-
- scsibus_data = (struct scsibus_data *)extend_get(scbusses, bus);
-
- if(!scsibus_data) {
- return ENXIO;
- }
-
- ad_link = scsibus_data->adapter_link;
-
- sc_link->adapter_unit = ad_link->adapter_unit;
- sc_link->adapter_targ = ad_link->adapter_targ;
- sc_link->adapter = ad_link->adapter;
- sc_link->device = ad_link->device;
- sc_link->flags = ad_link->flags;
-
- return 0;
-}
-
-/*
- * Allocate and attach as many SCSI target devices as configured.
- * There are two ways that you can configure the target device:
- * 1. In the configuration file. That is handled here.
- * 2. Via the minor number. That takes precedence over the config file.
- */
-static errval
-scsi_attach_sctarg()
-{
- struct scsi_link *sc_link = NULL;
- int dev_unit;
- struct scsi_device *sctarg = scsi_device_lookup(T_TARGET);
-
- if (sctarg == 0) {
- return ENXIO;
- }
-
- for (dev_unit = 0; dev_unit < NSCTARG; dev_unit++) {
-
- int target, lun, bus;
-
- /* If we don't have a link block allocate one.
- */
- if (!sc_link) {
- sc_link = malloc(sizeof(*sc_link), M_TEMP, M_NOWAIT);
- }
-
- scsi_sctarg_lookup(sctarg->name, dev_unit, &target, &lun, &bus);
-
- if (IS_SPECIFIED(bus)) {
- struct scsibus_data *scsibus_data;
-
- if (bus < 0 || bus > scbusses->nelem) {
- printf("%s%d: configured on illegal bus %d.\n",
- sctarg->name, dev_unit, bus);
- continue;
- }
-
- scsibus_data = (struct scsibus_data *)extend_get(scbusses, bus);
-
- if(!scsibus_data) {
- printf("%s%d: no bus %d.\n", sctarg->name, dev_unit, bus);
- continue;
- }
-
- *sc_link = *scsibus_data->adapter_link; /* struct copy */
- sc_link->target = target;
- sc_link->lun = lun;
- }
- else {
- /* This will be configured in the open routine.
- */
- sc_link->scsibus = SCCONF_UNSPEC;
- sc_link->target = SCCONF_UNSPEC;
- sc_link->lun = SCCONF_UNSPEC;
- }
-
- sc_link->quirks = 0;
- sc_link->device = sctarg;
- sc_link->dev_unit = dev_unit;
-
- if (scsi_alloc_unit(sc_link)) {
-
- if (scsi_device_attach(sc_link) == 0) {
- sc_link = NULL; /* it's been used */
- }
- else
- scsi_free_unit(sc_link);
- }
- }
-
- if (sc_link) {
- free(sc_link, M_TEMP);
- }
-
- return 0;
-}
-#endif /* NSCTARG > 0 */
-
-/*
- * Allocate a scsibus_data structure
- * The target/lun area is dynamically allocated in scsi_attachdevs after
- * the controller driver has a chance to update the maxtarg field.
- */
-struct scsibus_data*
-scsi_alloc_bus()
-{
- struct scsibus_data *scbus;
- /*
- * Prepare the scsibus_data area for the upperlevel
- * scsi code.
- */
- scbus = malloc(sizeof(struct scsibus_data), M_TEMP, M_NOWAIT);
- if(!scbus) {
- printf("scsi_alloc_bus: - cannot malloc!\n");
- return NULL;
- }
- bzero(scbus, sizeof(struct scsibus_data));
- /* Setup the defaults */
- scbus->maxtarg = 7;
- scbus->maxlun = 7;
- return scbus;
-}
-
-/*
- * Probe the requested scsi bus. It must be already set up.
- * targ and lun optionally narrow the search if not -1
- */
-errval
-scsi_probe_bus(int bus, int targ, int lun)
-{
- struct scsibus_data *scsibus_data ;
- int maxtarg,mintarg,maxlun,minlun;
- struct scsi_link *sc_link_proto;
- u_int8_t scsi_addr ;
- struct scsidevs *bestmatch = NULL;
- struct scsi_link *sc_link = NULL;
- boolean maybe_more;
- int type;
-
- if ((bus < 0 ) || ( bus >= scbusses->nelem)) {
- return ENXIO;
- }
- scsibus_data = (struct scsibus_data *)extend_get(scbusses, bus);
- if(!scsibus_data) return ENXIO;
- sc_link_proto = scsibus_data->adapter_link;
- scsi_addr = sc_link_proto->adapter_targ;
- if(targ == -1){
- maxtarg = scsibus_data->maxtarg;
- mintarg = 0;
- } else {
- if((targ < 0 ) || (targ > scsibus_data->maxtarg)) return EINVAL;
- maxtarg = mintarg = targ;
- }
-
- if(lun == -1){
- maxlun = scsibus_data->maxlun;
- minlun = 0;
- } else {
- if((lun < 0 ) || (lun > scsibus_data->maxlun)) return EINVAL;
- maxlun = minlun = lun;
- }
-
- printf("scbus%d at %s%d bus %d\n",
- sc_link_proto->scsibus, sc_link_proto->adapter->name,
- sc_link_proto->adapter_unit, sc_link_proto->adapter_bus);
-
- for ( targ = mintarg;targ <= maxtarg; targ++) {
- maybe_more = 0; /* by default only check 1 lun */
- if (targ == scsi_addr) {
- continue;
- }
- for ( lun = minlun; lun <= maxlun ;lun++) {
- /*
- * The spot appears to already have something
- * linked in, skip past it. Must be doing a 'reprobe'
- */
- if((*scsibus_data->sc_link)[targ][lun])
- {/* don't do this one, but check other luns */
- maybe_more = 1;
- continue;
- }
- /*
- * If we presently don't have a link block
- * then allocate one to use while probing
- */
- if (!sc_link) {
- sc_link = malloc(sizeof(*sc_link), M_TEMP, M_NOWAIT);
- }
- *sc_link = *sc_link_proto; /* struct copy */
- sc_link->device = &probe_switch;
- sc_link->target = targ;
- sc_link->lun = lun;
- sc_link->quirks = 0;
- bestmatch = scsi_probedev(sc_link, &maybe_more, &type);
- if (bestmatch) {
- sc_link->quirks = bestmatch->quirks;
- sc_link->devmodes = bestmatch->devmodes;
- } else {
- sc_link->quirks = 0;
- sc_link->devmodes = NULL;
- }
- if (bestmatch) { /* FOUND */
- sc_link->device = scsi_device_lookup(type);
-
- (void)scsi_assign_unit(sc_link);
-
- if (scsi_alloc_unit(sc_link)) {
-
- if (scsi_device_attach(sc_link) == 0) {
- (*scsibus_data->sc_link)[targ][lun] = sc_link;
- sc_link = NULL; /* it's been used */
- }
- else
- scsi_free_unit(sc_link);
- }
- }
-
- if (!(maybe_more)) { /* nothing suggests we'll find more */
- break; /* nothing here, skip to next targ */
- }
- /* otherwise something says we should look further */
- }
- }
- if (sc_link) {
- free(sc_link, M_TEMP);
- }
- return 0;
-}
-
-/* Return the scsi_link for this device, if any.
- */
-struct scsi_link *
-scsi_link_get(bus, targ, lun)
- int bus;
- int targ;
- int lun;
-{
- struct scsibus_data *scsibus_data =
- (struct scsibus_data *)extend_get(scbusses, bus);
- return (scsibus_data) ? (*scsibus_data->sc_link)[targ][lun] : 0;
-}
-
-/* make_readable: Make the inquiry data readable. Anything less than a ' '
- * is made a '?' and trailing spaces are removed.
- */
-static void
-make_readable(to, from, n)
- char *to;
- char *from;
- size_t n;
-{
- int i;
-
- for (i = 0; from[i] && i < n - 1; i++) {
- if (from[i] < ' ')
- to[i]='?';
- else
- to[i] = from[i];
- }
-
- while (i && to[i - 1] == ' ')
- i--;
-
- to[i] = 0;
-}
-
-#ifndef SCSIDEBUG
-void scsi_print_info(sc_link)
- struct scsi_link *sc_link;
-{
- int dtype = 0;
- char *desc;
- char *qtype;
- struct scsi_inquiry_data *inqbuf;
- u_int32_t len, qualifier, type;
- boolean remov;
- char manu[8 + 1];
- char model[16 + 1];
- char version[4 + 1];
-
- inqbuf = &sc_link->inqbuf;
-
- type = inqbuf->device & SID_TYPE;
- qualifier = inqbuf->device & SID_QUAL;
- remov = inqbuf->dev_qual2 & SID_REMOVABLE;
-
- switch ((int)qualifier) {
- case SID_QUAL_LU_OK:
- qtype = "";
- break;
-
- case SID_QUAL_LU_OFFLINE:
- qtype = "Supported device currently not connected";
- break;
-
- default:
- dtype = 1;
- qtype = "Vendor specific peripheral qualifier";
- break;
- }
-
- if ((inqbuf->version & SID_ANSII) > 0) {
- if ((len = inqbuf->additional_length
- + ((char *) inqbuf->unused
- - (char *) inqbuf))
- > (sizeof(struct scsi_inquiry_data) - 1))
- len = sizeof(struct scsi_inquiry_data) - 1;
- desc = inqbuf->vendor;
- desc[len - (desc - (char *) inqbuf)] = 0;
- make_readable(manu, inqbuf->vendor, sizeof(manu));
- make_readable(model, inqbuf->product, sizeof(model));
- make_readable(version, inqbuf->revision, sizeof(version));
- } else {
- /*
- * If not advanced enough, use default values
- */
- desc = "early protocol device";
- make_readable(manu, "unknown", sizeof(manu));
- make_readable(model, "unknown", sizeof(model));
- make_readable(version, "????", sizeof(version));
- }
-
- printf("%s%d: ", sc_link->device->name,
- sc_link->dev_unit);
- printf("<%s %s %s> ", manu, model, version );
- printf("type %lu %sSCSI %d",
- (u_long)type, remov ? "removable " : "fixed ",
- inqbuf->version & SID_ANSII);
- if (qtype[0]) {
- sc_print_addr(sc_link);
- printf(" qualifier %lu: %s", (u_long)qualifier, qtype);
- }
-
- printf("\n");
-}
-#endif
-
-/*
- * given a target and lu, ask the device what
- * it is, and find the correct driver table
- * entry.
- */
-static struct scsidevs *
-scsi_probedev(sc_link, maybe_more, type_p)
- boolean *maybe_more;
- struct scsi_link *sc_link;
- int *type_p;
-{
-#ifdef SCSIDEBUG
- u_int8_t target = sc_link->target;
- u_int8_t lu = sc_link->lun;
-#endif
- struct scsidevs *bestmatch = (struct scsidevs *) 0;
- int dtype = 0;
- char *desc;
- char *qtype;
- struct scsi_inquiry_data *inqbuf;
- u_int32_t len, qualifier, type;
- boolean remov;
- char manu[8 + 1];
- char model[16 + 1];
- char version[4 + 1];
-
- inqbuf = &sc_link->inqbuf;
-
- bzero(inqbuf, sizeof(*inqbuf));
- /*
- * Ask the device what it is
- */
-#ifdef SCSIDEBUG
- if ((target == DEBUGTARG) && (lu == DEBUGLUN))
- sc_link->flags |= (DEBUGLEVEL);
- else
- sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2 | SDEV_DB3 | SDEV_DB4);
-#endif /* SCSIDEBUG */
- /* catch unit attn */
- scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
-#ifdef DOUBTFULL
- switch (scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT)) {
- case 0: /* said it WAS ready */
- case EBUSY: /* replied 'NOT READY' but WAS present, continue */
- case ENXIO:
- break;
- case EIO: /* device timed out */
- case EINVAL: /* Lun not supported */
- default:
- return (struct scsidevs *) 0;
-
- }
-#endif /*DOUBTFULL*/
-#ifdef SCSI_2_DEF
- /* some devices need to be told to go to SCSI2 */
- /* However some just explode if you tell them this.. leave it out */
- scsi_change_def(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
-#endif /*SCSI_2_DEF */
-
- /* Now go ask the device all about itself */
- if (scsi_inquire(sc_link, inqbuf, SCSI_NOSLEEP | SCSI_NOMASK) != 0) {
- return (struct scsidevs *) 0;
- }
-
- /*
- * note what BASIC type of device it is
- */
- type = inqbuf->device & SID_TYPE;
- qualifier = inqbuf->device & SID_QUAL;
- remov = inqbuf->dev_qual2 & SID_REMOVABLE;
-
- /*
- * Any device qualifier that has the top bit set (qualifier&4 != 0)
- * is vendor specific and will match in the default of this switch.
- */
-
- switch ((int)qualifier) {
- case SID_QUAL_LU_OK:
- qtype = "";
- break;
-
- case SID_QUAL_LU_OFFLINE:
- qtype = "Supported device currently not connected";
- break;
-
- case SID_QUAL_RSVD: /* Peripheral qualifier reserved in SCSI-2 spec */
- *maybe_more = 1;
- return (struct scsidevs *) 0;
-
- case SID_QUAL_BAD_LU: /* Target can not support a device on this unit */
- /*
- * Check for a non-existent unit. If the device is returning
- * this much, then we must set the flag that has
- * the searchers keep looking on other luns.
- */
- *maybe_more = 1;
- return (struct scsidevs *) 0;
-
- default:
- dtype = 1;
- qtype = "Vendor specific peripheral qualifier";
- *maybe_more = 1;
- break;
- }
-
- if (dtype == 0) {
- if (type == T_NODEVICE) {
- *maybe_more = 1;
- return (struct scsidevs *) 0;
- }
- dtype = 1;
- }
- /*
- * Then if it's advanced enough, more detailed
- * information
- */
- if ((inqbuf->version & SID_ANSII) > 0) {
- if ((len = inqbuf->additional_length
- + ((char *) inqbuf->unused
- - (char *) inqbuf))
- > (sizeof(struct scsi_inquiry_data) - 1))
- len = sizeof(struct scsi_inquiry_data) - 1;
- desc = inqbuf->vendor;
- desc[len - (desc - (char *) inqbuf)] = 0;
- make_readable(manu, inqbuf->vendor, sizeof(manu));
- make_readable(model, inqbuf->product, sizeof(model));
- make_readable(version, inqbuf->revision, sizeof(version));
- } else {
- /*
- * If not advanced enough, use default values
- */
- desc = "early protocol device";
- make_readable(manu, "unknown", sizeof(manu));
- make_readable(model, "unknown", sizeof(model));
- make_readable(version, "????", sizeof(version));
- type = T_UNKNOWN;
- }
-
-#ifdef SCSIDEBUG
- sc_print_start(sc_link);
-
- printf("<%s %s %s> ", manu, model, version );
- printf("type %lu %sSCSI %d"
- ,(u_long)type
- ,remov ? "removable " : "fixed "
- ,inqbuf->version & SID_ANSII
- );
- if (qtype[0]) {
- sc_print_addr(sc_link);
- printf(" qualifier %lu: %s", (u_long)qualifier, qtype);
- }
-
- printf("\n");
- sc_print_finish();
-#endif
- /*
- * Try make as good a match as possible with
- * available sub drivers
- */
- bestmatch = (scsi_selectdev(
- qualifier, type, remov ? T_REMOV : T_FIXED, manu, model, version));
- if ((bestmatch) && (bestmatch->flags & SC_MORE_LUS)) {
- *maybe_more = 1;
- }
-
- /* If the device is unknown then we should be trying to look up a
- * type driver based on the inquiry type.
- */
- if (bestmatch == &unknowndev)
- *type_p = type;
- else
- *type_p =
- bestmatch->driver;
- return bestmatch;
-}
-
-/* Try to find the major number for a device during attach.
- */
-dev_t
-scsi_dev_lookup(d_open)
- d_open_t *d_open;
-{
- int i;
-
- dev_t d = NODEV;
-
- for (i = 0; i < nchrdev; i++)
- if (cdevsw[i] && cdevsw[i]->d_open == d_open)
- {
- d = makedev(i, 0);
- break;
- }
-
- return d;
-}
-
-/*
- * Compare name with pattern, return 0 on match.
- * Short pattern matches trailing blanks in name,
- * wildcard '*' in pattern matches rest of name
- */
-static int
-match(pattern, name)
- char *pattern;
- char *name;
-{
- char c;
- while (c = *pattern++)
- {
- if (c == '*') return 0;
- if ((c == '?') && (*name > ' ')) continue;
- if (c != *name++) return 1;
- }
- while (c = *name++)
- {
- if (c != ' ') return 1;
- }
- return 0;
-}
-
-/*
- * Try make as good a match as possible with
- * available sub drivers
- */
-static struct scsidevs *
-scsi_selectdev(qualifier, type, remov, manu, model, rev)
- u_int32_t qualifier, type;
- boolean remov;
- char *manu, *model, *rev;
-{
- struct scsidevs *bestmatch = NULL;
- struct scsidevs *thisentry;
-
- type |= qualifier; /* why? */
-
- for ( thisentry = knowndevs; thisentry->manufacturer; thisentry++ )
- {
- if (type != thisentry->type) {
- continue;
- }
- if (remov != thisentry->removable) {
- continue;
- }
-
- if (thisentry->flags & SC_SHOWME)
- printf("\n%s-\n%s-", thisentry->manufacturer, manu);
- if (match(thisentry->manufacturer, manu)) {
- continue;
- }
- if (thisentry->flags & SC_SHOWME)
- printf("\n%s-\n%s-", thisentry->model, model);
- if (match(thisentry->model, model)) {
- continue;
- }
- if (thisentry->flags & SC_SHOWME)
- printf("\n%s-\n%s-", thisentry->version, rev);
- if (match(thisentry->version, rev)) {
- continue;
- }
- bestmatch = thisentry;
- break;
- }
- if (bestmatch == (struct scsidevs *) 0) {
- bestmatch = &unknowndev;
- }
- return (bestmatch);
-}
diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h
deleted file mode 100644
index 6961077..0000000
--- a/sys/scsi/scsiconf.h
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- * Written by Julian Elischer (julian@tfs.com)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- *
- * $Id: scsiconf.h,v 1.60 1998/05/24 04:52:31 julian Exp $
- */
-#ifndef SCSI_SCSICONF_H
-#define SCSI_SCSICONF_H 1
-typedef int boolean;
-typedef int errval;
-
-#include <scsi/scsi_all.h>
-#include <sys/callout.h> /* XXX For ioconf.c */
-
-/*
- * The following documentation tries to describe the relationship between the
- * various structures defined in this file:
- *
- * each adapter type has a scsi_adapter struct. This describes the adapter and
- * identifies routines that can be called to use the adapter.
- * each device type has a scsi_device struct. This describes the device and
- * identifies routines that can be called to use the device.
- * each existing device position (scsibus + target + lun)
- * can be described by a scsi_link struct.
- * Only scsi positions that actually have devices, have a scsi_link
- * structure assigned. so in effect each device has scsi_link struct.
- * The scsi_link structure contains information identifying both the
- * device driver and the adapter driver for that position on that scsi bus,
- * and can be said to 'link' the two.
- * each individual scsi bus has an array that points to all the scsi_link
- * structs associated with that scsi bus. Slots with no device have
- * a NULL pointer.
- * each individual device also knows the address of its own scsi_link
- * structure.
- *
- * -------------
- *
- * The key to all this is the scsi_link structure which associates all the
- * other structures with each other in the correct configuration. The
- * scsi_link is the connecting information that allows each part of the
- * scsi system to find the associated other parts.
- */
-
-struct buf;
-struct scsi_xfer;
-#ifdef PC98
-struct cfdata;
-#endif
-
-/* Don't poke around inside of "scsi_data". Each low level
- * driver has its own definition for it.
- */
-struct scsi_data;
-struct scsi_link; /* scsi_link refers to scsi_device and vice-versa */
-
-struct proc;
-
-/*
- * These entrypoints are called by the high-end drivers to get services from
- * whatever low-end drivers they are attached to each adapter type has one of
- * these statically allocated.
- */
-struct scsi_adapter
-{
-/* 04*/ int32_t (*scsi_cmd) __P((struct scsi_xfer *xs));
-/* 08*/ void (*scsi_minphys) __P((struct buf *bp));
-#ifdef PC98
-/* 12*/ int32_t (*open_target_lu) __P((struct scsi_link *sc_link,
- struct cfdata *cf));
-#else
-/* 12*/ int32_t (*open_target_lu) __P((void));
-#endif
-/* 16*/ int32_t (*close_target_lu) __P((void));
-/* 20*/ u_int32_t (*adapter_info) __P((int unit)); /* see definitions below */
-/* 24*/ char *name; /* name of scsi bus controller */
-/* 32*/ u_long spare[2];
-};
-
-/*
- * return values for scsi_cmd()
- */
-#define SUCCESSFULLY_QUEUED 0
-#define TRY_AGAIN_LATER 1
-#define COMPLETE 2
-#define HAD_ERROR 3 /* do not use this, use COMPLETE */
-#define ESCAPE_NOT_SUPPORTED 4
-
-/*
- * Return value from sense handler. IMHO, These ought to be merged
- * in with the return codes above, all made negative to distinguish
- * from valid errno values, and replace "try again later" with "do retry"
- */
-#define SCSIRET_CONTINUE -1 /* Continue with standard sense processing */
-#define SCSIRET_DO_RETRY -2 /* Retry the command that got this sense */
-
-/*
- * Format of adapter_info() response data
- * e.g. maximum number of entries queuable to a device by the adapter
- */
-
-/*
- * These entry points are called by the low-end drivers to get services from
- * whatever high-end drivers they are attached to. Each device type has one
- * of these statically allocated.
- *
- * XXX dufault@hda.com: Each adapter driver has a scsi_device structure
- * that I don't think should be there.
- * This structure should be rearranged and cleaned up once the
- * instance down in the adapter drivers is removed.
- */
-
-/*
- * XXX this is so that everything that includes this bloated header doesn't
- * also need to include <sys/conf.h>.
- */
-typedef int yet_another_d_open_t __P((dev_t, int, int, struct proc *));
-
-struct scsi_device
-{
-/* 4*/ errval (*err_handler)(struct scsi_xfer *xs);
-/* 8*/ void (*start)(u_int32_t unit, u_int32_t flags);
-/* 12*/ int32_t (*async) __P((void));
-/* 16*/ int32_t (*done) __P((struct scsi_xfer *xs));
-/* 20*/ char *name; /* name of device type */
-/* 24*/ u_int32_t flags; /* device type dependent flags */
-/* 32*/ int32_t spare[2];
-/* 36*/ int32_t link_flags; /* set -> sc_link at attach time */
-/* 40*/ errval (*attach)(struct scsi_link *sc_link);
-/* 44*/ char *desc; /* Description of device */
-/* 48*/ yet_another_d_open_t *open;
-/* 52*/ int sizeof_scsi_data;
-/* 56*/ int type; /* Type of device this supports */
-/* 60*/ int (*getunit)(dev_t dev);
-/* 64*/ dev_t (*setunit)(dev_t dev, int unit);
-/* 68*/ int (*dev_open)(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-/* 72*/ int (*dev_ioctl)(dev_t dev, u_long cmd, caddr_t arg, int mode,
- struct proc *p, struct scsi_link *sc_link);
-/* 76*/ int (*dev_close)(dev_t dev, int flag, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-/* 80*/ void (*dev_strategy)(struct buf *bp, struct scsi_link *sc_link);
- /* Not initialized after this */
-/* 84*/ struct extend_array *links;
-/* 88*/ int free_unit;
-/* 92*/ struct scsi_device *next; /* Next in list in the registry. */
-};
-/*
- * Macros to access soem fields above.
- */
-#define SCSI_LINK(DEV, UNIT) \
- ((struct scsi_link *)(extend_get((DEV)->links, (UNIT))))
-
-#define SCSI_DATA(DEV, UNIT) \
- ((SCSI_LINK((DEV), (UNIT)) ? (SCSI_LINK((DEV), (UNIT))->sd) : NULL))
-
-/*
- * SCSI_DEVICE_ENTRIES: A macro to generate all the entry points from the
- * name.
- */
-#define SCSI_DEVICE_ENTRIES(NAME) \
-static errval NAME##attach(struct scsi_link *sc_link); \
-extern struct scsi_device NAME##_switch; /* XXX actually static */ \
-void NAME##init(void) { \
- scsi_device_register(&NAME##_switch); \
-} \
-static int NAME##open(dev_t dev, int flags, int fmt, struct proc *p) { \
- return scsi_open(dev, flags, fmt, p, &NAME##_switch); \
-} \
-static int NAME##ioctl(dev_t dev, u_long cmd, caddr_t addr, \
- int flag, struct proc *p) { \
- return scsi_ioctl(dev, cmd, addr, flag, p, &NAME##_switch); \
-} \
-static int NAME##close(dev_t dev, int flag, int fmt, struct proc *p) { \
- return scsi_close(dev, flag, fmt, p, &NAME##_switch); \
-} \
-static void NAME##minphys(struct buf *bp) { \
- scsi_minphys(bp, &NAME##_switch); \
-} \
-static void NAME##strategy(struct buf *bp) { \
- scsi_strategy(bp, &NAME##_switch); \
-}
-
-#ifdef KERNEL
-/* Configuration tables for config.
- */
-/* A unit, type, etc can be SCCONF_ANY to indicate it is a '?'
- * in the config.
- */
-#define SCCONF_UNSPEC 255
-#define SCCONF_ANY 254
-
-struct isa_driver;
-struct scsi_ctlr_config
-{
- int scbus;
- char *driver;
- int unit;
- int bus;
-};
-
-struct scsi_device_config
-{
- char *name; /* SCSI device name (sd, st, etc) */
- int unit; /* desired device unit */
- int cunit; /* Controller unit */
- int target; /* SCSI ID (target) */
- int lun; /* SCSI lun */
- int flags; /* Flags from config */
-};
-
-extern void (*scsi_tinit[])(void);
-extern struct scsi_ctlr_config scsi_cinit[];
-extern struct scsi_device_config scsi_dinit[];
-
-#endif
-
-/*
- * Define various devices that we know mis-behave in some way,
- * and note how they are bad, so we can correct for them
- */
-struct st_mode {
-/* 4*/ u_int32_t blksiz;
-/* 6*/ u_int16_t quirks; /* same definitions as in XXX */
-/* 7*/ u_int8_t density;
-/* 8*/ u_int8_t spare[1];
-};
-
-typedef struct st_mode st_modes[4];
-
-/* define behaviour codes (quirks) */
-/* common to all SCSI devices */
-#define SCSI_Q_NO_SYNC 0x8000
-#define SCSI_Q_NO_FAST 0x4000
-#define SCSI_Q_NO_WIDE 0x2000
-
-/* tape specific ST_Q_* */
-#define ST_Q_NEEDS_PAGE_0 0x0001
-#define ST_Q_FORCE_FIXED_MODE 0x0002
-#define ST_Q_FORCE_VAR_MODE 0x0004
-#define ST_Q_SNS_HLP 0x0008 /* must do READ for good MODE SENSE */
-#define ST_Q_IGNORE_LOADS 0x0010
-#define ST_Q_BLKSIZ 0x0020 /* variable-block media_blksiz > 0 */
-#define ST_Q_CC_NOMSG 0x0040 /* no messages accepted in CC state */
-#define ST_Q_NO_1024 0x0080 /* never ever use 1024-byte fix blk */
-
-#define ST_Q_NO_SYNC SCSI_Q_NO_SYNC
-#define ST_Q_NO_FAST SCSI_Q_NO_FAST
-#define ST_Q_NO_WIDE SCSI_Q_NO_WIDE
-
-/* disk specific SD_Q_* */
-#define SD_Q_NO_TAGS 0x0001
-
-#define SD_Q_NO_SYNC SCSI_Q_NO_SYNC
-#define SD_Q_NO_FAST SCSI_Q_NO_FAST
-#define SD_Q_NO_WIDE SCSI_Q_NO_WIDE
-
-/* cd specific CD_Q_* */
-#define CD_Q_NO_TOUCH 0x0001
-#define CD_Q_BCD_TRACKS 0x0002
-#define CD_Q_NO_START 0x0004
-
-
-/* worm specific WORM_Q_* */
-#define WORM_Q_PLASMON 0x0001
-#define WORM_Q_PHILIPS 0x0002
-/*
- * This structure describes the connection between an adapter driver and
- * a device driver, and is used by each to call services provided by
- * the other, and to allow generic scsi glue code to call these services
- * as well.
- */
-struct scsi_link
-{
- u_int8_t target; /* targ of this dev */
- u_int8_t lun; /* lun of this dev */
- u_int8_t adapter_targ; /* what are we on the scsi bus*/
- u_int8_t adapter_unit; /* e.g. the 0 in aha0 */
- u_int8_t adapter_bus; /* e.g. the 0 in bus0 */
- u_int8_t scsibus; /* the Nth scsibus */
- u_int8_t dev_unit; /* e.g. the 0 in sd0 */
- u_int8_t opennings; /* available operations */
- u_int8_t active; /* operations in progress */
- u_int16_t flags; /* flags all devices have */
- u_int16_t quirks; /* device specific quirks */
- struct scsi_adapter *adapter; /* adapter entry points etc. */
- struct scsi_device *device; /* device entry points etc. */
- struct scsi_xfer *active_xs; /* operations under way */
- void *fordriver; /* for driver's private user */
- void *devmodes; /* dev specific mode tables */
- dev_t dev; /* Device major # (character) */
- struct scsi_data *sd; /* Device data structure */
- struct scsi_inquiry_data inqbuf; /* Inquiry data */
- void *adapter_softc; /* to call foo_scsi_cmd */
-};
-
-/* XXX-HA: dufault@hda.com: SDEV_BOUNCE is set down in the adapter drivers
- * in an sc_link structure to indicate that this host adapter requires
- * ISA DMA bounce buffers. I think the link structure should
- * be associated only with the type drive and not the adapter driver,
- * and the bounce flag should be in something associated with the
- * adapter driver.
- * XXX-HA And I added the "supports residuals properly" flag that ALSO goes
- * in an adapter structure. I figure I'll fix both at once.
- *
- * XXX SDEV_OPEN is used for two things: To prevent more than one
- * open and to make unit attentions errors be logged on the console.
- * These should be split up; I'm adding SDEV_IS_OPEN to enforce one
- * open only.
- *
- * XXX SDEV_UK is used to mark the "uk" device.
- */
-
-#define SDEV_MEDIA_LOADED 0x0001 /* device figures are still valid */
-#define SDEV_WAITING 0x0002 /* a process is waiting for this */
-#define SDEV_OPEN 0x0004 /* at least 1 open session */
-#define SDEV_BOUNCE 0x0008 /* XXX-HA: unit needs DMA bounce buffer */
-#define SDEV_DBX 0x00F0 /* debugging flags (scsi_debug.h) */
-#define SDEV_ONCE_ONLY 0x0100 /* unit can only be opened once */
-#define SDEV_BOOTVERBOSE 0x0200 /* be noisy during boot */
-#define SDEV_RESIDS_WORK 0x0400 /* XXX-HA: Residuals work */
-#define SDEV_TARGET_OPS 0x0800 /* XXX-HA: Supports target ops */
-#define SDEV_IS_OPEN 0x1000 /* at least 1 open session */
-#define SDEV_UK 0x2000 /* this is the "uk" device */
-#define SDEV_XLOCK 0x4000 /* Device is locked */
-#define SDEV_WANT 0x8000 /* A process is waiting for lock */
-
-/*
- * One of these is allocated and filled in for each scsi bus.
- * it holds pointers to allow the scsi bus to get to the driver
- * That is running each LUN on the bus
- * it also has a template entry which is the prototype struct
- * supplied by the adapter driver, this is used to initialise
- * the others, before they have the rest of the fields filled in
- */
-struct scsibus_data {
- u_char maxtarg;
- u_char maxlun;
- struct scsi_link *adapter_link; /* prototype supplied by adapter */
- struct scsi_link *(*sc_link)[][8]; /* dynamically allocated */
-};
-
-/*
- * Each scsi transaction is fully described by one of these structures
- * It includes information about the source of the command and also the
- * device and adapter for which the command is destined.
- * (via the scsi_link structure) *
- */
-struct scsi_xfer
-{
-/*04*/ struct scsi_xfer *next; /* when free */
-/*08*/ u_int32_t flags;
-/*12*/ struct scsi_link *sc_link; /* all about our device and adapter */
-/*13*/ u_int8_t retries; /* the number of times to retry */
-/*16*/ u_int8_t spare[3];
-/*20*/ int32_t timeout; /* in milliseconds */
-/*24*/ struct scsi_generic *cmd; /* The scsi command to execute */
-/*28*/ int32_t cmdlen; /* how long it is */
-/*32*/ u_char *data; /* dma address OR a uio address */
-/*36*/ int32_t datalen; /* data len (blank if uio) */
-/*40*/ int32_t resid; /* how much buffer was not touched */
-/*44*/ int32_t error; /* an error value */
-/*48*/ struct buf *bp; /* If we need to associate with a buf */
-/*80*/ struct scsi_sense_data sense; /* 32 bytes*/
- /*
- * Believe it or not, Some targets fall on the ground with
- * anything but a certain sense length.
- */
-/*84*/ int32_t req_sense_length; /* Explicit request sense length */
-/*88*/ int32_t status; /* SCSI status */
-/*100*/ struct scsi_generic cmdstore; /* stash the command in here */
- /*
- * Handle for scheduling
- * command timeouts.
- */
- struct callout_handle timeout_ch;
-};
-
-/*
- * Per-request Flag values
- */
-#define SCSI_NOSLEEP 0x01 /* Not a user... don't sleep */
-#define SCSI_NOMASK 0x02 /* dont allow interrupts.. booting */
-#define SCSI_NOSTART 0x04 /* left over from ancient history */
-#define SCSI_USER 0x08 /* Is a user cmd, call scsi_user_done */
-#define SCSI_ITSDONE 0x10 /* the transfer is as done as it gets */
-#define ITSDONE 0x10 /* the transfer is as done as it gets */
-#define SCSI_INUSE 0x20 /* The scsi_xfer block is in use */
-#define INUSE 0x20 /* The scsi_xfer block is in use */
-#define SCSI_SILENT 0x40 /* Don't report errors to console */
-#define SCSI_ERR_OK 0x80 /* An error on this operation is OK. */
-#define SCSI_RESET 0x100 /* Reset the device in question */
-#define SCSI_DATA_UIO 0x200 /* The data address refers to a UIO */
-#define SCSI_DATA_IN 0x400 /* expect data to come INTO memory */
-#define SCSI_DATA_OUT 0x800 /* expect data to flow OUT of memory */
-#define SCSI_TARGET 0x1000 /* This defines a TARGET mode op. */
-#define SCSI_ESCAPE 0x2000 /* Escape operation */
-#define SCSI_EOF 0x4000 /* The operation should return EOF */
-#define SCSI_RESID_VALID 0x8000 /* The resid field contains valid data */
-
-/*
- * Escape op codes. This provides an extensible setup for operations
- * that are not scsi commands. They are intended for modal operations.
- */
-
-#define SCSI_OP_TARGET 0x0001
-#define SCSI_OP_RESET 0x0002
-#define SCSI_OP_BDINFO 0x0003
-
-/*
- * Error values an adapter driver may return
- */
-#define XS_NOERROR 0x0 /* there is no error, (sense is invalid) */
-#define XS_SENSE 0x1 /* Check the returned sense for the error */
-#define XS_DRIVER_STUFFUP 0x2 /* Driver failed to perform operation */
-#define XS_TIMEOUT 0x03 /* The device timed out.. turned off? */
-#define XS_SWTIMEOUT 0x04 /* The Timeout reported was caught by SW */
-#define XS_BUSY 0x08 /* The device busy, try again later? */
-#define XS_LENGTH 0x09 /* Illegal length (over/under run) */
-#define XS_SELTIMEOUT 0x10 /* Device failed to respond to selection */
-
-#ifdef KERNEL
-void *extend_get(struct extend_array *ea, int index);
-void scsi_attachdevs __P((struct scsibus_data *scbus));
-u_int32_t scsi_read_capacity __P(( struct scsi_link *sc_link,
- u_int32_t *blk_size, u_int32_t flags));
-errval scsi_test_unit_ready __P(( struct scsi_link *sc_link, u_int32_t flags));
-errval scsi_reset_target __P((struct scsi_link *));
-errval scsi_target_mode __P((struct scsi_link *, int));
-errval scsi_inquire( struct scsi_link *sc_link,
- struct scsi_inquiry_data *inqbuf, u_int32_t flags);
-errval scsi_prevent( struct scsi_link *sc_link, u_int32_t type,u_int32_t flags);
-struct scsibus_data *scsi_alloc_bus __P((void));
-errval scsi_probe_bus __P((int, int, int));
-errval scsi_probe_busses __P(( int, int, int));
-errval scsi_start_unit( struct scsi_link *sc_link, u_int32_t flags);
-errval scsi_stop_unit(struct scsi_link *sc_link, u_int32_t eject, u_int32_t flags);
-void scsi_done(struct scsi_xfer *xs);
-void scsi_user_done(struct scsi_xfer *xs);
-errval scsi_scsi_cmd __P(( struct scsi_link *, struct scsi_generic *,
- u_int32_t, u_char *,
- u_int32_t, u_int32_t,
- u_int32_t, struct buf *,
- u_int32_t));
-int scsi_do_ioctl __P((dev_t dev, u_long cmd, caddr_t addr, int mode,
- struct proc *p, struct scsi_link *sc_link));
-
-struct scsi_link *scsi_link_get __P((int bus, int targ, int lun));
-dev_t scsi_dev_lookup __P((int (*opener)(dev_t dev, int flags, int fmt,
-struct proc *p)));
-
-int scsi_opened_ok __P((dev_t dev, int flag, int type, struct scsi_link *sc_link));
-errval scsi_set_bus __P((int, struct scsi_link *));
-
-char *scsi_sense_desc __P((int, int));
-void scsi_sense_print __P((struct scsi_xfer *));
-void show_scsi_cmd __P((struct scsi_xfer *));
-
-void scsi_uto3b __P((u_int32_t , u_char *));
-u_int32_t scsi_3btou __P((u_char *));
-int32_t scsi_3btoi __P((u_char *));
-void scsi_uto4b __P((u_int32_t, u_char *));
-u_int32_t scsi_4btou __P((u_char *));
-void scsi_uto2b __P((u_int32_t, u_char *));
-u_int32_t scsi_2btou __P((u_char *));
-
-void sc_print_addr __P((struct scsi_link *));
-void sc_print_start __P((struct scsi_link *));
-void sc_print_init __P((void));
-void sc_print_finish __P((void));
-
-#ifndef SCSIDEBUG
-void scsi_print_info __P((struct scsi_link *));
-#endif
-
-void scsi_device_register __P((struct scsi_device *sd));
-
-void scsi_configure_start __P((void));
-void scsi_configure_finish __P((void));
-
-void ukinit __P((void));
-
-#ifdef SCSI_2_DEF
-errval scsi_change_def( struct scsi_link *sc_link, u_int32_t flags);
-#endif
-#endif /* KERNEL */
-
-#define SCSI_EXTERNALLEN (sizeof(struct scsi_link))
-
-
-/* XXX This belongs in a tape file.
- */
-
-/**********************************************************************
- from the scsi2 spec
- Value Tracks Density(bpi) Code Type Reference Note
- 0x1 9 800 NRZI R X3.22-1983 2
- 0x2 9 1600 PE R X3.39-1986 2
- 0x3 9 6250 GCR R X3.54-1986 2
- 0x5 4/9 8000 GCR C X3.136-1986 1
- 0x6 9 3200 PE R X3.157-1987 2
- 0x7 4 6400 IMFM C X3.116-1986 1
- 0x8 4 8000 GCR CS X3.158-1986 1
- 0x9 18 37871 GCR C X3B5/87-099 2
- 0xA 22 6667 MFM C X3B5/86-199 1
- 0xB 4 1600 PE C X3.56-1986 1
- 0xC 24 12690 GCR C HI-TC1 1,5
- 0xD 24 25380 GCR C HI-TC2 1,5
- 0xF 15 10000 GCR C QIC-120 1,5
- 0x10 18 10000 GCR C QIC-150 1,5
- 0x11 26 16000 GCR C QIC-320(525?) 1,5
- 0x12 30 51667 RLL C QIC-1350 1,5
- 0x13 1 61000 DDS CS X3B5/88-185A 4
- 0x14 1 43245 RLL CS X3.202-1991 4
- 0x15 1 45434 RLL CS ECMA TC17 4
- 0x16 48 10000 MFM C X3.193-1990 1
- 0x17 48 42500 MFM C X3B5/91-174 1
-
- where Code means:
- NRZI Non Return to Zero, change on ones
- GCR Group Code Recording
- PE Phase Encoded
- IMFM Inverted Modified Frequency Modulation
- MFM Modified Frequency Modulation
- DDS Dat Data Storage
- RLL Run Length Encoding
-
- where Type means:
- R Real-to-Real
- C Cartridge
- CS cassette
-
- where Notes means:
- 1 Serial Recorded
- 2 Parallel Recorded
- 3 Old format know as QIC-11
- 4 Helical Scan
- 5 Not ANSI standard, rather industry standard.
-
-********************************************************************/
-
-#define HALFINCH_800 0x01
-#define HALFINCH_1600 0x02
-#define HALFINCH_6250 0x03
-#define QIC_11 0x04 /* from Archive 150S Theory of Op. XXX */
-#define QIC_24 0x05 /* may be bad, works for CIPHER ST150S XXX */
-#define QIC_120 0x0f
-#define QIC_150 0x10
-#define QIC_320 0x11
-#define QIC_525 0x11
-#define QIC_1320 0x12
-#define DDS 0x13
-#define DAT_1 0x13
-#define QIC_3080 0x29
-
-
-/* XXX (dufault@hda.com) This is used only by "su" and "sctarg".
- * The minor number field conflicts with the disk slice code,
- * and so it is tough to access the disks through the "su" device.
- */
-
-/* Device number fields:
- *
- * NON-FIXED SCSI devices:
- *
- * ?FC? ???? ???? ???? MMMMMMMM mmmmmmmm
- *
- * F: Fixed device (nexus in number): must be 0.
- * C: Control device; only user mode ioctl is supported.
- * ?: Don't know; those bits didn't use to exist, currently always 0.
- * M: Major device number.
- * m: Old style minor device number.
- *
- * FIXED SCSI devices:
- *
- * XXX Conflicts with the slice code. Maybe the slice code can be
- * changed to respect the F bit?
- *
- * ?FC? ?BBB TTTT ?LLL MMMMMMMM mmmmmmmm
- *
- * F: Fixed device (nexus in number); must be 1.
- * C: Control device; only user mode ioctl is supported.
- * B: SCSI bus
- * T: SCSI target ID
- * L: Logical unit
- * M: Major device number
- * m: Old style minor device number.
- */
-
-#define SCSI_FIXED_MASK 0x40000000
-#define SCSI_FIXED(DEV) (((DEV) & SCSI_FIXED_MASK))
-#define SCSI_CONTROL_MASK 0x20000000
-#define SCSI_CONTROL(DEV) (((DEV) & SCSI_CONTROL_MASK))
-
-#define SCSI_BUS(DEV) (((DEV) & 0x07000000) >> 24)
-#define SCSI_ID(DEV) (((DEV) & 0x00F00000) >> 20)
-#define SCSI_LUN(DEV) (((DEV) & 0x00070000) >> 16)
-
-#define SCSI_MKFIXED(B, T, L, P) ( \
- ((B) << 24) | \
- ((T) << 20) | \
- ((L) << 16) | \
- (P) | \
- SCSI_FIXED_MASK )
-
-#endif /*SCSI_SCSICONF_H*/
-/* END OF FILE */
diff --git a/sys/scsi/sctarg.c b/sys/scsi/sctarg.c
deleted file mode 100644
index d2f8f6f..0000000
--- a/sys/scsi/sctarg.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * sctarg: Target mode user interface
- *
- * Copyright (C) 1995, HD Associates, Inc.
- * PO Box 276
- * Pepperell, MA 01463
- * 508 433 5266
- * dufault@hda.com
- *
- * This code is contributed to the University of California at Berkeley:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: sctarg.c,v 1.27 1998/07/04 22:30:24 julian Exp $
- */
-
-#include "opt_bounce.h"
-#include "opt_devfs.h"
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-#include "ioconf.h"
-
-#define OPEN 0x01
-
-struct scsi_data {
- struct buf_queue_head buf_queue;
- int flags; /* Already open */
-};
-
-static d_open_t sctargopen;
-static d_read_t sctargread;
-static d_write_t sctargwrite;
-static d_close_t sctargclose;
-static d_ioctl_t sctargioctl;
-static d_strategy_t sctargstrategy;
-
-#define CDEV_MAJOR 65
-static struct cdevsw sctarg_cdevsw =
- { sctargopen, sctargclose, sctargread, sctargwrite, /*65*/
- sctargioctl, nostop, nullreset, nodevtotty,/* sctarg */
- seltrue, nommap, sctargstrategy, "sctarg", NULL, -1 };
-
-SCSI_DEVICE_ENTRIES(sctarg)
-
-static errval sctarg_open(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-static void sctargstart(u_int32_t unit, u_int32_t unused_flags);
-static void sctarg_strategy(struct buf *bp, struct scsi_link *sc_link);
-
-static struct scsi_device sctarg_switch =
-{
- NULL,
- sctargstart, /* we have a queue, and this is how we service it */
- NULL,
- NULL,
- "sctarg",
- 0,
- {0, 0},
- SDEV_ONCE_ONLY,
- sctargattach,
- "Processor Target",
- sctargopen,
- sizeof(struct scsi_data),
- T_TARGET,
- 0,
- 0,
- sctarg_open,
- 0,
- 0,
- sctarg_strategy,
-};
-
-static errval
-sctargattach(struct scsi_link *sc_link)
-{
- struct scsi_data *sctarg;
-
- sctarg = sc_link->sd;
- bufq_init(&sctarg->buf_queue);
- sctarg->flags = 0;
-
- return 0;
-}
-
-static errval
-sctarg_open(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link)
-{
- int ret = 0;
-
- /* Does this host adapter support target mode operation?
- */
- if ((sc_link->flags & SDEV_TARGET_OPS) == 0)
- return ENODEV; /* Operation not supported */
-
- if (SCSI_FIXED(dev)) {
- sc_link->scsibus = SCSI_BUS(dev);
- scsi_set_bus(sc_link->scsibus, sc_link);
-
- sc_link->target = SCSI_ID(dev);
- sc_link->lun = SCSI_LUN(dev);
- }
-
- if (sc_link->scsibus == SCCONF_UNSPEC ||
- sc_link->target == SCCONF_UNSPEC ||
- sc_link->lun == SCCONF_UNSPEC)
- return ENXIO;
-
- /* XXX: You can have more than one target device on a single
- * host adapter. We need a reference count.
- */
- if ((sc_link->sd->flags & OPEN) == 0) /* Enable target mode */
- {
- ret = scsi_target_mode(sc_link, 1);
- sc_link->sd->flags |= OPEN;
- }
-
- return ret;
-}
-
-static int
-sctargread( dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(sctargstrategy, NULL, dev, 1, minphys, uio));
-}
-
-static int
-sctargwrite ( dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(sctargstrategy, NULL, dev, 0, minphys, uio));
-}
-
-/*
- * sctargstart looks to see if there is a buf waiting for the device
- * and that the device is not already busy. If both are true,
- * It dequeues the buf and creates a scsi command to perform the
- * transfer required. The transfer request will call scsi_done
- * on completion, which will in turn call this routine again
- * so that the next queued transfer is performed.
- * The bufs are queued by the strategy routine (sctargstrategy)
- *
- * This routine is also called after other non-queued requests
- * have been made of the scsi driver, to ensure that the queue
- * continues to be drained.
- * sctargstart() is called at splbio
- */
-static void
-sctargstart(unit, unused_flags)
- u_int32_t unit;
- u_int32_t unused_flags;
-{
- struct scsi_link *sc_link = SCSI_LINK(&sctarg_switch, unit);
- struct scsi_data *sctarg = sc_link->sd;
- register struct buf *bp = 0;
- struct
- {
-#define PROCESSOR_SEND 0x0A
-#define PROCESSOR_RECEIVE 0x08
- u_char op_code;
- u_char byte2;
- u_char len[3];
- u_char control;
- } cmd;
-
- u_int32_t flags;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("sctargstart "));
- /*
- * See if there is a buf to do and we are not already
- * doing one
- */
- while (sc_link->opennings != 0) {
-
- /* if a special awaits, let it proceed first */
- if (sc_link->flags & SDEV_WAITING) {
- sc_link->flags &= ~SDEV_WAITING;
- wakeup((caddr_t)sc_link);
- return;
- }
-
- bp = bufq_first(&sctarg->buf_queue);
- if (bp == NULL)
- return;
- bufq_remove(&sctarg->buf_queue, bp);
-
- /*
- * Fill out the scsi command
- */
- bzero(&cmd, sizeof(cmd));
- flags = SCSI_TARGET;
- if ((bp->b_flags & B_READ) == B_WRITE) {
- cmd.op_code = PROCESSOR_SEND;
- flags |= SCSI_DATA_OUT;
- } else {
- cmd.op_code = PROCESSOR_RECEIVE;
- flags |= SCSI_DATA_IN;
- }
-
- scsi_uto3b(bp->b_bcount, cmd.len);
- /*
- * go ask the adapter to do all this for us
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- (u_char *) bp->b_data,
- bp->b_bcount,
- 0,
- 100000,
- bp,
- flags | SCSI_NOSLEEP) == SUCCESSFULLY_QUEUED) {
- } else {
- printf("sctarg%lu: oops not queued\n", (u_long)unit);
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- biodone(bp);
- }
- } /* go back and see if we can cram more work in.. */
-}
-
-static void
-sctarg_strategy(struct buf *bp, struct scsi_link *sc_link)
-{
- unsigned char unit;
- u_int32_t opri;
- struct scsi_data *sctarg;
-
- unit = minor((bp->b_dev));
- sctarg = sc_link->sd;
-
- opri = splbio();
-
- /*
- * Use a bounce buffer if necessary
- */
-#ifdef BOUNCE_BUFFERS
- if (sc_link->flags & SDEV_BOUNCE)
- vm_bounce_alloc(bp);
-#endif
-
- /*
- * Place it at the end of the queue of activities for this device.
- */
- bufq_insert_tail(&sctarg->buf_queue, bp);
-
- /*
- * Tell the device to get going on the transfer if it's
- * not doing anything, otherwise just wait for completion
- * (All a bit silly if we're only allowing 1 open but..)
- */
- sctargstart(unit, 0);
-
- splx(opri);
- return;
-}
-
-static sctarg_devsw_installed = 0;
-#ifdef DEVFS
-static void *sctarg_devfs_token;
-#endif
-
-static void sctarg_drvinit(void *unused)
-{
- dev_t dev;
-
- if( ! sctarg_devsw_installed ) {
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev,&sctarg_cdevsw, NULL);
- sctarg_devsw_installed = 1;
-#ifdef DEVFS
- /* XXX should be in ADAPTER code */
- sctarg_devfs_token =
- devfs_add_devswf(&sctarg_cdevsw, 0, DV_CHR, 0, 0,
- 0600, "sctarg");
-#endif
- }
-}
-
-SYSINIT(sctargdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,sctarg_drvinit,NULL)
-
-
diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c
deleted file mode 100644
index 56aa859..0000000
--- a/sys/scsi/sd.c
+++ /dev/null
@@ -1,1065 +0,0 @@
-/*
- * Written by Julian Elischer (julian@dialix.oz.au)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * Ported to run under 386BSD by Julian Elischer (julian@dialix.oz.au) Sept 1992
- *
- * $Id: sd.c,v 1.139 1998/08/23 20:16:35 phk Exp $
- */
-
-#include "opt_bounce.h"
-#include "opt_devfs.h"
-#include "opt_hw_wdog.h"
-#include "opt_scsi.h"
-
-#define SPLSD splbio
-#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/dkbad.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/disklabel.h>
-#include <sys/diskslice.h>
-#include <sys/dkstat.h>
-#include <sys/conf.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /* DEVFS */
-
-#include <scsi/scsi_disk.h>
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-#include <vm/vm.h>
-#include <vm/vm_prot.h>
-#include <vm/pmap.h>
-#include <machine/md_var.h>
-#include <i386/i386/cons.h> /* XXX *//* for aborting dump */
-#ifdef PC98
-#include <pc98/pc98/pc98_machdep.h>
-#endif
-
-#include "ioconf.h"
-
-static u_int32_t sdstrats, sdqueues;
-
-#define SECSIZE 512
-#ifdef PC98
-#define SDOUTSTANDING 2
-#else
-#define SDOUTSTANDING 4
-#endif
-#define SD_RETRIES 4
-#define MAXTRANSFER 8 /* 1 page at a time */
-
-#define PARTITION(dev) dkpart(dev)
-#define SDUNIT(dev) dkunit(dev)
-
-/* XXX introduce a dkmodunit() macro for this. */
-#define SDSETUNIT(DEV, U) \
- makedev(major(DEV), dkmakeminor((U), dkslice(DEV), dkpart(DEV)))
-
-static errval sd_get_parms __P((int unit, int flags));
-#if 0
-static errval sd_reassign_blocks __P((int unit, int block));
-#endif
-static int sd_size(int unit, u_int32_t *sizep, u_int16_t *secsizep, int flags);
-static void sdstrategy1 __P((struct buf *));
-
-static int sd_sense_handler __P((struct scsi_xfer *));
-static void sdstart __P((u_int32_t, u_int32_t));
-
-struct scsi_data {
- u_int32_t flags;
-#define SDINIT 0x04 /* device has been init'd */
- struct disk_parms {
- u_char heads; /* Number of heads */
- u_int16_t cyls; /* Number of cylinders */
- u_char sectors;/*XXX*/ /* Number of sectors/track */
- u_int16_t secsiz; /* Number of bytes/sector */
- u_int32_t disksize; /* total number sectors */
- } params;
- struct diskslices *dk_slices; /* virtual drives */
- struct buf_queue_head buf_queue;
- int dkunit; /* disk stats unit number */
-#ifdef DEVFS
- void *b_devfs_token;
- void *c_devfs_token;
- void *ctl_devfs_token;
-#endif
-};
-
-
-static int sdunit(dev_t dev) { return SDUNIT(dev); }
-static dev_t sdsetunit(dev_t dev, int unit) { return SDSETUNIT(dev, unit); }
-static errval sd_open __P((dev_t dev, int mode, int fmt, struct proc *p,
- struct scsi_link *sc_link));
-static errval sd_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag,
- struct proc *p, struct scsi_link *sc_link);
-static errval sd_close __P((dev_t dev, int flag, int fmt, struct proc *p,
- struct scsi_link *sc_link));
-static void sd_strategy(struct buf *bp, struct scsi_link *sc_link);
-
-static d_open_t sdopen;
-static d_read_t sdread;
-static d_write_t sdwrite;
-static d_close_t sdclose;
-static d_ioctl_t sdioctl;
-static d_dump_t sddump;
-static d_psize_t sdsize;
-static d_strategy_t sdstrategy;
-
-#define CDEV_MAJOR 13
-#define BDEV_MAJOR 4
-
-static struct cdevsw sd_cdevsw = {
- sdopen, sdclose, sdread, sdwrite,
- sdioctl, nostop, nullreset, nodevtotty,
- seltrue, nommap, sdstrategy, "sd",
- NULL, -1, sddump, sdsize,
- D_DISK, 0, -1 };
-
-
-
-
-SCSI_DEVICE_ENTRIES(sd)
-
-static struct scsi_device sd_switch =
-{
- sd_sense_handler,
- sdstart, /* have a queue, served by this */
- NULL, /* have no async handler */
- NULL, /* Use default 'done' routine */
- "sd",
- 0,
- {0, 0},
- 0, /* Link flags */
- sdattach,
- "Direct-Access",
- sdopen,
- sizeof(struct scsi_data),
- T_DIRECT,
- sdunit,
- sdsetunit,
- sd_open,
- sd_ioctl,
- sd_close,
- sd_strategy,
-};
-static struct scsi_xfer sx;
-
-
-static __inline void
-sd_registerdev(int unit)
-{
- if(dk_ndrive < DK_NDRIVE) {
- sprintf(dk_names[dk_ndrive], "sd%d", unit);
- dk_wpms[dk_ndrive] = (8*1024*1024/2);
- SCSI_DATA(&sd_switch, unit)->dkunit = dk_ndrive++;
- } else {
- SCSI_DATA(&sd_switch, unit)->dkunit = -1;
- }
-}
-
-
-/*
- * The routine called by the low level scsi routine when it discovers
- * a device suitable for this driver.
- */
-static errval
-sdattach(struct scsi_link *sc_link)
-{
- u_int32_t unit;
- struct disk_parms *dp;
-#ifdef DEVFS
- int mynor;
-#endif
-
- struct scsi_data *sd = sc_link->sd;
-
- unit = sc_link->dev_unit;
-
- dp = &(sd->params);
-
- if (sc_link->opennings > SDOUTSTANDING)
- sc_link->opennings = SDOUTSTANDING;
-
- bufq_init(&sd->buf_queue);
- /*
- * In case it is a funny one, tell it to start
- * not needed for most hard drives (ignore failure)
- */
- scsi_start_unit(sc_link,
- SCSI_ERR_OK | SCSI_SILENT | SCSI_NOSLEEP | SCSI_NOMASK);
- /*
- * Use the subdriver to request information regarding
- * the drive. We cannot use interrupts yet, so the
- * request must specify this. This may fail with removable media.
- */
- if (sd_get_parms(unit, SCSI_NOSLEEP | SCSI_NOMASK) == 0) {
- /*
- * if we don't have actual parameters, assume 512 bytes/sec
- * (could happen on removable media - MOD)
- * -- this avoids the division below from falling over
- */
- printf("%luMB (%lu %u byte sectors)",
- (u_long)(dp->disksize / ((1024L * 1024L) / dp->secsiz)),
- (u_long)dp->disksize, dp->secsiz);
-
-#ifndef SCSI_REPORT_GEOMETRY
- if ( (sc_link->flags & SDEV_BOOTVERBOSE) )
-#endif
- {
- sc_print_addr(sc_link);
- printf("with %d cyls, %d heads, and an average %d sectors/track",
- dp->cyls, dp->heads, dp->sectors);
- }
- } else {
- printf("Media parameters not available");
- }
- sd->flags |= SDINIT;
- sd_registerdev(unit);
-
-#ifdef DEVFS
- mynor = dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART);
- sd->b_devfs_token = devfs_add_devswf(&sd_cdevsw, mynor, DV_BLK,
- UID_ROOT, GID_OPERATOR, 0640,
- "sd%d", unit);
- sd->c_devfs_token = devfs_add_devswf(&sd_cdevsw, mynor, DV_CHR,
- UID_ROOT, GID_OPERATOR, 0640,
- "rsd%d", unit);
- mynor = dkmakeminor(unit, 0, 0); /* XXX */
- sd->ctl_devfs_token = devfs_add_devswf(&sd_cdevsw,
- mynor | SCSI_CONTROL_MASK,
- DV_CHR,
- UID_ROOT, GID_WHEEL, 0600,
- "rsd%d.ctl", unit);
-#endif
- return 0;
-}
-
-
-/*
- * open the device. Make sure the partition info is a up-to-date as can be.
- */
-static errval
-sd_open(dev_t dev, int mode, int fmt, struct proc *p, struct scsi_link *sc_link)
-{
- errval errcode = 0;
- u_int32_t unit;
- struct disklabel label;
- struct scsi_data *sd;
-
- unit = SDUNIT(dev);
- sd = sc_link->sd;
-
- /*
- * Make sure the disk has been initialised
- * At some point in the future, get the scsi driver
- * to look for a new device if we are not initted
- */
- if ((!sd) || (!(sd->flags & SDINIT))) {
- return (ENXIO);
- }
-
- SC_DEBUG(sc_link, SDEV_DB1,
- ("sd_open: dev=0x%lx (unit %lu, partition %d)\n",
- (u_long)dev, (u_long)unit, PARTITION(dev)));
-
- /*
- * "unit attention" errors should occur here if the
- * drive has been restarted or the pack changed.
- * just ingnore the result, it's a decoy instruction
- * The error handlers will act on the error though
- * and invalidate any media information we had.
- */
- scsi_test_unit_ready(sc_link, 0);
-
- errcode = scsi_device_lock(sc_link);
- if (errcode)
- return errcode;
-
- /*
- * If it's been invalidated, then forget the label
- */
- sc_link->flags |= SDEV_OPEN; /* unit attn becomes an err now */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED) && sd->dk_slices != NULL) {
- /*
- * If somebody still has it open, then forbid re-entry.
- */
- if (dsisopen(sd->dk_slices)) {
- errcode = ENXIO;
- goto close;
- }
-
- dsgone(&sd->dk_slices);
- }
-
- /*
- * Check that it is still responding and ok.
- */
- if (scsi_test_unit_ready(sc_link, 0)) {
- SC_DEBUG(sc_link, SDEV_DB3, ("device not reponding\n"));
- errcode = ENXIO;
- goto close;
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("device ok\n"));
-
- /*
- * Load the physical device parameters
- */
- if(errcode = sd_get_parms(unit, 0)) /* sets SDEV_MEDIA_LOADED */
- goto close;
-
- SC_DEBUG(sc_link, SDEV_DB3, ("Params loaded "));
-
- /* Lock the pack in. */
- scsi_prevent(sc_link, PR_PREVENT, SCSI_ERR_OK | SCSI_SILENT);
-
- /* Build label for whole disk. */
- bzero(&label, sizeof label);
- label.d_type = DTYPE_SCSI;
- label.d_secsize = sd->params.secsiz;
- label.d_nsectors = sd->params.sectors;
- label.d_ntracks = sd->params.heads;
- label.d_ncylinders = sd->params.cyls;
- label.d_secpercyl = sd->params.heads * sd->params.sectors;
- if (label.d_secpercyl == 0)
- label.d_secpercyl = 100;
- /* XXX as long as it's not 0 - readdisklabel divides by it (?) */
- label.d_secperunit = sd->params.disksize;
-
- /* Initialize slice tables. */
- errcode = dsopen("sd", dev, fmt, 0, &sd->dk_slices, &label, sdstrategy1,
- (ds_setgeom_t *)NULL, &sd_cdevsw);
- if (errcode != 0)
- goto close;
- SC_DEBUG(sc_link, SDEV_DB3, ("Slice tables initialized "));
-
- SC_DEBUG(sc_link, SDEV_DB3, ("open %lu %lu\n",
- (u_long)sdstrats, (u_long)sdqueues));
-
- scsi_device_unlock(sc_link);
- return 0;
-
-close:
- if (!dsisopen(sd->dk_slices))
- {
- scsi_prevent(sc_link, PR_ALLOW, SCSI_ERR_OK | SCSI_SILENT);
- sc_link->flags &= ~SDEV_OPEN;
- }
- scsi_device_unlock(sc_link);
- return errcode;
-}
-
-/*
- * close the device.. only called if we are the LAST occurence of an open
- * device. Convenient now but usually a pain.
- */
-static errval
-sd_close(dev_t dev,int mode, int fmt, struct proc *p, struct scsi_link *sc_link)
-{
- struct scsi_data *sd;
- errval errcode;
-
- sd = sc_link->sd;
- errcode = scsi_device_lock(sc_link);
- if (errcode)
- return errcode;
- dsclose(dev, fmt, sd->dk_slices);
- if (!dsisopen(sd->dk_slices)) {
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT | SCSI_ERR_OK);
- sc_link->flags &= ~SDEV_OPEN;
- }
- scsi_device_unlock(sc_link);
- return (0);
-}
-
-static int
-sdread(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(sdstrategy, NULL, dev, 1, minphys, uio));
-}
-
-static int
-sdwrite(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(sdstrategy, NULL, dev, 0, minphys, uio));
-}
-
-/*
- * Actually translate the requested transfer into one the physical driver
- * can understand. The transfer is described by a buf and will include
- * only one physical transfer.
- */
-static void
-sd_strategy(struct buf *bp, struct scsi_link *sc_link)
-{
- u_int32_t opri;
- struct scsi_data *sd;
- u_int32_t unit;
-
- sdstrats++;
- unit = SDUNIT((bp->b_dev));
- sd = sc_link->sd;
- /*
- * If the device has been made invalid, error out
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- bp->b_error = EIO;
- goto bad;
- }
-
- /*
- * check it's not too big a transfer for our adapter
- */
- scsi_minphys(bp,&sd_switch);
-
- /*
- * Do bounds checking, adjust transfer, and set b_pbklno.
- */
- if (dscheck(bp, sd->dk_slices) <= 0)
- goto done; /* XXX check b_resid */
-
- opri = SPLSD();
- /*
- * Use a bounce buffer if necessary
- */
-#ifdef BOUNCE_BUFFERS
- if (sc_link->flags & SDEV_BOUNCE)
- vm_bounce_alloc(bp);
-#endif
-
- /*
- * Place it in the queue of disk activities for this disk
- */
-#ifdef SDDISKSORT
- bufq_disksort(&sd->buf_queue, bp);
-#else
- bufq_insert_tail(&sd->buf_queue, bp);
-#endif
-
- /*
- * Tell the device to get going on the transfer if it's
- * not doing anything, otherwise just wait for completion
- */
- sdstart(unit, 0);
-
- splx(opri);
- return /*0*/;
-bad:
- bp->b_flags |= B_ERROR;
-done:
-
- /*
- * Correctly set the buf to indicate a completed xfer
- */
- bp->b_resid = bp->b_bcount;
- biodone(bp);
- return /*0*/;
-}
-
-static void
-sdstrategy1(struct buf *bp)
-{
- /*
- * XXX - do something to make sdstrategy() but not this block while
- * we're doing dsinit() and dsioctl().
- */
- sdstrategy(bp);
-}
-
-/*
- * sdstart looks to see if there is a buf waiting for the device
- * and that the device is not already busy. If both are true,
- * It dequeues the buf and creates a scsi command to perform the
- * transfer in the buf. The transfer request will call scsi_done
- * on completion, which will in turn call this routine again
- * so that the next queued transfer is performed.
- * The bufs are queued by the strategy routine (sdstrategy)
- *
- * This routine is also called after other non-queued requests
- * have been made of the scsi driver, to ensure that the queue
- * continues to be drained.
- *
- * must be called at the correct (highish) spl level
- * sdstart() is called at SPLSD from sdstrategy and scsi_done
- */
-static void
-sdstart(u_int32_t unit, u_int32_t flags)
-{
- register struct scsi_link *sc_link = SCSI_LINK(&sd_switch, unit);
- register struct scsi_data *sd = sc_link->sd;
- struct buf *bp = NULL;
- struct scsi_rw_big cmd;
- u_int32_t blkno, nblk, secsize;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("sdstart "));
- /*
- * Check if the device has room for another command
- */
- while (sc_link->opennings) {
-
- /*
- * there is excess capacity, but a special waits
- * It'll need the adapter as soon as we clear out of the
- * way and let it run (user level wait).
- */
- if (sc_link->flags & SDEV_WAITING) {
- return;
- }
- /*
- * See if there is a buf with work for us to do..
- */
- bp = bufq_first(&sd->buf_queue);
- if (bp == NULL) { /* yes, an assign */
- return;
- }
- bufq_remove(&sd->buf_queue, bp);
-
- /*
- * If the device has become invalid, abort all the
- * reads and writes until all files have been closed and
- * re-openned
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- goto bad;
- }
- /*
- * We have a buf, now we know we are going to go through
- * With this thing..
- */
- secsize = sd->params.secsiz;
- blkno = bp->b_pblkno;
- if (bp->b_bcount & (secsize - 1))
- {
- goto bad;
- }
- nblk = bp->b_bcount / secsize;
-
- /*
- * Fill out the scsi command
- */
- cmd.op_code = (bp->b_flags & B_READ)
- ? READ_BIG : WRITE_BIG;
- cmd.addr_3 = (blkno & 0xff000000UL) >> 24;
- cmd.addr_2 = (blkno & 0xff0000) >> 16;
- cmd.addr_1 = (blkno & 0xff00) >> 8;
- cmd.addr_0 = blkno & 0xff;
- cmd.length2 = (nblk & 0xff00) >> 8;
- cmd.length1 = (nblk & 0xff);
- cmd.byte2 = cmd.reserved = cmd.control = 0;
- /*
- * Call the routine that chats with the adapter.
- * Note: we cannot sleep as we may be an interrupt
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- (u_char *) bp->b_data,
- bp->b_bcount,
- SD_RETRIES,
- 10000,
- bp,
- flags | ((bp->b_flags & B_READ) ?
- SCSI_DATA_IN : SCSI_DATA_OUT))
- == SUCCESSFULLY_QUEUED) {
- sdqueues++;
- if(sd->dkunit >= 0) {
- dk_xfer[sd->dkunit]++;
- dk_seek[sd->dkunit]++; /* don't know */
- dk_wds[sd->dkunit] += bp->b_bcount >> 6;
- }
- } else {
-bad:
- printf("sd%lu: oops not queued\n", (u_long)unit);
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- biodone(bp);
- }
- }
-}
-
-/*
- * Perform special action on behalf of the user
- * Knows about the internals of this device
- */
-static errval
-sd_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p,
- struct scsi_link *sc_link)
-{
- errval error;
- struct scsi_data *sd = sc_link->sd;
- SC_DEBUG(sc_link, SDEV_DB1, ("sdioctl (0x%lx)", cmd));
-
-#if 0
- /* Wait until we have exclusive access to the device. */
- /* XXX this is how wd does it. How did we work without this? */
- sdsleep(du->dk_ctrlr, "wdioct");
-#endif
-
- /*
- * If the device is not valid.. abandon ship
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED))
- return (EIO);
-
- if (cmd == DIOCSBAD)
- return (EINVAL); /* XXX */
-
- error = scsi_device_lock(sc_link);
- if (error)
- return error;
- error = dsioctl("sd", dev, cmd, addr, flag, &sd->dk_slices,
- sdstrategy1, (ds_setgeom_t *)NULL);
- scsi_device_unlock(sc_link);
- if (error != ENOIOCTL)
- return (error);
- if (PARTITION(dev) != RAW_PART)
- return (ENOTTY);
- return (scsi_do_ioctl(dev, cmd, addr, flag, p, sc_link));
-}
-
-/*
- * Find out from the device what its capacity is. It turns
- * out this is also the best way to find out the sector size.
- */
-static int
-sd_size(int unit, u_int32_t *sizep, u_int16_t *secsizep, int flags)
-{
- struct scsi_read_cap_data rdcap;
- struct scsi_read_capacity scsi_cmd;
- u_int32_t size;
- u_int32_t secsize;
- struct scsi_link *sc_link = SCSI_LINK(&sd_switch, unit);
-
- /*
- * make up a scsi command and ask the scsi driver to do
- * it for you.
- */
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = READ_CAPACITY;
-
- /*
- * If the command works, interpret the result as a 4 byte
- * number of blocks
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) & rdcap,
- sizeof(rdcap),
- SD_RETRIES,
- 2000,
- NULL,
- flags | SCSI_DATA_IN) != 0) {
- printf("sd%d: could not get size\n", unit);
- return (ENXIO);
- }
- size = rdcap.addr_0 + 1;
- size += rdcap.addr_1 << 8;
- size += rdcap.addr_2 << 16;
- size += rdcap.addr_3 << 24;
- secsize = rdcap.length_0;
- secsize += rdcap.length_1 << 8;
- secsize += rdcap.length_2 << 16;
- secsize += rdcap.length_3 << 24;
- *secsizep = secsize;
- *sizep = size;
- return (0);
-}
-
-#if 0
-/*
- * Tell the device to map out a defective block
- */
-static errval
-sd_reassign_blocks(unit, block)
- int unit, block;
-{
- struct scsi_reassign_blocks scsi_cmd;
- struct scsi_reassign_blocks_data rbdata;
- struct scsi_link *sc_link = SCSI_LINK(&sd_switch, unit);
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- bzero(&rbdata, sizeof(rbdata));
- scsi_cmd.op_code = REASSIGN_BLOCKS;
-
- rbdata.length_msb = 0;
- rbdata.length_lsb = sizeof(rbdata.defect_descriptor[0]);
- rbdata.defect_descriptor[0].dlbaddr_3 = ((block >> 24) & 0xff);
- rbdata.defect_descriptor[0].dlbaddr_2 = ((block >> 16) & 0xff);
- rbdata.defect_descriptor[0].dlbaddr_1 = ((block >> 8) & 0xff);
- rbdata.defect_descriptor[0].dlbaddr_0 = ((block) & 0xff);
-
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) & rbdata,
- sizeof(rbdata),
- SD_RETRIES,
- 5000,
- NULL,
- SCSI_DATA_OUT));
-}
-#endif
-
-#define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
-
-/*
- * Get the scsi driver to send a full inquiry to the
- * device and use the results to fill out the disk
- * parameter structure.
- * Even if we get an error, complete with some dummy information.
- * XXX this is backwards. The read_cap (sd_size()) should be done first.
- */
-static errval
-sd_get_parms(int unit, int flags)
-{
- struct scsi_link *sc_link = SCSI_LINK(&sd_switch, unit);
- struct scsi_data *sd = sc_link->sd;
- struct disk_parms *disk_parms = &sd->params;
- struct scsi_mode_sense scsi_cmd;
- struct scsi_mode_sense_data {
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- union disk_pages pages;
- } scsi_sense;
- u_int32_t sectors;
- int error = 0;
-
- /*
- * First check if we have it all loaded
- */
- if (sc_link->flags & SDEV_MEDIA_LOADED)
- return 0;
-
- /*
- * do a "mode sense page 4"
- */
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SENSE;
- scsi_cmd.page = 4;
- scsi_cmd.length = 0x20;
-#ifdef PC98
- if (sd_bios_parms(disk_parms, sc_link)) {
- } else
-#endif
- /*
- * If the command worked, use the results to fill out
- * the parameter structure
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) & scsi_sense,
- sizeof(scsi_sense),
- SD_RETRIES,
- 4000,
- NULL,
- flags | SCSI_DATA_IN) != 0) {
-
- printf("sd%d could not mode sense (4).", unit);
- printf(" Using fictitious geometry\n");
- /*
- * use adaptec standard fictitious geometry
- * this depends on which controller (e.g. 1542C is
- * different. but we have to put SOMETHING here..)
- */
- if (error = sd_size(unit, &sectors, &disk_parms->secsiz, flags)) {
- /* we couldn't get anyhthing. removable? */
- sectors = 32 * 64;
- disk_parms->secsiz= DEV_BSIZE;;
- }
- disk_parms->heads = 64;
- disk_parms->sectors = 32;
- disk_parms->cyls = sectors / (64 * 32);
- disk_parms->disksize = sectors;
- } else {
-
- SC_DEBUG(sc_link, SDEV_DB3,
- ("%lu cyls, %d heads, %u precomp, %u red_write, %u land_zone\n",
- (u_long)scsi_3btou(&scsi_sense.pages.rigid_geometry.ncyl_2),
- scsi_sense.pages.rigid_geometry.nheads,
- b2tol(scsi_sense.pages.rigid_geometry.st_cyl_wp),
- b2tol(scsi_sense.pages.rigid_geometry.st_cyl_rwc),
- b2tol(scsi_sense.pages.rigid_geometry.land_zone)));
-
- /*
- * KLUDGE!!(for zone recorded disks)
- * give a number of sectors so that sec * trks * cyls
- * is <= disk_size
- * can lead to wasted space! THINK ABOUT THIS !
- */
- disk_parms->heads = scsi_sense.pages.rigid_geometry.nheads;
- disk_parms->cyls = scsi_3btou(
- &scsi_sense.pages.rigid_geometry.ncyl_2);
- /* set in a default value */
- disk_parms->secsiz = scsi_3btou(scsi_sense.blk_desc.blklen);
-
- if (error = sd_size(unit, &sectors,
- &disk_parms->secsiz, flags)) {
- /* we couldn't get anyhthing. removable? */
- sectors = 64 * 32; /* just so non 0 */
- }
- disk_parms->disksize = sectors;
- /* Check if none of these values are zero */
- if(disk_parms->heads && disk_parms->cyls) {
- sectors /= (disk_parms->heads * disk_parms->cyls);
- } else {
- /* set it to something reasonable */
- disk_parms->heads = 64;
- disk_parms->cyls = sectors / (64 * 32);
- sectors = 32;
- }
- /* keep secsiz sane too - we may divide by it later */
- if(disk_parms->secsiz == 0)
- disk_parms->secsiz = SECSIZE;
- disk_parms->sectors = sectors; /* dubious on SCSI *//*XXX */
- }
- switch (sd->params.secsiz) {
- case 512:
- case 1024:
- case 2048:
- break;
- default:
- printf("sd%lu: Can't deal with %u bytes logical blocks\n",
- (u_long)unit, sd->params.secsiz);
- error = ENXIO;
- }
- if (error == 0)
- sc_link->flags |= SDEV_MEDIA_LOADED;
- return (error);
-}
-
-static int
-sdsize(dev_t dev)
-{
- struct scsi_data *sd;
-
- sd = SCSI_DATA(&sd_switch, (u_int32_t) SDUNIT(dev));
- if (sd == NULL)
- return (-1);
- return (dssize(dev, &sd->dk_slices, sdopen, sdclose));
-}
-
-/*
- * sense handler: Called to determine what to do when the
- * device returns a CHECK CONDITION.
- *
- * This will issue a retry when the device returns a
- * non-media hardware failure. The CDC-WREN IV does this
- * when you access it during thermal calibrarion, so the drive
- * is pretty useless without this.
- *
- * In general, you probably almost always would like to issue a retry
- * for your disk I/O. It can't hurt too much (the caller only retries
- * so many times) and it may save your butt.
- */
-
-static int
-sd_sense_handler(struct scsi_xfer *xs)
-{
- struct scsi_sense_data *sense;
- struct scsi_inquiry_data *inqbuf;
-
- sense = &(xs->sense);
-
- /* I don't know what the heck to do with a deferred error,
- * so I'll just kick it back to the caller.
- */
- if ((sense->error_code & SSD_ERRCODE) == 0x71)
- return SCSIRET_CONTINUE;
-
- if (((sense->error_code & SSD_ERRCODE) == 0x70) &&
- ((sense->ext.extended.flags & SSD_KEY) == 0x05))
- /* No point in retrying Illegal Requests */
- return SCSIRET_CONTINUE;
-
- inqbuf = &(xs->sc_link->inqbuf);
-
- /* It is dangerous to retry on removable drives without
- * looking carefully at the additional sense code
- * and sense code qualifier and ensuring the disk hasn't changed:
- */
- if (inqbuf->dev_qual2 & SID_REMOVABLE)
- return SCSIRET_CONTINUE;
-
- /* Retry all disk errors.
- */
- scsi_sense_print(xs);
- if (xs->retries)
- printf(", retries:%d\n", xs->retries);
- else
- printf(", FAILURE\n");
-
- return SCSIRET_DO_RETRY;
-}
-
-/*
- * dump all of physical memory into the partition specified, starting
- * at offset 'dumplo' into the partition.
- * XXX for SLICE starts at argument 'start'.
- */
-static errval
-sddump(dev_t dev)
-{ /* dump core after a system crash */
- struct disklabel *lp;
- int32_t num; /* number of sectors to write */
- u_int32_t unit, part;
- int32_t nblocks;
- int32_t blkoff;
- static int sddoingadump = 0;
- register struct scsi_data *sd; /* disk unit to do the IO */
- struct scsi_link *sc_link;
- int32_t blknum, blkcnt = MAXTRANSFER;
- char *addr;
- struct scsi_rw_big cmd;
- struct scsi_xfer *xs = &sx;
- errval retval;
-
- addr = (char *) 0; /* starting address */
-
- /* toss any characters present prior to dump */
- while (cncheckc() != -1) ;
-
- /* size of memory to dump */
- num = Maxmem;
- unit = SDUNIT(dev); /* eventually support floppies? */
- part = PARTITION(dev); /* file system */
-
- sc_link = SCSI_LINK(&sd_switch, unit);
-
- if (!sc_link)
- return ENXIO;
-
- sd = sc_link->sd;
-
- /* was it ever initialized etc. ? */
- if (!(sd->flags & SDINIT))
- return (ENXIO);
- if ((sc_link->flags & SDEV_MEDIA_LOADED) != SDEV_MEDIA_LOADED)
- return (ENXIO);
- if (sd->dk_slices == NULL)
- Debugger("sddump: no slices");
- if ((lp = dsgetlabel(dev, sd->dk_slices)) == NULL)
- return (ENXIO);
-
- /* Convert to disk sectors */
- /* XXX it must be 512 */
- num = (u_int32_t) num * PAGE_SIZE / sd->params.secsiz;
-
- /* check if controller active */
- if (sddoingadump)
- return (EFAULT);
-
- nblocks = lp->d_partitions[part].p_size;
- blkoff = lp->d_partitions[part].p_offset;
- /* XXX */
- blkoff += sd->dk_slices->dss_slices[dkslice(dev)].ds_offset;
-
- /* check transfer bounds against partition size */
- if ((dumplo < 0) || ((dumplo + num) > nblocks))
- return (EINVAL);
-
- sddoingadump = 1;
-
- blknum = dumplo + blkoff;
- while (num > 0) {
- if (is_physical_memory((vm_offset_t)addr))
- pmap_enter(kernel_pmap, (vm_offset_t)CADDR1,
- trunc_page(addr), VM_PROT_READ, TRUE);
- else
- pmap_enter(kernel_pmap, (vm_offset_t)CADDR1,
- trunc_page(0), VM_PROT_READ, TRUE);
- /*
- * Fill out the scsi command
- */
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = WRITE_BIG;
- cmd.addr_3 = (blknum & 0xff000000) >> 24;
- cmd.addr_2 = (blknum & 0xff0000) >> 16;
- cmd.addr_1 = (blknum & 0xff00) >> 8;
- cmd.addr_0 = blknum & 0xff;
- cmd.length2 = (blkcnt & 0xff00) >> 8;
- cmd.length1 = (blkcnt & 0xff);
- /*
- * Fill out the scsi_xfer structure
- * Note: we cannot sleep as we may be an interrupt
- * don't use scsi_scsi_cmd() as it may want
- * to wait for an xs.
- */
- bzero(xs, sizeof(sx));
- xs->flags |= SCSI_NOMASK | SCSI_NOSLEEP | INUSE | SCSI_DATA_OUT;
- xs->sc_link = sc_link;
- xs->retries = SD_RETRIES;
- xs->timeout = 10000; /* 10000 millisecs for a disk ! */
- xs->cmd = (struct scsi_generic *) &cmd;
- xs->cmdlen = sizeof(cmd);
- xs->resid = 0;
- xs->error = XS_NOERROR;
- xs->bp = 0;
- xs->data = (u_char *) CADDR1; /* XXX use pmap_enter() */
- xs->datalen = blkcnt * sd->params.secsiz;
-
- /*
- * Pass all this info to the scsi driver.
- */
- retval = (*(sc_link->adapter->scsi_cmd)) (xs);
- switch (retval) {
- case SUCCESSFULLY_QUEUED:
- case HAD_ERROR:
- return (ENXIO); /* we said not to sleep! */
- case COMPLETE:
- break;
- default:
- return (ENXIO); /* we said not to sleep! */
- }
-
- /*
- * If we are dumping core, it may take a while.
- * So reassure the user and hold off any watchdogs.
- */
- if ((uintptr_t)addr % (1024 * 1024) == 0) {
-#ifdef HW_WDOG
- if (wdog_tickler)
- (*wdog_tickler)();
-#endif /* HW_WDOG */
- printf("%ld ", (u_long)(num / 2048));
- }
- /* update block count */
- num -= blkcnt;
- blknum += blkcnt;
- addr += blkcnt * sd->params.secsiz;
-
- /* operator aborting dump? */
- if (cncheckc() != -1)
- return (EINTR);
- }
- return (0);
-}
-
-static sd_devsw_installed = 0;
-
-static void sd_drvinit(void *unused)
-{
-
- if( ! sd_devsw_installed ) {
- cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &sd_cdevsw);
- sd_devsw_installed = 1;
- }
-}
-
-SYSINIT(sddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,sd_drvinit,NULL)
-
diff --git a/sys/scsi/ssc.c b/sys/scsi/ssc.c
deleted file mode 100644
index 1014daa..0000000
--- a/sys/scsi/ssc.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/* "superscsi" pseudo device.
- * "superscsi" supports general SCSI utilities that can iterate
- * over all SCSI targets, including those without device entry
- * points.
- *
- * "superscsi" supports the SCIOCADDR ioctl to change the BUS, ID, LUN
- * of the target so that you can get to all devices. The only thing
- * you can do to "superscsi" is open it, set the target, perform ioctl
- * calls, and close it.
- *
- * Keep "superscsi" protected: you can drive a truck through the
- * security hole if you don't.
- *
- *Begin copyright
- *
- * Copyright (C) 1993, 1994, 1995, HD Associates, Inc.
- * PO Box 276
- * Pepperell, MA 01463
- * 508 433 5266
- * dufault@hda.com
- *
- * This code is contributed to the University of California at Berkeley:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *End copyright
- * $Id: ssc.c,v 1.18 1998/01/24 02:54:52 eivind Exp $
- */
-
-#include "opt_devfs.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/disklabel.h>
-#include <sys/scsiio.h>
-#include <sys/kernel.h>
-#include <sys/stat.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-#include <scsi/scsiconf.h>
-
-static d_open_t sscopen;
-static d_close_t sscclose;
-static d_ioctl_t sscioctl;
-
-extern d_open_t suopen;
-extern d_close_t suclose;
-extern d_ioctl_t suioctl;
-
-#define CDEV_MAJOR 49
-static struct cdevsw ssc_cdevsw =
- { sscopen, sscclose, noread, nowrite, /*49*/
- sscioctl, nostop, nullreset, nodevtotty,
- seltrue, nommap, nostrategy, "ssc", NULL, -1 };
-
-static dev_t sscdev = NODEV;
-
-static int
-sscopen(dev_t dev, int flag, int type, struct proc *p)
-{
- if (sscdev != NODEV)
- return suopen(sscdev, flag, type, p);
- return 0;
-}
-
-static int
-sscclose(dev_t dev, int fflag, int type, struct proc *p)
-{
-
- if (sscdev != NODEV)
- return suclose(sscdev, fflag, type, p);
- return 0;
-}
-
-static int
-sscioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
-{
- if (cmd == SCIOCADDR)
- {
- struct scsi_addr *sca;
- dev_t newdev;
- int ret;
-
- sca = (struct scsi_addr *) data;
- newdev = SCSI_MKFIXED(sca->scbus,sca->target,sca->lun,RAW_PART);
-
- if (sscdev != NODEV)
- {
- suclose(sscdev, fflag, S_IFCHR, p);
- sscdev = NODEV;
- }
-
- if ( (ret = suopen(newdev, fflag, S_IFCHR, p)) )
- return ret;
-
- sscdev = newdev;
-
- return 0;
- }
-
- if (sscdev != NODEV)
- return suioctl(sscdev, cmd, data, fflag, p);
-
- return ENXIO;
-}
-
-/*
- * I've elected not to support any other entries. There really is no
- * good reason other than I'm not sure how you would use them.
- */
-
-static ssc_devsw_installed = 0;
-#ifdef DEVFS
-static void *ssc_devfs_token;
-#endif
-
-static void
-ssc_drvinit(void *unused)
-{
- dev_t dev;
-
- if( ! ssc_devsw_installed ) {
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev,&ssc_cdevsw, NULL);
- ssc_devsw_installed = 1;
-#ifdef DEVFS
- ssc_devfs_token =
- devfs_add_devswf(&ssc_cdevsw, 0, DV_CHR, 0, 0,
- 0600, "ssc");
-#endif
- }
-}
-
-SYSINIT(sscdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,ssc_drvinit,NULL)
-
diff --git a/sys/scsi/st.c b/sys/scsi/st.c
deleted file mode 100644
index b4feb02..0000000
--- a/sys/scsi/st.c
+++ /dev/null
@@ -1,2005 +0,0 @@
-/*
- * Written by Julian Elischer (julian@tfs.com)(now julian@DIALix.oz.au)
- * for TRW Financial Systems for use under the MACH(2.5) operating system.
- *
- * TRW Financial Systems, in accordance with their agreement with Carnegie
- * Mellon University, makes this software available to CMU to distribute
- * or use in any manner that they see fit as long as this message is kept with
- * the software. For this reason TFS also grants any other persons or
- * organisations permission to use or modify this software.
- *
- * TFS supplies this software to be publicly redistributed
- * on the understanding that TFS is not responsible for the correct
- * functioning of this software in any circumstances.
- *
- * $Id: st.c,v 1.93 1998/08/18 00:32:49 bde Exp $
- */
-
-/*
- * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
- * major changes by Julian Elischer (julian@jules.dialix.oz.au) May 1993
- */
-
-/*
- * To do:
- * work out some better way of guessing what a good timeout is going
- * to be depending on whether we expect to retension or not.
- *
- */
-
-#include "opt_bounce.h"
-#include "opt_devfs.h"
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-
-#include <sys/fcntl.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
-#include <sys/mtio.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-
-#include <scsi/scsi_tape.h>
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_driver.h>
-
-#include "ioconf.h"
-
-/* Defines for device specific stuff */
-#define PAGE_0_SENSE_DATA_SIZE 12
-#define DEF_FIXED_BSIZE 512
-#define ST_RETRIES 4 /* only on non IO commands */
-
-#define STUNIT(DEV) ((minor(DEV)&0xF0) >> 4) /* 4 bit unit. */
-#define STSETUNIT(DEV, U) makedev(major(DEV), ((U) << 4))
-
-#define MODE(z) ( (minor(z) & 0x03) )
-#define DSTY(z) ( ((minor(z) >> 2) & 0x03) )
-#define CTLMODE 3
-
-#define IS_CTLMODE(DEV) (MODE(DEV) == CTLMODE)
-
-static errval st_space __P((u_int32_t unit, int32_t number, u_int32_t what, u_int32_t flags));
-static errval st_rewind __P((u_int32_t unit, boolean immed, u_int32_t flags));
-static errval st_erase __P((u_int32_t unit, boolean immed, u_int32_t flags));
-static errval st_mode_sense __P((u_int32_t unit, u_int32_t flags, \
- struct tape_pages *page, u_int32_t pagelen, u_int32_t pagecode));
-static errval st_decide_mode __P((u_int32_t unit, boolean first_read));
-static errval st_read __P((u_int32_t unit, char *buf, u_int32_t size,
- u_int32_t flags));
-static errval st_rd_blk_lim __P((u_int32_t unit, u_int32_t flags));
-static errval st_touch_tape __P((u_int32_t unit));
-static errval st_write_filemarks __P((u_int32_t unit, int32_t number, u_int32_t flags));
-static errval st_load __P((u_int32_t unit, u_int32_t type, u_int32_t flags));
-static errval st_mode_select __P((u_int32_t unit, u_int32_t flags, \
- struct tape_pages *page, u_int32_t pagelen, u_int32_t byte2));
-static errval st_comp __P((u_int32_t unit, u_int32_t mode));
-static int32_t st_chkeod __P((u_int32_t unit, boolean position, int32_t *nmarks,
- u_int32_t flags));
-static void ststart(u_int32_t unit, u_int32_t flags);
-static void st_unmount __P((int unit, boolean eject));
-static errval st_mount_tape __P((dev_t dev, u_int32_t flags));
-static void st_loadquirks __P((struct scsi_link *sc_link));
-static errval st_interpret_sense __P((struct scsi_xfer *xs));
-
-#define ESUCCESS 0
-#define NOEJECT 0
-#define EJECT 1
-
-struct scsi_data {
-/*--------------------present operating parameters, flags etc.----------------*/
- u_int32_t flags; /* see below */
- u_int32_t blksiz; /* blksiz we are using */
- u_int32_t density; /* present density */
- u_int32_t comp; /* present compression mode */
- u_int32_t quirks; /* quirks for the open mode */
- u_int32_t last_dsty; /* last density openned */
-/*--------------------parameters reported by the device ----------------------*/
- u_int32_t blkmin; /* min blk size */
- u_int32_t blkmax; /* max blk size */
-/*--------------------parameters reported by the device for this media--------*/
- u_int32_t numblks; /* nominal blocks capacity */
- u_int32_t media_blksiz; /* 0 if not ST_FIXEDBLOCKS */
- u_int32_t media_density; /* this is what it said when asked */
-/*--------------------quirks for the whole drive------------------------------*/
- u_int32_t drive_quirks; /* quirks of this drive */
-/*--------------------How we should set up when openning each minor device----*/
- st_modes modes; /* plus more for each mode */
- u_int8_t modeflags[4]; /* flags for the modes */
-#define DENSITY_SET_BY_USER 0x01
-#define DENSITY_SET_BY_QUIRK 0x02
-#define BLKSIZE_SET_BY_USER 0x04
-#define BLKSIZE_SET_BY_QUIRK 0x08
-#define COMPRES_SET_BY_USER 0x10
-#define COMPRES_SET_BY_QUIRK 0x20
-/*--------------------storage for sense data returned by the drive------------*/
- unsigned char saved_page0[PAGE_0_SENSE_DATA_SIZE]; /*
- * additional sense data needed
- * for mode sense/select.
- */
- struct buf_queue_head buf_queue;
- struct scsi_xfer scsi_xfer; /* scsi xfer struct for this drive */
- u_int32_t xfer_block_wait; /* is a process waiting? */
-#ifdef DEVFS
- struct {
- void *rst;
- void *nrst;
- void *erst;
- /* end of aliases */
- void *rst_[4];
- void *nrst_[4];
- void *erst_[4];
- void *ctl_[4];
- void *ctl;
- } devfs_token;
-#endif
-};
-
-static int stunit(dev_t dev) { return STUNIT(dev); }
-static dev_t stsetunit(dev_t dev, int unit) { return STSETUNIT(dev, unit); }
-
-static errval st_open(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-static errval st_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag,
- struct proc *p, struct scsi_link *sc_link);
-static errval st_close(dev_t dev, int flag, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-static void st_strategy(struct buf *bp, struct scsi_link *sc_link);
-
-static d_open_t stopen;
-static d_read_t stread;
-static d_write_t stwrite;
-static d_close_t stclose;
-static d_ioctl_t stioctl;
-static d_strategy_t ststrategy;
-
-#define CDEV_MAJOR 14
-#define BDEV_MAJOR 5
-static struct cdevsw st_cdevsw = {
- stopen, stclose, stread, stwrite,
- stioctl, nostop, nullreset, nodevtotty,
- seltrue, nommap, ststrategy, "st",
- NULL, -1 };
-
-SCSI_DEVICE_ENTRIES(st)
-
-static struct scsi_device st_switch =
-{
- st_interpret_sense, /* check errors with us first */
- ststart, /* we have a queue, and this is how we service it */
- NULL,
- NULL, /* use the default 'done' routine */
- "st",
- 0,
- {0, 0},
- 0, /* Link flags */
- stattach,
- "Sequential-Access",
- stopen,
- sizeof(struct scsi_data),
- T_SEQUENTIAL,
- stunit,
- stsetunit,
- st_open,
- st_ioctl,
- st_close,
- st_strategy,
-};
-
-#define ST_INITIALIZED 0x01
-#define ST_INFO_VALID 0x02
-#define ST_OPEN 0x04
-#define ST_BLOCK_SET 0x08 /* block size, mode set by ioctl */
-#define ST_WRITTEN 0x10 /* data have been written, EOD needed */
-#define ST_FIXEDBLOCKS 0x20
-#define ST_AT_FILEMARK 0x40
-#define ST_EIO_PENDING 0x80 /* we couldn't report it then (had data) */
-#define ST_NEW_MOUNT 0x100 /* still need to decide mode */
-#define ST_READONLY 0x200 /* st_mode_sense says write protected */
-#define ST_FM_WRITTEN 0x400 /*
- * EOF file mark written -- used with
- * ~ST_WRITTEN to indicate that multiple file
- * marks have been written
- */
-#define ST_BLANK_READ 0x800 /* BLANK CHECK encountered already */
-#define ST_2FM_AT_EOD 0x1000 /* write 2 file marks at EOD */
-#define ST_MOUNTED 0x2000 /* Device is presently mounted */
-#define ST_SENSE_READ 0x4000 /* mode sense read from drive */
-
-#define ST_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ)
-#define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
- ST_FIXEDBLOCKS | ST_READONLY | \
- ST_FM_WRITTEN | ST_2FM_AT_EOD | ST_PER_ACTION)
-
-/*
- * The routine called by the low level scsi routine when it discovers
- * a device suitable for this driver
- */
-
-static errval
-stattach(struct scsi_link *sc_link)
-{
- u_int32_t unit;
-#ifdef DEVFS
- int ii;
-#endif /*DEVFS*/
-
- struct scsi_data *st = sc_link->sd;
-
- unit = sc_link->dev_unit;
-
- bufq_init(&st->buf_queue);
- /*
- * Check if the drive is a known criminal and take
- * Any steps needed to bring it into line
- */
- st_loadquirks(sc_link);
- /*
- * Use the subdriver to request information regarding
- * the drive. We cannot use interrupts yet, so the
- * request must specify this.
- */
- if (st_mode_sense(unit, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT,
- NULL, 0, 0)) {
- printf("drive offline");
- } else {
- printf("density code 0x%lx, ", (u_long)st->media_density);
- if (!scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT)) {
- if (st->media_blksiz) {
- printf("%lu-byte", (u_long)st->media_blksiz);
- } else {
- printf("variable");
- }
- printf(" blocks, write-%s",
- (st->flags & ST_READONLY) ? "protected" : "enabled");
- } else {
- printf(" drive empty");
- }
- }
- /*
- * Set up the buf queue for this device
- */
- st->flags |= ST_INITIALIZED;
-#ifdef DEVFS
- for(ii=0; ii<4; ii++) {
- st->devfs_token.rst_[ii] =
- devfs_add_devswf(&st_cdevsw,
- (unit << 4 ) + (ii * 4), DV_CHR,
- UID_ROOT, GID_OPERATOR, 0660,
- "rst%lu.%d", (u_long)unit, ii);
- st->devfs_token.nrst_[ii] =
- devfs_add_devswf(&st_cdevsw,
- (unit << 4 ) + ((ii * 4) + 1), DV_CHR,
- UID_ROOT, GID_OPERATOR, 0660,
- "nrst%lu.%d", (u_long)unit, ii);
- st->devfs_token.erst_[ii] =
- devfs_add_devswf(&st_cdevsw,
- (unit << 4 ) + ((ii * 4) + 2), DV_CHR,
- UID_ROOT, GID_OPERATOR, 0660,
- "erst%lu.%d", (u_long)unit, ii);
- st->devfs_token.ctl_[ii] =
- devfs_add_devswf(&st_cdevsw,
- (unit << 4 ) + ((ii * 4) + 3), DV_CHR,
- UID_ROOT, GID_OPERATOR, 0600,
- "st%luctl.%d", (u_long)unit, ii);
- }
-
- st->devfs_token.ctl =
- devfs_add_devswf(&st_cdevsw, (unit << 4 ) | SCSI_CONTROL_MASK,
- DV_CHR, UID_ROOT, GID_WHEEL, 0600,
- "rst%d.ctl", unit);
- /** add links **/
- st->devfs_token.rst =
- devfs_link(st->devfs_token.rst_[0], "rst%lu", (u_long)unit);
- st->devfs_token.nrst =
- devfs_link(st->devfs_token.nrst_[0], "nrst%lu", (u_long)unit);
- st->devfs_token.erst =
- devfs_link(st->devfs_token.erst_[0], "erst%lu", (u_long)unit);
-#endif
- return 0;
-}
-
-
-/*
- * initialise the subdevices to the default (QUIRK) state.
- * this will remove any setting made by the system operator or previous
- * operations.
- */
-static void
-st_loadquirks(sc_link)
- struct scsi_link *sc_link;
-{
- struct scsi_data *st = sc_link->sd;
- int i;
- struct st_mode *mode;
- struct st_mode *mode2;
-
- mode = (struct st_mode*) sc_link->devmodes;
- if (!mode)
- return;
-
- st->quirks = st->drive_quirks = sc_link->quirks;
-
- mode2 = st->modes;
-
- for (i = 0; i < 4; i++) {
- bzero(mode2, sizeof(*mode2));
- st->modeflags[i] &= ~(BLKSIZE_SET_BY_QUIRK
- | DENSITY_SET_BY_QUIRK
- | BLKSIZE_SET_BY_USER
- | DENSITY_SET_BY_USER);
- if (mode->blksiz && ((mode->quirks | st->drive_quirks)
- & (ST_Q_FORCE_FIXED_MODE))) {
- mode2->blksiz = mode->blksiz;
- st->modeflags[i] |= BLKSIZE_SET_BY_QUIRK;
- } else {
- if ((mode->quirks | st->drive_quirks)
- & ST_Q_FORCE_VAR_MODE) {
- mode2->blksiz = 0;
- st->modeflags[i] |= BLKSIZE_SET_BY_QUIRK;
- }
- }
- if (mode->density) {
- mode2->density = mode->density;
- st->modeflags[i] |= DENSITY_SET_BY_QUIRK;
- }
- mode++;
- mode2++;
- }
-}
-
-/*
- * open the device.
- */
-static errval
-st_open(dev_t dev, int flags, int fmt, struct proc *p,
-struct scsi_link *sc_link)
-{
- u_int32_t unit, mode, dsty;
- errval errno = 0;
- struct scsi_data *st;
-
- unit = STUNIT(dev);
- mode = MODE(dev);
- dsty = DSTY(dev);
-
- st = sc_link->sd;
- /*
- * Make sure the device has been initialised
- */
- if ((st == NULL) || (!(st->flags & ST_INITIALIZED)))
- return (ENXIO);
-
- /*
- * Only allow one at a time
- */
- if (st->flags & ST_OPEN) {
- return (EBUSY);
- }
- /*
- * Throw out a dummy instruction to catch 'Unit attention
- * errors (the error handling will invalidate all our
- * device info if we get one, but otherwise, ignore it)
- */
- scsi_test_unit_ready(sc_link, SCSI_SILENT);
-
- sc_link->flags |= SDEV_OPEN; /* unit attn are now errors */
- /*
- * If the mode is 3 (e.g. minor = 3,7,11,15)
- * then the device has been openned to set defaults
- * This mode does NOT ALLOW I/O, only ioctls.
- * XXX: Where do we lock out I/O?
- */
- if (IS_CTLMODE(dev))
- return 0;
-
- /*
- * Check that the device is ready to use (media loaded?)
- * This time take notice of the return result
- */
- if ( (errno = scsi_test_unit_ready(sc_link, 0)) ) {
- uprintf("st%d: not ready\n", unit);
- st_unmount(unit, NOEJECT);
- return (errno);
- }
- /*
- * if it's a different mode, or if the media has been
- * invalidated, unmount the tape from the previous
- * session but continue with open processing
- */
- if ((st->last_dsty != dsty)
- || (!(sc_link->flags & SDEV_MEDIA_LOADED))) {
- st_unmount(unit, NOEJECT);
- }
- /*
- * If we are not mounted, then we should start a new
- * mount session.
- */
- if (!(st->flags & ST_MOUNTED)) {
- st_mount_tape(dev, flags);
- st->last_dsty = dsty;
- }
- /*
- * Make sure that a tape opened in write-only mode will have
- * file marks written on it when closed, even if not written to.
- * This is for SUN compatibility
- */
- if (flags & FWRITE)
- st->flags |= ST_WRITTEN;
-
- /* PREVENT ALLOW MEDIUM REMOVAL is optional per the SCSI-2 specs */
- scsi_prevent(sc_link, PR_PREVENT, SCSI_SILENT | SCSI_ERR_OK);
-
- SC_DEBUG(sc_link, SDEV_DB2, ("Open complete\n"));
-
- st->flags |= ST_OPEN;
- return 0;
-}
-
-/*
- * close the device.. only called if we are the LAST
- * occurence of an open device
- */
-static errval
-st_close(dev_t dev, int flag, int fmt, struct proc *p,
- struct scsi_link *sc_link)
-{
- u_int32_t unit, mode;
- struct scsi_data *st;
- errval errcode = 0;
-
- unit = STUNIT(dev);
- mode = MODE(dev);
- st = sc_link->sd;
-
- if ((st->flags & (ST_WRITTEN | ST_FM_WRITTEN)) == ST_WRITTEN)
- errcode = st_write_filemarks(unit, 1, 0);
-
- /*
- * Since the device has seen its last close, allow media removal.
- * Do this before we attempt an eject.
- */
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
-
- switch (mode & 0x3) {
- case 0:
- case 3: /* for now */
- st_unmount(unit, NOEJECT);
- break;
- case 1: /*leave mounted unless media seems to have been removed */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- st_unmount(unit, NOEJECT);
- }
- break;
- case 2:
- st_unmount(unit, EJECT);
- break;
- }
-
- sc_link->flags &= ~SDEV_OPEN;
- st->flags &= ~ST_OPEN;
-
- return (errcode);
-}
-
-/*
- * Start a new mount session.
- * Copy in all the default parameters from the selected device mode.
- * and try guess any that seem to be defaulted.
- */
-static errval
-st_mount_tape(dev, flags)
- dev_t dev;
- u_int32_t flags;
-{
- u_int32_t unit, mode, dsty;
- struct scsi_data *st;
- struct scsi_link *sc_link;
- errval errno = 0;
-
- unit = STUNIT(dev);
- mode = MODE(dev);
- dsty = DSTY(dev);
- sc_link = SCSI_LINK(&st_switch, unit);
- st = sc_link->sd;
-
- if (st->flags & ST_MOUNTED)
- return 0;
-
- SC_DEBUG(sc_link, SDEV_DB1, ("mounting\n "));
- st->flags |= ST_NEW_MOUNT;
- st->quirks = st->drive_quirks | st->modes[dsty].quirks;
- /*
- * If the media is new, then make sure we give it a chance to
- * to do a 'load' instruction. ( We assume it is new)
- */
- if ( (errno = st_load(unit, LD_LOAD, 0)) ) {
- return (errno);
- }
- /*
- * Throw another dummy instruction to catch
- * 'Unit attention' errors. Some drives appear to give
- * these after doing a Load instruction.
- * (noteably some DAT drives)
- */
- scsi_test_unit_ready(sc_link, SCSI_SILENT);
-
- /*
- * Some devices can't tell you much until they have been
- * asked to look at the media. This quirk does this.
- */
- if (st->quirks & ST_Q_SNS_HLP) {
- if ( (errno = st_touch_tape(unit)) )
- return errno;
- }
- /*
- * Load the physical device parameters
- * loads: blkmin, blkmax
- */
- if ( (errno = st_rd_blk_lim(unit, 0)) ) {
- return errno;
- }
- /*
- * Load the media dependent parameters
- * includes: media_blksiz,media_density,numblks
- * As we have a tape in, it should be reflected here.
- * If not you may need the "quirk" above.
- */
- if ( (errno = st_mode_sense(unit, 0, NULL, 0, 0)) ) {
- return errno;
- }
- /*
- * If we have gained a permanent density from somewhere,
- * then use it in preference to the one supplied by
- * default by the driver.
- */
- if (st->modeflags[dsty] & (DENSITY_SET_BY_QUIRK | DENSITY_SET_BY_USER)) {
- st->density = st->modes[dsty].density;
- } else {
- st->density = st->media_density;
- }
- /*
- * If we have gained a permanent blocksize
- * then use it in preference to the one supplied by
- * default by the driver.
- */
- st->flags &= ~ST_FIXEDBLOCKS;
- if (st->modeflags[dsty] & (BLKSIZE_SET_BY_QUIRK | BLKSIZE_SET_BY_USER)) {
- st->blksiz = st->modes[dsty].blksiz;
- if (st->blksiz) {
- st->flags |= ST_FIXEDBLOCKS;
- }
- } else {
- if ( (errno = st_decide_mode(unit, FALSE)) ) {
- return errno;
- }
- }
- if ( (errno = st_mode_select(unit, 0, NULL, 0, 0)) ) {
- printf("st%lu: Cannot set selected mode", (u_long)unit);
- return errno;
- }
- st->flags &= ~ST_NEW_MOUNT;
- st->flags |= ST_MOUNTED;
- sc_link->flags |= SDEV_MEDIA_LOADED;
-
- return 0;
-}
-
-/*
- * End the present mount session.
- * Rewind, and optionally eject the tape.
- * Reset various flags to indicate that all new
- * operations require another mount operation
- */
-void
-st_unmount(int unit, boolean eject)
-{
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
- int32_t nmarks;
-
- if (!(st->flags & ST_MOUNTED))
- return;
- SC_DEBUG(sc_link, SDEV_DB1, ("unmounting\n"));
- st_chkeod(unit, FALSE, &nmarks, SCSI_SILENT);
- st_rewind(unit, FALSE, SCSI_SILENT);
- if (eject) {
- st_load(unit, LD_UNLOAD, SCSI_SILENT);
- }
- st->flags &= ~(ST_MOUNTED | ST_NEW_MOUNT);
- sc_link->flags &= ~SDEV_MEDIA_LOADED;
-}
-
-/*
- * Given all we know about the device, media, mode, 'quirks' and
- * initial operation, make a decision as to how we should be set
- * to run (regarding blocking and EOD marks)
- */
-static errval
-st_decide_mode(unit, first_read)
- u_int32_t unit;
- boolean first_read;
-{
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("starting block mode decision\n"));
-
- /*
- * If the user hasn't already specified fixed or variable-length
- * blocks and the block size (zero if variable-length), we'll
- * have to try to figure them out ourselves.
- *
- * Our first shot at a method is, "The quirks made me do it!"
- */
- switch ((int)(st->quirks & (ST_Q_FORCE_FIXED_MODE | ST_Q_FORCE_VAR_MODE))) {
- case (ST_Q_FORCE_FIXED_MODE | ST_Q_FORCE_VAR_MODE):
- printf("st%lu: bad quirks\n", (u_long)unit);
- return (EINVAL);
- case ST_Q_FORCE_FIXED_MODE: /*specified fixed, but not what size */
- st->flags |= ST_FIXEDBLOCKS;
- if (st->blkmin && (st->blkmin == st->blkmax))
- st->blksiz = st->blkmin;
- else if (st->media_blksiz > 0)
- st->blksiz = st->media_blksiz;
- else
- st->blksiz = DEF_FIXED_BSIZE;
- SC_DEBUG(sc_link, SDEV_DB3, ("Quirks force fixed mode(%lu)\n",
- (u_long)st->blksiz));
- goto done;
- case ST_Q_FORCE_VAR_MODE:
- st->flags &= ~ST_FIXEDBLOCKS;
- st->blksiz = 0;
- SC_DEBUG(sc_link, SDEV_DB3, ("Quirks force variable mode\n"));
- goto done;
- }
- /*
- * If the drive can only handle fixed-length blocks and only at
- * one size, perhaps we should just do that.
- */
- if (st->blkmin && (st->blkmin == st->blkmax)) {
- st->flags |= ST_FIXEDBLOCKS;
- st->blksiz = st->blkmin;
- SC_DEBUG(sc_link, SDEV_DB3,
- ("blkmin == blkmax of %lu\n", (u_long)st->blkmin));
- goto done;
- }
- /*
- * If the tape density mandates (or even suggests) use of fixed
- * or variable-length blocks, comply.
- */
- switch ((int)st->density) {
- case HALFINCH_800:
- case HALFINCH_1600:
- case HALFINCH_6250:
- case DDS:
- case QIC_525:
- case QIC_1320:
- case QIC_3080:
- st->flags &= ~ST_FIXEDBLOCKS;
- st->blksiz = 0;
- SC_DEBUG(sc_link, SDEV_DB3, ("density specified variable\n"));
- goto done;
- case QIC_11:
- case QIC_24:
- case QIC_120:
- case QIC_150:
- st->flags |= ST_FIXEDBLOCKS;
- if (st->media_blksiz > 0) {
- st->blksiz = st->media_blksiz;
- } else {
- st->blksiz = DEF_FIXED_BSIZE;
- }
- SC_DEBUG(sc_link, SDEV_DB3, ("density specified fixed\n"));
- goto done;
- }
- /*
- * If we're about to read the tape, perhaps we should choose
- * fixed or variable-length blocks and block size according to
- * what the drive found on the tape.
- */
- if (first_read
- && (!(st->quirks & ST_Q_BLKSIZ)
- || (st->media_blksiz == 0)
- || (st->media_blksiz == DEF_FIXED_BSIZE)
- || (st->media_blksiz == 1024))) {
- if (st->media_blksiz == 0) {
- st->flags &= ~ST_FIXEDBLOCKS;
- } else {
- st->flags |= ST_FIXEDBLOCKS;
- }
- st->blksiz = st->media_blksiz;
- SC_DEBUG(sc_link, SDEV_DB3,
- ("Used media_blksiz of %lu\n", (u_long)st->media_blksiz));
- goto done;
- }
- /*
- * We're getting no hints from any direction. Choose variable-
- * length blocks arbitrarily.
- */
- st->flags &= ~ST_FIXEDBLOCKS;
- st->blksiz = 0;
- SC_DEBUG(sc_link, SDEV_DB3, ("Give up and default to variable mode\n"));
-done:
-
- /*
- * Decide whether or not to write two file marks to signify end-
- * of-data. Make the decision as a function of density. If
- * the decision is not to use a second file mark, the SCSI BLANK
- * CHECK condition code will be recognized as end-of-data when
- * first read.
- * (I think this should be a by-product of fixed/variable..julian)
- */
- switch ((int)st->density) {
-/* case 8 mm: What is the SCSI density code for 8 mm, anyway? */
- case QIC_11:
- case QIC_24:
- case QIC_120:
- case QIC_150:
- case QIC_525:
- case QIC_1320:
- case QIC_3080:
- st->flags &= ~ST_2FM_AT_EOD;
- break;
- default:
- st->flags |= ST_2FM_AT_EOD;
- }
- return 0;
-}
-
-static int
-stread(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(ststrategy, NULL, dev, 1, minphys, uio));
-}
-
-static int
-stwrite(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(ststrategy, NULL, dev, 0, minphys, uio));
-}
-
-/*
- * Actually translate the requested transfer into
- * one the physical driver can understand
- * The transfer is described by a buf and will include
- * only one physical transfer.
- */
-static void
-st_strategy(struct buf *bp, struct scsi_link *sc_link)
-{
- u_int32_t unit;
- u_int32_t opri;
- struct scsi_data *st;
- int len;
-
- unit = STUNIT((bp->b_dev));
- st = sc_link->sd;
- /*
- * If it's a null transfer, return immediatly
- */
- if ((len = bp->b_bcount) == 0) {
- goto done;
- }
- /*
- * Check the adapter can do it
- */
- scsi_minphys(bp,&st_switch);
- /*
- * Odd sized request on fixed drives are verboten
- */
- if (st->flags & ST_FIXEDBLOCKS) {
- if (bp->b_bcount % st->blksiz) {
- printf("st%lu: bad request, must be multiple of %lu\n",
- (u_long)unit, (u_long)st->blksiz);
- bp->b_error = EIO;
- goto bad;
- }
- }
- /*
- * as are out-of-range requests on variable drives.
- * (or if we got chopped by minphys)
- */
- else {
- if ((bp->b_bcount < st->blkmin || bp->b_bcount > st->blkmax)) {
- printf(
- "st%lu: bad request, must be between %lu and %lu\n",
- (u_long)unit, (u_long)st->blkmin,
- (u_long)st->blkmax);
- bp->b_error = EIO;
- goto bad;
- }
- if (len != bp->b_bcount) {
- printf(
- "st%lu: bad request, must be less than %ld bytes\n",
- (u_long)unit, bp->b_bcount + 1);
- bp->b_error = EIO;
- goto bad;
- }
- }
- opri = splbio();
-
- /*
- * Use a bounce buffer if necessary
- */
-#ifdef BOUNCE_BUFFERS
- if (sc_link->flags & SDEV_BOUNCE)
- vm_bounce_alloc(bp);
-#endif
-
- /*
- * Place it in the queue of activities for this tape
- * at the end (a bit silly because we only have on user..
- * (but it could fork() ))
- */
- bufq_insert_tail(&st->buf_queue, bp);
-
- /*
- * Tell the device to get going on the transfer if it's
- * not doing anything, otherwise just wait for completion
- * (All a bit silly if we're only allowing 1 open but..)
- */
- ststart(unit, 0);
-
- splx(opri);
- return;
-bad:
- bp->b_flags |= B_ERROR;
-done:
- /*
- * Correctly set the buf to indicate a completed xfer
- */
- biodone(bp);
- return;
-}
-
-/*
- * ststart looks to see if there is a buf waiting for the device
- * and that the device is not already busy. If both are true,
- * It dequeues the buf and creates a scsi command to perform the
- * transfer required. The transfer request will call scsi_done
- * on completion, which will in turn call this routine again
- * so that the next queued transfer is performed.
- * The bufs are queued by the strategy routine (ststrategy)
- *
- * This routine is also called after other non-queued requests
- * have been made of the scsi driver, to ensure that the queue
- * continues to be drained.
- * ststart() is called at splbio
- */
-static void
-ststart(unit, flags)
- u_int32_t unit;
- u_int32_t flags;
-{
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
- register struct buf *bp = 0;
- struct scsi_rw_tape cmd;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("ststart "));
- /*
- * See if there is a buf to do and we are not already
- * doing one
- */
- while (sc_link->opennings != 0) {
-
- /* if a special awaits, let it proceed first */
- if (sc_link->flags & SDEV_WAITING) {
- sc_link->flags &= ~SDEV_WAITING;
- wakeup((caddr_t)sc_link);
- return;
- }
-
- bp = bufq_first(&st->buf_queue);
- if (bp == NULL) { /* yes, an assign */
- return;
- }
- bufq_remove(&st->buf_queue, bp);
-
- /*
- * if the device has been unmounted by the user
- * then throw away all requests until done
- */
- if ((!(st->flags & ST_MOUNTED))
- || (!(sc_link->flags & SDEV_MEDIA_LOADED))) {
- /* make sure that one implies the other.. */
- sc_link->flags &= ~SDEV_MEDIA_LOADED;
- goto badnews;
- }
- /*
- * only FIXEDBLOCK devices have pending operations
- */
- if (st->flags & ST_FIXEDBLOCKS) {
- /*
- * If we are at a filemark but have not reported it yet
- * then we should report it now
- */
- if (st->flags & ST_AT_FILEMARK) {
- if ((bp->b_flags & B_READ) == B_WRITE) {
- /*
- * Handling of ST_AT_FILEMARK in
- * st_space will fill in the right file
- * mark count.
- * Back up over filemark
- */
- if (st_space(unit, 0, SP_FILEMARKS, 0) !=
- ESUCCESS)
- goto badnews;
- } else {
- bp->b_resid = bp->b_bcount;
- bp->b_error = 0;
- bp->b_flags &= ~B_ERROR;
- st->flags &= ~ST_AT_FILEMARK;
- biodone(bp);
- continue; /* seek more work */
- }
- }
- /*
- * If we are at EIO (e.g. EOM) but have not reported it
- * yet then we should report it now
- */
- if (st->flags & ST_EIO_PENDING) {
- bp->b_resid = bp->b_bcount;
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- st->flags &= ~ST_EIO_PENDING;
- biodone(bp);
- continue; /* seek more work */
- }
- }
- /*
- * Fill out the scsi command
- */
- bzero(&cmd, sizeof(cmd));
- if ((bp->b_flags & B_READ) == B_WRITE) {
- cmd.op_code = WRITE_COMMAND_TAPE;
- st->flags &= ~ST_FM_WRITTEN;
- st->flags |= ST_WRITTEN;
- flags |= SCSI_DATA_OUT;
- } else {
- cmd.op_code = READ_COMMAND_TAPE;
- flags |= SCSI_DATA_IN;
- }
- /*
- * Handle "fixed-block-mode" tape drives by using the
- * block count instead of the length.
- */
- if (st->flags & ST_FIXEDBLOCKS) {
- cmd.byte2 |= SRWT_FIXED;
- scsi_uto3b(bp->b_bcount / st->blksiz, cmd.len);
- } else {
- scsi_uto3b(bp->b_bcount, cmd.len);
- }
- /*
- * go ask the adapter to do all this for us
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- (u_char *) bp->b_data,
- bp->b_bcount,
- 0, /* can't retry a read on a tape really */
- 1000000,
- bp,
- flags) == SUCCESSFULLY_QUEUED) {
- } else {
-badnews:
- printf("st%lu: oops not queued\n", (u_long)unit);
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- biodone(bp);
- }
- } /* go back and see if we can cram more work in.. */
-}
-
-/*
- * Perform special action on behalf of the user;
- * knows about the internals of this device
- */
-static errval
-st_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag,
-struct proc *p, struct scsi_link *sc_link)
-{
- errval errcode = 0;
- u_int32_t unit;
- u_int32_t number, flags, dsty;
- struct scsi_data *st;
- u_int32_t hold_blksiz;
- u_int32_t hold_density;
- int32_t nmarks;
- struct mtop *mt = (struct mtop *) arg;
-
- /*
- * Find the device that the user is talking about
- */
- flags = 0; /* give error messages, act on errors etc. */
- unit = STUNIT(dev);
- dsty = DSTY(dev);
- st = sc_link->sd;
- hold_blksiz = st->blksiz;
- hold_density = st->density;
-
- switch (cmd) {
-
- case MTIOCGET:
- {
- struct mtget *g = (struct mtget *) arg;
-
- SC_DEBUG(sc_link, SDEV_DB1, ("[ioctl: get status]\n"));
- bzero(g, sizeof(struct mtget));
- g->mt_type = 0x7; /* Ultrix compat *//*? */
- g->mt_density = st->density;
- g->mt_blksiz = st->blksiz;
- g->mt_comp = st->comp;
- g->mt_density0 = st->modes[0].density;
- g->mt_density1 = st->modes[1].density;
- g->mt_density2 = st->modes[2].density;
- g->mt_density3 = st->modes[3].density;
- g->mt_blksiz0 = st->modes[0].blksiz;
- g->mt_blksiz1 = st->modes[1].blksiz;
- g->mt_blksiz2 = st->modes[2].blksiz;
- g->mt_blksiz3 = st->modes[3].blksiz;
- g->mt_comp0 = 0;
- g->mt_comp1 = 0;
- g->mt_comp2 = 0;
- g->mt_comp3 = 0;
- break;
- }
- case MTIOCTOP:
- {
-
- SC_DEBUG(sc_link, SDEV_DB1,
- ("[ioctl: op=0x%x count=0x%lx]\n",
- mt->mt_op, (long)mt->mt_count));
-
- /* compat: in U*x it is a short */
- number = mt->mt_count;
- switch ((short) (mt->mt_op)) {
- case MTWEOF: /* write an end-of-file record */
- errcode = st_write_filemarks(unit, number, flags);
- break;
- case MTBSF: /* backward space file */
- number = -number;
- case MTFSF: /* forward space file */
- errcode = st_chkeod(unit, FALSE, &nmarks, flags);
- if (errcode == ESUCCESS)
- errcode = st_space(unit, number - nmarks,
- SP_FILEMARKS, flags);
- break;
- case MTBSR: /* backward space record */
- number = -number;
- case MTFSR: /* forward space record */
- errcode = st_chkeod(unit, TRUE, &nmarks, flags);
- if (errcode == ESUCCESS)
- errcode = st_space(unit, number, SP_BLKS, flags);
- break;
- case MTEOD: /* space to end of recorded medium */
- errcode = st_chkeod(unit, FALSE, &nmarks, flags);
- if (errcode == ESUCCESS)
- errcode = st_space(unit, 0, SP_EOM,
- flags);
- break;
- case MTREW: /* rewind */
- errcode = st_rewind(unit, FALSE, flags);
- break;
- case MTERASE: /* erase */
- errcode = st_erase(unit, FALSE, flags);
- break;
- case MTRETENS: /* re-tension tape */
- errcode = st_load(unit, LD_LOAD|LD_RETEN,
- flags);
- break;
- case MTOFFL: /* rewind and put the drive offline */
- /*
- * Be sure to allow media removal before
- * attempting the eject.
- */
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
- st_unmount(unit, EJECT);
- break;
- case MTNOP: /* no operation, sets status only */
- case MTCACHE: /* enable controller cache */
- case MTNOCACHE: /* disable controller cache */
- break;
- case MTSETBSIZ: /* Set block size for device */
-#ifdef NOTYET
- if (!(st->flags & ST_NEW_MOUNT)) {
- uprintf("re-mount tape before changing blocksize");
- errcode = EINVAL;
- break;
- }
-#endif
- if (number == 0) {
- st->flags &= ~ST_FIXEDBLOCKS;
- } else {
- if ((st->blkmin || st->blkmax) /* they exist */
- &&((number < st->blkmin
- || number > st->blkmax))) {
- errcode = EINVAL;
- break;
- }
- st->flags |= ST_FIXEDBLOCKS;
- }
- st->blksiz = number;
- st->flags |= ST_BLOCK_SET; /*XXX */
- goto try_new_value;
-
- case MTSETDNSTY: /* Set density for device and mode */
- if (number > (u_int8_t)0xff) {
- /* Guard against overflows */
- errcode = EINVAL;
- } else {
- st->density = number;
- goto try_new_value;
- }
- break;
- case MTCOMP: /* enable default compression */
- errcode = st_comp(unit,number);
- break;
- default:
- errcode = EINVAL;
- }
- break;
- }
- case MTIOCIEOT:
- case MTIOCEEOT:
- break;
- default:
- if(IS_CTLMODE(dev))
- errcode = scsi_do_ioctl(dev, cmd, arg, flag, p, sc_link);
- else
- errcode = ENOTTY;
- break;
- }
- return errcode;
-/*-----------------------------*/
-try_new_value:
- /*
- * Check that the mode being asked for is aggreeable to the
- * drive. If not, put it back the way it was.
- */
- if ( (errcode = st_mode_select(unit, 0, NULL, 0, 0)) ) {
- /*
- * put back as it was
- */
- printf("st%lu: Cannot set selected mode", (u_long)unit);
- st->density = hold_density;
- st->blksiz = hold_blksiz;
- if (st->blksiz) {
- st->flags |= ST_FIXEDBLOCKS;
- } else {
- st->flags &= ~ST_FIXEDBLOCKS;
- }
- return (errcode);
- }
- /*
- * As the drive liked it, if we are setting a new default,
- * set it into the structures as such.
- *
- * The means for deciding this are not finalised yet
- */
- if (IS_CTLMODE(dev)) {
- /* special mode */
- /* XXX */
- switch ((short) (mt->mt_op)) {
- case MTSETBSIZ:
- st->modes[dsty].blksiz = st->blksiz;
- st->modeflags[dsty] |= BLKSIZE_SET_BY_USER;
- break;
- case MTSETDNSTY:
- st->modes[dsty].density = st->density;
- st->modeflags[dsty] |= DENSITY_SET_BY_USER;
- break;
- }
- }
- return 0;
-}
-
-/*
- * Do a synchronous read.
- */
-static errval
-st_read(unit, buf, size, flags)
- u_int32_t unit, size, flags;
- char *buf;
-{
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
- struct scsi_rw_tape scsi_cmd;
-
- /*
- * If it's a null transfer, return immediatly
- */
- if (size == 0) {
- return (ESUCCESS);
- }
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = READ_COMMAND_TAPE;
- if (st->flags & ST_FIXEDBLOCKS) {
- scsi_cmd.byte2 |= SRWT_FIXED;
- scsi_uto3b(size / (st->blksiz ? st->blksiz : DEF_FIXED_BSIZE),
- scsi_cmd.len);
- } else {
- scsi_uto3b(size, scsi_cmd.len);
- }
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) buf,
- size,
- 0, /* not on io commands */
- 1000000,
- NULL,
- flags | SCSI_DATA_IN));
-}
-#ifdef __STDC__
-#define b2tol(a) (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
-#else
-#define b2tol(a) (((unsigned)(a/**/_1) << 8) + (unsigned)a/**/_0 )
-#endif
-
-/*
- * Ask the drive what its min and max blk sizes are.
- */
-static errval
-st_rd_blk_lim(unit, flags)
- u_int32_t unit, flags;
-{
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
- struct scsi_blk_limits scsi_cmd;
- struct scsi_blk_limits_data scsi_blkl;
- errval errno;
-
- /*
- * First check if we have it all loaded
- */
- if ((sc_link->flags & SDEV_MEDIA_LOADED))
- return 0;
-
- /*
- * do a 'Read Block Limits'
- */
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = READ_BLK_LIMITS;
-
- /*
- * do the command, update the global values
- */
- if ( (errno = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) & scsi_blkl,
- sizeof(scsi_blkl),
- ST_RETRIES,
- 5000,
- NULL,
- flags | SCSI_DATA_IN)) ) {
- return errno;
- }
- st->blkmin = b2tol(scsi_blkl.min_length);
- st->blkmax = scsi_3btou(&scsi_blkl.max_length_2);
-
- SC_DEBUG(sc_link, SDEV_DB3,
- ("(%lu <= blksiz <= %lu)\n",
- (u_long)st->blkmin, (u_long)st->blkmax));
- return 0;
-}
-
-/*
- * Get the scsi driver to send a full inquiry to the
- * device and use the results to fill out the global
- * parameter structure.
- *
- * called from:
- * attach
- * open
- * ioctl (to reset original blksize)
- */
-static errval
-st_mode_sense(unit, flags, page, pagelen, pagecode)
- u_int32_t unit, flags;
- struct tape_pages *page;
- u_int32_t pagelen,pagecode;
-{
- u_int32_t dat_len;
- errval errno;
- struct scsi_mode_sense scsi_cmd;
- struct {
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- struct tape_pages page;
- } dat;
-
- /* Tandberg tape drives returns page 00
- * with the sense data, whether or not
- * you want it( ie the don't like you
- * saying you want anything less!!!!!
- * They also expect page 00
- * back when you issue a mode select
- */
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
-
- st->flags &= ~ST_SENSE_READ;
- /*
- * Check if we need to use a default page..
- */
- if ((st->quirks & ST_Q_NEEDS_PAGE_0) && (!page)) {
- pagelen = PAGE_0_SENSE_DATA_SIZE;
- page = (struct tape_pages *) st->saved_page0;
- pagecode = 0;
- }
- /*
- * Now work out the total dat size etc.
- */
- dat_len = sizeof(struct scsi_mode_header)
- + sizeof(struct blk_desc)
- + (page ? pagelen : 0);
- /*
- * Set up a mode sense
- */
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SENSE;
- scsi_cmd.page = (u_char) pagecode;
- scsi_cmd.length = dat_len;
-
- /*
- * do the command,
- * use the results to set blksiz, numblks and density
- * or if we need it as a template for the mode select
- * store it away.
- */
- if ( (errno = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) &dat,
- dat_len,
- ST_RETRIES,
- 5000,
- NULL,
- flags | SCSI_DATA_IN)) ) {
- return errno;
- }
- st->numblks = scsi_3btou(dat.blk_desc.nblocks);
- st->media_blksiz = scsi_3btou(dat.blk_desc.blklen);
- st->media_density = dat.blk_desc.density;
- if (dat.header.dev_spec & SMH_DSP_WRITE_PROT) {
- st->flags |= ST_READONLY;
- }
- SC_DEBUG(sc_link, SDEV_DB3,
- ("density code 0x%lx, %lu-byte blocks, write-%s, ",
- (u_long)st->media_density, (u_long)st->media_blksiz,
- st->flags & ST_READONLY ? "protected" : "enabled"));
- SC_DEBUG(sc_link, SDEV_DB3, ("%sbuffered\n",
- ((dat.header.dev_spec & SMH_DSP_BUFF_MODE) ? "" : "un")));
- if (page) {
- bcopy(&dat.page, page, pagelen);
- }
- st->flags |= ST_SENSE_READ;
- return 0;
-}
-
-/*
- * Send a filled out parameter structure to the drive to
- * set it into the desire modes etc.
- */
-static errval
-st_mode_select(unit, flags, page, pagelen, byte2)
- u_int32_t unit, flags;
- struct tape_pages *page;
- u_int32_t pagelen;
- u_int32_t byte2;
-{
- u_int32_t dat_len;
- struct scsi_mode_select scsi_cmd;
- struct {
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- struct tape_pages page;
- } dat;
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
-
- /*
- * Check if we need to use a default page..
- * Gee, hope we saved one before now........
- */
- if ((st->quirks & ST_Q_NEEDS_PAGE_0) && (!page)) {
- pagelen = PAGE_0_SENSE_DATA_SIZE;
- page = (struct tape_pages *) st->saved_page0;
- }
- /*
- * Now work out the total dat size etc.
- */
- dat_len = sizeof(struct scsi_mode_header)
- + sizeof(struct blk_desc)
- + (page ? pagelen : 0);
- /*
- * Set up for a mode select
- */
- bzero(&dat, dat_len);
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SELECT;
- scsi_cmd.length = dat_len;
- scsi_cmd.byte2 = (u_char)byte2;
- dat.header.blk_desc_len = sizeof(struct blk_desc);
- dat.header.dev_spec |= SMH_DSP_BUFF_MODE_ON;
- dat.blk_desc.density = st->density;
- if (st->flags & ST_FIXEDBLOCKS) {
- scsi_uto3b(st->blksiz, dat.blk_desc.blklen);
- }
- if (page) {
- bcopy(page, &dat.page, pagelen);
- /* the Tandberg tapes need the block size to */
- /* be set on each mode sense/select. */
- }
- /*
- * do the command
- */
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) &dat,
- dat_len,
- ST_RETRIES,
- 5000,
- NULL,
- flags | SCSI_DATA_OUT));
-}
-
-static int noisy_st = 0;
-/***************************************************************\
-* Set the compression mode of the drive to on (1) or off (0) *
- still doesn't work! grrr!
-\***************************************************************/
-static errval
-st_comp(unit,mode)
-u_int32_t unit,mode;
-{
- struct tape_pages page;
- int pagesize;
- int retval;
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
-
- bzero(&page, sizeof(page));
- pagesize = sizeof(page.pages.configuration) + PAGE_HEADERLEN;
-
- if ( (retval = st_mode_sense(unit, 0,
- &page, pagesize, ST_PAGE_CONFIGURATION)) )
- {
- printf("sense returned an error of %d\n",retval);
- return retval;
- }
- if ( noisy_st)
- printf("drive reports value of %d, setting %lu\n",
- page.pages.configuration.data_compress_alg,
- (u_long)mode);
-
- page.pg_code &= ST_P_CODE;
- page.pg_length = sizeof(page.pages.configuration);
-
- switch(mode)
- {
- case 0:
- page.pages.configuration.data_compress_alg = 0;
- break;
- case 1:
- page.pages.configuration.data_compress_alg = 1;
- break;
- default:
- printf("st%lu: bad value for compression mode\n", (u_long)unit);
- return EINVAL;
- }
- /*
- * send ST_PAGE_CONFIGURATION page as SCSI-II command because it
- * is a SCSI-II structure. This requires the PF bit (0x10) to be
- * set for byte2.
- */
- if ( (retval = st_mode_select(unit, 0, &page, pagesize, 0x10)) )
- {
- printf("select returned an error of %d\n",retval);
- return retval;
- }
- st->comp = mode;
- return 0;
-}
-/*
- * skip N blocks/filemarks/seq filemarks/eom
- */
-static errval
-st_space(unit, number, what, flags)
- u_int32_t unit, what, flags;
- int32_t number;
-{
- errval error;
- struct scsi_space scsi_cmd;
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
-
- switch ((int)what) {
- case SP_BLKS:
- if (st->flags & ST_PER_ACTION) {
- if (number > 0) {
- st->flags &= ~ST_PER_ACTION;
- return (EIO);
- } else if (number < 0) {
- if (st->flags & ST_AT_FILEMARK) {
- /*
- * Handling of ST_AT_FILEMARK
- * in st_space will fill in the
- * right file mark count.
- */
- error = st_space(unit, 0, SP_FILEMARKS,
- flags);
- if (error)
- return (error);
- }
- if (st->flags & ST_BLANK_READ) {
- st->flags &= ~ST_BLANK_READ;
- return (EIO);
- }
- st->flags &= ~ST_EIO_PENDING;
- }
- }
- break;
- case SP_FILEMARKS:
- if (st->flags & ST_EIO_PENDING) {
- if (number > 0) { /* pretend we just discover the error */
- st->flags &= ~ST_EIO_PENDING;
- return (EIO);
- } else if (number < 0) { /* back away from the error */
- st->flags &= ~ST_EIO_PENDING;
- }
- }
- if (st->flags & ST_AT_FILEMARK) {
- st->flags &= ~ST_AT_FILEMARK;
- number--;
- }
- if ((st->flags & ST_BLANK_READ) && (number < 0)) { /* back away from unwritten tape */
- st->flags &= ~ST_BLANK_READ;
- number++; /* dubious */
- }
- break;
- case SP_EOM:
- if (st->flags & ST_EIO_PENDING)
- {
- /* we are already at EOM */
- st->flags &= ~ST_EIO_PENDING;
- return(ESUCCESS);
- }
- number = 1; /* we have only one end-of-medium */
- break;
- }
- if (number == 0) {
- return (ESUCCESS);
- }
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = SPACE;
- scsi_cmd.byte2 = what & SS_CODE;
- scsi_uto3b(number, scsi_cmd.number);
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 0, /* no retries please , just fail */
- 3600000, /* wait up to an hour for completion */
- NULL,
- flags));
-}
-
-/*
- * write N filemarks
- */
-static errval
-st_write_filemarks(unit, number, flags)
- u_int32_t unit, flags;
- int32_t number;
-{
- struct scsi_write_filemarks scsi_cmd;
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
-
- /*
- * It's hard to write a negative number of file marks.
- * Don't try.
- */
- if (number < 0) {
- return EINVAL;
- }
- switch ((int)number) {
- case 0: /* really a command to sync the drive's buffers */
- break;
- case 1:
- if (st->flags & ST_FM_WRITTEN) { /* already have one down */
- st->flags &= ~ST_WRITTEN;
- } else {
- st->flags |= ST_FM_WRITTEN;
- }
- st->flags &= ~ST_PER_ACTION;
- break;
- default:
- st->flags &= ~(ST_PER_ACTION | ST_WRITTEN);
- }
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = WRITE_FILEMARKS;
- scsi_uto3b(number, scsi_cmd.number);
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- 0, /* no retries, just fail */
- 1000000, /* 100 secs.. (may need to repos head ) */
- NULL,
- flags);
-}
-
-/*
- * Make sure the right number of file marks is on tape if the
- * tape has been written. If the position argument is true,
- * leave the tape positioned where it was originally.
- *
- * nmarks returns the number of marks to skip (or, if position
- * true, which were skipped) to get back original position.
- */
-static int32_t
-st_chkeod(unit, position, nmarks, flags)
- u_int32_t unit;
- boolean position;
- int32_t *nmarks;
- u_int32_t flags;
-{
- errval error;
- struct scsi_data *st = SCSI_DATA(&st_switch, unit);
-
- switch ((int)(st->flags & (ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD))) {
- default:
- *nmarks = 0;
- return (ESUCCESS);
- case ST_WRITTEN:
- case ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD:
- *nmarks = 1;
- break;
- case ST_WRITTEN | ST_2FM_AT_EOD:
- *nmarks = 2;
- }
- error = st_write_filemarks(unit, *nmarks, flags);
- if (position && (error == ESUCCESS))
- error = st_space(unit, -*nmarks, SP_FILEMARKS, flags);
- return (error);
-}
-
-/*
- * load/unload (with retension if true)
- */
-static errval
-st_load(unit, type, flags)
- u_int32_t unit, type, flags;
-{
- struct scsi_load scsi_cmd;
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- if (type != LD_LOAD) {
- errval error;
- int32_t nmarks;
-
- error = st_chkeod(unit, FALSE, &nmarks, flags);
- if (error != ESUCCESS)
- return (error);
- sc_link->flags &= ~SDEV_MEDIA_LOADED;
- }
- if (st->quirks & ST_Q_IGNORE_LOADS)
- return (0);
- scsi_cmd.op_code = LOAD_UNLOAD;
- scsi_cmd.how |= type;
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- ST_RETRIES,
- 900000, /* 15 min */
- NULL,
- flags));
-}
-
-/*
- * Rewind the device
- */
-static errval
-st_rewind(unit, immed, flags)
- u_int32_t unit, flags;
- boolean immed;
-{
- struct scsi_rewind scsi_cmd;
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
- errval error;
- int32_t nmarks;
-
- error = st_chkeod(unit, FALSE, &nmarks, flags);
- if (error != ESUCCESS)
- return (error);
- st->flags &= ~ST_PER_ACTION;
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = REWIND;
- scsi_cmd.byte2 = immed ? SR_IMMED : 0;
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- ST_RETRIES,
- immed ? 5000 : 300000, /* 5 sec or 5 min */
- NULL,
- flags));
-}
-
-/*
-** Erase the device
-*/
-static errval
-st_erase(unit, immed, flags)
- u_int32_t unit, flags;
- boolean immed;
-{
- struct scsi_erase scsi_cmd;
- struct scsi_link *sc_link = SCSI_LINK(&st_switch, unit);
- struct scsi_data *st = sc_link->sd;
- errval error;
- int32_t nmarks;
-
- error = st_chkeod(unit, FALSE, &nmarks, flags);
- if (error != ESUCCESS)
- return (error);
- /*
- ** Archive Viper 2525 technical manual 5.7 (ERASE 19h):
- ** tape has to be positioned to BOT first before erase command
- ** is issued or command is rejected. So we rewind the tape first
- ** and exit with an error, if the tape can't be rewinded.
- */
- error = st_rewind(unit, FALSE, SCSI_SILENT);
- if (error != ESUCCESS)
- return (error);
- st->flags &= ~ST_PER_ACTION;
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = ERASE;
- scsi_cmd.byte2 = SE_LONG; /* LONG_ERASE */
- scsi_cmd.byte2 += immed ? SE_IMMED : 0; /* immed bit is here the 2nd! */
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- 0,
- 0,
- ST_RETRIES,
- immed ? 5000 : (200 * 60 * 1000), /* 5 sec or 200 min */
- NULL,
- flags));
-}
-
-/*
- * Look at the returned sense and act on the error and detirmine
- * The unix error number to pass back... (0 = report no error)
- * (SCSIRET_CONTINUE = continue processing)
- */
-static errval
-st_interpret_sense(xs)
- struct scsi_xfer *xs;
-{
- struct scsi_link *sc_link = xs->sc_link;
- struct scsi_sense_data *sense = &(xs->sense);
- boolean silent = xs->flags & SCSI_SILENT;
- u_int32_t unit = sc_link->dev_unit;
- struct scsi_data *st = SCSI_DATA(&st_switch, unit);
- u_int32_t key;
- int32_t info;
-
- /*
- * Get the sense fields and work out what code
- */
- if (sense->error_code & SSD_ERRCODE_VALID) {
- info = ntohl(*((int32_t *) sense->ext.extended.info));
- } else {
- if (st->flags & ST_FIXEDBLOCKS) {
- info = xs->datalen / st->blksiz;
- } else {
- info = xs->datalen;
- }
- }
-
- key = sense->ext.extended.flags & SSD_KEY;
-
- if (((sense->error_code & SSD_ERRCODE) != 0x70)
- || (key == 0x7)) /* Media Write Protected */ {
- return SCSIRET_CONTINUE;/* let the generic code handle it */
- }
- if(sense->ext.extended.flags & (SSD_EOM|SSD_FILEMARK|SSD_ILI)) {
- if (st->flags & ST_FIXEDBLOCKS) {
- xs->resid = info * st->blksiz;
- xs->flags |= SCSI_RESID_VALID;
- if (sense->ext.extended.flags & SSD_EOM) {
- st->flags |= ST_EIO_PENDING;
- }
- if (sense->ext.extended.flags & SSD_FILEMARK) {
- st->flags |= ST_AT_FILEMARK;
- }
- if (sense->ext.extended.flags & SSD_ILI) {
- st->flags |= ST_EIO_PENDING;
- if (sense->error_code & SSD_ERRCODE_VALID &&
- !silent)
- printf(
- "st%lu: block wrong size, %ld blocks residual\n",
- (u_long)unit, (long)info);
- /*XXX*/ /* is this how it works ? */
- /* check def of ILI for fixed blk tapes */
-
- /*
- * This quirk code helps the drive read
- * the first tape block, regardless of
- * format. That is required for these
- * drives to return proper MODE SENSE
- * information.
- */
- if ((st->quirks & ST_Q_SNS_HLP) &&
- !(st->flags & ST_SENSE_READ)) {
- st->blksiz -= 512;
- }
- }
- /*
- * If no data was tranfered, do it immediatly
- */
- if (xs->resid >= xs->datalen) {
- xs->flags &= ~SCSI_RESID_VALID;
- if (st->flags & ST_AT_FILEMARK) {
- xs->flags |= SCSI_EOF;
- st->flags &= ~ST_AT_FILEMARK;
- return 0;
- }
- if (st->flags & ST_EIO_PENDING) {
- st->flags &= ~ST_EIO_PENDING;
- return EIO;
- }
- }
- return 0;
- } else { /* must be variable mode */
- xs->resid = xs->datalen; /* to be sure */
- if (sense->ext.extended.flags & SSD_EOM) {
- return (EIO);
- }
- if (sense->ext.extended.flags & SSD_FILEMARK) {
- xs->flags |= SCSI_EOF;
- }
- if (sense->ext.extended.flags & SSD_ILI) {
- if (info < 0) {
- /*
- * the record was bigger than the read
- */
- if (!silent)
- printf(
- "st%lu: %ld-byte record too big\n",
- (u_long)unit,
- (long)(xs->datalen - info));
- return (EIO);
- }
- xs->resid = info;
- xs->flags |= SCSI_RESID_VALID;
- }
- }
- return 0;
- }
-
- if (key == 0x8) {
- xs->flags |= SCSI_EOF; /* some drives need this */
- /*
- * This quirk code helps the drive read the
- * first tape block, regardless of format. That
- * is required for these drives to return proper
- * MODE SENSE information.
- */
- if ((st->quirks & ST_Q_SNS_HLP) &&
- !(st->flags & ST_SENSE_READ)) {
- /* still starting */
- st->blksiz -= 512;
- } else if (!(st->flags & (ST_2FM_AT_EOD | ST_BLANK_READ))) {
- st->flags |= ST_BLANK_READ;
- xs->flags |= SCSI_EOF;
- return (ESUCCESS);
- }
- }
- return SCSIRET_CONTINUE; /* Use the the generic handler */
-}
-
-/*
- * The quirk here is that the drive returns some value to st_mode_sense
- * incorrectly until the tape has actually passed by the head.
- *
- * The method is to set the drive to large fixed-block state (user-specified
- * density and 1024-byte blocks), then read and rewind to get it to sense the
- * tape. If that doesn't work, try 512-byte fixed blocks. If that doesn't
- * work, as a last resort, try variable- length blocks. The result will be
- * the ability to do an accurate st_mode_sense.
- *
- * We know we can do a rewind because we just did a load, which implies rewind.
- * Rewind seems preferable to space backward if we have a virgin tape.
- *
- * The rest of the code for this quirk is in ILI processing and BLANK CHECK
- * error processing, both part of st_interpret_sense.
- */
-static errval
-st_touch_tape(unit)
- u_int32_t unit;
-{
- struct scsi_data *st = SCSI_DATA(&st_switch, unit);
- char *buf;
- u_int32_t readsiz;
- errval errno;
-
-#ifdef BOUNCE_BUFFERS
- buf = (caddr_t) vm_bounce_kva_alloc(btoc(1024));
-#else
- buf = malloc(1024, M_TEMP, M_NOWAIT);
-#endif
- if (!buf)
- return (ENOMEM);
-
- if (( errno = st_mode_sense(unit, 0, NULL, 0, 0)) ) {
- goto bad;
- }
- st->blksiz = (st->quirks & ST_Q_NO_1024)? 512: 1024;
- do {
- switch ((int)st->blksiz) {
- case 512:
- case 1024:
- readsiz = st->blksiz;
- st->flags |= ST_FIXEDBLOCKS;
- break;
- default:
- readsiz = 1;
- st->flags &= ~ST_FIXEDBLOCKS;
- } if ( (errno = st_mode_select(unit, 0, NULL, 0, 0)) ) {
- goto bad;
- }
- st_read(unit, buf, readsiz, SCSI_SILENT);
- if ( (errno = st_rewind(unit, FALSE, 0)) ) {
-bad: free(buf, M_TEMP);
- return (errno);
- }
- } while (readsiz != 1 && readsiz > st->blksiz);
-#ifdef BOUNCE_BUFFERS
- vm_bounce_kva_alloc_free((vm_offset_t) buf, btoc(1024));
-#else
- free(buf, M_TEMP);
-#endif
- return 0;
-}
-
-static st_devsw_installed = 0;
-
-static void
-st_drvinit(void *unused)
-{
-
- if( ! st_devsw_installed ) {
- dev_t dev;
-
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev, &st_cdevsw, NULL);
- st_devsw_installed = 1;
- }
-}
-
-SYSINIT(stdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,st_drvinit,NULL)
-
-
diff --git a/sys/scsi/su.c b/sys/scsi/su.c
deleted file mode 100644
index 785e831..0000000
--- a/sys/scsi/su.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/* su: SCSI Universal. This is a universal SCSI device that
- * has a fixed minor number format. This allows you to refer
- * to your devices by BUS, ID, LUN instead of st0, st1, ...
- *
- * This code looks up the underlying device for a given SCSI
- * target and uses that driver.
- *
- *Begin copyright
- *
- * Copyright (C) 1993, 1994, 1995, HD Associates, Inc.
- * PO Box 276
- * Pepperell, MA 01463
- * 508 433 5266
- * dufault@hda.com
- *
- * This code is contributed to the University of California at Berkeley:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *End copyright
- *
- * $Id: su.c,v 1.20 1998/07/04 22:30:25 julian Exp $
- *
- * Tabstops 4
- * XXX devfs entries for this device should be handled by generic scsiconfig
- * Add a bdevsw interface.. ?
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/stat.h>
-#include <sys/buf.h>
-#include <sys/kernel.h>
-#include <scsi/scsiconf.h>
-#define CDEV_MAJOR 18
-
-/* These three used by ssc. */
-extern d_open_t suopen;
-extern d_close_t suclose;
-extern d_ioctl_t suioctl;
-
-static d_read_t suread;
-static d_write_t suwrite;
-static d_poll_t supoll;
-static d_strategy_t sustrategy;
-
-static struct cdevsw su_cdevsw =
- { suopen, suclose, suread, suwrite, /*18*/
- suioctl, nostop, nullreset, nodevtotty,/* scsi */
- supoll, nommap, sustrategy, "su", NULL, -1 };
-
-
-/* Build an old style device number (unit encoded in the minor number)
- * from a base old one (no flag bits) and a full new one
- * (BUS, LUN, TARG in the minor number, and flag bits).
- *
- * OLDDEV has the major number and device unit only. It was constructed
- * at attach time and is stored in the scsi_link structure.
- *
- * NEWDEV can have whatever in it, but only the old control flags and the
- * super bit are present. IT CAN'T HAVE ANY UNIT INFORMATION or you'll
- * wind up with the wrong unit.
- */
-#define OLD_DEV(NEWDEV, OLDDEV) ((OLDDEV) | ((NEWDEV) & 0x080000FF))
-
-/* cnxio: non existent device entries. */
-
-static d_open_t nxopen;
-static d_close_t nxclose;
-static d_read_t nxread;
-static d_write_t nxwrite;
-static d_ioctl_t nxioctl;
-#define nxstop nostop /* one void return is as good as another */
-#define nxreset noreset /* one unused function is as good as another */
-#define nxdevtotty nodevtotty /* one NULL return is as good as another */
-#define nxmmap nommap /* one -1 return is as good as another */
-#define nxstrategy nostrategy /* one NULL value is as good as another */
-static d_dump_t nxdump;
-#define nxpsize nopsize /* one NULL value is as good as another */
-
-static struct cdevsw cnxio = {
- nxopen,
- nxclose,
- nxread,
- nxwrite,
- nxioctl,
- nxstop,
- nxreset,
- nxdevtotty,
- seltrue,
- nxmmap,
- nxstrategy,
- "NON",
- NULL,
- -1,
- nxdump,
- nxpsize,
- 0,
- 0,
- -1
-};
-
-/* getsws: Look up the base dev switch for a given "by minor number" style
- * device.
- */
-static int
-getsws(dev_t dev, int type, struct cdevsw **devswpp, dev_t *base)
-{
- int ret = 0;
- struct scsi_link *scsi_link;
- int chr_dev, blk_dev;
-
- struct cdevsw *devswp;
-
- int bus = SCSI_BUS(dev),
- lun = SCSI_LUN(dev),
- id = SCSI_ID(dev);
-
- /* Try to look up the base device by finding the major number in
- * the scsi_link structure:
- */
- if ((scsi_link = scsi_link_get(bus, id, lun)) == 0 ||
- scsi_link->dev == NODEV)
- {
- ret = ENXIO;
- devswp = &cnxio;
- chr_dev = NODEV;
- blk_dev = NODEV;
- }
- else
- {
- int bmaj, cmaj;
-
- cmaj = major(scsi_link->dev);
- devswp = cdevsw[cmaj];
- chr_dev = OLD_DEV(dev, scsi_link->dev);
- bmaj = devswp->d_bmaj;
- blk_dev = OLD_DEV(dev, makedev(bmaj, minor(scsi_link->dev)));
- }
-
- if (devswp)
- *devswpp = devswp;
-
- if (type == S_IFCHR)
- *base = chr_dev;
- else
- *base = blk_dev;
-
- return ret;
-}
-
-int
-suopen(dev_t dev, int flag, int type, struct proc *p)
-{
- struct cdevsw *devswp;
- dev_t base;
-
- if (getsws(dev, type, &devswp, &base))
- {
- /* Device not configured? Reprobe then try again.
- */
- int bus = SCSI_BUS(dev), lun = SCSI_LUN(dev), id = SCSI_ID(dev);
-
- if (scsi_probe_bus(bus, id, lun) || getsws(dev, type, &devswp,
- &base))
- return ENXIO;
- }
-
- /* There is a properly configured underlying device.
- * Synthesize an appropriate device number:
- */
- return (*devswp->d_open)(base, flag, type, p);
-}
-
-int
-suclose(dev_t dev, int fflag, int type, struct proc *p)
-{
- struct cdevsw *devswp;
- dev_t base;
-
- (void)getsws(dev, type, &devswp, &base);
-
- return (*devswp->d_close)(base, fflag, type, p);
-}
-
-static void
-sustrategy(struct buf *bp)
-{
- dev_t base;
- struct cdevsw *devswp;
- dev_t dev = bp->b_dev;
-
- /* XXX: I have no way of knowing if this was through the
- * block or the character entry point.
- */
- (void)getsws(dev, S_IFBLK, &devswp, &base);
-
- bp->b_dev = base;
-
- (*devswp->d_strategy)(bp);
-
- bp->b_dev = dev; /* strat needs a dev_t */
-}
-
-int
-suioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
-{
- struct cdevsw *devswp;
- dev_t base;
-
- /* XXX: I have no way of knowing if this was through the
- * block or the character entry point.
- */
- (void)getsws(dev, S_IFCHR, &devswp, &base);
-
- return (*devswp->d_ioctl)(base, cmd, data, fflag, p);
-}
-
-static int
-suread(dev_t dev, struct uio *uio, int ioflag)
-{
- dev_t base;
- struct cdevsw *devswp;
-
- (void)getsws(dev, S_IFCHR, &devswp, &base);
-
- return (*devswp->d_read)(base, uio, ioflag);
-}
-
-static int
-suwrite(dev_t dev, struct uio *uio, int ioflag)
-{
- dev_t base;
- struct cdevsw *devswp;
-
- (void)getsws(dev, S_IFCHR, &devswp, &base);
-
- return (*devswp->d_write)(base, uio, ioflag);
-}
-
-static int
-supoll(dev_t dev, int events, struct proc *p)
-{
- dev_t base;
- struct cdevsw *devswp;
-
- (void)getsws(dev, S_IFCHR, &devswp, &base);
-
- return (*devswp->d_poll)(base, events, p);
-}
-
-static int
-nxopen(dev, flags, fmt, p)
- dev_t dev;
- int flags;
- int fmt;
- struct proc *p;
-{
-
- return (ENXIO);
-}
-
-static int
-nxclose(dev, flags, fmt, p)
- dev_t dev;
- int flags;
- int fmt;
- struct proc *p;
-{
-
- printf("nxclose(0x%x) called\n", dev);
- return (ENXIO);
-}
-
-static int
-nxread(dev, uio, ioflag)
- dev_t dev;
- struct uio *uio;
- int ioflag;
-{
-
- printf("nxread(0x%x) called\n", dev);
- return (ENXIO);
-}
-
-static int
-nxwrite(dev, uio, ioflag)
- dev_t dev;
- struct uio *uio;
- int ioflag;
-{
-
- printf("nxwrite(0x%x) called\n", dev);
- return (ENXIO);
-}
-
-static int
-nxioctl(dev, cmd, data, flags, p)
- dev_t dev;
- u_long cmd;
- caddr_t data;
- int flags;
- struct proc *p;
-{
-
- printf("nxioctl(0x%x) called\n", dev);
- return (ENXIO);
-}
-
-static int
-nxdump(dev)
- dev_t dev;
-{
-
- printf("nxdump(0x%x) called\n", dev);
- return (ENXIO);
-}
-
-static su_devsw_installed = 0;
-
-static void
-su_drvinit(void *unused)
-{
- dev_t dev;
-
- if( ! su_devsw_installed ) {
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev,&su_cdevsw, NULL);
- su_devsw_installed = 1;
- }
-}
-
-SYSINIT(sudev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,su_drvinit,NULL)
-
-
diff --git a/sys/scsi/uk.c b/sys/scsi/uk.c
deleted file mode 100644
index a9b8edf..0000000
--- a/sys/scsi/uk.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Driver for a device we can't identify.
- * by Julian Elischer (julian@tfs.com)
- *
- * $Id: uk.c,v 1.18 1997/08/02 14:33:16 bde Exp $
- *
- * If you find that you are adding any code to this file look closely
- * at putting it in "scsi_driver.c" instead.
- */
-
-#include <opt_devfs.h>
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_driver.h>
-
-struct scsi_data {
-#ifdef DEVFS
- void *devfs_data_tok;
-#endif
-};
-
-static d_open_t ukopen;
-static d_close_t ukclose;
-static d_ioctl_t ukioctl;
-
-#define CDEV_MAJOR 31
-static struct cdevsw uk_cdevsw =
- { ukopen, ukclose, noread, nowrite, /*31*/
- ukioctl, nostop, nullreset, nodevtotty,/* unknown */
- seltrue, nommap, NULL, "uk" ,NULL, -1 };
-
-SCSI_DEVICE_ENTRIES(uk)
-
-struct scsi_device uk_switch =
-{
- NULL,
- NULL,
- NULL,
- NULL,
- "uk",
- 0,
- {0, 0},
- SDEV_ONCE_ONLY|SDEV_UK, /* Only one open allowed */
- ukattach,
- "Unknown",
- ukopen,
- sizeof(struct scsi_data),
- T_UNKNOWN,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
-};
-
-
-static uk_devsw_installed = 0;
-
-static errval
-ukattach(struct scsi_link *sc_link)
-{
-#ifdef DEVFS
- struct scsi_data *uk = sc_link->sd;
-
- uk->devfs_data_tok = devfs_add_devswf(&uk_cdevsw,
- sc_link->dev_unit,
- DV_CHR,
- UID_ROOT, GID_WHEEL, 0600,
- "uk%d", sc_link->dev_unit);
-#endif
- return 0;
-}
-
-
-static void uk_drvinit(void *unused)
-{
- dev_t dev;
-
- if( ! uk_devsw_installed ) {
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev,&uk_cdevsw, NULL);
- uk_devsw_installed = 1;
- }
-}
-
-SYSINIT(ukdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,uk_drvinit,NULL)
-
-
diff --git a/sys/scsi/worm.c b/sys/scsi/worm.c
deleted file mode 100644
index 1601d8e..0000000
--- a/sys/scsi/worm.c
+++ /dev/null
@@ -1,1811 +0,0 @@
-/*
- * worm: Write Once device driver
- *
- * Copyright (C) 1995, HD Associates, Inc.
- * PO Box 276
- * Pepperell, MA 01463
- * 508 433 5266
- * dufault@hda.com
- *
- * Copyright (C) 1996-97 interface business GmbH
- * Naumannstr. 1
- * D-01309 Dresden
- * F.R. Germany
- * <joerg_wunsch@interface-business.de>
- *
- * This code is contributed to the University of California at Berkeley:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Id: worm.c,v 1.58 1998/07/04 22:30:25 julian Exp $
- */
-
-#include "opt_bounce.h"
-#include "opt_devfs.h"
-#include "opt_scsi.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/buf.h>
-#include <sys/cdio.h>
-#include <sys/wormio.h>
-#include <sys/fcntl.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#ifdef DEVFS
-#include <sys/devfsext.h>
-#endif /*DEVFS*/
-#include <scsi/scsiconf.h>
-#include <scsi/scsi_debug.h>
-#include <scsi/scsi_disk.h>
-#include <scsi/scsi_driver.h>
-#include <scsi/scsi_worm.h>
-#include <scsi/scsi_cd.h>
-#include <sys/dkstat.h>
-#include <sys/malloc.h>
-
-#include "ioconf.h"
-
-struct worm_quirks
-{
- /*
- * The device-specific functions that need to be called during
- * the several steps.
- */
- errval (*prepare_disk)(struct scsi_link *, int dummy, int speed);
- errval (*prepare_track)(struct scsi_link *, struct wormio_prepare_track *t);
- errval (*finalize_track)(struct scsi_link *);
- errval (*finalize_disk)(struct scsi_link *, int toc_type, int onp);
- errval (*write_session)(struct scsi_link *, struct wormio_write_session *);
- errval (*read_first_writable_address)(struct scsi_link *sc_link,
- int track, int mode, int raw, int audio, int *addr);
-};
-
-
-struct scsi_data
-{
- struct buf_queue_head buf_queue;
- int dkunit; /* disk stats unit number */
- u_int32_t blk_size; /* Size of each blocks */
-#ifdef DEVFS
- void *b_devfs_token;
- void *c_devfs_token;
- void *ctl_devfs_token;
-#endif
-
- struct worm_quirks *quirks; /* model-specific functions */
- struct wormio_prepare_track preptrack; /* scratch region */
- struct wormio_write_session *write_session; /* scratch region */
-
- u_int8_t dummy; /* use dummy writes */
- u_int8_t speed; /* select drive speed */
-
- u_int32_t worm_flags; /* driver-internal flags */
-#define WORMFL_DISK_PREPED 0x01 /* disk parameters have been spec'ed */
-#define WORMFL_TRACK_PREPED 0x02 /* track parameters have been sent */
-#define WORMFL_WRITTEN 0x04 /* track has been written */
-#define WORMFL_IOCTL_ONLY 0x08 /* O_NDELAY, only ioctls allowed */
-#define WORMFL_TRACK_PREP 0x10 /* track parameters have been spec'ed */
-
- int error; /* last error */
-};
-
-static struct {
- int asc;
- int devmode;
- int error;
- int ret;
-} worm_error[] = {
- {0x24, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_ABSORPTION_CONTROL_ERROR, 0},
- {0xb0, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_CALIBRATION_AREA_ALMOST_FULL, 0},
- {0xb4, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_CALIBRATION_AREA_FULL, SCSIRET_CONTINUE},
- {0xb5, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_DUMMY_BLOCKS_ADDED, 0},
- {0xaa, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_END_OF_MEDIUM, SCSIRET_CONTINUE},
- {0xad, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_BUFFER_UNDERRUN, SCSIRET_CONTINUE},
- {0xaf, WORM_Q_PLASMON|WORM_Q_PHILIPS, WORM_OPTIMUM_POWER_CALIBRATION_ERROR, SCSIRET_CONTINUE},
- {0, 0, 0, 0}
-};
-
-static void wormstart(u_int32_t unit, u_int32_t flags);
-
-static errval worm_open(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-static errval worm_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag,
- struct proc *p, struct scsi_link *sc_link);
-static errval worm_close(dev_t dev, int flag, int fmt, struct proc *p,
- struct scsi_link *sc_link);
-static void worm_strategy(struct buf *bp, struct scsi_link *sc_link);
-static errval worm_read_toc(struct scsi_link *sc_link,
- u_int32_t mode, u_int32_t start,
- struct cd_toc_entry *data, u_int32_t len);
-static errval worm_rezero_unit(struct scsi_link *sc_link);
-static errval worm_read_session_info(struct scsi_link *, struct wormio_session_info *);
-static int worm_sense_handler(struct scsi_xfer *);
-static errval worm_set_blksize(struct scsi_link *sc_link, int size);
-
-/* XXX should be moved out to an LKM */
-static errval rf4100_prepare_disk(struct scsi_link *, int dummy, int speed);
-static errval rf4100_prepare_track(struct scsi_link *, struct wormio_prepare_track *);
-static errval rf4100_finalize_track(struct scsi_link *);
-static errval rf4100_finalize_disk(struct scsi_link *, int toc_type, int onp);
-
-static errval hp4020i_prepare_disk(struct scsi_link *, int dummy, int speed);
-static errval hp4020i_prepare_track(struct scsi_link *, struct wormio_prepare_track *);
-static errval hp4020i_finalize_track(struct scsi_link *);
-static errval hp4020i_finalize_disk(struct scsi_link *, int toc_type, int onp);
-static errval hp4020i_write_session(struct scsi_link *, struct wormio_write_session *);
-static errval hp4020i_read_first_writable_address (struct scsi_link *sc_link,
- int track, int mode, int raw, int audio, int *addr);
-
-static worm_devsw_installed = 0;
-
-static d_open_t wormopen;
-static d_read_t wormread;
-static d_write_t wormwrite;
-static d_close_t wormclose;
-static d_ioctl_t wormioctl;
-static d_strategy_t wormstrategy;
-
-#define CDEV_MAJOR 62
-#define BDEV_MAJOR 23
-
-static struct cdevsw worm_cdevsw = {
- wormopen, wormclose, wormread, wormwrite,
- wormioctl, nostop, nullreset, nodevtotty,
- seltrue, nommap, wormstrategy, "worm",
- NULL, -1, nodump, nopsize,
- D_DISK, 0, -1 };
-
-static int
-wormunit(dev_t dev)
-{
- return (minor(dev) & ~(SCSI_FIXED_MASK|SCSI_CONTROL_MASK));
-}
-
-SCSI_DEVICE_ENTRIES(worm)
-
-static struct scsi_device worm_switch =
-{
- worm_sense_handler,
- wormstart, /* we have a queue, and this is how we service it */
- NULL,
- NULL,
- "worm",
- 0,
- {0, 0},
- SDEV_ONCE_ONLY, /* Only one open allowed */
- wormattach,
- "Write-Once",
- wormopen,
- sizeof(struct scsi_data),
- T_WORM,
- wormunit,
- 0,
- worm_open,
- worm_ioctl,
- worm_close,
- worm_strategy,
-};
-
-static struct worm_quirks worm_quirks_plasmon = {
- rf4100_prepare_disk, rf4100_prepare_track,
- rf4100_finalize_track, rf4100_finalize_disk,
- 0, hp4020i_read_first_writable_address
-};
-static struct worm_quirks worm_quirks_philips = {
- hp4020i_prepare_disk, hp4020i_prepare_track,
- hp4020i_finalize_track, hp4020i_finalize_disk,
- hp4020i_write_session, hp4020i_read_first_writable_address
-};
-
-static __inline void
-worm_registerdev(int unit)
-{
- if (dk_ndrive < DK_NDRIVE) {
- sprintf(dk_names[dk_ndrive], "worm%d", unit);
- dk_wpms[dk_ndrive] = (1*1024*1024/2); /* 1MB/sec XXX - fake! */
- SCSI_DATA(&worm_switch, unit)->dkunit = dk_ndrive++;
- } else {
- SCSI_DATA(&worm_switch, unit)->dkunit = -1;
- }
-}
-
-static errval
-worm_size(struct scsi_link *sc_link, int flags)
-{
- errval ret;
- struct scsi_data *worm = sc_link->sd;
- int blk_size;
- u_int32_t n_blks;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("worm_size"));
-
- n_blks = scsi_read_capacity(sc_link, &blk_size, flags);
-
- /*
- * CD-R devices can assume various sizes, depending on the
- * intended purpose of the track. Hence, READ CAPACITY
- * doesn't give us any good results. We make a more educated
- * guess when it comes to prepare a track.
- */
-
- if (n_blks > 0) {
- sc_link->flags |= SDEV_MEDIA_LOADED;
- ret = 0;
- } else {
- sc_link->flags &= ~SDEV_MEDIA_LOADED;
- ret = ENXIO;
- }
-
- return ret;
-}
-
-static errval
-wormattach(struct scsi_link *sc_link)
-{
- u_int32_t unit = sc_link->dev_unit;
-#ifdef DEVFS
- int mynor;
-#endif
- struct scsi_data *worm = sc_link->sd;
-
- if (sc_link->devmodes == 0)
- printf(", warning: unknown drive type");
-
- bufq_init(&worm->buf_queue);
-
-#ifdef DEVFS
- mynor = wormunit(sc_link->dev);
- worm->b_devfs_token =
- devfs_add_devswf(&worm_cdevsw, mynor,
- DV_BLK, 0, 0, 0444, "worm%d", mynor);
- worm->c_devfs_token =
- devfs_add_devswf(&worm_cdevsw, mynor,
- DV_CHR, 0, 0, 0644, "rworm%d", mynor);
- worm->ctl_devfs_token =
- devfs_add_devswf(&worm_cdevsw, mynor | SCSI_CONTROL_MASK,
- DV_CHR, 0, 0, 0600, "rworm%d.ctl", mynor);
-#endif
- worm_registerdev(unit);
- return 0;
-}
-
-static int
-wormread(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(wormstrategy, NULL, dev, 1, minphys, uio));
-}
-
-static int
-wormwrite(dev_t dev, struct uio *uio, int ioflag)
-{
- return (physio(wormstrategy, NULL, dev, 0, minphys, uio));
-}
-
-/*
- * wormstart looks to see if there is a buf waiting for the device
- * and that the device is not already busy. If both are true,
- * It dequeues the buf and creates a scsi command to perform the
- * transfer required. The transfer request will call scsi_done
- * on completion, which will in turn call this routine again
- * so that the next queued transfer is performed.
- * The bufs are queued by the strategy routine (wormstrategy)
- *
- * This routine is also called after other non-queued requests
- * have been made of the scsi driver, to ensure that the queue
- * continues to be drained.
- * wormstart() is called at splbio
- *
- * XXX It looks like we need a "scsistart" to hoist common code up
- * into. In particular, the removable media checking should be
- * handled in one place.
- *
- * Writes will fail if the disk and track not been prepared via the control
- * device.
- */
-static void
-wormstart(unit, flags)
- u_int32_t unit;
- u_int32_t flags;
-{
- struct scsi_link *sc_link = SCSI_LINK(&worm_switch, unit);
- struct scsi_data *worm = sc_link->sd;
- register struct buf *bp = 0;
- struct scsi_rw_big cmd;
-
- u_int32_t lba; /* Logical block address */
- u_int32_t tl; /* Transfer length */
-
- SC_DEBUG(sc_link, SDEV_DB2, ("wormstart "));
-
- /*
- * We should reject all queued entries if SDEV_MEDIA_LOADED is not true.
- */
- if (!(sc_link->flags & SDEV_MEDIA_LOADED)) {
- goto badnews; /* no I/O.. media changed or something */
- }
-
- /*
- * See if there is a buf to do and we are not already
- * doing one
- */
- while (sc_link->opennings != 0) {
-
- /* if a special awaits, let it proceed first */
- if (sc_link->flags & SDEV_WAITING) {
- sc_link->flags &= ~SDEV_WAITING;
- wakeup(sc_link);
- return;
- }
-
- bp = bufq_first(&worm->buf_queue);
- if (bp == NULL)
- return;
-
- bufq_remove(&worm->buf_queue, bp);
-
- if ((bp->b_flags & B_READ) == B_WRITE) {
- if ((worm->worm_flags & WORMFL_TRACK_PREPED) == 0) {
- if ((worm->worm_flags & WORMFL_TRACK_PREP) == 0 &&
- !worm->write_session) {
- SC_DEBUG(sc_link, SDEV_DB3, ("sequence error\n"));
- bp->b_error = EIO;
- bp->b_flags |= B_ERROR;
- worm->error = WORM_SEQUENCE_ERROR;
- biodone(bp);
- goto badnews;
- } else {
- if (worm->write_session) {
- if ((worm->quirks->write_session)
- (sc_link, worm->write_session)) {
- biodone(bp);
- goto badnews;
- }
- } else
- if (worm->quirks->prepare_track(sc_link, &worm->preptrack)
- != 0) {
- biodone(bp);
- goto badnews;
- }
- worm->worm_flags |= WORMFL_TRACK_PREPED;
- }
- }
- }
- /*
- * Fill out the scsi command
- */
- bzero(&cmd, sizeof(cmd));
- if ((bp->b_flags & B_READ) == B_WRITE) {
- cmd.op_code = WRITE_BIG;
- flags |= SCSI_DATA_OUT;
- } else {
- cmd.op_code = READ_BIG;
- flags |= SCSI_DATA_IN;
- }
-
- worm->error = 0;
-
- lba = bp->b_blkno / (worm->blk_size / DEV_BSIZE);
- tl = bp->b_bcount / worm->blk_size;
-
- if (bp->b_flags & B_READ)
- /*
- * Leave the LBA as 0 for write operations, it
- * is reserved in this case (and wouldn't make
- * any sense to set it at all, since CD-R write
- * operations are in `streaming' mode anyway.
- */
- scsi_uto4b(lba, &cmd.addr_3);
- scsi_uto2b(tl, &cmd.length2);
-
- /*
- * go ask the adapter to do all this for us
- */
- if (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- (u_char *) bp->b_data,
- bp->b_bcount,
- 0,
- 100000,
- bp,
- flags | SCSI_NOSLEEP) == SUCCESSFULLY_QUEUED) {
- if (worm->dkunit >= 0) { /* Cloned from od.c, possibly with same mistakes. :) */
- dk_xfer[worm->dkunit]++;
- dk_seek[worm->dkunit] = 1; /* single track */
- dk_wds[worm->dkunit] += bp->b_bcount >> 6;
- }
- if ((bp->b_flags & B_READ) == B_WRITE)
- worm->worm_flags |= WORMFL_WRITTEN;
- } else {
- printf("worm%lu: oops not queued\n", (u_long)unit);
- if (bp) {
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- biodone(bp);
- }
- }
- } /* go back and see if we can cram more work in.. */
-badnews: ;
-}
-
-static void
-worm_strategy(struct buf *bp, struct scsi_link *sc_link)
-{
- unsigned char unit;
- u_int32_t opri;
- struct scsi_data *worm;
-
- unit = wormunit(bp->b_dev);
- worm = sc_link->sd;
-
- if ((worm->worm_flags & WORMFL_IOCTL_ONLY) != 0) {
- SC_DEBUG(sc_link, SDEV_DB3,
- ("attempted IO on ioctl-only descriptor\n"));
- bp->b_error = EBADF;
- bp->b_flags |= B_ERROR;
- biodone(bp);
- return;
- }
-
- /*
- * check it's not too big a transfer for our adapter
- */
- wormminphys(bp);
-
- opri = splbio();
-
- /*
- * Use a bounce buffer if necessary
- * XXX: How can we move this up?
- */
-#ifdef BOUNCE_BUFFERS
- if (sc_link->flags & SDEV_BOUNCE)
- vm_bounce_alloc(bp);
-#endif
-
- /*
- * Place it in the queue of activities for this device
- * at the end.
- */
- bufq_insert_tail(&worm->buf_queue, bp);
-
- wormstart(unit, 0);
-
- splx(opri);
- return;
-}
-
-/*
- * Open the device.
- * Only called for the "real" device, not for the control device.
- */
-static int
-worm_open(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link)
-{
- struct scsi_data *worm;
- errval error;
-
- error = 0;
- worm = sc_link->sd;
-
- if (sc_link->flags & SDEV_OPEN)
- return EBUSY;
-
- /*
- * Unknown drive type: only the control device can be opened
- * in this case, so scsi(8) and things like cdrecord will
- * work.
- */
- if (sc_link->devmodes == 0)
- return ENXIO;
-
- /*
- * Check that it is still responding and ok.
- * if the media has been changed this will result in a
- * "unit attention" error which the error code will
- * disregard because the SDEV_OPEN flag is not yet set
- *
- * XXX This should REALLY be hoisted up. As soon as Bruce
- * finishes that slice stuff. (Add a different flag,
- * and then do a "scsi_test_unit_ready" with the "ignore
- * unit attention" thing set. Then all this replicated
- * test unit ready code can be pulled up.
- */
- scsi_test_unit_ready(sc_link, SCSI_SILENT);
-
- /*
- * The semantics of the "flags" is as follows:
- *
- * If the device has been opened with O_NONBLOCK set, no
- * actual IO will be allowed, and the command sequence is only
- * subject to the restrictions as in worm_ioctl() below.
- */
- /*
- * Next time actually take notice of error returns,
- * unit attn errors are now errors.
- */
- sc_link->flags |= SDEV_OPEN;
-
- if (scsi_test_unit_ready(sc_link, SCSI_SILENT) != 0) {
- SC_DEBUG(sc_link, SDEV_DB3, ("not ready\n"));
- error = ENXIO;
- goto out;
- }
-
- if ((flags & O_NONBLOCK) == 0) {
- scsi_start_unit(sc_link, SCSI_SILENT);
- scsi_prevent(sc_link, PR_PREVENT, SCSI_SILENT);
-
- if((flags & FWRITE) != 0) {
- if ((error = worm_rezero_unit(sc_link)) != 0 ||
- (error = worm_size(sc_link, 0)) != 0) {
- SC_DEBUG(sc_link, SDEV_DB3,
- ("rezero, or get size failed\n"));
- error = EIO;
- goto out;
- }
- } else {
- /* read/only */
- if ((error = worm_size(sc_link, 0)) != 0) {
- SC_DEBUG(sc_link, SDEV_DB3,
- ("get size failed\n"));
- error = EIO;
- goto out;
- }
- worm->blk_size = 2048;
- }
- } else
- worm->worm_flags |= WORMFL_IOCTL_ONLY;
-
- switch (*(int *) sc_link->devmodes) {
- case WORM_Q_PLASMON:
- worm->quirks = &worm_quirks_plasmon;
- break;
- case WORM_Q_PHILIPS:
- worm->quirks = &worm_quirks_philips;
- break;
- default:
- error = ENXIO;
- }
- worm->error = 0;
-
- out:
- if (error) {
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
- worm->worm_flags &= ~(WORMFL_TRACK_PREPED| WORMFL_TRACK_PREP);
- sc_link->flags &= ~SDEV_OPEN;
- }
-
- return error;
-}
-
-static int
-worm_close(dev_t dev, int flags, int fmt, struct proc *p,
- struct scsi_link *sc_link)
-{
- struct scsi_data *worm = sc_link->sd;
- errval error;
-
- error = 0;
-
- if ((worm->worm_flags & WORMFL_IOCTL_ONLY) == 0) {
- if ((flags & FWRITE) != 0) {
- worm->error = 0;
- if ((worm->worm_flags & WORMFL_TRACK_PREPED) != 0) {
- error = (worm->quirks->finalize_track)(sc_link);
- worm->worm_flags &=
- ~(WORMFL_TRACK_PREPED | WORMFL_TRACK_PREP);
- }
- }
- scsi_prevent(sc_link, PR_ALLOW, SCSI_SILENT);
- } else {
- worm->worm_flags &= ~WORMFL_IOCTL_ONLY;
- if (worm->write_session) {
-#ifdef BOUNCE_BUFFERS
- vm_bounce_kva_alloc_free((vm_offset_t)worm->write_session,
- btoc(sizeof(struct wormio_write_session) +
- worm->write_session->length));
-#else
- free(worm->write_session, M_DEVBUF);
-#endif
- worm->write_session = 0;
- }
- }
- sc_link->flags &= ~SDEV_OPEN;
-
- return error;
-}
-
-/*
- * Perform special action on behalf of the user.
- * Knows about the internals of this device
- */
-errval
-worm_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p,
- struct scsi_link *sc_link)
-{
- errval error = 0;
- u_int8_t unit;
- register struct scsi_data *worm;
-
- /*
- * Find the device that the user is talking about
- */
- unit = wormunit(dev);
- worm = sc_link->sd;
- SC_DEBUG(sc_link, SDEV_DB2, ("wormioctl 0x%lx ", cmd));
-
- switch (cmd) {
- case WORMIOCPREPDISK:
- {
- struct wormio_prepare_disk *w =
- (struct wormio_prepare_disk *)addr;
- if (w->dummy != 0 && w->dummy != 1)
- error = EINVAL;
- else {
- error = (worm->quirks->prepare_disk)
- (sc_link, w->dummy, w->speed);
- if (error == 0) {
- worm->worm_flags |= WORMFL_DISK_PREPED;
- worm->dummy = w->dummy;
- worm->speed = w->speed;
- }
- }
- }
- break;
-
- case WORMIOCPREPTRACK:
- {
- struct wormio_prepare_track *w =
- (struct wormio_prepare_track *)addr;
- if (w->audio != 0 && w->audio != 1)
- error = EINVAL;
- else if (w->audio == 0 && w->preemp)
- error = EINVAL;
- else if ((worm->worm_flags & WORMFL_DISK_PREPED)==0) {
- error = EINVAL;
- worm->error = WORM_SEQUENCE_ERROR;
- } else {
- /*
- * This sets a flag only. Actual preparation of a
- * track will be deferred up to the first write.
- */
- worm->worm_flags |= WORMFL_TRACK_PREP;
- worm->preptrack = *w;
- if (worm->write_session) {
-#ifdef BOUNCE_BUFFERS
- vm_bounce_kva_alloc_free((vm_offset_t)worm->write_session,
- btoc(sizeof(struct wormio_write_session) +
- worm->write_session->length));
-#else
- free(worm->write_session, M_DEVBUF);
-#endif
- worm->write_session = 0;
- }
- }
- }
- break;
-
- case WORMIOCFINISHTRACK:
- if ((worm->worm_flags & WORMFL_TRACK_PREPED) != 0)
- error = (worm->quirks->finalize_track)(sc_link);
- worm->worm_flags &= ~(WORMFL_TRACK_PREPED | WORMFL_TRACK_PREP);
- break;
-
- case WORMIOCFIXATION:
- {
- struct wormio_fixation *w =
- (struct wormio_fixation *)addr;
-
- if ((worm->worm_flags & WORMFL_WRITTEN) == 0)
- error = EINVAL;
- else if (w->toc_type < WORM_TOC_TYPE_AUDIO ||
- w->toc_type > WORM_TOC_TYPE_CDI)
- error = EINVAL;
- else if (w->onp != 0 && w->onp != 1)
- error = EINVAL;
- else {
- worm->worm_flags = 0;
- /* no fixation needed if dummy write */
- if (worm->dummy == 0) {
- worm->error = 0;
- error = (worm->quirks->finalize_disk)
- (sc_link, w->toc_type, w->onp);
- }
- }
- }
- break;
-
- case WORMIOCREADSESSIONINFO:
- {
- struct wormio_session_info si;
- error = worm_read_session_info(sc_link, &si);
- if (error)
- break;
- NTOHS(si.lead_in);
- NTOHS(si.lead_out);
- bcopy(&si, addr, sizeof si);
- }
- break;
-
- case WORMIOCWRITESESSION:
- if (worm->quirks->write_session) {
- if ((worm->worm_flags & WORMFL_DISK_PREPED)==0) {
- error = EINVAL;
- worm->error = WORM_SEQUENCE_ERROR;
- } else {
-#ifdef BOUNCE_BUFFERS
- worm->write_session = (struct wormio_write_session *)
- vm_bounce_kva_alloc(
- btoc(sizeof(struct wormio_write_session) +
- ((struct wormio_write_session *) addr)->length));
- if (!worm->write_session) {
- error = ENOMEM;
- break;
- }
-#else
- worm->write_session = malloc(sizeof(struct wormio_write_session) +
- ((struct wormio_write_session *) addr)->length,
- M_DEVBUF, M_WAITOK);
-#endif
- bcopy(addr, worm->write_session, sizeof(struct wormio_write_session));
- worm->write_session->track_desc = sizeof(struct wormio_write_session) +
- (u_char *) worm->write_session;
- bcopy(((struct wormio_write_session *) addr)->track_desc,
- worm->write_session->track_desc, ((struct wormio_write_session *) addr)->length);
- }
- } else
- error = ENXIO;
- break;
-
- case WORMIOCFIRSTWRITABLEADDR:
- if (worm->quirks->read_first_writable_address) {
- int address;
- struct wormio_first_writable_addr *a =
- (struct wormio_first_writable_addr *) addr;
- if ((a->audio & ~1) || (a->raw & ~1) || (a->mode & ~3)
- || (a->track & ~0x7f)) {
- error = EINVAL;
- break;
- }
- error = worm->quirks->read_first_writable_address(sc_link, a->track,
- a->mode, a->raw,
- a->audio, &address);
- if (error)
- break;
- error = copyout(&address, a->addr, sizeof(int));
- } else
- error = ENXIO;
- break;
-
- case WORMIOERROR:
- bcopy(&(worm->error), addr, sizeof (int));
- break;
-
- case CDIOREADTOCHEADER:
- {
- struct ioc_toc_header th;
- error = worm_read_toc(sc_link, 0, 0,
- (struct cd_toc_entry *)&th,
- sizeof th);
- if (error)
- break;
- NTOHS(th.len);
- bcopy(&th, addr, sizeof th);
- }
- break;
-
- case CDIOREADTOCENTRYS:
- {
- struct {
- struct ioc_toc_header header;
- struct cd_toc_entry entries[100];
- } data;
- struct {
- struct ioc_toc_header header;
- struct cd_toc_entry entry;
- } lead;
- struct ioc_read_toc_entry *te =
- (struct ioc_read_toc_entry *) addr;
- struct ioc_toc_header *th;
- u_int32_t len, readlen, idx, num;
- u_int32_t starting_track = te->starting_track;
-
- if (te->data_len < sizeof(struct cd_toc_entry)
- || (te->data_len % sizeof(struct cd_toc_entry)) != 0
- || te->address_format != CD_MSF_FORMAT
- && te->address_format != CD_LBA_FORMAT) {
- error = EINVAL;
- break;
- }
-
- th = &data.header;
- error = worm_read_toc(sc_link, 0, 0,
- (struct cd_toc_entry *)th,
- sizeof (*th));
- if (error)
- break;
-
- if (starting_track == 0)
- starting_track = th->starting_track;
- else if (starting_track == 0xaa)
- starting_track = th->ending_track + 1;
- else if (starting_track < th->starting_track ||
- starting_track > th->ending_track + 1) {
- error = EINVAL;
- break;
- }
-
- /* calculate reading length without leadout entry */
- readlen = (th->ending_track - starting_track + 1) *
- sizeof(struct cd_toc_entry);
-
- /* and with leadout entry */
- len = readlen + sizeof(struct cd_toc_entry);
- if (te->data_len < len) {
- len = te->data_len;
- if (readlen > len)
- readlen = len;
- }
- if (len > sizeof(data.entries)) {
- error = EINVAL;
- break;
- }
- num = len / sizeof(struct cd_toc_entry);
-
- if (readlen > 0) {
- error = worm_read_toc(sc_link,
- te->address_format,
- starting_track,
- (struct cd_toc_entry *)&data,
- readlen + sizeof (*th));
- if (error)
- break;
- }
-
- /* make leadout entry if needed */
- idx = starting_track + num - 1;
- if (idx == th->ending_track + 1) {
- error = worm_read_toc(sc_link,
- te->address_format, 0xaa,
- (struct cd_toc_entry *)&lead,
- sizeof(lead));
- if (error)
- break;
- data.entries[idx - starting_track] = lead.entry;
- }
-
- error = copyout(data.entries, te->data, len);
- }
- break;
-
- case CDIOREADTOCENTRY:
- {
- struct {
- struct ioc_toc_header header;
- struct cd_toc_entry entry;
- } data;
- struct ioc_read_toc_single_entry *te =
- (struct ioc_read_toc_single_entry *) addr;
- struct ioc_toc_header *th;
- u_int32_t track;
-
- if (te->address_format != CD_MSF_FORMAT
- && te->address_format != CD_LBA_FORMAT) {
- error = EINVAL;
- break;
- }
-
- th = &data.header;
- error = worm_read_toc(sc_link, 0, 0,
- (struct cd_toc_entry *)th,
- sizeof (*th));
- if (error)
- break;
-
- track = te->track;
- if (track == 0)
- track = th->starting_track;
- else if (track == 0xaa)
- /* OK */;
- else if (track < th->starting_track ||
- track > th->ending_track + 1) {
- error = EINVAL;
- break;
- }
-
- error = worm_read_toc(sc_link, te->address_format,
- track,
- (struct cd_toc_entry *)&data,
- sizeof data);
- if (error)
- break;
-
- bcopy(&data.entry, &te->entry,
- sizeof(struct cd_toc_entry));
- }
- break;
-
- default:
- error = ENOTTY;
- break;
- }
- return (error);
-}
-
-
-static errval
-worm_rezero_unit(struct scsi_link *sc_link)
-{
- struct scsi_rezero_unit cmd;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("worm_rezero_unit"));
-
- /*
- * Re-initialize the unit, just to be sure.
- */
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = REZERO_UNIT;
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- 0, /* no data transfer */
- 0,
- /*WORMRETRY*/ 4,
- 5000,
- NULL,
- 0);
-}
-
-static errval
-worm_read_session_info(struct scsi_link *sc_link, struct wormio_session_info *data)
-{
- struct scsi_read_session_info cmd;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("worm_read_session_info"));
-
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = READ_SESSION_INFO;
- cmd.transfer_length = sizeof(struct wormio_session_info);
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- (u_char *) data,
- sizeof(struct wormio_session_info),
- /*WORMRETRY*/ 4,
- 5000,
- NULL,
- SCSI_DATA_IN);
-}
-
-/*
- * Read table of contents
- *
- * Stolen from cd.c
- */
-static errval
-worm_read_toc(struct scsi_link *sc_link, u_int32_t mode, u_int32_t start,
- struct cd_toc_entry *data, u_int32_t len)
-{
- struct scsi_read_toc scsi_cmd;
- u_int32_t ntoc;
-
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- ntoc = len;
-
- scsi_cmd.op_code = READ_TOC;
- if (mode == CD_MSF_FORMAT)
- scsi_cmd.byte2 |= CD_MSF;
- scsi_cmd.from_track = start;
- scsi_cmd.data_len[0] = (ntoc) >> 8;
- scsi_cmd.data_len[1] = (ntoc) & 0xff;
- return (scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(struct scsi_read_toc),
- (u_char *) data,
- len,
- /*WORMRETRY*/ 4,
- 5000,
- NULL,
- SCSI_DATA_IN));
-}
-
-static int
-worm_sense_handler(struct scsi_xfer *xs)
-{
- struct scsi_data *worm;
- struct scsi_sense_data *sense;
- struct scsi_sense_extended *ext;
- int asc, devmode, i;
-
- worm = xs->sc_link->sd;
- sense = &(xs->sense);
- ext = (struct scsi_sense_extended *) &(sense->ext.extended);
- asc = ext->add_sense_code;
- devmode = *(int *) xs->sc_link->devmodes;
-
- for (i = 0; worm_error[i].asc; i++)
- if ((asc == worm_error[i].asc) && (devmode & worm_error[i].devmode)) {
- worm->error = worm_error[i].error;
- return worm_error[i].ret;
- }
- worm->error = -1;
- return SCSIRET_CONTINUE;
-}
-
-static errval
-worm_set_blksize(struct scsi_link *sc_link, int size)
-{
- struct scsi_mode_select scsi_cmd;
- struct {
- struct scsi_mode_header header;
- struct blk_desc desc;
- } dat;
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- bzero(&dat, sizeof(dat));
- scsi_cmd.op_code = MODE_SELECT;
- scsi_cmd.length = sizeof(dat);
- dat.header.blk_desc_len = sizeof(struct blk_desc);
- scsi_uto3b(size, dat.desc.blklen);
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) &dat,
- sizeof(dat),
- /*WORM_RETRIES*/ 4,
- 5000,
- NULL,
- SCSI_DATA_OUT);
-}
-
-static void
-worm_drvinit(void *unused)
-{
-
- if (!worm_devsw_installed) {
- cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &worm_cdevsw);
- worm_devsw_installed = 1;
- }
-}
-
-SYSINIT(wormdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,worm_drvinit,NULL)
-
-/*
- * Begin device-specific stuff. Subject to being moved out to LKMs.
- */
-
-static u_char
-ascii_to_6bit (char c)
-{
- if (c < '0' || c > 'Z' || (c > '9' && c < 'A'))
- return 0;
- if (c <= '9')
- return c - '0';
- else
- return c - 'A' + 11;
-}
-/*
- * PLASMON RF4100/4102
- * Perhaps other Plasmon's, too.
- *
- * NB: By now, you'll certainly have to compare the SCSI reference
- * manual in order to understand the following.
- */
-
-/* The following mode pages might apply to other drives as well. */
-
-struct plasmon_rf4100_pages
-{
- u_char page_code;
-#define RF4100_PAGE_CODE_20 0x20
-#define RF4100_PAGE_CODE_21 0x21
-#define RF4100_PAGE_CODE_22 0x22
-#define RF4100_PAGE_CODE_23 0x23
-#define RF4100_PAGE_CODE_24 0x24
-#define RF4100_PAGE_CODE_25 0x25
- u_char param_len;
- union
- {
- /* page 0x20 omitted by now */
- struct
- {
- u_char reserved1;
- u_char mode;
-#define RF4100_RAW_MODE 0x10 /* raw mode enabled */
-#define RF4100_MIXED_MODE 0x08 /* mixed mode data enabled */
-#define RF4100_AUDIO_MODE 0x04 /* audio mode data enabled */
-#define RF4100_MODE_1 0x01 /* mode 1 blocks are enabled */
-#define RF4100_MODE_2 0x02 /* mode 2 blocks are enabled */
- u_char track_number;
- u_char isrc_i1; /* country code, ASCII */
- u_char isrc_i2;
- u_char isrc_i3; /* owner code, ASCII */
- u_char isrc_i4;
- u_char isrc_i5;
- u_char isrc_i6_7; /* country code, BCD */
- u_char isrc_i8_9; /* serial number, BCD */
- u_char isrc_i10_11;
- u_char isrc_i12_0;
- u_char reserved2[2];
- }
- page_0x21;
- /* mode page 0x22 omitted by now */
- struct
- {
- u_char speed_select;
-#define RF4100_SPEED_AUDIO 0x01
-#define RF4100_SPEED_DOUBLE 0x02
- u_char dummy_write;
-#define RF4100_DUMMY_WRITE 0x01
- u_char reserved[4];
- }
- page_0x23;
- /* pages 0x24 and 0x25 omitted by now */
- }
- pages;
-};
-
-
-static errval
-rf4100_prepare_disk(struct scsi_link *sc_link, int dummy, int speed)
-{
- struct scsi_mode_select scsi_cmd;
- struct {
- struct scsi_mode_header header;
- struct plasmon_rf4100_pages page;
- } dat;
- u_int32_t pagelen, dat_len;
-
- pagelen = sizeof(dat.page.pages.page_0x23) + PAGE_HEADERLEN;
- dat_len = sizeof(struct scsi_mode_header) + pagelen;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("rf4100_prepare_disk"));
-
- if (speed != RF4100_SPEED_AUDIO && speed != RF4100_SPEED_DOUBLE)
- return EINVAL;
-
- /*
- * Set up a mode page 0x23
- */
- bzero(&dat, sizeof(dat));
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SELECT;
- scsi_cmd.length = dat_len;
- /* dat.header.dev_spec = host application code; (see spec) */
- dat.page.page_code = RF4100_PAGE_CODE_23;
- dat.page.param_len = sizeof(dat.page.pages.page_0x23);
- dat.page.pages.page_0x23.speed_select = speed;
- dat.page.pages.page_0x23.dummy_write = dummy? RF4100_DUMMY_WRITE: 0;
- /*
- * Fire it off.
- */
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) &dat,
- dat_len,
- /*WORM_RETRIES*/ 4,
- 5000,
- NULL,
- SCSI_DATA_OUT);
-}
-
-
-static errval
-rf4100_prepare_track(struct scsi_link *sc_link, struct wormio_prepare_track *t)
-{
- struct scsi_mode_select scsi_cmd;
- struct scsi_data *worm;
- struct {
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- struct plasmon_rf4100_pages page;
- } dat;
- u_int32_t pagelen, dat_len, blk_len;
- int year;
-
- worm = sc_link->sd;
-
- pagelen = sizeof(dat.page.pages.page_0x21) + PAGE_HEADERLEN;
- dat_len = sizeof(struct scsi_mode_header)
- + sizeof(struct blk_desc)
- + pagelen;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("rf4100_prepare_track"));
-
- /*
- * Set up a mode page 0x21. Note that the block descriptor is
- * mandatory in at least one of the MODE SELECT commands, in
- * order to select the block length in question. We do this
- * here, just prior to opening the write channel. (Spec:
- * ``All information for the write is included in the MODE
- * SELECT, MODE PAGE 21h, and the write channel can be
- * considered open on receipt of the first WRITE command.'' I
- * didn't have luck with an explicit WRITE TRACK command
- * anyway, this might be different for other CD-R drives. -
- * Jörg)
- */
- bzero(&dat, sizeof(dat));
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SELECT;
- scsi_cmd.length = dat_len;
- dat.header.blk_desc_len = sizeof(struct blk_desc);
- dat.page.page_code = RF4100_PAGE_CODE_21;
- dat.page.param_len = sizeof(dat.page.pages.page_0x21);
- /* dat.header.dev_spec = host application code; (see spec) */
- if (t->audio) {
- blk_len = 2352;
- dat.page.pages.page_0x21.mode = RF4100_AUDIO_MODE +
- (t->preemp? RF4100_MODE_1 : 0);
- } else
- switch (t->track_type) {
- case BLOCK_RAW:
- blk_len = 2352;
- dat.page.pages.page_0x21.mode = RF4100_RAW_MODE;
- break;
- case BLOCK_MODE_1:
- blk_len = 2048;
- dat.page.pages.page_0x21.mode = RF4100_MODE_1;
- break;
- case BLOCK_MODE_2:
- blk_len = 2336;
- dat.page.pages.page_0x21.mode = RF4100_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_1:
- blk_len = 2048;
- dat.page.pages.page_0x21.mode = RF4100_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_1b:
- blk_len = 2056;
- dat.page.pages.page_0x21.mode = RF4100_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_2:
- blk_len = 2324;
- dat.page.pages.page_0x21.mode = RF4100_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_2b:
- blk_len = 2332;
- dat.page.pages.page_0x21.mode = RF4100_MODE_2;
- break;
- default:
- return EINVAL;
- }
- dat.page.pages.page_0x21.mode |= t->copy_bits << 5;
-
- worm->blk_size = blk_len;
-
- dat.page.pages.page_0x21.track_number = t->track_number;
-
- dat.page.pages.page_0x21.isrc_i1 = ascii_to_6bit(t->ISRC_country[0]);
- dat.page.pages.page_0x21.isrc_i2 = ascii_to_6bit(t->ISRC_country[1]);
- dat.page.pages.page_0x21.isrc_i3 = ascii_to_6bit(t->ISRC_owner[0]);
- dat.page.pages.page_0x21.isrc_i4 = ascii_to_6bit(t->ISRC_owner[1]);
- dat.page.pages.page_0x21.isrc_i5 = ascii_to_6bit(t->ISRC_owner[2]);
- year = t->ISRC_year % 100;
- if (year < 0)
- return EINVAL;
- dat.page.pages.page_0x21.isrc_i6_7 = bin2bcd(year);
- if (t->ISRC_serial[0]) {
- dat.page.pages.page_0x21.isrc_i8_9 = ((t->ISRC_serial[0]-'0') << 4) |
- (t->ISRC_serial[1] - '0');
- dat.page.pages.page_0x21.isrc_i10_11 = ((t->ISRC_serial[2]-'0') << 4) |
- (t->ISRC_serial[3] - '0');
- dat.page.pages.page_0x21.isrc_i12_0 = (t->ISRC_serial[4] - '0' << 4);
- }
- scsi_uto3b(blk_len, dat.blk_desc.blklen);
-
- /*
- * Fire it off.
- */
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) &dat,
- dat_len,
- /*WORM_RETRIES*/ 4,
- 5000,
- NULL,
- SCSI_DATA_OUT);
-}
-
-
-static errval
-rf4100_finalize_track(struct scsi_link *sc_link)
-{
- struct scsi_synchronize_cache cmd;
- int error;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("rf4100_finalize_track"));
-
- /*
- * Only a "synchronize cache" is needed.
- */
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = SYNCHRONIZE_CACHE;
- error = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- 0, /* no data transfer */
- 0,
- 1,
- 60000, /* this may take a while */
- NULL,
- 0);
- if (!error)
- error = worm_set_blksize(sc_link, 2048);
-
- return error;
-}
-
-
-static errval
-rf4100_finalize_disk(struct scsi_link *sc_link, int toc_type, int onp)
-{
- struct scsi_fixation cmd;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("rf4100_finalize_disk"));
-
- if (toc_type < 0 || toc_type > WORM_TOC_TYPE_CDI)
- return EINVAL;
-
- /*
- * Fixate this session. Mark the next one as opened if onp
- * is true. Otherwise, the disk will be finalized once and
- * for all. ONP stands for "open next program area".
- */
-
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = FIXATION;
- cmd.action = (onp? WORM_FIXATION_ONP: 0) + toc_type;
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- 0, /* no data transfer */
- 0,
- 1,
- 20*60*1000, /* takes a huge amount of time */
- NULL,
- 0);
-}
-
-/*
- * End Plasmon RF4100/4102 section.
- */
-
-/*
- * HP C4324/C4325 (This is what the scsi spec. and firmware says)
- * Drive model 4020i
- * This is very similar to the Plasmon above.
- */
-
-/* The following mode pages might apply to other drives as well. */
-
-struct hp_4020i_pages
-{
- u_char page_code;
-#define HP4020I_PAGE_CODE_20 0x20
-#define HP4020I_PAGE_CODE_21 0x21
-#define HP4020I_PAGE_CODE_22 0x22
-#define HP4020I_PAGE_CODE_23 0x23
-#define HP4020I_PAGE_CODE_24 0x24
-#define HP4020I_PAGE_CODE_25 0x25
- u_char param_len;
- union
- {
- /* page 0x20 omitted by now */
- struct
- {
- u_char reserved1;
- u_char mode;
-#define HP4020I_RAW_MODE 0x10 /* raw mode enabled */
-#define HP4020I_MIXED_MODE 0x08 /* mixed mode data enabled */
-#define HP4020I_AUDIO_MODE 0x04 /* audio mode data enabled */
-#define HP4020I_MODE_1 0x01 /* mode 1 blocks are enabled */
-#define HP4020I_MODE_2 0x02 /* mode 2 blocks are enabled */
- u_char track_number;
- u_char isrc_i1; /* country code, ASCII */
- u_char isrc_i2;
- u_char isrc_i3; /* owner code, ASCII */
- u_char isrc_i4;
- u_char isrc_i5;
- u_char isrc_i6_7; /* year code, BCD */
- u_char isrc_i8_9; /* serial number, BCD */
- u_char isrc_i10_11;
- u_char isrc_i12_0;
- u_char reserved2[2];
- }
- page_0x21;
- struct
- {
- u_char catalog_valid;
- u_char catalog_c1_c2; /* catalog number, BCD */
- u_char catalog_c3_c4;
- u_char catalog_c5_c6;
- u_char catalog_c7_c8;
- u_char catalog_c9_c10;
- u_char catalog_c11_c12;
- u_char catalog_c13_0;
- } page_0x22;
- struct
- {
- u_char speed_select;
-#define HP4020I_SPEED_AUDIO 0x01
-#define HP4020I_SPEED_DOUBLE 0x02
- u_char dummy_write;
-#define HP4020I_DUMMY_WRITE 0x01
- u_char reserved[4];
- }
- page_0x23;
- /* pages 0x24 and 0x25 omitted by now */
- }
- pages;
-};
-
-static errval
-hp4020i_prepare_disk(struct scsi_link *sc_link, int dummy, int speed)
-{
- struct scsi_mode_select scsi_cmd;
- struct {
- struct scsi_mode_header header;
- struct hp_4020i_pages page;
- } dat;
- u_int32_t pagelen, dat_len;
-
- pagelen = sizeof(dat.page.pages.page_0x23) + PAGE_HEADERLEN;
- dat_len = sizeof(struct scsi_mode_header) + pagelen;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("hp4020i_prepare_disk"));
-
- if (speed != HP4020I_SPEED_AUDIO && speed != HP4020I_SPEED_DOUBLE)
- return EINVAL;
-
- /*
- * Set up a mode page 0x23
- */
- bzero(&dat, sizeof(dat));
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SELECT;
- scsi_cmd.byte2 |= SMS_PF;
- scsi_cmd.length = dat_len;
- /* dat.header.dev_spec = host application code; (see spec) */
- dat.page.page_code = HP4020I_PAGE_CODE_23;
- dat.page.param_len = sizeof(dat.page.pages.page_0x23);
- dat.page.pages.page_0x23.speed_select = speed;
- dat.page.pages.page_0x23.dummy_write = dummy? HP4020I_DUMMY_WRITE: 0;
- /*
- * Fire it off.
- */
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) &dat,
- dat_len,
- /*WORM_RETRIES*/ 4,
- 5000,
- NULL,
- SCSI_DATA_OUT);
-}
-
-
-static errval
-hp4020i_prepare_track(struct scsi_link *sc_link, struct wormio_prepare_track *t)
-{
- struct scsi_mode_select scsi_cmd;
- struct scsi_data *worm;
- struct {
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- struct hp_4020i_pages page;
- } dat;
- u_int32_t pagelen, dat_len, blk_len;
- int year;
-
- worm = sc_link->sd;
-
- pagelen = sizeof(dat.page.pages.page_0x21) + PAGE_HEADERLEN;
- dat_len = sizeof(struct scsi_mode_header)
- + sizeof(struct blk_desc)
- + pagelen;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("hp4020i_prepare_track"));
-
-
- /*
- * Set up a mode page 0x21. Note that the block descriptor is
- * mandatory in at least one of the MODE SELECT commands, in
- * order to select the block length in question. We do this
- * here, just prior to opening the write channel. (Spec:
- * ``All information for the write is included in the MODE
- * SELECT, MODE PAGE 21h, and the write channel can be
- * considered open on receipt of the first WRITE command.'' I
- * didn't have luck with an explicit WRITE TRACK command
- * anyway, this might be different for other CD-R drives. -
- * Jörg)
- */
- bzero(&dat, sizeof(dat));
- bzero(&scsi_cmd, sizeof(scsi_cmd));
- scsi_cmd.op_code = MODE_SELECT;
- scsi_cmd.byte2 |= SMS_PF;
- scsi_cmd.length = dat_len;
- dat.header.blk_desc_len = sizeof(struct blk_desc);
- dat.page.page_code = HP4020I_PAGE_CODE_21;
- dat.page.param_len = sizeof(dat.page.pages.page_0x21);
- /* dat.header.dev_spec = host application code; (see spec) */
- if (t->audio) {
- blk_len = 2352;
- dat.page.pages.page_0x21.mode = HP4020I_AUDIO_MODE +
- (t->preemp? HP4020I_MODE_1 : 0);
- } else
- switch (t->track_type) {
- case BLOCK_RAW:
- blk_len = 2352;
- dat.page.pages.page_0x21.mode = HP4020I_RAW_MODE;
- break;
- case BLOCK_MODE_1:
- blk_len = 2048;
- dat.page.pages.page_0x21.mode = HP4020I_MODE_1;
- break;
- case BLOCK_MODE_2:
- blk_len = 2336;
- dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_1:
- blk_len = 2048;
- dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_1b:
- blk_len = 2056;
- dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_2:
- blk_len = 2324;
- dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
- break;
- case BLOCK_MODE_2_FORM_2b:
- blk_len = 2332;
- dat.page.pages.page_0x21.mode = HP4020I_MODE_2;
- break;
- default:
- return EINVAL;
- }
- dat.page.pages.page_0x21.mode |= t->copy_bits << 5;
-
- worm->blk_size = blk_len;
-
- dat.page.pages.page_0x21.track_number = t->track_number;
-
- dat.page.pages.page_0x21.isrc_i1 = ascii_to_6bit(t->ISRC_country[0]);
- dat.page.pages.page_0x21.isrc_i2 = ascii_to_6bit(t->ISRC_country[1]);
- dat.page.pages.page_0x21.isrc_i3 = ascii_to_6bit(t->ISRC_owner[0]);
- dat.page.pages.page_0x21.isrc_i4 = ascii_to_6bit(t->ISRC_owner[1]);
- dat.page.pages.page_0x21.isrc_i5 = ascii_to_6bit(t->ISRC_owner[2]);
- year = t->ISRC_year % 100;
- if (year < 0)
- return EINVAL;
- dat.page.pages.page_0x21.isrc_i6_7 = bin2bcd(year);
- if (t->ISRC_serial[0]) {
- dat.page.pages.page_0x21.isrc_i8_9 = ((t->ISRC_serial[0]-'0') << 4) |
- (t->ISRC_serial[1] - '0');
- dat.page.pages.page_0x21.isrc_i10_11 = ((t->ISRC_serial[2]-'0') << 4) |
- (t->ISRC_serial[3] - '0');
- dat.page.pages.page_0x21.isrc_i12_0 = (t->ISRC_serial[4] - '0' << 4);
- }
-
- scsi_uto3b(blk_len, dat.blk_desc.blklen);
-
- /*
- * Fire it off.
- */
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &scsi_cmd,
- sizeof(scsi_cmd),
- (u_char *) &dat,
- dat_len,
- /*WORM_RETRIES*/ 4,
- 5000,
- NULL,
- SCSI_DATA_OUT);
-}
-
-
-static errval
-hp4020i_finalize_track(struct scsi_link *sc_link)
-{
- struct scsi_synchronize_cache cmd;
- int error;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("hp4020i_finalize_track"));
-
- /*
- * Only a "synchronize cache" is needed.
- */
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = SYNCHRONIZE_CACHE;
- error = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- 0, /* no data transfer */
- 0,
- 1,
- 60000, /* this may take a while */
- NULL,
- 0);
- if (!error)
- error = worm_set_blksize(sc_link, 2048);
-
- return error;
-}
-
-
-static errval
-hp4020i_finalize_disk(struct scsi_link *sc_link, int toc_type, int onp)
-{
- struct scsi_fixation cmd;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("hp4020i_finalize_disk"));
-
- if (toc_type < 0 || toc_type > WORM_TOC_TYPE_CDI)
- return EINVAL;
-
- /*
- * Fixate this session. Mark the next one as opened if onp
- * is true. Otherwise, the disk will be finalized once and
- * for all. ONP stands for "open next program area".
- */
-
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = FIXATION;
- cmd.action = (onp? WORM_FIXATION_ONP: 0) + toc_type;
- return scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- 0, /* no data transfer */
- 0,
- 1,
- 20*60*1000, /* takes a huge amount of time */
- NULL,
- 0);
-}
-static errval
-hp4020i_write_session(struct scsi_link *sc_link, struct wormio_write_session *ws)
-{
- struct {
- struct scsi_mode_header header;
- struct blk_desc blk_desc;
- struct hp_4020i_pages page;
- } dat;
- struct scsi_mode_select cmd1;
- struct scsi_write_session cmd2;
- struct scsi_data *worm;
- u_int32_t pagelen, dat_len, blk_len;
- errval error;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("hp4020i_write_session"));
-
- if (ws->toc_type < 0 || ws->toc_type > WORM_TOC_TYPE_CDI || ws->lofp & ~3)
- return EINVAL;
-
- pagelen = sizeof(dat.page.pages.page_0x22) + PAGE_HEADERLEN;
- dat_len = sizeof(struct scsi_mode_header)
- + sizeof(struct blk_desc)
- + pagelen;
-
- worm = sc_link->sd;
-
- /* set the block size to 2352 and the catalog */
- bzero(&dat, sizeof(dat));
- bzero(&cmd1, sizeof(cmd1));
- cmd1.op_code = MODE_SELECT;
- cmd1.byte2 |= SMS_PF;
- cmd1.length = dat_len;
- dat.header.blk_desc_len = sizeof(struct blk_desc);
- dat.page.page_code = HP4020I_PAGE_CODE_22;
- dat.page.param_len = sizeof(dat.page.pages.page_0x22);
- blk_len = 2352;
- if (ws->catalog[0] >= '0' && ws->catalog[0] <= '9') {
- dat.page.pages.page_0x22.catalog_valid = 1;
- dat.page.pages.page_0x22.catalog_c1_c2 = ((ws->catalog[0]-'0') << 4)
- | ((ws->catalog[1]-'0') << 4);
- dat.page.pages.page_0x22.catalog_c3_c4 = ((ws->catalog[2]-'0') << 4)
- | ((ws->catalog[3]-'0') << 4);
- dat.page.pages.page_0x22.catalog_c5_c6 = ((ws->catalog[4]-'0') << 4)
- | ((ws->catalog[5]-'0') << 4);
- dat.page.pages.page_0x22.catalog_c7_c8 = ((ws->catalog[6]-'0') << 4)
- | ((ws->catalog[7]-'0') << 4);
- dat.page.pages.page_0x22.catalog_c9_c10 = ((ws->catalog[8]-'0') << 4)
- | ((ws->catalog[9]-'0') << 4);
- dat.page.pages.page_0x22.catalog_c11_c12 = ((ws->catalog[10]-'0') << 4)
- | ((ws->catalog[11]-'0') << 4);
- dat.page.pages.page_0x22.catalog_c13_0 = ((ws->catalog[12]-'0') << 4);
- }
- scsi_uto3b(blk_len, dat.blk_desc.blklen);
-
- error = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd1,
- sizeof(cmd1),
- (u_char *) &dat,
- dat_len,
- /*WORM_RETRIES*/ 4,
- 5000,
- NULL,
- SCSI_DATA_OUT);
-
- if (!error) {
- worm->blk_size = blk_len;
- bzero(&cmd2, sizeof(cmd2));
- cmd2.op_code = WRITE_SESSION;
- cmd2.action = (ws->lofp << 4) | (ws->onp? WORM_FIXATION_ONP: 0) + ws->toc_type;
- scsi_uto2b(ws->length, &cmd2.transfer_length_2);
-
- error = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd2,
- sizeof(cmd2),
- ws->track_desc,
- ws->length,
- 1,
- 5000,
- NULL,
- SCSI_DATA_OUT);
- }
- return error;
-}
-
-static errval
-hp4020i_read_first_writable_address (struct scsi_link *sc_link,
- int track, int mode, int raw, int audio, int *addr)
-{
- struct scsi_first_writable_address cmd;
- char data[6];
- errval error;
-
- SC_DEBUG(sc_link, SDEV_DB2, ("worm_read_first_writable_address"));
-
- bzero(&cmd, sizeof(cmd));
- cmd.op_code = FIRST_WRITEABLE_ADDR;
- cmd.track_number = track;
- cmd.mode = (raw << 3) | (audio << 2) | mode;
- cmd.transfer_length = sizeof(data);
- error = scsi_scsi_cmd(sc_link,
- (struct scsi_generic *) &cmd,
- sizeof(cmd),
- (u_char *) data,
- sizeof(data),
- /*WORMRETRY*/ 4,
- 5000,
- NULL,
- SCSI_DATA_IN);
- *addr = scsi_4btou (data+1);
- return error;
-}
-
-/*
- * End HP C4324/C4325 (4020i) section.
- */
OpenPOWER on IntegriCloud