430 lines
12 KiB
C
430 lines
12 KiB
C
/*-
|
|
* Generic register and struct definitions for the Adaptech 1540, 1542,
|
|
* 1640, 1642 SCSI host adapters. Product specific probe and attach
|
|
* routines can be found in:
|
|
* aha_isa.c, aha_mca.c
|
|
*
|
|
* Derived from bt.c written by:
|
|
*
|
|
* Copyright (c) 1998 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, this list of conditions, and the following disclaimer,
|
|
* without modification, immediately at the beginning of the file.
|
|
* 2. 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.
|
|
*
|
|
* $FreeBSD$
|
|
*/
|
|
|
|
#ifndef _AHAREG_H_
|
|
#define _AHAREG_H_
|
|
|
|
#include <sys/queue.h>
|
|
#include <cam/scsi/scsi_all.h>
|
|
|
|
#define AHA_MAXTRANSFER_SIZE 0xffffff /* limited by 24bit counter */
|
|
#define AHA_NSEG 17 /* The number of dma segments
|
|
* supported. */
|
|
#define ALL_TARGETS (~0)
|
|
|
|
/*
|
|
* Control Register pp. 1-8, 1-9 (Write Only)
|
|
*/
|
|
#define CONTROL_REG 0x00
|
|
#define HARD_RESET 0x80 /* Hard Reset - return to POST state */
|
|
#define SOFT_RESET 0x40 /* Soft Reset - Clears Adapter state */
|
|
#define RESET_INTR 0x20 /* Reset/Ack Interrupt */
|
|
#define RESET_SBUS 0x10 /* Drive SCSI bus reset signal */
|
|
|
|
/*
|
|
* Status Register pp. 1-9, 1-10 (Read Only)
|
|
*/
|
|
#define STATUS_REG 0x00
|
|
#define DIAG_ACTIVE 0x80 /* Performing Internal Diags */
|
|
#define DIAG_FAIL 0x40 /* Internal Diags failed */
|
|
#define INIT_REQUIRED 0x20 /* MBOXes need initialization */
|
|
#define HA_READY 0x10 /* HA ready for new commands */
|
|
#define CMD_REG_BUSY 0x08 /* HA busy with last cmd byte */
|
|
#define DATAIN_REG_READY 0x04 /* Data-in Byte available */
|
|
#define STATUS_REG_RSVD 0x02
|
|
#define CMD_INVALID 0x01 /* Invalid Command detected */
|
|
|
|
/*
|
|
* Command/Parameter Register pp. 1-10, 1-11 (Write Only)
|
|
*/
|
|
#define COMMAND_REG 0x01
|
|
|
|
/*
|
|
* Data in Register p. 1-11 (Read Only)
|
|
*/
|
|
#define DATAIN_REG 0x01
|
|
|
|
/*
|
|
* Interrupt Status Register pp. 1-12 -> 1-14 (Read Only)
|
|
*/
|
|
#define INTSTAT_REG 0x02
|
|
#define INTR_PENDING 0x80 /* There is a pending INTR */
|
|
#define INTSTAT_REG_RSVD 0x70
|
|
#define SCSI_BUS_RESET 0x08 /* Bus Reset detected */
|
|
#define CMD_COMPLETE 0x04
|
|
#define OMB_READY 0x02 /* Outgoin Mailbox Ready */
|
|
#define IMB_LOADED 0x01 /* Incoming Mailbox loaded */
|
|
|
|
/*
|
|
* Definitions for the "undocumented" geometry register, we just need
|
|
* its location.
|
|
*/
|
|
#define GEOMETRY_REG 0x03
|
|
|
|
#define AHA_NREGS (4)
|
|
|
|
/*
|
|
* Opcodes for Adapter commands.
|
|
*/
|
|
typedef enum {
|
|
AOP_NOP = 0x00,
|
|
AOP_INITIALIZE_MBOX = 0x01,
|
|
AOP_START_MBOX = 0x02,
|
|
AOP_EXECUTE_BIOS_CMD = 0x03,
|
|
AOP_INQUIRE_BOARD_ID = 0x04,
|
|
AOP_ENABLE_OMBR_INT = 0x05,
|
|
AOP_SET_SEL_TIMOUT = 0x06,
|
|
AOP_SET_TIME_ON_BUS = 0x07,
|
|
AOP_SET_TIME_OFF_BUS = 0x08,
|
|
AOP_SET_BUS_TRANS_RATE = 0x09,
|
|
AOP_INQUIRE_INST_LDEVS = 0x0A,
|
|
AOP_INQUIRE_CONFIG = 0x0B,
|
|
AOP_ENABLE_TARGET_MODE = 0x0C,
|
|
AOP_INQUIRE_SETUP_INFO = 0x0D,
|
|
AOP_WRITE_LRAM = 0x1A,
|
|
AOP_READ_LRAM = 0x1B,
|
|
AOP_WRITE_CHIP_FIFO = 0x1C,
|
|
AOP_READ_CHIP_FIFO = 0x1D,
|
|
AOP_ECHO_DATA_BYTE = 0x1F,
|
|
AOP_ADAPTER_DIAGNOSTICS = 0x20,
|
|
AOP_SET_ADAPTER_OPTIONS = 0x21,
|
|
AOP_SET_EEPROM = 0x22,
|
|
AOP_RETURN_EEPROM = 0x23,
|
|
AOP_ENABLE_SHADOW_RAM = 0x24,
|
|
AOP_INIT_BIOS_MBOX = 0x25,
|
|
AOP_SET_BIOS_BANK_1 = 0x26,
|
|
AOP_SET_BIOS_BANK_2 = 0x27,
|
|
AOP_RETURN_EXT_BIOS_INFO= 0x28,
|
|
AOP_MBOX_IF_ENABLE = 0x29,
|
|
AOP_SCSI_TERM_STATUS = 0x2C,
|
|
AOP_INQUIRE_SCAM_DEV = 0x2D,
|
|
AOP_SCSI_DEV_TABLE = 0x2E,
|
|
AOP_SCAM_OP = 0x2F,
|
|
AOP_START_BIOS_CMD = 0x82,
|
|
AOP_INQUIRE_ESETUP_INFO = 0x8D
|
|
} aha_op_t;
|
|
|
|
/************** Definitions of Multi-byte commands and responses ************/
|
|
|
|
struct aha_extbios
|
|
{
|
|
uint8_t flags; /* Bit 3 == 1 extended bios enabled */
|
|
uint8_t mailboxlock; /* mail box lock code to unlock it */
|
|
};
|
|
|
|
typedef struct {
|
|
uint8_t num_mboxes;
|
|
uint8_t base_addr[3];
|
|
} init_24b_mbox_params_t;
|
|
|
|
typedef struct {
|
|
uint8_t board_type;
|
|
/* These values are mostly from the aha-1540CP technical reference, but */
|
|
/* with other values from the old aha1542.c driver. The values from the */
|
|
/* aha-1540CP technical manual are used where conflicts arise */
|
|
#define BOARD_1540_16HEAD_BIOS 0x00
|
|
#define BOARD_1540_64HEAD_BIOS 0x30
|
|
#define BOARD_1542 0x41 /* aha-1540/1542 w/64-h bios */
|
|
#define BOARD_1640 0x42 /* aha-1640 */
|
|
#define BOARD_1740 0x43 /* aha-1740A/1742A/1744 */
|
|
#define BOARD_1542C 0x44 /* aha-1542C */
|
|
#define BOARD_1542CF 0x45 /* aha-1542CF */
|
|
#define BOARD_1542CP 0x46 /* aha-1542CP, plug and play */
|
|
uint8_t cust_features;
|
|
#define FEATURES_STANDARD 0x30
|
|
uint8_t firmware_rev_major;
|
|
uint8_t firmware_rev_minor;
|
|
} board_id_data_t;
|
|
|
|
typedef struct {
|
|
uint8_t dma_chan;
|
|
#define DMA_CHAN_5 0x20
|
|
#define DMA_CHAN_6 0x40
|
|
#define DMA_CHAN_7 0x80
|
|
uint8_t irq;
|
|
#define IRQ_9 0x01
|
|
#define IRQ_10 0x02
|
|
#define IRQ_11 0x04
|
|
#define IRQ_12 0x08
|
|
#define IRQ_14 0x20
|
|
#define IRQ_15 0x40
|
|
uint8_t scsi_id;
|
|
} config_data_t;
|
|
|
|
typedef struct {
|
|
uint8_t enable;
|
|
} target_mode_params_t;
|
|
|
|
typedef struct {
|
|
uint8_t offset : 4,
|
|
period : 3,
|
|
sync : 1;
|
|
} targ_syncinfo_t;
|
|
|
|
typedef struct {
|
|
uint8_t initiate_sync : 1,
|
|
parity_enable : 1,
|
|
: 6;
|
|
|
|
uint8_t bus_transfer_rate;
|
|
uint8_t time_on_bus;
|
|
uint8_t time_off_bus;
|
|
uint8_t num_mboxes;
|
|
uint8_t mbox_base_addr[3];
|
|
targ_syncinfo_t syncinfo[8];
|
|
uint8_t discinfo;
|
|
uint8_t customer_sig[20];
|
|
uint8_t auto_retry;
|
|
uint8_t board_switches;
|
|
uint8_t firmware_cksum[2];
|
|
uint8_t bios_mbox_addr[3];
|
|
} setup_data_t;
|
|
|
|
struct aha_isa_port {
|
|
uint16_t addr;
|
|
uint8_t bio; /* board IO offset */
|
|
};
|
|
|
|
#define AHA_NUM_ISAPORTS 6
|
|
|
|
typedef enum {
|
|
BIO_330 = 0,
|
|
BIO_334 = 1,
|
|
BIO_230 = 2,
|
|
BIO_234 = 3,
|
|
BIO_130 = 4,
|
|
BIO_134 = 5,
|
|
BIO_DISABLED = 6,
|
|
BIO_DISABLED2 = 7
|
|
} isa_compat_io_t;
|
|
|
|
typedef struct {
|
|
uint8_t sync_rate[16]; /* Sync in 10ns units */
|
|
} target_sync_info_data_t;
|
|
|
|
typedef struct {
|
|
uint8_t len[3];
|
|
uint8_t addr[3];
|
|
} aha_sg_t;
|
|
|
|
/********************** Mail Box definitions *******************************/
|
|
|
|
typedef enum {
|
|
AMBO_FREE = 0x0, /* MBO intry is free */
|
|
AMBO_START = 0x1, /* MBO activate entry */
|
|
AMBO_ABORT = 0x2 /* MBO abort entry */
|
|
} aha_mbo_action_code_t;
|
|
|
|
typedef struct aha_mbox_out {
|
|
uint8_t action_code;
|
|
uint8_t ccb_addr[3];
|
|
} aha_mbox_out_t;
|
|
|
|
typedef enum {
|
|
AMBI_FREE = 0x0, /* MBI entry is free */
|
|
AMBI_OK = 0x1, /* completed without error */
|
|
AMBI_ABORT = 0x2, /* aborted ccb */
|
|
AMBI_NOT_FOUND = 0x3, /* Tried to abort invalid CCB */
|
|
AMBI_ERROR = 0x4 /* Completed with error */
|
|
} aha_mbi_comp_code_t;
|
|
|
|
typedef struct aha_mbox_in {
|
|
uint8_t comp_code;
|
|
uint8_t ccb_addr[3];
|
|
} aha_mbox_in_t;
|
|
|
|
/****************** Hardware CCB definition *********************************/
|
|
typedef enum {
|
|
INITIATOR_CCB = 0x00,
|
|
INITIATOR_SG_CCB = 0x02,
|
|
INITIATOR_CCB_WRESID = 0x03,
|
|
INITIATOR_SG_CCB_WRESID = 0x04,
|
|
INITIATOR_BUS_DEV_RESET = 0x81
|
|
} aha_ccb_opcode_t;
|
|
|
|
typedef enum {
|
|
AHASTAT_NOERROR = 0x00,
|
|
AHASTAT_SELTIMEOUT = 0x11,
|
|
AHASTAT_DATARUN_ERROR = 0x12,
|
|
AHASTAT_UNEXPECTED_BUSFREE = 0x13,
|
|
AHASTAT_INVALID_PHASE = 0x14,
|
|
AHASTAT_INVALID_ACTION_CODE = 0x15,
|
|
AHASTAT_INVALID_OPCODE = 0x16,
|
|
AHASTAT_LINKED_CCB_LUN_MISMATCH = 0x17,
|
|
AHASTAT_INVALID_CCB_OR_SG_PARAM = 0x1A,
|
|
AHASTAT_HA_SCSI_BUS_RESET = 0x22, /* stolen from bt */
|
|
AHASTAT_HA_BDR = 0x25 /* Stolen from bt */
|
|
} ahastat_t;
|
|
|
|
struct aha_hccb {
|
|
uint8_t opcode; /* 0 */
|
|
uint8_t lun : 3, /* 1 */
|
|
datain : 1,
|
|
dataout : 1,
|
|
target : 3;
|
|
uint8_t cmd_len; /* 2 */
|
|
uint8_t sense_len; /* 3 */
|
|
uint8_t data_len[3]; /* 4 */
|
|
uint8_t data_addr[3]; /* 7 */
|
|
uint8_t link_ptr[3]; /* 10 */
|
|
uint8_t link_id; /* 13 */
|
|
uint8_t ahastat; /* 14 */
|
|
uint8_t sdstat; /* 15 */
|
|
uint8_t reserved1; /* 16 */
|
|
uint8_t reserved2; /* 17 */
|
|
uint8_t scsi_cdb[16]; /* 18 */
|
|
uint8_t sense_data[SSD_FULL_SIZE];
|
|
};
|
|
|
|
typedef enum {
|
|
ACCB_FREE = 0x0,
|
|
ACCB_ACTIVE = 0x1,
|
|
ACCB_DEVICE_RESET = 0x2,
|
|
ACCB_RELEASE_SIMQ = 0x4
|
|
} accb_flags_t;
|
|
|
|
struct aha_ccb {
|
|
struct aha_hccb hccb; /* hccb assumed to be at 0 */
|
|
SLIST_ENTRY(aha_ccb) links;
|
|
uint32_t flags;
|
|
union ccb *ccb;
|
|
bus_dmamap_t dmamap;
|
|
aha_sg_t *sg_list;
|
|
uint32_t sg_list_phys;
|
|
};
|
|
|
|
struct sg_map_node {
|
|
bus_dmamap_t sg_dmamap;
|
|
bus_addr_t sg_physaddr;
|
|
aha_sg_t* sg_vaddr;
|
|
SLIST_ENTRY(sg_map_node) links;
|
|
};
|
|
|
|
struct aha_softc {
|
|
bus_space_tag_t tag;
|
|
bus_space_handle_t bsh;
|
|
struct cam_sim *sim;
|
|
struct cam_path *path;
|
|
aha_mbox_out_t *cur_outbox;
|
|
aha_mbox_in_t *cur_inbox;
|
|
aha_mbox_out_t *last_outbox;
|
|
aha_mbox_in_t *last_inbox;
|
|
struct aha_ccb *aha_ccb_array;
|
|
SLIST_HEAD(,aha_ccb) free_aha_ccbs;
|
|
LIST_HEAD(,ccb_hdr) pending_ccbs;
|
|
u_int active_ccbs;
|
|
uint32_t aha_ccb_physbase;
|
|
aha_ccb_opcode_t ccb_sg_opcode;
|
|
aha_ccb_opcode_t ccb_ccb_opcode;
|
|
aha_mbox_in_t *in_boxes;
|
|
aha_mbox_out_t *out_boxes;
|
|
struct scsi_sense_data *sense_buffers;
|
|
uint32_t sense_buffers_physbase;
|
|
struct aha_ccb *recovery_accb;
|
|
u_int num_boxes;
|
|
bus_dma_tag_t parent_dmat; /*
|
|
* All dmat's derive from
|
|
* the dmat defined by our
|
|
* bus.
|
|
*/
|
|
bus_dma_tag_t buffer_dmat; /* dmat for buffer I/O */
|
|
bus_dma_tag_t mailbox_dmat; /* dmat for our mailboxes */
|
|
bus_dmamap_t mailbox_dmamap;
|
|
bus_dma_tag_t ccb_dmat; /* dmat for our ccb array */
|
|
bus_dmamap_t ccb_dmamap;
|
|
bus_dma_tag_t sg_dmat; /* dmat for our sg maps */
|
|
SLIST_HEAD(, sg_map_node) sg_maps;
|
|
bus_addr_t mailbox_physbase;
|
|
u_int num_ccbs; /* Number of CCBs malloc'd */
|
|
u_int max_ccbs; /* Maximum allocatable CCBs */
|
|
u_int max_sg;
|
|
u_int unit;
|
|
u_int scsi_id;
|
|
uint32_t extended_trans :1,
|
|
diff_bus :1,
|
|
extended_lun :1,
|
|
strict_rr :1,
|
|
tag_capable :1,
|
|
resource_shortage:1,
|
|
:26;
|
|
uint16_t disc_permitted;
|
|
uint16_t sync_permitted;
|
|
uint8_t init_level;
|
|
volatile uint8_t command_cmp;
|
|
volatile uint8_t latched_status;
|
|
uint32_t bios_addr;
|
|
uint8_t fw_major;
|
|
uint8_t fw_minor;
|
|
char model[32];
|
|
uint8_t boardid;
|
|
struct resource *irq;
|
|
int irqrid;
|
|
struct resource *port;
|
|
int portrid;
|
|
struct resource *drq;
|
|
int drqrid;
|
|
void **ih;
|
|
device_t dev;
|
|
};
|
|
|
|
void aha_alloc(struct aha_softc *, int, bus_space_tag_t, bus_space_handle_t);
|
|
int aha_attach(struct aha_softc *);
|
|
int aha_cmd(struct aha_softc *, aha_op_t, uint8_t *, u_int, uint8_t *, u_int,
|
|
u_int);
|
|
int aha_detach(struct aha_softc *);
|
|
int aha_fetch_adapter_info(struct aha_softc *);
|
|
void aha_find_probe_range(int, int *, int *);
|
|
void aha_free(struct aha_softc *);
|
|
int aha_init(struct aha_softc *);
|
|
void aha_intr(void *);
|
|
int aha_iop_from_bio(isa_compat_io_t);
|
|
int aha_probe(struct aha_softc *);
|
|
|
|
#define DEFAULT_CMD_TIMEOUT 10000 /* 1 sec */
|
|
|
|
#define aha_inb(aha, port) \
|
|
bus_space_read_1((aha)->tag, (aha)->bsh, port)
|
|
|
|
#define aha_outb(aha, port, value) \
|
|
bus_space_write_1((aha)->tag, (aha)->bsh, port, value)
|
|
|
|
#define ADP0100_PNP 0x00019004 /* ADP0100 */
|
|
#define AHA1540_PNP 0x40159004 /* ADP1540 */
|
|
#define AHA1542_PNP 0x42159004 /* ADP1542 */
|
|
#define AHA1542_PNPCOMPAT 0xA000D040 /* PNP00A0 */
|
|
#define ICU0091_PNP 0X91005AA4 /* ICU0091 */
|
|
|
|
#endif /* _AHAREG_H_ */
|