Rework the Buslogic SCSI driver in preparation for some pending improvements

to the SCSIPI subsystem.
- Determine more characteristics about the board, including the number
  of concurrent commands that the processor can execute at a time.
- Rework memory allocation strategy so that we can do dynamic pre-allocation
  of resources according to workload.

Thanks to the Linux Buslogic driver for having some useful comments.
This commit is contained in:
thorpej 1999-09-30 23:12:28 +00:00
parent fe12736867
commit 415b44a62a
3 changed files with 1610 additions and 1161 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $NetBSD: bhareg.h,v 1.12 1998/08/17 00:26:33 mycroft Exp $ */
/* $NetBSD: bhareg.h,v 1.13 1999/09/30 23:12:29 thorpej Exp $ */
/*-
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@ -92,29 +92,48 @@ typedef u_int8_t physlen[4];
#define BHA_NOP 0x00 /* No operation */
#define BHA_MBX_INIT 0x01 /* Mbx initialization */
#define BHA_START_SCSI 0x02 /* start scsi command */
#define BHA_EXECUTE_BIOS_CMD 0x03 /* execute BIOS command */
#define BHA_INQUIRE_REVISION 0x04 /* Adapter Inquiry */
#define BHA_MBO_INTR_EN 0x05 /* Enable MBO available interrupt */
#if 0
#define BHA_SEL_TIMEOUT_SET 0x06 /* set selection time-out */
#define BHA_BUS_ON_TIME_SET 0x07 /* set bus-on time */
#define BHA_BUS_OFF_TIME_SET 0x08 /* set bus-off time */
#define BHA_SPEED_SET 0x09 /* set transfer speed */
#endif
#define BHA_BUS_SPEED_SET 0x09 /* set bus transfer speed */
#define BHA_INQUIRE_DEVICES 0x0a /* return installed devices 0-7 */
#define BHA_INQUIRE_CONFIG 0x0b /* return configuration data */
#define BHA_TARGET_EN 0x0c /* enable target mode */
#define BHA_INQUIRE_SETUP 0x0d /* return setup data */
#define BHA_ECHO 0x1e /* Echo command data */
#define BHA_WRITE_LRAM 0x1a /* write adapter local RAM */
#define BHA_READ_LRAM 0x1b /* read adapter local RAM */
#define BHA_WRITE_CHIP_FIFO 0x1c /* write bus master chip FIFO */
#define BHA_READ_CHIP_FIFO 0x1d /* read bus master chip FIFO */
#define BHA_ECHO 0x1f /* Echo command byte */
#define BHA_ADAPTER_DIAGNOSTICS 0x20 /* host adapter diagnostics */
#define BHA_SET_ADAPTER_OPTIONS 0x21 /* set adapter options */
#define BHA_INQUIRE_DEVICES_2 0x23 /* return installed devices 8-15 */
#define BHA_INQUIRE_TARG_DEVS 0x24 /* inquire target devices */
#define BHA_DISABLE_HAC_INTR 0x25 /* disable host adapter interrupt */
#define BHA_MBX_INIT_EXTENDED 0x81 /* Mbx initialization */
#define BHA_EXECUTE_SCSI_CMD 0x83 /* execute SCSI command */
#define BHA_INQUIRE_REVISION_3 0x84 /* Get 3rd firmware version byte */
#define BHA_INQUIRE_REVISION_4 0x85 /* Get 4th firmware version byte */
#define BHA_INQUIRE_PCI_INFO 0x86 /* get PCI host adapter information */
#define BHA_INQUIRE_MODEL 0x8b /* Get hardware ID and revision */
#define BHA_INQUIRE_PERIOD 0x8c /* Get synchronous period */
#define BHA_INQUIRE_EXTENDED 0x8d /* Adapter Setup Inquiry */
#define BHA_ROUND_ROBIN 0x8f /* Enable/Disable(default) round robin */
#define BHA_ROUND_ROBIN 0x8f /* Enable/Disable(default)
round robin */
#define BHA_STORE_LRAM 0x90 /* store host adapter local RAM */
#define BHA_FETCH_LRAM 0x91 /* fetch host adapter local RAM */
#define BHA_SAVE_TO_EEPROM 0x92 /* store local RAM data in EEPROM */
#define BHA_UPLOAD_AUTOSCSI 0x94 /* upload AutoSCSI code */
#define BHA_MODIFY_IOPORT 0x95 /* change or disable I/O port */
#define BHA_SET_CCB_FORMAT 0x96 /* set CCB format (legacy/wide lun) */
#define BHA_WRITE_INQUIRY_BUF 0x9a /* write inquiry buffer */
#define BHA_READ_INQUIRY_BUF 0x9b /* read inquiry buffer */
#define BHA_FLASH_UP_DOWNLOAD 0xa7 /* flash upload/downlod */
#define BHA_READ_SCAM_DATA 0xa8 /* read SCAM data */
#define BHA_WRITE_SCAM_DATA 0xa9 /* write SCAM data */
/*
* BHA_INTR bits
@ -127,14 +146,16 @@ typedef u_int8_t physlen[4];
struct bha_mbx_out {
physaddr ccb_addr;
u_char dummy[3];
u_char cmd;
u_int8_t reserved[3];
u_int8_t cmd;
};
struct bha_mbx_in {
physaddr ccb_addr;
u_char dummy[3];
u_char stat;
u_int8_t host_stat;
u_int8_t target_stat;
u_int8_t reserved;
u_int8_t comp_stat;
};
/*
@ -145,7 +166,7 @@ struct bha_mbx_in {
#define BHA_MBO_ABORT 0x2 /* MBO abort entry */
/*
* mbi.stat values
* mbi.comp_stat values
*/
#define BHA_MBI_FREE 0x0 /* MBI entry is free */
#define BHA_MBI_OK 0x1 /* completed without error */
@ -164,42 +185,50 @@ WARNING...THIS WON'T WORK(won't fit on 1 page)
#endif /* BIG_DMA */
struct bha_scat_gath {
physlen seg_len;
physlen seg_len;
physaddr seg_addr;
};
struct bha_ccb {
u_char opcode;
u_char:3, data_in:1, data_out:1,:3;
u_char scsi_cmd_length;
u_char req_sense_length;
u_int8_t opcode;
u_int8_t :3,
data_in :1,
data_out :1,
wide_tag_enable :1, /* Wide Lun CCB format */
wide_tag_type :2; /* Wide Lun CCB format */
u_int8_t scsi_cmd_length;
u_int8_t req_sense_length;
/*------------------------------------longword boundary */
physlen data_length;
physlen data_length;
/*------------------------------------longword boundary */
physaddr data_addr;
physaddr data_addr;
/*------------------------------------longword boundary */
u_char dummy1[2];
u_char host_stat;
u_char target_stat;
u_int8_t reserved1[2];
u_int8_t host_stat;
u_int8_t target_stat;
/*------------------------------------longword boundary */
u_char target;
u_char lun;
struct scsi_generic scsi_cmd;
u_char dummy2[1];
u_char link_id;
u_int8_t target;
u_int8_t lun :5,
tag_enable :1,
tag_type :2;
u_int8_t scsi_cmd[12];
u_int8_t reserved2[1];
u_int8_t link_id;
/*------------------------------------longword boundary */
physaddr link_addr;
physaddr link_addr;
/*------------------------------------longword boundary */
physaddr sense_ptr;
physaddr sense_ptr;
/*-----end of HW fields-----------------------longword boundary */
struct scsipi_sense_data scsi_sense;
/*------------------------------------longword boundary */
struct bha_scat_gath scat_gath[BHA_NSEG];
/*------------------------------------longword boundary */
TAILQ_ENTRY(bha_ccb) chain;
struct bha_ccb *nexthash;
u_long hashkey;
struct bha_ccb *nexthash;
bus_addr_t hashkey;
struct scsipi_xfer *xs; /* the scsipi_xfer for this cmd */
int flags;
#define CCB_ALLOC 0x01
#define CCB_ABORT 0x02
@ -220,25 +249,41 @@ struct bha_ccb {
*/
#define BHA_INITIATOR_CCB 0x00 /* SCSI Initiator CCB */
#define BHA_TARGET_CCB 0x01 /* SCSI Target CCB */
#define BHA_INIT_SCAT_GATH_CCB 0x02 /* SCSI Initiator with scattter gather */
#define BHA_INIT_SCAT_GATH_CCB 0x02 /* SCSI Initiator with S/G */
#define BHA_INIT_RESID_CCB 0x03 /* SCSI Initiator w/ residual */
#define BHA_INIT_RESID_SG_CCB 0x04 /* SCSI Initiator w/ residual and S/G */
#define BHA_RESET_CCB 0x81 /* SCSI Bus reset */
/*
* bha_ccb.host_stat values
*/
#define BHA_OK 0x00 /* cmd ok */
#define BHA_LINK_OK 0x0a /* Link cmd ok */
#define BHA_LINK_IT 0x0b /* Link cmd ok + int */
#define BHA_SEL_TIMEOUT 0x11 /* Selection time out */
#define BHA_OVER_UNDER 0x12 /* Data over/under run */
#define BHA_BUS_FREE 0x13 /* Bus dropped at unexpected time */
#define BHA_INV_BUS 0x14 /* Invalid bus phase/sequence */
#define BHA_BAD_MBO 0x15 /* Incorrect MBO cmd */
#define BHA_BAD_CCB 0x16 /* Incorrect ccb opcode */
#define BHA_BAD_LINK 0x17 /* Not same values of LUN for links */
#define BHA_INV_TARGET 0x18 /* Invalid target direction */
#define BHA_CCB_DUP 0x19 /* Duplicate CCB received */
#define BHA_INV_CCB 0x1a /* Invalid CCB or segment list */
#define BHA_OK 0x00 /* cmd ok */
#define BHA_LINK_OK 0x0a /* Link cmd ok */
#define BHA_LINK_IT 0x0b /* Link cmd ok + int */
#define BHA_DATA_UNDRN 0x0c /* data underrun error */
#define BHA_SEL_TIMEOUT 0x11 /* Selection time out */
#define BHA_OVER_UNDER 0x12 /* Data over/under run */
#define BHA_BUS_FREE 0x13 /* Bus dropped at unexpected time */
#define BHA_INV_BUS 0x14 /* Invalid bus phase/sequence */
#define BHA_BAD_MBO 0x15 /* Incorrect MBO cmd */
#define BHA_BAD_CCB 0x16 /* Incorrect ccb opcode */
#define BHA_BAD_LINK 0x17 /* Not same values of LUN for links */
#define BHA_INV_TARGET 0x18 /* Invalid target direction */
#define BHA_CCB_DUP 0x19 /* Duplicate CCB received */
#define BHA_INV_CCB 0x1a /* Invalid CCB or segment list */
#define BHA_AUTOSENSE_FAILED 0x1b /* auto REQUEST SENSE failed */
#define BHA_TAGGED_MSG_REJ 0x1c /* tagged queueing message rejected */
#define BHA_UNSUP_MSG_RECVD 0x1d /* unsupported message received */
#define BHA_HARDWARE_FAILURE 0x20 /* host adapter hardware failure */
#define BHA_TARG_IGNORED_ATN 0x21 /* target ignored ATN signal */
#define BHA_HA_SCSI_BUS_RESET 0x22 /* host adapter asserted RST */
#define BHA_OTHER_SCSI_BUS_RESET 0x23 /* other device asserted RST */
#define BHA_BAD_RECONNECT 0x24 /* target reconnected improperly */
#define BHA_HA_BUS_DEVICE_RESET 0x25 /* host adapter performed BDR */
#define BHA_ABORT_QUEUE 0x26 /* abort queue generated */
#define BHA_SOFTWARE_FAILURE 0x27 /* host adapter software failure */
#define BHA_HARDWARE_WATCHDOG 0x30 /* host adapter watchdog timer fired */
#define BHA_SCSI_PARITY_ERROR 0x34 /* SCSI parity error detected */
struct bha_extended_inquire {
struct {
@ -253,16 +298,18 @@ struct bha_extended_inquire {
u_char bios_address; /* Address of adapter BIOS */
u_short sg_limit;
u_char mbox_count;
u_char mbox_baseaddr[4]; /* packed/unaligned uint_32_t */
u_char mbox_baseaddr[4]; /* packed/unaligned u_int32_t */
u_char intrflags;
#define BHA_INTR_LEVEL 0x40 /* bit 6: level-sensitive interrupt */
#define BHA_INTR_FASTEISA 0x04
#define BHA_INTR_LEVEL 0x40 /* bit 6: level-sensitive interrupt */
u_char firmware_level[3]; /* last 3 digits of firmware rev */
u_char scsi_flags; /* supported SCSI features */
#define BHA_SCSI_WIDE 0x01
#define BHA_SCSI_DIFFERENTIAL 0x02
#define BHA_SCSI_AUTOCONF 0x04
#define BHA_SCSI_ULTRA 0x08
#define BHA_SCSI_TERMINATION 0x10
u_char scsi_flags; /* supported SCSI features */
#define BHA_SCSI_WIDE 0x01 /* host adapter is wide */
#define BHA_SCSI_DIFFERENTIAL 0x02 /* host adapter is differential */
#define BHA_SCSI_SCAM 0x04 /* host adapter supports SCAM */
#define BHA_SCSI_ULTRA 0x08 /* host adapter supports Ultra */
#define BHA_SCSI_TERMINATION 0x10 /* host adapter supports smart
termination */
} reply;
};
@ -341,24 +388,31 @@ struct bha_sync {
};
struct bha_setup_reply {
u_char sync_neg:1;
u_char parity:1;
u_char :6;
u_char speed;
u_char bus_on;
u_char bus_off;
u_char num_mbx;
u_char mbx[3]; /*XXX */
u_int8_t sync_neg :1,
parity :1,
:6;
u_int8_t speed;
u_int8_t bus_on;
u_int8_t bus_off;
u_int8_t num_mbx;
u_int8_t mbx[3]; /*XXX */
/* doesn't make sense with 32bit addresses */
struct bha_sync sync[8];
u_char disc_sts;
struct bha_sync sync_low[8];
u_int8_t low_disc_info;
};
/* additional reply data supplied by wide controlers */
struct bus_setup_reply_wide {
u_char pad[5]; /* ??? */
struct bha_sync sync[8];
u_char disc_sts;
u_int8_t signature;
u_int8_t letter_d;
u_int8_t ha_type;
u_int8_t low_wide_allowed;
u_int8_t low_wide_active;
struct bha_sync sync_high[8];
u_int8_t high_disc_info;
u_int8_t reserved;
u_int8_t high_wide_allowed;
u_int8_t high_wide_active;
};
struct bha_setup {

View File

@ -1,7 +1,7 @@
/* $NetBSD: bhavar.h,v 1.13 1998/12/09 08:47:19 thorpej Exp $ */
/* $NetBSD: bhavar.h,v 1.14 1999/09/30 23:12:29 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -39,35 +39,49 @@
#include <sys/queue.h>
/*
* Mail box defs etc.
* these could be bigger but we need the bha_softc to fit on a single page..
*/
#define BHA_MBX_SIZE 32 /* mail box size (MAX 255 MBxs) */
/* don't need that many really */
#define BHA_CCB_MAX 32 /* store up to 32 CCBs at one time */
/* XXX adjust hash for large numbers of CCBs */
#define CCB_HASH_SIZE 32 /* hash table size for phystokv */
#define CCB_HASH_SHIFT 9
#define CCB_HASH(x) ((((long)(x))>>CCB_HASH_SHIFT) & (CCB_HASH_SIZE - 1))
#define bha_nextmbx(wmb, mbx, mbio) \
if ((wmb) == &(mbx)->mbio[BHA_MBX_SIZE - 1]) \
(wmb) = &(mbx)->mbio[0]; \
else \
(wmb)++;
struct bha_mbx {
struct bha_mbx_out mbo[BHA_MBX_SIZE];
struct bha_mbx_in mbi[BHA_MBX_SIZE];
struct bha_mbx_out *cmbo; /* Collection Mail Box out */
struct bha_mbx_out *tmbo; /* Target Mail Box out */
struct bha_mbx_in *tmbi; /* Target Mail Box in */
/*
* A CCB allocation group. Each group is a page size. We can find
* the allocation group for a CCB by truncating the CCB address to
* a page boundary, and the offset from the group's DMA mapping
* by taking the offset of the CCB into the page.
*/
#define BHA_CCBS_PER_GROUP ((PAGE_SIZE - sizeof(bus_dmamap_t)) / \
sizeof(struct bha_ccb))
struct bha_ccb_group {
bus_dmamap_t bcg_dmamap;
struct bha_ccb bcg_ccbs[1]; /* determined at run-time */
};
struct bha_control {
struct bha_mbx bc_mbx; /* all our mailboxes */
struct bha_ccb bc_ccbs[BHA_CCB_MAX]; /* all our control blocks */
};
#define BHA_CCB_GROUP(ccb) (struct bha_ccb_group *)(trunc_page(ccb))
#define BHA_CCB_OFFSET(ccb) ((vaddr_t)(ccb) & PAGE_MASK)
#define BHA_CCB_SYNC(sc, ccb, ops) \
do { \
struct bha_ccb_group *bcg = BHA_CCB_GROUP((ccb)); \
\
bus_dmamap_sync((sc)->sc_dmat, bcg->bcg_dmamap, \
BHA_CCB_OFFSET(ccb), sizeof(struct bha_ccb), (ops)); \
} while (0)
#define BHA_MBI_OFFSET(sc, mbi) ((u_long)(mbi) - (u_long)(sc)->sc_mbi)
#define BHA_MBO_OFFSET(sc, mbo) ((u_long)(mbo) - (u_long)(sc)->sc_mbo)
#define BHA_MBI_SYNC(sc, mbi, ops) \
do { \
bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_dmamap_mbox, \
BHA_MBI_OFFSET((sc), (mbi)), sizeof(struct bha_mbx_in), (ops)); \
} while (0)
#define BHA_MBO_SYNC(sc, mbo, ops) \
do { \
bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_dmamap_mbox, \
BHA_MBO_OFFSET((sc), (mbo)), sizeof(struct bha_mbx_out), (ops)); \
} while (0)
struct bha_softc {
struct device sc_dev;
@ -75,17 +89,50 @@ struct bha_softc {
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
bus_dma_tag_t sc_dmat;
bus_dmamap_t sc_dmamap_control; /* maps the control structures */
bus_dmamap_t sc_dmamap_mbox; /* maps the mailboxes */
int sc_dmaflags; /* bus-specific dma map flags */
void *sc_ih;
struct bha_control *sc_control; /* control structures */
int sc_scsi_id; /* host adapter SCSI ID */
#define wmbx (&sc->sc_control->bc_mbx)
int sc_flags;
#define BHAF_WIDE 0x01 /* device is wide */
#define BHAF_DIFFERENTIAL 0x02 /* device is differential */
#define BHAF_ULTRA 0x04 /* device is ultra-scsi */
#define BHAF_TAGGED_QUEUEING 0x08 /* device supports tagged queueing */
#define BHAF_WIDE_LUN 0x10 /* device supported wide lun CCBs */
#define BHAF_STRICT_ROUND_ROBIN 0x20 /* device supports strict RR mode */
int sc_max_dmaseg; /* maximum number of DMA segments */
int sc_hw_ccbs; /* maximum number of CCBs (HW) */
int sc_max_ccbs; /* maximum number of CCBs (SW) */
int sc_cur_ccbs; /* current number of CCBs */
int sc_mbox_count; /* maximum number of mailboxes */
int sc_disc_mask; /* mask of targets allowing discnnct */
int sc_ultra_mask; /* mask of targets allowing ultra */
int sc_fast_mask; /* mask of targets allowing fast */
int sc_sync_mask; /* mask of targets allowing sync */
int sc_wide_mask; /* mask of targets allowing wide */
int sc_tag_mask; /* mask of targets allowing t/q'ing */
/*
* In and Out mailboxes.
*/
struct bha_mbx_out *sc_mbo;
struct bha_mbx_in *sc_mbi;
struct bha_mbx_out *sc_cmbo; /* Collection Mail Box out */
struct bha_mbx_out *sc_tmbo; /* Target Mail Box out */
int sc_mbofull; /* number of full Mail Box Out */
struct bha_mbx_in *sc_tmbi; /* Target Mail Box in */
struct bha_ccb *sc_ccbhash[CCB_HASH_SIZE];
TAILQ_HEAD(, bha_ccb) sc_free_ccb, sc_waiting_ccb;
int sc_mbofull;
TAILQ_HEAD(, bha_ccb) sc_free_ccb,
sc_waiting_ccb,
sc_allocating_ccbs;
struct scsipi_link sc_link; /* prototype for devs */
struct scsipi_adapter sc_adapter;
@ -95,36 +142,13 @@ struct bha_softc {
sc_firmware[6];
};
/*
* Offset of a Mail Box In from the beginning of the control DMA mapping.
*/
#define BHA_MBI_OFF(m) (offsetof(struct bha_control, bc_mbx.mbi[0]) + \
(((u_long)(m)) - ((u_long)&wmbx->mbi[0])))
/*
* Offset of a Mail Box Out from the beginning of the control DMA mapping.
*/
#define BHA_MBO_OFF(m) (offsetof(struct bha_control, bc_mbx.mbo[0]) + \
(((u_long)(m)) - ((u_long)&wmbx->mbo[0])))
/*
* Offset of a CCB from the beginning of the control DMA mapping.
*/
#define BHA_CCB_OFF(c) (offsetof(struct bha_control, bc_ccbs[0]) + \
(((u_long)(c)) - ((u_long)&sc->sc_control->bc_ccbs[0])))
struct bha_probe_data {
int sc_irq, sc_drq;
int sc_scsi_dev; /* adapters scsi id */
int sc_iswide; /* adapter is wide */
};
#define ISWIDE(sc) (sc->sc_link.scsipi_scsi.max_target >= 8)
int bha_find __P((bus_space_tag_t, bus_space_handle_t,
struct bha_probe_data *));
void bha_attach __P((struct bha_softc *, struct bha_probe_data *));
int bha_intr __P((void *));
int bha_disable_isacompat __P((struct bha_softc *));
void bha_inquire_setup_information __P((struct bha_softc *));