Obsoleted by CAM.

This commit is contained in:
Justin T. Gibbs 1998-09-15 10:40:55 +00:00
parent d13e6580b9
commit bd9d336e40
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=39266
39 changed files with 0 additions and 25864 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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_ */

File diff suppressed because it is too large Load Diff

View File

@ -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_ */

File diff suppressed because it is too large Load Diff

View File

@ -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_ */

View File

@ -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 */

View File

@ -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 */

View File

@ -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.

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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*/

File diff suppressed because it is too large Load Diff

View File

@ -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*/

View File

@ -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 */

View File

@ -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 */

View File

@ -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*/

View File

@ -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);
}
}

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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*/

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -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)

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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)

File diff suppressed because it is too large Load Diff