|
|
GNU Mach 1.2
/* $Id: wd7000.h,v 1.1.1.1 2020/09/02 04:41:40 root Exp $
*
* Header file for the WD-7000 driver for Linux
*
* John Boyd <[email protected]> Jan 1994:
* This file has been reduced to only the definitions needed for the
* WD7000 host structure.
*
* Revision by Miroslav Zagorac <[email protected]> Jun 1997.
*/
#ifndef _WD7000_H
#include <linux/version.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#ifndef NULL
#define NULL 0L
#endif
/*
* In this version, sg_tablesize now defaults to WD7000_SG, and will
* be set to SG_NONE for older boards. This is the reverse of the
* previous default, and was changed so that the driver-level
* Scsi_Host_Template would reflect the driver's support for scatter/
* gather.
*
* Also, it has been reported that boards at Revision 6 support scatter/
* gather, so the new definition of an "older" board has been changed
* accordingly.
*/
#define WD7000_Q 16
#define WD7000_SG 16
#ifdef WD7000_DEFINES
/*
* Mailbox structure sizes.
* I prefer to keep the number of ICMBs much larger than the number of
* OGMBs. OGMBs are used very quickly by the driver to start one or
* more commands, while ICMBs are used by the host adapter per command.
*/
#define OGMB_CNT 16
#define ICMB_CNT 32
/*
* Scb's are shared by all active adapters. If you'd rather conserve
* memory, use a smaller number (> 0, of course) - things will should
* still work OK.
*/
#define MAX_SCBS (4 * WD7000_Q)
/*
* WD7000-specific mailbox structure
*/
typedef volatile struct {
unchar status;
unchar scbptr[3]; /* SCSI-style - MSB first (big endian) */
} Mailbox;
/*
* This structure should contain all per-adapter global data. I.e., any
* new global per-adapter data should put in here.
*/
typedef struct {
struct Scsi_Host *sh; /* Pointer to Scsi_Host structure */
int iobase; /* This adapter's I/O base address */
int irq; /* This adapter's IRQ level */
int dma; /* This adapter's DMA channel */
int int_counter; /* This adapter's interrupt counter */
int bus_on; /* This adapter's BUS_ON time */
int bus_off; /* This adapter's BUS_OFF time */
struct { /* This adapter's mailboxes */
Mailbox ogmb[OGMB_CNT]; /* Outgoing mailboxes */
Mailbox icmb[ICMB_CNT]; /* Incoming mailboxes */
} mb;
int next_ogmb; /* to reduce contention at mailboxes */
unchar control; /* shadows CONTROL port value */
unchar rev1; /* filled in by wd7000_revision */
unchar rev2;
} Adapter;
/*
* possible irq range
*/
#define IRQ_MIN 3
#define IRQ_MAX 15
#define IRQS (IRQ_MAX - IRQ_MIN + 1)
#define BUS_ON 64 /* x 125ns = 8000ns (BIOS default) */
#define BUS_OFF 15 /* x 125ns = 1875ns (BIOS default) */
/*
* Standard Adapter Configurations - used by wd7000_detect
*/
typedef struct {
short irq; /* IRQ level */
short dma; /* DMA channel */
uint iobase; /* I/O base address */
short bus_on; /* Time that WD7000 spends on the AT-bus when */
/* transferring data. BIOS default is 8000ns. */
short bus_off; /* Time that WD7000 spends OFF THE BUS after */
/* while it is transferring data. */
/* BIOS default is 1875ns */
} Config;
/*
* The following list defines strings to look for in the BIOS that identify
* it as the WD7000-FASST2 SST BIOS. I suspect that something should be
* added for the Future Domain version.
*/
typedef struct {
const char *sig; /* String to look for */
ulong ofs; /* offset from BIOS base address */
uint len; /* length of string */
} Signature;
/*
* I/O Port Offsets and Bit Definitions
* 4 addresses are used. Those not defined here are reserved.
*/
#define ASC_STAT 0 /* Status, Read */
#define ASC_COMMAND 0 /* Command, Write */
#define ASC_INTR_STAT 1 /* Interrupt Status, Read */
#define ASC_INTR_ACK 1 /* Acknowledge, Write */
#define ASC_CONTROL 2 /* Control, Write */
/*
* ASC Status Port
*/
#define INT_IM 0x80 /* Interrupt Image Flag */
#define CMD_RDY 0x40 /* Command Port Ready */
#define CMD_REJ 0x20 /* Command Port Byte Rejected */
#define ASC_INIT 0x10 /* ASC Initialized Flag */
#define ASC_STATMASK 0xf0 /* The lower 4 Bytes are reserved */
/*
* COMMAND opcodes
*
* Unfortunately, I have no idea how to properly use some of these commands,
* as the OEM manual does not make it clear. I have not been able to use
* enable/disable unsolicited interrupts or the reset commands with any
* discernible effect whatsoever. I think they may be related to certain
* ICB commands, but again, the OEM manual doesn't make that clear.
*/
#define NO_OP 0 /* NO-OP toggles CMD_RDY bit in ASC_STAT */
#define INITIALIZATION 1 /* initialization (10 bytes) */
#define DISABLE_UNS_INTR 2 /* disable unsolicited interrupts */
#define ENABLE_UNS_INTR 3 /* enable unsolicited interrupts */
#define INTR_ON_FREE_OGMB 4 /* interrupt on free OGMB */
#define SOFT_RESET 5 /* SCSI bus soft reset */
#define HARD_RESET_ACK 6 /* SCSI bus hard reset acknowledge */
#define START_OGMB 0x80 /* start command in OGMB (n) */
#define SCAN_OGMBS 0xc0 /* start multiple commands, signature (n) */
/* where (n) = lower 6 bits */
/*
* For INITIALIZATION:
*/
typedef struct {
unchar op; /* command opcode (= 1) */
unchar ID; /* Adapter's SCSI ID */
unchar bus_on; /* Bus on time, x 125ns (see below) */
unchar bus_off; /* Bus off time, "" "" */
unchar rsvd; /* Reserved */
unchar mailboxes[3]; /* Address of Mailboxes, MSB first */
unchar ogmbs; /* Number of outgoing MBs, max 64, 0,1 = 1 */
unchar icmbs; /* Number of incoming MBs, "" "" */
} InitCmd;
/*
* Interrupt Status Port - also returns diagnostic codes at ASC reset
*
* if msb is zero, the lower bits are diagnostic status
* Diagnostics:
* 01 No diagnostic error occurred
* 02 RAM failure
* 03 FIFO R/W failed
* 04 SBIC register read/write failed
* 05 Initialization D-FF failed
* 06 Host IRQ D-FF failed
* 07 ROM checksum error
* Interrupt status (bitwise):
* 10NNNNNN outgoing mailbox NNNNNN is free
* 11NNNNNN incoming mailbox NNNNNN needs service
*/
#define MB_INTR 0xC0 /* Mailbox Service possible/required */
#define IMB_INTR 0x40 /* 1 Incoming / 0 Outgoing */
#define MB_MASK 0x3f /* mask for mailbox number */
/*
* CONTROL port bits
*/
#define INT_EN 0x08 /* Interrupt Enable */
#define DMA_EN 0x04 /* DMA Enable */
#define SCSI_RES 0x02 /* SCSI Reset */
#define ASC_RES 0x01 /* ASC Reset */
/*
* Driver data structures:
* - mb and scbs are required for interfacing with the host adapter.
* An SCB has extra fields not visible to the adapter; mb's
* _cannot_ do this, since the adapter assumes they are contiguous in
* memory, 4 bytes each, with ICMBs following OGMBs, and uses this fact
* to access them.
* - An icb is for host-only (non-SCSI) commands. ICBs are 16 bytes each;
* the additional bytes are used only by the driver.
* - For now, a pool of SCBs are kept in global storage by this driver,
* and are allocated and freed as needed.
*
* The 7000-FASST2 marks OGMBs empty as soon as it has _started_ a command,
* not when it has finished. Since the SCB must be around for completion,
* problems arise when SCBs correspond to OGMBs, which may be reallocated
* earlier (or delayed unnecessarily until a command completes).
* Mailboxes are used as transient data structures, simply for
* carrying SCB addresses to/from the 7000-FASST2.
*
* Note also since SCBs are not "permanently" associated with mailboxes,
* there is no need to keep a global list of Scsi_Cmnd pointers indexed
* by OGMB. Again, SCBs reference their Scsi_Cmnds directly, so mailbox
* indices need not be involved.
*/
/*
* WD7000-specific scatter/gather element structure
*/
typedef struct {
unchar len[3];
unchar ptr[3]; /* Also SCSI-style - MSB first */
} Sgb;
typedef struct { /* Command Control Block 5.4.1 */
unchar op; /* Command Control Block Operation Code */
unchar idlun; /* op=0,2:Target Id, op=1:Initiator Id */
/* Outbound data transfer, length is checked */
/* Inbound data transfer, length is checked */
/* Logical Unit Number */
unchar cdb[12]; /* SCSI Command Block */
volatile unchar status; /* SCSI Return Status */
volatile unchar vue; /* Vendor Unique Error Code */
unchar maxlen[3]; /* Maximum Data Transfer Length */
unchar dataptr[3]; /* SCSI Data Block Pointer */
unchar linkptr[3]; /* Next Command Link Pointer */
unchar direc; /* Transfer Direction */
unchar reserved2[6]; /* SCSI Command Descriptor Block */
/* end of hardware SCB */
Scsi_Cmnd *SCpnt; /* Scsi_Cmnd using this SCB */
Sgb sgb[WD7000_SG]; /* Scatter/gather list for this SCB */
Adapter *host; /* host adapter */
unchar used; /* flag */
} Scb;
/*
* This driver is written to allow host-only commands to be executed.
* These use a 16-byte block called an ICB. The format is extended by the
* driver to 18 bytes, to support the status returned in the ICMB and
* an execution phase code.
*
* There are other formats besides these; these are the ones I've tried
* to use. Formats for some of the defined ICB opcodes are not defined
* (notably, get/set unsolicited interrupt status) in my copy of the OEM
* manual, and others are ambiguous/hard to follow.
*/
#define ICB_OP_MASK 0x80 /* distinguishes scbs from icbs */
#define ICB_OP_OPEN_RBUF 0x80 /* open receive buffer */
#define ICB_OP_RECV_CMD 0x81 /* receive command from initiator */
#define ICB_OP_RECV_DATA 0x82 /* receive data from initiator */
#define ICB_OP_RECV_SDATA 0x83 /* receive data with status from init. */
#define ICB_OP_SEND_DATA 0x84 /* send data with status to initiator */
#define ICB_OP_SEND_STAT 0x86 /* send command status to initiator */
/* 0x87 is reserved */
#define ICB_OP_READ_INIT 0x88 /* read initialization bytes */
#define ICB_OP_READ_ID 0x89 /* read adapter's SCSI ID */
#define ICB_OP_SET_UMASK 0x8A /* set unsolicited interrupt mask */
#define ICB_OP_GET_UMASK 0x8B /* read unsolicited interrupt mask */
#define ICB_OP_GET_REVISION 0x8C /* read firmware revision level */
#define ICB_OP_DIAGNOSTICS 0x8D /* execute diagnostics */
#define ICB_OP_SET_EPARMS 0x8E /* set execution parameters */
#define ICB_OP_GET_EPARMS 0x8F /* read execution parameters */
typedef struct {
unchar op;
unchar IDlun; /* Initiator SCSI ID/lun */
unchar len[3]; /* command buffer length */
unchar ptr[3]; /* command buffer address */
unchar rsvd[7]; /* reserved */
volatile unchar vue; /* vendor-unique error code */
volatile unchar status; /* returned (icmb) status */
volatile unchar phase; /* used by interrupt handler */
} IcbRecvCmd;
typedef struct {
unchar op;
unchar IDlun; /* Target SCSI ID/lun */
unchar stat; /* (outgoing) completion status byte 1 */
unchar rsvd[12]; /* reserved */
volatile unchar vue; /* vendor-unique error code */
volatile unchar status; /* returned (icmb) status */
volatile unchar phase; /* used by interrupt handler */
} IcbSendStat;
typedef struct {
unchar op;
volatile unchar primary; /* primary revision level (returned) */
volatile unchar secondary; /* secondary revision level (returned) */
unchar rsvd[12]; /* reserved */
volatile unchar vue; /* vendor-unique error code */
volatile unchar status; /* returned (icmb) status */
volatile unchar phase; /* used by interrupt handler */
} IcbRevLvl;
typedef struct { /* I'm totally guessing here */
unchar op;
volatile unchar mask[14]; /* mask bits */
#if 0
unchar rsvd[12]; /* reserved */
#endif
volatile unchar vue; /* vendor-unique error code */
volatile unchar status; /* returned (icmb) status */
volatile unchar phase; /* used by interrupt handler */
} IcbUnsMask;
typedef struct {
unchar op;
unchar type; /* diagnostics type code (0-3) */
unchar len[3]; /* buffer length */
unchar ptr[3]; /* buffer address */
unchar rsvd[7]; /* reserved */
volatile unchar vue; /* vendor-unique error code */
volatile unchar status; /* returned (icmb) status */
volatile unchar phase; /* used by interrupt handler */
} IcbDiag;
#define ICB_DIAG_POWERUP 0 /* Power-up diags only */
#define ICB_DIAG_WALKING 1 /* walking 1's pattern */
#define ICB_DIAG_DMA 2 /* DMA - system memory diags */
#define ICB_DIAG_FULL 3 /* do both 1 & 2 */
typedef struct {
unchar op;
unchar rsvd1; /* reserved */
unchar len[3]; /* parms buffer length */
unchar ptr[3]; /* parms buffer address */
unchar idx[2]; /* index (MSB-LSB) */
unchar rsvd2[5]; /* reserved */
volatile unchar vue; /* vendor-unique error code */
volatile unchar status; /* returned (icmb) status */
volatile unchar phase; /* used by interrupt handler */
} IcbParms;
typedef struct {
unchar op;
unchar data[14]; /* format-specific data */
volatile unchar vue; /* vendor-unique error code */
volatile unchar status; /* returned (icmb) status */
volatile unchar phase; /* used by interrupt handler */
} IcbAny;
typedef union {
unchar op; /* ICB opcode */
IcbRecvCmd recv_cmd; /* format for receive command */
IcbSendStat send_stat; /* format for send status */
IcbRevLvl rev_lvl; /* format for get revision level */
IcbDiag diag; /* format for execute diagnostics */
IcbParms eparms; /* format for get/set exec parms */
IcbAny icb; /* generic format */
unchar data[18];
} Icb;
#define WAITnexttimeout 200 /* 2 seconds */
typedef union { /* let's cheat... */
int i;
unchar u[sizeof (int)]; /* the sizeof(int) makes it more portable */
} i_u;
#endif /* WD7000_DEFINES */
#if (LINUX_VERSION_CODE >= 0x020100)
#define WD7000 { \
proc_dir: &proc_scsi_wd7000, \
proc_info: wd7000_proc_info, \
name: "Western Digital WD-7000", \
detect: wd7000_detect, \
command: wd7000_command, \
queuecommand: wd7000_queuecommand, \
abort: wd7000_abort, \
reset: wd7000_reset, \
bios_param: wd7000_biosparam, \
can_queue: WD7000_Q, \
this_id: 7, \
sg_tablesize: WD7000_SG, \
cmd_per_lun: 1, \
unchecked_isa_dma: 1, \
use_clustering: ENABLE_CLUSTERING, \
use_new_eh_code: 0 \
}
#else /* Use old scsi code */
#define WD7000 { \
proc_dir: &proc_scsi_wd7000, \
proc_info: wd7000_proc_info, \
name: "Western Digital WD-7000", \
detect: wd7000_detect, \
command: wd7000_command, \
queuecommand: wd7000_queuecommand, \
abort: wd7000_abort, \
reset: wd7000_reset, \
bios_param: wd7000_biosparam, \
can_queue: WD7000_Q, \
this_id: 7, \
sg_tablesize: WD7000_SG, \
cmd_per_lun: 1, \
unchecked_isa_dma: 1, \
use_clustering: ENABLE_CLUSTERING, \
}
#endif /* LINUX_VERSION_CODE */
extern struct proc_dir_entry proc_scsi_wd7000;
#ifdef WD7000_DEFINES
int wd7000_diagnostics (Adapter *, int);
int wd7000_init (Adapter *);
void wd7000_revision (Adapter *);
#endif /* WD7000_DEFINES */
void wd7000_setup (char *, int *);
int make_code (uint, uint);
void wd7000_intr_handle (int, void *, struct pt_regs *);
void do_wd7000_intr_handle (int, void *, struct pt_regs *);
int wd7000_queuecommand (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int wd7000_command (Scsi_Cmnd *);
int wd7000_set_info (char *, int, struct Scsi_Host *);
int wd7000_proc_info (char *, char **, off_t, int, int, int);
int wd7000_detect (Scsi_Host_Template *);
int wd7000_abort (Scsi_Cmnd *);
int wd7000_reset (Scsi_Cmnd *, uint);
int wd7000_biosparam (Disk *, kdev_t, int *);
#endif /* _WD7000_H */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.