advansys.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:724k
- ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */
- ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */
- ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */
- ushort tagqng_able; /* try tagged queuing with a device */
- ushort ppr_able; /* PPR message capable per TID bitmask. */
- uchar max_dvc_qng; /* maximum number of tagged commands per device */
- ushort start_motor; /* start motor command allowed */
- uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
- uchar chip_no; /* should be assigned by caller */
- uchar max_host_qng; /* maximum number of Q'ed command allowed */
- uchar irq_no; /* IRQ number */
- ushort no_scam; /* scam_tolerant of EEPROM */
- struct asc_board *drv_ptr; /* driver pointer to private structure */
- uchar chip_scsi_id; /* chip SCSI target ID */
- uchar chip_type;
- uchar bist_err_code;
- ADV_CARR_T *carrier_buf;
- ADV_CARR_T *carr_freelist; /* Carrier free list. */
- ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */
- ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */
- ushort carr_pending_cnt; /* Count of pending carriers. */
- /*
- * Note: The following fields will not be used after initialization. The
- * driver may discard the buffer after initialization is done.
- */
- ADV_DVC_CFG *cfg; /* temporary configuration structure */
- } ADV_DVC_VAR;
- #define NO_OF_SG_PER_BLOCK 15
- typedef struct asc_sg_block {
- uchar reserved1;
- uchar reserved2;
- uchar reserved3;
- uchar sg_cnt; /* Valid entries in block. */
- ADV_PADDR sg_ptr; /* Pointer to next sg block. */
- struct {
- ADV_PADDR sg_addr; /* SG element address. */
- ADV_DCNT sg_count; /* SG element count. */
- } sg_list[NO_OF_SG_PER_BLOCK];
- } ADV_SG_BLOCK;
- /*
- * ADV_SCSI_REQ_Q - microcode request structure
- *
- * All fields in this structure up to byte 60 are used by the microcode.
- * The microcode makes assumptions about the size and ordering of fields
- * in this structure. Do not change the structure definition here without
- * coordinating the change with the microcode.
- *
- * All fields accessed by microcode must be maintained in little_endian
- * order.
- */
- typedef struct adv_scsi_req_q {
- uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
- uchar target_cmd;
- uchar target_id; /* Device target identifier. */
- uchar target_lun; /* Device target logical unit number. */
- ADV_PADDR data_addr; /* Data buffer physical address. */
- ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */
- ADV_PADDR sense_addr;
- ADV_PADDR carr_pa;
- uchar mflag;
- uchar sense_len;
- uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */
- uchar scsi_cntl;
- uchar done_status; /* Completion status. */
- uchar scsi_status; /* SCSI status byte. */
- uchar host_status; /* Ucode host status. */
- uchar sg_working_ix;
- uchar cdb[12]; /* SCSI CDB bytes 0-11. */
- ADV_PADDR sg_real_addr; /* SG list physical address. */
- ADV_PADDR scsiq_rptr;
- uchar cdb16[4]; /* SCSI CDB bytes 12-15. */
- ADV_VADDR scsiq_ptr;
- ADV_VADDR carr_va;
- /*
- * End of microcode structure - 60 bytes. The rest of the structure
- * is used by the Adv Library and ignored by the microcode.
- */
- ADV_VADDR srb_ptr;
- ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
- char *vdata_addr; /* Data buffer virtual address. */
- uchar a_flag;
- uchar pad[2]; /* Pad out to a word boundary. */
- } ADV_SCSI_REQ_Q;
- /*
- * Microcode idle loop commands
- */
- #define IDLE_CMD_COMPLETED 0
- #define IDLE_CMD_STOP_CHIP 0x0001
- #define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
- #define IDLE_CMD_SEND_INT 0x0004
- #define IDLE_CMD_ABORT 0x0008
- #define IDLE_CMD_DEVICE_RESET 0x0010
- #define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */
- #define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */
- #define IDLE_CMD_SCSIREQ 0x0080
- #define IDLE_CMD_STATUS_SUCCESS 0x0001
- #define IDLE_CMD_STATUS_FAILURE 0x0002
- /*
- * AdvSendIdleCmd() flag definitions.
- */
- #define ADV_NOWAIT 0x01
- /*
- * Wait loop time out values.
- */
- #define SCSI_WAIT_10_SEC 10UL /* 10 seconds */
- #define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */
- #define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */
- #define SCSI_MS_PER_SEC 1000UL /* milliseconds per second */
- #define SCSI_MAX_RETRY 10 /* retry count */
- #define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */
- #define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */
- #define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */
- #define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */
- #define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */
- /*
- * Device drivers must define the following functions.
- */
- STATIC inline ulong DvcEnterCritical(void);
- STATIC inline void DvcLeaveCritical(ulong);
- STATIC void DvcSleepMilliSecond(ADV_DCNT);
- STATIC uchar DvcAdvReadPCIConfigByte(ADV_DVC_VAR *, ushort);
- STATIC void DvcAdvWritePCIConfigByte(ADV_DVC_VAR *, ushort, uchar);
- STATIC ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *,
- uchar *, ASC_SDCNT *, int);
- STATIC void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort);
- /*
- * Adv Library functions available to drivers.
- */
- STATIC int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
- STATIC int AdvISR(ADV_DVC_VAR *);
- STATIC int AdvInitGetConfig(ADV_DVC_VAR *);
- STATIC int AdvInitAsc3550Driver(ADV_DVC_VAR *);
- STATIC int AdvInitAsc38C0800Driver(ADV_DVC_VAR *);
- STATIC int AdvInitAsc38C1600Driver(ADV_DVC_VAR *);
- STATIC int AdvResetChipAndSB(ADV_DVC_VAR *);
- STATIC int AdvResetSB(ADV_DVC_VAR *asc_dvc);
- /*
- * Internal Adv Library functions.
- */
- STATIC int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT);
- STATIC void AdvInquiryHandling(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
- STATIC int AdvInitFrom3550EEP(ADV_DVC_VAR *);
- STATIC int AdvInitFrom38C0800EEP(ADV_DVC_VAR *);
- STATIC int AdvInitFrom38C1600EEP(ADV_DVC_VAR *);
- STATIC ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
- STATIC void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
- STATIC ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
- STATIC void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
- STATIC ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
- STATIC void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
- STATIC void AdvWaitEEPCmd(AdvPortAddr);
- STATIC ushort AdvReadEEPWord(AdvPortAddr, int);
- /*
- * PCI Bus Definitions
- */
- #define AscPCICmdRegBits_BusMastering 0x0007
- #define AscPCICmdRegBits_ParErrRespCtrl 0x0040
- /* Read byte from a register. */
- #define AdvReadByteRegister(iop_base, reg_off)
- (ADV_MEM_READB((iop_base) + (reg_off)))
- /* Write byte to a register. */
- #define AdvWriteByteRegister(iop_base, reg_off, byte)
- (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
- /* Read word (2 bytes) from a register. */
- #define AdvReadWordRegister(iop_base, reg_off)
- (ADV_MEM_READW((iop_base) + (reg_off)))
- /* Write word (2 bytes) to a register. */
- #define AdvWriteWordRegister(iop_base, reg_off, word)
- (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
- /* Write dword (4 bytes) to a register. */
- #define AdvWriteDWordRegister(iop_base, reg_off, dword)
- (ADV_MEM_WRITEDW((iop_base) + (reg_off), (dword)))
- /* Read byte from LRAM. */
- #define AdvReadByteLram(iop_base, addr, byte)
- do {
- ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr));
- (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA);
- } while (0)
- /* Write byte to LRAM. */
- #define AdvWriteByteLram(iop_base, addr, byte)
- (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)),
- ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
- /* Read word (2 bytes) from LRAM. */
- #define AdvReadWordLram(iop_base, addr, word)
- do {
- ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr));
- (word) = (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA));
- } while (0)
- /* Write word (2 bytes) to LRAM. */
- #define AdvWriteWordLram(iop_base, addr, word)
- (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)),
- ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
- /* Write little-endian double word (4 bytes) to LRAM */
- /* Because of unspecified C language ordering don't use auto-increment. */
- #define AdvWriteDWordLramNoSwap(iop_base, addr, dword)
- ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)),
- ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA,
- cpu_to_le16((ushort) ((dword) & 0xFFFF)))),
- (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2),
- ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA,
- cpu_to_le16((ushort) ((dword >> 16) & 0xFFFF)))))
- /* Read word (2 bytes) from LRAM assuming that the address is already set. */
- #define AdvReadWordAutoIncLram(iop_base)
- (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
- /* Write word (2 bytes) to LRAM assuming that the address is already set. */
- #define AdvWriteWordAutoIncLram(iop_base, word)
- (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
- /*
- * Define macro to check for Condor signature.
- *
- * Evaluate to ADV_TRUE if a Condor chip is found the specified port
- * address 'iop_base'. Otherwise evalue to ADV_FALSE.
- */
- #define AdvFindSignature(iop_base)
- (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) ==
- ADV_CHIP_ID_BYTE) &&
- (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) ==
- ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
- /*
- * Define macro to Return the version number of the chip at 'iop_base'.
- *
- * The second parameter 'bus_type' is currently unused.
- */
- #define AdvGetChipVersion(iop_base, bus_type)
- AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
- /*
- * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
- * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
- *
- * If the request has not yet been sent to the device it will simply be
- * aborted from RISC memory. If the request is disconnected it will be
- * aborted on reselection by sending an Abort Message to the target ID.
- *
- * Return value:
- * ADV_TRUE(1) - Queue was successfully aborted.
- * ADV_FALSE(0) - Queue was not found on the active queue list.
- */
- #define AdvAbortQueue(asc_dvc, scsiq)
- AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT,
- (ADV_DCNT) (scsiq))
- /*
- * Send a Bus Device Reset Message to the specified target ID.
- *
- * All outstanding commands will be purged if sending the
- * Bus Device Reset Message is successful.
- *
- * Return Value:
- * ADV_TRUE(1) - All requests on the target are purged.
- * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
- * are not purged.
- */
- #define AdvResetDevice(asc_dvc, target_id)
- AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET,
- (ADV_DCNT) (target_id))
- /*
- * SCSI Wide Type definition.
- */
- #define ADV_SCSI_BIT_ID_TYPE ushort
- /*
- * AdvInitScsiTarget() 'cntl_flag' options.
- */
- #define ADV_SCAN_LUN 0x01
- #define ADV_CAPINFO_NOLUN 0x02
- /*
- * Convert target id to target id bit mask.
- */
- #define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
- /*
- * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
- */
- #define QD_NO_STATUS 0x00 /* Request not completed yet. */
- #define QD_NO_ERROR 0x01
- #define QD_ABORTED_BY_HOST 0x02
- #define QD_WITH_ERROR 0x04
- #define QHSTA_NO_ERROR 0x00
- #define QHSTA_M_SEL_TIMEOUT 0x11
- #define QHSTA_M_DATA_OVER_RUN 0x12
- #define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
- #define QHSTA_M_QUEUE_ABORTED 0x15
- #define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
- #define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
- #define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
- #define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
- #define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
- #define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
- #define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
- /* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
- #define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
- #define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
- #define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
- #define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */
- #define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */
- #define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */
- #define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */
- #define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */
- #define QHSTA_M_WTM_TIMEOUT 0x41
- #define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
- #define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
- #define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
- #define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
- #define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */
- #define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */
- /*
- * Default EEPROM Configuration structure defined in a_init.c.
- */
- extern ADVEEP_3550_CONFIG Default_3550_EEPROM_Config;
- extern ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config;
- extern ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
- /*
- * DvcGetPhyAddr() flag arguments
- */
- #define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
- #define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
- #define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
- #define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
- #define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
- #define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */
- /* Return the address that is aligned at the next doubleword >= to 'addr'. */
- #define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7)
- #define ADV_16BALIGN(addr) (((ulong) (addr) + 0xF) & ~0xF)
- #define ADV_32BALIGN(addr) (((ulong) (addr) + 0x1F) & ~0x1F)
- /*
- * Total contiguous memory needed for driver SG blocks.
- *
- * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
- * number of scatter-gather elements the driver supports in a
- * single request.
- */
- #define ADV_SG_LIST_MAX_BYTE_SIZE
- (sizeof(ADV_SG_BLOCK) *
- ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
- /*
- * Inquiry data structure and bitfield macros
- *
- * Using bitfields to access the subchar data isn't portable across
- * endianness, so instead mask and shift. Only quantities of more
- * than 1 bit are shifted, since the others are just tested for true
- * or false.
- */
- #define ADV_INQ_DVC_TYPE(inq) ((inq)->periph & 0x1f)
- #define ADV_INQ_QUALIFIER(inq) (((inq)->periph & 0xe0) >> 5)
- #define ADV_INQ_DVC_TYPE_MOD(inq) ((inq)->devtype & 0x7f)
- #define ADV_INQ_REMOVABLE(inq) ((inq)->devtype & 0x80)
- #define ADV_INQ_ANSI_VER(inq) ((inq)->ver & 0x07)
- #define ADV_INQ_ECMA_VER(inq) (((inq)->ver & 0x38) >> 3)
- #define ADV_INQ_ISO_VER(inq) (((inq)->ver & 0xc0) >> 6)
- #define ADV_INQ_RESPONSE_FMT(inq) ((inq)->byte3 & 0x0f)
- #define ADV_INQ_TERM_IO(inq) ((inq)->byte3 & 0x40)
- #define ADV_INQ_ASYNC_NOTIF(inq) ((inq)->byte3 & 0x80)
- #define ADV_INQ_SOFT_RESET(inq) ((inq)->flags & 0x01)
- #define ADV_INQ_CMD_QUEUE(inq) ((inq)->flags & 0x02)
- #define ADV_INQ_LINK_CMD(inq) ((inq)->flags & 0x08)
- #define ADV_INQ_SYNC(inq) ((inq)->flags & 0x10)
- #define ADV_INQ_WIDE16(inq) ((inq)->flags & 0x20)
- #define ADV_INQ_WIDE32(inq) ((inq)->flags & 0x40)
- #define ADV_INQ_REL_ADDR(inq) ((inq)->flags & 0x80)
- #define ADV_INQ_INFO_UNIT(inq) ((inq)->info & 0x01)
- #define ADV_INQ_QUICK_ARB(inq) ((inq)->info & 0x02)
- #define ADV_INQ_CLOCKING(inq) (((inq)->info & 0x0c) >> 2)
- typedef struct {
- uchar periph; /* peripheral device type [0:4] */
- /* peripheral qualifier [5:7] */
- uchar devtype; /* device type modifier (for SCSI I) [0:6] */
- /* RMB - removable medium bit [7] */
- uchar ver; /* ANSI approved version [0:2] */
- /* ECMA version [3:5] */
- /* ISO version [6:7] */
- uchar byte3; /* response data format [0:3] */
- /* 0 SCSI 1 */
- /* 1 CCS */
- /* 2 SCSI-2 */
- /* 3-F reserved */
- /* reserved [4:5] */
- /* terminate I/O process bit (see 5.6.22) [6] */
- /* asynch. event notification (processor) [7] */
- uchar add_len; /* additional length */
- uchar res1; /* reserved */
- uchar res2; /* reserved */
- uchar flags; /* soft reset implemented [0] */
- /* command queuing [1] */
- /* reserved [2] */
- /* linked command for this logical unit [3] */
- /* synchronous data transfer [4] */
- /* wide bus 16 bit data transfer [5] */
- /* wide bus 32 bit data transfer [6] */
- /* relative addressing mode [7] */
- uchar vendor_id[8]; /* vendor identification */
- uchar product_id[16]; /* product identification */
- uchar product_rev_level[4]; /* product revision level */
- uchar vendor_specific[20]; /* vendor specific */
- uchar info; /* information unit supported [0] */
- /* quick arbitrate supported [1] */
- /* clocking field [2:3] */
- /* reserved [4:7] */
- uchar res3; /* reserved */
- } ADV_SCSI_INQUIRY; /* 58 bytes */
- /*
- * --- Driver Constants and Macros
- */
- #define ASC_NUM_BOARD_SUPPORTED 16
- #define ASC_NUM_IOPORT_PROBE 4
- #define ASC_NUM_BUS 4
- /* Reference Scsi_Host hostdata */
- #define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
- /* asc_board_t flags */
- #define ASC_HOST_IN_RESET 0x01
- #define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
- #define ASC_SELECT_QUEUE_DEPTHS 0x08
- #define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
- #define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD)
- #define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
- /*
- * If the Linux kernel version supports freeing initialization code
- * and data after loading, define macros for this purpose. These macros
- * are not used when the driver is built as a module, cf. linux/init.h.
- */
- #if ASC_LINUX_KERNEL24
- #define ASC_INITFUNC(type, func) type __init func
- #elif ASC_LINUX_KERNEL22
- #define ASC_INITFUNC(type, func) __initfunc(type func)
- #endif
- #define ASC_INITDATA __initdata
- #define ASC_INIT __init
- #define ASC_INFO_SIZE 128 /* advansys_info() line size */
- #ifdef CONFIG_PROC_FS
- /* /proc/scsi/advansys/[0...] related definitions */
- #define ASC_PRTBUF_SIZE 2048
- #define ASC_PRTLINE_SIZE 160
- #define ASC_PRT_NEXT()
- if (cp) {
- totlen += len;
- leftlen -= len;
- if (leftlen == 0) {
- return totlen;
- }
- cp += len;
- }
- #define ASC_MIN(a, b) (((a) < (b)) ? (a) : (b))
- #endif /* CONFIG_PROC_FS */
- /*
- * XXX - Release and acquire the io_request_lock. These macros are needed
- * because the 2.4 kernel SCSI mid-level driver holds the 'io_request_lock'
- * on entry to SCSI low-level drivers.
- *
- * These definitions and all code that uses code should be removed when the
- * SCSI mid-level driver no longer holds the 'io_request_lock' on entry to
- * SCSI low-level driver detect, queuecommand, and reset entrypoints.
- *
- * The interrupt flags values doesn't matter in the macros because the
- * SCSI mid-level will save and restore the flags values before and after
- * calling advansys_detect, advansys_queuecommand, and advansys_reset where
- * these macros are used. We do want interrupts enabled after the lock is
- * released so an explicit sti() is done. The driver only needs interrupts
- * disabled when it acquires the per board lock.
- */
- #define ASC_UNLOCK_IO_REQUEST_LOCK
- {
- ulong flags; /* flags value not needed, cf. comment above. */
- save_flags(flags);
- spin_unlock_irqrestore(&io_request_lock, flags);
- sti(); /* enable interrupts */
- }
- #define ASC_LOCK_IO_REQUEST_LOCK
- {
- ulong flags; /* flags value not needed, cf. comment above. */
- spin_lock_irqsave(&io_request_lock, flags);
- }
- /* Asc Library return codes */
- #define ASC_TRUE 1
- #define ASC_FALSE 0
- #define ASC_NOERROR 1
- #define ASC_BUSY 0
- #define ASC_ERROR (-1)
- /* Scsi_Cmnd function return codes */
- #define STATUS_BYTE(byte) (byte)
- #define MSG_BYTE(byte) ((byte) << 8)
- #define HOST_BYTE(byte) ((byte) << 16)
- #define DRIVER_BYTE(byte) ((byte) << 24)
- /*
- * The following definitions and macros are OS independent interfaces to
- * the queue functions:
- * REQ - SCSI request structure
- * REQP - pointer to SCSI request structure
- * REQPTID(reqp) - reqp's target id
- * REQPNEXT(reqp) - reqp's next pointer
- * REQPNEXTP(reqp) - pointer to reqp's next pointer
- * REQPTIME(reqp) - reqp's time stamp value
- * REQTIMESTAMP() - system time stamp value
- */
- typedef Scsi_Cmnd REQ, *REQP;
- #define REQPNEXT(reqp) ((REQP) ((reqp)->host_scribble))
- #define REQPNEXTP(reqp) ((REQP *) &((reqp)->host_scribble))
- #define REQPTID(reqp) ((reqp)->target)
- #define REQPTIME(reqp) ((reqp)->SCp.this_residual)
- #define REQTIMESTAMP() (jiffies)
- #define REQTIMESTAT(function, ascq, reqp, tid)
- {
- /*
- * If the request time stamp is less than the system time stamp, then
- * maybe the system time stamp wrapped. Set the request time to zero.
- */
- if (REQPTIME(reqp) <= REQTIMESTAMP()) {
- REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp);
- } else {
- /* Indicate an error occurred with the assertion. */
- ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP());
- REQPTIME(reqp) = 0;
- }
- /* Handle first minimum time case without external initialization. */
- if (((ascq)->q_tot_cnt[tid] == 1) ||
- (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) {
- (ascq)->q_min_tim[tid] = REQPTIME(reqp);
- ASC_DBG3(1, "%s: new q_min_tim[%d] %un",
- (function), (tid), (ascq)->q_min_tim[tid]);
- }
- if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) {
- (ascq)->q_max_tim[tid] = REQPTIME(reqp);
- ASC_DBG3(1, "%s: new q_max_tim[%d] %un",
- (function), tid, (ascq)->q_max_tim[tid]);
- }
- (ascq)->q_tot_tim[tid] += REQPTIME(reqp);
- /* Reset the time stamp field. */
- REQPTIME(reqp) = 0;
- }
- /* asc_enqueue() flags */
- #define ASC_FRONT 1
- #define ASC_BACK 2
- /* asc_dequeue_list() argument */
- #define ASC_TID_ALL (-1)
- /* Return non-zero, if the queue is empty. */
- #define ASC_QUEUE_EMPTY(ascq) ((ascq)->q_tidmask == 0)
- /* PCI configuration declarations */
- #define PCI_BASE_CLASS_PREDEFINED 0x00
- #define PCI_BASE_CLASS_MASS_STORAGE 0x01
- #define PCI_BASE_CLASS_NETWORK 0x02
- #define PCI_BASE_CLASS_DISPLAY 0x03
- #define PCI_BASE_CLASS_MULTIMEDIA 0x04
- #define PCI_BASE_CLASS_MEMORY_CONTROLLER 0x05
- #define PCI_BASE_CLASS_BRIDGE_DEVICE 0x06
- /* MASS STORAGE */
- #define PCI_SUB_CLASS_SCSI_CONTROLLER 0x00
- #define PCI_SUB_CLASS_IDE_CONTROLLER 0x01
- #define PCI_SUB_CLASS_FLOPPY_DISK_CONTROLLER 0x02
- #define PCI_SUB_CLASS_IPI_BUS_CONTROLLER 0x03
- #define PCI_SUB_CLASS_OTHER_MASS_CONTROLLER 0x80
- /* NETWORK CONTROLLER */
- #define PCI_SUB_CLASS_ETHERNET_CONTROLLER 0x00
- #define PCI_SUB_CLASS_TOKEN_RING_CONTROLLER 0x01
- #define PCI_SUB_CLASS_FDDI_CONTROLLER 0x02
- #define PCI_SUB_CLASS_OTHER_NETWORK_CONTROLLER 0x80
- /* DISPLAY CONTROLLER */
- #define PCI_SUB_CLASS_VGA_CONTROLLER 0x00
- #define PCI_SUB_CLASS_XGA_CONTROLLER 0x01
- #define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER 0x80
- /* MULTIMEDIA CONTROLLER */
- #define PCI_SUB_CLASS_VIDEO_DEVICE 0x00
- #define PCI_SUB_CLASS_AUDIO_DEVICE 0x01
- #define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE 0x80
- /* MEMORY CONTROLLER */
- #define PCI_SUB_CLASS_RAM_CONTROLLER 0x00
- #define PCI_SUB_CLASS_FLASH_CONTROLLER 0x01
- #define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER 0x80
- /* BRIDGE CONTROLLER */
- #define PCI_SUB_CLASS_HOST_BRIDGE_CONTROLLER 0x00
- #define PCI_SUB_CLASS_ISA_BRIDGE_CONTROLLER 0x01
- #define PCI_SUB_CLASS_EISA_BRIDGE_CONTROLLER 0x02
- #define PCI_SUB_CLASS_MC_BRIDGE_CONTROLLER 0x03
- #define PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER 0x04
- #define PCI_SUB_CLASS_PCMCIA_BRIDGE_CONTROLLER 0x05
- #define PCI_SUB_CLASS_OTHER_BRIDGE_CONTROLLER 0x80
- #define PCI_MAX_SLOT 0x1F
- #define PCI_MAX_BUS 0xFF
- #define PCI_IOADDRESS_MASK 0xFFFE
- #define ASC_PCI_VENDORID 0x10CD
- #define ASC_PCI_DEVICE_ID_CNT 6 /* PCI Device ID count. */
- #define ASC_PCI_DEVICE_ID_1100 0x1100
- #define ASC_PCI_DEVICE_ID_1200 0x1200
- #define ASC_PCI_DEVICE_ID_1300 0x1300
- #define ASC_PCI_DEVICE_ID_2300 0x2300 /* ASC-3550 */
- #define ASC_PCI_DEVICE_ID_2500 0x2500 /* ASC-38C0800 */
- #define ASC_PCI_DEVICE_ID_2700 0x2700 /* ASC-38C1600 */
- /* PCI IO Port Addresses to generate special cycle */
- #define PCI_CONFIG_ADDRESS_MECH1 0x0CF8
- #define PCI_CONFIG_DATA_MECH1 0x0CFC
- #define PCI_CONFIG_FORWARD_REGISTER 0x0CFA /* 0=type 0; 1=type 1; */
- #define PCI_CONFIG_BUS_NUMBER_MASK 0x00FF0000
- #define PCI_CONFIG_DEVICE_FUNCTION_MASK 0x0000FF00
- #define PCI_CONFIG_REGISTER_NUMBER_MASK 0x000000F8
- #define PCI_DEVICE_FOUND 0x0000
- #define PCI_DEVICE_NOT_FOUND 0xffff
- #define SUBCLASS_OFFSET 0x0A
- #define CLASSCODE_OFFSET 0x0B
- #define VENDORID_OFFSET 0x00
- #define DEVICEID_OFFSET 0x02
- #ifndef ADVANSYS_STATS
- #define ASC_STATS(shp, counter)
- #define ASC_STATS_ADD(shp, counter, count)
- #else /* ADVANSYS_STATS */
- #define ASC_STATS(shp, counter)
- (ASC_BOARDP(shp)->asc_stats.counter++)
- #define ASC_STATS_ADD(shp, counter, count)
- (ASC_BOARDP(shp)->asc_stats.counter += (count))
- #endif /* ADVANSYS_STATS */
- #define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
- /* If the result wraps when calculating tenths, return 0. */
- #define ASC_TENTHS(num, den)
- (((10 * ((num)/(den))) > (((num) * 10)/(den))) ?
- 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
- /*
- * Display a message to the console.
- */
- #define ASC_PRINT(s)
- {
- printk("advansys: ");
- printk(s);
- }
- #define ASC_PRINT1(s, a1)
- {
- printk("advansys: ");
- printk((s), (a1));
- }
- #define ASC_PRINT2(s, a1, a2)
- {
- printk("advansys: ");
- printk((s), (a1), (a2));
- }
- #define ASC_PRINT3(s, a1, a2, a3)
- {
- printk("advansys: ");
- printk((s), (a1), (a2), (a3));
- }
- #define ASC_PRINT4(s, a1, a2, a3, a4)
- {
- printk("advansys: ");
- printk((s), (a1), (a2), (a3), (a4));
- }
- #ifndef ADVANSYS_DEBUG
- #define ASC_DBG(lvl, s)
- #define ASC_DBG1(lvl, s, a1)
- #define ASC_DBG2(lvl, s, a1, a2)
- #define ASC_DBG3(lvl, s, a1, a2, a3)
- #define ASC_DBG4(lvl, s, a1, a2, a3, a4)
- #define ASC_DBG_PRT_SCSI_HOST(lvl, s)
- #define ASC_DBG_PRT_SCSI_CMND(lvl, s)
- #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
- #define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
- #define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
- #define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
- #define ASC_DBG_PRT_HEX(lvl, name, start, length)
- #define ASC_DBG_PRT_CDB(lvl, cdb, len)
- #define ASC_DBG_PRT_SENSE(lvl, sense, len)
- #define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
- #else /* ADVANSYS_DEBUG */
- /*
- * Debugging Message Levels:
- * 0: Errors Only
- * 1: High-Level Tracing
- * 2-N: Verbose Tracing
- */
- #define ASC_DBG(lvl, s)
- {
- if (asc_dbglvl >= (lvl)) {
- printk(s);
- }
- }
- #define ASC_DBG1(lvl, s, a1)
- {
- if (asc_dbglvl >= (lvl)) {
- printk((s), (a1));
- }
- }
- #define ASC_DBG2(lvl, s, a1, a2)
- {
- if (asc_dbglvl >= (lvl)) {
- printk((s), (a1), (a2));
- }
- }
- #define ASC_DBG3(lvl, s, a1, a2, a3)
- {
- if (asc_dbglvl >= (lvl)) {
- printk((s), (a1), (a2), (a3));
- }
- }
- #define ASC_DBG4(lvl, s, a1, a2, a3, a4)
- {
- if (asc_dbglvl >= (lvl)) {
- printk((s), (a1), (a2), (a3), (a4));
- }
- }
- #define ASC_DBG_PRT_SCSI_HOST(lvl, s)
- {
- if (asc_dbglvl >= (lvl)) {
- asc_prt_scsi_host(s);
- }
- }
- #define ASC_DBG_PRT_SCSI_CMND(lvl, s)
- {
- if (asc_dbglvl >= (lvl)) {
- asc_prt_scsi_cmnd(s);
- }
- }
- #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
- {
- if (asc_dbglvl >= (lvl)) {
- asc_prt_asc_scsi_q(scsiqp);
- }
- }
- #define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
- {
- if (asc_dbglvl >= (lvl)) {
- asc_prt_asc_qdone_info(qdone);
- }
- }
- #define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
- {
- if (asc_dbglvl >= (lvl)) {
- asc_prt_adv_scsi_req_q(scsiqp);
- }
- }
- #define ASC_DBG_PRT_HEX(lvl, name, start, length)
- {
- if (asc_dbglvl >= (lvl)) {
- asc_prt_hex((name), (start), (length));
- }
- }
- #define ASC_DBG_PRT_CDB(lvl, cdb, len)
- ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
- #define ASC_DBG_PRT_SENSE(lvl, sense, len)
- ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
- #define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
- ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
- #endif /* ADVANSYS_DEBUG */
- #ifndef ADVANSYS_ASSERT
- #define ASC_ASSERT(a)
- #else /* ADVANSYS_ASSERT */
- #define ASC_ASSERT(a)
- {
- if (!(a)) {
- printk("ASC_ASSERT() Failure: file %s, line %dn",
- __FILE__, __LINE__);
- }
- }
- #endif /* ADVANSYS_ASSERT */
- /*
- * --- Driver Structures
- */
- #ifdef ADVANSYS_STATS
- /* Per board statistics structure */
- struct asc_stats {
- /* Driver Entrypoint Statistics */
- ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */
- ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */
- ADV_DCNT biosparam; /* # calls to advansys_biosparam() */
- ADV_DCNT interrupt; /* # advansys_interrupt() calls */
- ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */
- ADV_DCNT done; /* # calls to request's scsi_done function */
- ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
- ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
- ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
- /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
- ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */
- ADV_DCNT exe_busy; /* # ASC_BUSY returns. */
- ADV_DCNT exe_error; /* # ASC_ERROR returns. */
- ADV_DCNT exe_unknown; /* # unknown returns. */
- /* Data Transfer Statistics */
- ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */
- ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */
- ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */
- ADV_DCNT sg_elem; /* # scatter-gather elements */
- ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */
- };
- #endif /* ADVANSYS_STATS */
- /*
- * Request queuing structure
- */
- typedef struct asc_queue {
- ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */
- REQP q_first[ADV_MAX_TID+1]; /* first queued request */
- REQP q_last[ADV_MAX_TID+1]; /* last queued request */
- #ifdef ADVANSYS_STATS
- short q_cur_cnt[ADV_MAX_TID+1]; /* current queue count */
- short q_max_cnt[ADV_MAX_TID+1]; /* maximum queue count */
- ADV_DCNT q_tot_cnt[ADV_MAX_TID+1]; /* total enqueue count */
- ADV_DCNT q_tot_tim[ADV_MAX_TID+1]; /* total time queued */
- ushort q_max_tim[ADV_MAX_TID+1]; /* maximum time queued */
- ushort q_min_tim[ADV_MAX_TID+1]; /* minimum time queued */
- #endif /* ADVANSYS_STATS */
- } asc_queue_t;
- /*
- * Adv Library Request Structures
- *
- * The following two structures are used to process Wide Board requests.
- *
- * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
- * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
- * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
- * Mid-Level SCSI request structure.
- *
- * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
- * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
- * up to 255 scatter-gather elements may be used per request or
- * ADV_SCSI_REQ_Q.
- *
- * Both structures must be 32 byte aligned.
- */
- typedef struct adv_sgblk {
- ADV_SG_BLOCK sg_block; /* Sgblock structure. */
- uchar align[32]; /* Sgblock structure padding. */
- struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
- } adv_sgblk_t;
- typedef struct adv_req {
- ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
- uchar align[32]; /* Request structure padding. */
- Scsi_Cmnd *cmndp; /* Mid-Level SCSI command pointer. */
- adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
- struct adv_req *next_reqp; /* Next Request Structure. */
- } adv_req_t;
- /*
- * Structure allocated for each board.
- *
- * This structure is allocated by scsi_register() at the end
- * of the 'Scsi_Host' structure starting at the 'hostdata'
- * field. It is guaranteed to be allocated from DMA-able memory.
- */
- typedef struct asc_board {
- int id; /* Board Id */
- uint flags; /* Board flags */
- union {
- ASC_DVC_VAR asc_dvc_var; /* Narrow board */
- ADV_DVC_VAR adv_dvc_var; /* Wide board */
- } dvc_var;
- union {
- ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
- ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
- } dvc_cfg;
- ushort asc_n_io_port; /* Number I/O ports. */
- asc_queue_t active; /* Active command queue */
- asc_queue_t waiting; /* Waiting command queue */
- asc_queue_t done; /* Done command queue */
- ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
- Scsi_Device *device[ADV_MAX_TID+1]; /* Mid-Level Scsi Device */
- ushort reqcnt[ADV_MAX_TID+1]; /* Starvation request count */
- ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
- ushort queue_full_cnt[ADV_MAX_TID+1]; /* Queue full count */
- union {
- ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
- ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */
- ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */
- ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */
- } eep_config;
- ulong last_reset; /* Saved last reset time */
- spinlock_t lock; /* Board spinlock */
- #ifdef CONFIG_PROC_FS
- /* /proc/scsi/advansys/[0...] */
- char *prtbuf; /* /proc print buffer */
- #endif /* CONFIG_PROC_FS */
- #ifdef ADVANSYS_STATS
- struct asc_stats asc_stats; /* Board statistics */
- #endif /* ADVANSYS_STATS */
- /*
- * The following fields are used only for Narrow Boards.
- */
- /* The following three structures must be in DMA-able memory. */
- ASC_SCSI_REQ_Q scsireqq;
- ASC_CAP_INFO cap_info;
- ASC_SCSI_INQUIRY inquiry;
- uchar sdtr_data[ASC_MAX_TID+1]; /* SDTR information */
- /*
- * The following fields are used only for Wide Boards.
- */
- void *ioremap_addr; /* I/O Memory remap address. */
- ushort ioport; /* I/O Port address. */
- ADV_CARR_T *orig_carrp; /* ADV_CARR_T memory block. */
- adv_req_t *orig_reqp; /* adv_req_t memory block. */
- adv_req_t *adv_reqp; /* Request structures. */
- adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
- ushort bios_signature; /* BIOS Signature. */
- ushort bios_version; /* BIOS Version. */
- ushort bios_codeseg; /* BIOS Code Segment. */
- ushort bios_codelen; /* BIOS Code Segment Length. */
- } asc_board_t;
- /*
- * PCI configuration structures
- */
- typedef struct _PCI_DATA_
- {
- uchar type;
- uchar bus;
- uchar slot;
- uchar func;
- uchar offset;
- } PCI_DATA;
- typedef struct _PCI_DEVICE_
- {
- ushort vendorID;
- ushort deviceID;
- ushort slotNumber;
- ushort slotFound;
- uchar busNumber;
- uchar maxBusNumber;
- uchar devFunc;
- ushort startSlot;
- ushort endSlot;
- uchar bridge;
- uchar type;
- } PCI_DEVICE;
- typedef struct _PCI_CONFIG_SPACE_
- {
- ushort vendorID;
- ushort deviceID;
- ushort command;
- ushort status;
- uchar revision;
- uchar classCode[3];
- uchar cacheSize;
- uchar latencyTimer;
- uchar headerType;
- uchar bist;
- ADV_PADDR baseAddress[6];
- ushort reserved[4];
- ADV_PADDR optionRomAddr;
- ushort reserved2[4];
- uchar irqLine;
- uchar irqPin;
- uchar minGnt;
- uchar maxLatency;
- } PCI_CONFIG_SPACE;
- /*
- * --- Driver Data
- */
- /* Note: All driver global data should be initialized. */
- #if ASC_LINUX_KERNEL22
- #ifdef CONFIG_PROC_FS
- struct proc_dir_entry proc_scsi_advansys =
- {
- PROC_SCSI_ADVANSYS, /* unsigned short low_ino */
- 8, /* unsigned short namelen */
- "advansys", /* const char *name */
- S_IFDIR | S_IRUGO | S_IXUGO, /* mode_t mode */
- 2 /* nlink_t nlink */
- };
- #endif /* CONFIG_PROC_FS */
- #endif /* ASC_LINUX_KERNEL22 */
- /* Number of boards detected in system. */
- STATIC int asc_board_count = 0;
- STATIC struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { 0 };
- /* Overrun buffer used by all narrow boards. */
- STATIC uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
- /*
- * Global structures required to issue a command.
- */
- STATIC ASC_SCSI_Q asc_scsi_q = { { 0 } };
- STATIC ASC_SG_HEAD asc_sg_head = { 0 };
- /* List of supported bus types. */
- STATIC ushort asc_bus[ASC_NUM_BUS] ASC_INITDATA = {
- ASC_IS_ISA,
- ASC_IS_VL,
- ASC_IS_EISA,
- ASC_IS_PCI,
- };
- /*
- * Used with the LILO 'advansys' option to eliminate or
- * limit I/O port probing at boot time, cf. advansys_setup().
- */
- STATIC int asc_iopflag = ASC_FALSE;
- STATIC int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 };
- #ifdef ADVANSYS_DEBUG
- STATIC char *
- asc_bus_name[ASC_NUM_BUS] = {
- "ASC_IS_ISA",
- "ASC_IS_VL",
- "ASC_IS_EISA",
- "ASC_IS_PCI",
- };
- STATIC int asc_dbglvl = 3;
- #endif /* ADVANSYS_DEBUG */
- /* Declaration for Asc Library internal data referenced by driver. */
- STATIC PortAddr _asc_def_iop_base[];
- /*
- * --- Driver Function Prototypes
- *
- * advansys.h contains function prototypes for functions global to Linux.
- */
- STATIC void advansys_interrupt(int, void *, struct pt_regs *);
- STATIC void advansys_select_queue_depths(struct Scsi_Host *,
- Scsi_Device *);
- STATIC void asc_scsi_done_list(Scsi_Cmnd *);
- STATIC int asc_execute_scsi_cmnd(Scsi_Cmnd *);
- STATIC int asc_build_req(asc_board_t *, Scsi_Cmnd *);
- STATIC int adv_build_req(asc_board_t *, Scsi_Cmnd *, ADV_SCSI_REQ_Q **);
- STATIC int adv_get_sglist(asc_board_t *, adv_req_t *, Scsi_Cmnd *);
- STATIC void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
- STATIC void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
- STATIC void adv_async_callback(ADV_DVC_VAR *, uchar);
- STATIC void asc_enqueue(asc_queue_t *, REQP, int);
- STATIC REQP asc_dequeue(asc_queue_t *, int);
- STATIC REQP asc_dequeue_list(asc_queue_t *, REQP *, int);
- STATIC int asc_rmqueue(asc_queue_t *, REQP);
- STATIC void asc_execute_queue(asc_queue_t *);
- #ifdef CONFIG_PROC_FS
- STATIC int asc_proc_copy(off_t, off_t, char *, int , char *, int);
- STATIC int asc_prt_board_devices(struct Scsi_Host *, char *, int);
- STATIC int asc_prt_adv_bios(struct Scsi_Host *, char *, int);
- STATIC int asc_get_eeprom_string(ushort *serialnum, uchar *cp);
- STATIC int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int);
- STATIC int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int);
- STATIC int asc_prt_driver_conf(struct Scsi_Host *, char *, int);
- STATIC int asc_prt_asc_board_info(struct Scsi_Host *, char *, int);
- STATIC int asc_prt_adv_board_info(struct Scsi_Host *, char *, int);
- STATIC int asc_prt_line(char *, int, char *fmt, ...);
- #endif /* CONFIG_PROC_FS */
- /* Declaration for Asc Library internal functions referenced by driver. */
- STATIC int AscFindSignature(PortAddr);
- STATIC ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
- /* Statistics function prototypes. */
- #ifdef ADVANSYS_STATS
- #ifdef CONFIG_PROC_FS
- STATIC int asc_prt_board_stats(struct Scsi_Host *, char *, int);
- STATIC int asc_prt_target_stats(struct Scsi_Host *, int, char *, int);
- #endif /* CONFIG_PROC_FS */
- #endif /* ADVANSYS_STATS */
- /* Debug function prototypes. */
- #ifdef ADVANSYS_DEBUG
- STATIC void asc_prt_scsi_host(struct Scsi_Host *);
- STATIC void asc_prt_scsi_cmnd(Scsi_Cmnd *);
- STATIC void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *);
- STATIC void asc_prt_asc_dvc_var(ASC_DVC_VAR *);
- STATIC void asc_prt_asc_scsi_q(ASC_SCSI_Q *);
- STATIC void asc_prt_asc_qdone_info(ASC_QDONE_INFO *);
- STATIC void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *);
- STATIC void asc_prt_adv_dvc_var(ADV_DVC_VAR *);
- STATIC void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *);
- STATIC void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *);
- STATIC void asc_prt_hex(char *f, uchar *, int);
- #endif /* ADVANSYS_DEBUG */
- /*
- * --- Linux 'Scsi_Host_Template' and advansys_setup() Functions
- */
- #ifdef CONFIG_PROC_FS
- /*
- * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)]
- *
- * *buffer: I/O buffer
- * **start: if inout == FALSE pointer into buffer where user read should start
- * offset: current offset into a /proc/scsi/advansys/[0...] file
- * length: length of buffer
- * hostno: Scsi_Host host_no
- * inout: TRUE - user is writing; FALSE - user is reading
- *
- * Return the number of bytes read from or written to a
- * /proc/scsi/advansys/[0...] file.
- *
- * Note: This function uses the per board buffer 'prtbuf' which is
- * allocated when the board is initialized in advansys_detect(). The
- * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
- * used to write to the buffer. The way asc_proc_copy() is written
- * if 'prtbuf' is too small it will not be overwritten. Instead the
- * user just won't get all the available statistics.
- */
- int
- advansys_proc_info(char *buffer, char **start, off_t offset, int length,
- int hostno, int inout)
- {
- struct Scsi_Host *shp;
- asc_board_t *boardp;
- int i;
- char *cp;
- int cplen;
- int cnt;
- int totcnt;
- int leftlen;
- char *curbuf;
- off_t advoffset;
- Scsi_Device *scd;
- #ifdef ADVANSYS_STATS
- int tgt_id;
- #endif /* ADVANSYS_STATS */
- ASC_DBG(1, "advansys_proc_info: beginn");
- /*
- * User write not supported.
- */
- if (inout == TRUE) {
- return(-ENOSYS);
- }
- /*
- * User read of /proc/scsi/advansys/[0...] file.
- */
- /* Find the specified board. */
- for (i = 0; i < asc_board_count; i++) {
- if (asc_host[i]->host_no == hostno) {
- break;
- }
- }
- if (i == asc_board_count) {
- return(-ENOENT);
- }
- shp = asc_host[i];
- boardp = ASC_BOARDP(shp);
- /* Copy read data starting at the beginning of the buffer. */
- *start = buffer;
- curbuf = buffer;
- advoffset = 0;
- totcnt = 0;
- leftlen = length;
- /*
- * Get board configuration information.
- *
- * advansys_info() returns the board string from its own static buffer.
- */
- cp = (char *) advansys_info(shp);
- strcat(cp, "n");
- cplen = strlen(cp);
- /* Copy board information. */
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG1(1, "advansys_proc_info: totcnt %dn", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
- /*
- * Display Wide Board BIOS Information.
- */
- if (ASC_WIDE_BOARD(boardp)) {
- cp = boardp->prtbuf;
- cplen = asc_prt_adv_bios(shp, cp, ASC_PRTBUF_SIZE);
- ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG1(1, "advansys_proc_info: totcnt %dn", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
- }
- /*
- * Display driver information for each device attached to the board.
- */
- cp = boardp->prtbuf;
- cplen = asc_prt_board_devices(shp, cp, ASC_PRTBUF_SIZE);
- ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG1(1, "advansys_proc_info: totcnt %dn", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
- /*
- * Display target driver information for each device attached
- * to the board.
- */
- for (scd = shp->host_queue; scd; scd = scd->next)
- {
- if (scd->host == shp) {
- cp = boardp->prtbuf;
- /*
- * Note: If proc_print_scsidevice() writes more than
- * ASC_PRTBUF_SIZE bytes, it will overrun 'prtbuf'.
- */
- proc_print_scsidevice(scd, cp, &cplen, 0);
- ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG1(1, "advansys_proc_info: totcnt %dn", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
- }
- }
- /*
- * Display EEPROM configuration for the board.
- */
- cp = boardp->prtbuf;
- if (ASC_NARROW_BOARD(boardp)) {
- cplen = asc_prt_asc_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
- } else {
- cplen = asc_prt_adv_board_eeprom(shp, cp, ASC_PRTBUF_SIZE);
- }
- ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG1(1, "advansys_proc_info: totcnt %dn", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
- /*
- * Display driver configuration and information for the board.
- */
- cp = boardp->prtbuf;
- cplen = asc_prt_driver_conf(shp, cp, ASC_PRTBUF_SIZE);
- ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG1(1, "advansys_proc_info: totcnt %dn", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
- #ifdef ADVANSYS_STATS
- /*
- * Display driver statistics for the board.
- */
- cp = boardp->prtbuf;
- cplen = asc_prt_board_stats(shp, cp, ASC_PRTBUF_SIZE);
- ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG1(1, "advansys_proc_info: totcnt %dn", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
- /*
- * Display driver statistics for each target.
- */
- for (tgt_id = 0; tgt_id <= ADV_MAX_TID; tgt_id++) {
- cp = boardp->prtbuf;
- cplen = asc_prt_target_stats(shp, tgt_id, cp, ASC_PRTBUF_SIZE);
- ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE);
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG1(1, "advansys_proc_info: totcnt %dn", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
- }
- #endif /* ADVANSYS_STATS */
- /*
- * Display Asc Library dynamic configuration information
- * for the board.
- */
- cp = boardp->prtbuf;
- if (ASC_NARROW_BOARD(boardp)) {
- cplen = asc_prt_asc_board_info(shp, cp, ASC_PRTBUF_SIZE);
- } else {
- cplen = asc_prt_adv_board_info(shp, cp, ASC_PRTBUF_SIZE);
- }
- ASC_ASSERT(cplen < ASC_PRTBUF_SIZE);
- cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
- totcnt += cnt;
- leftlen -= cnt;
- if (leftlen == 0) {
- ASC_DBG1(1, "advansys_proc_info: totcnt %dn", totcnt);
- return totcnt;
- }
- advoffset += cplen;
- curbuf += cnt;
- ASC_DBG1(1, "advansys_proc_info: totcnt %dn", totcnt);
- return totcnt;
- }
- #endif /* CONFIG_PROC_FS */
- /*
- * advansys_detect()
- *
- * Detect function for AdvanSys adapters.
- *
- * Argument is a pointer to the host driver's scsi_hosts entry.
- *
- * Return number of adapters found.
- *
- * Note: Because this function is called during system initialization
- * it must not call SCSI mid-level functions including scsi_malloc()
- * and scsi_free().
- */
- ASC_INITFUNC(
- int,
- advansys_detect(Scsi_Host_Template *tpnt)
- )
- {
- static int detect_called = ASC_FALSE;
- int iop;
- int bus;
- struct Scsi_Host *shp = NULL;
- asc_board_t *boardp = NULL;
- ASC_DVC_VAR *asc_dvc_varp = NULL;
- ADV_DVC_VAR *adv_dvc_varp = NULL;
- adv_sgblk_t *sgp = NULL;
- int ioport = 0;
- int share_irq = FALSE;
- int iolen = 0;
- #ifdef CONFIG_PCI
- int pci_init_search = 0;
- struct pci_dev *pci_devicep[ASC_NUM_BOARD_SUPPORTED];
- int pci_card_cnt_max = 0;
- int pci_card_cnt = 0;
- struct pci_dev *pci_devp = NULL;
- int pci_device_id_cnt = 0;
- unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = {
- ASC_PCI_DEVICE_ID_1100,
- ASC_PCI_DEVICE_ID_1200,
- ASC_PCI_DEVICE_ID_1300,
- ASC_PCI_DEVICE_ID_2300,
- ASC_PCI_DEVICE_ID_2500,
- ASC_PCI_DEVICE_ID_2700
- };
- ADV_PADDR pci_memory_address;
- #endif /* CONFIG_PCI */
- int warn_code, err_code;
- int ret;
- if (detect_called == ASC_FALSE) {
- detect_called = ASC_TRUE;
- } else {
- printk("AdvanSys SCSI: advansys_detect() multiple calls ignoredn");
- return 0;
- }
- ASC_DBG(1, "advansys_detect: beginn");
- /*
- * XXX - Remove this comment and the next line when SCSI mid-level
- * no longer acquires 'io_request_lock' before calling the SCSI
- * low-level detect entrypoint.
- */
- ASC_UNLOCK_IO_REQUEST_LOCK
- #if ASC_LINUX_KERNEL24
- tpnt->proc_name = "advansys";
- #elif ASC_LINUX_KERNEL22
- tpnt->proc_dir = &proc_scsi_advansys;
- #endif
- asc_board_count = 0;
- /*
- * If I/O port probing has been modified, then verify and
- * clean-up the 'asc_ioport' list.
- */
- if (asc_iopflag == ASC_TRUE) {
- for (ioport = 0; ioport < ASC_NUM_IOPORT_PROBE; ioport++) {
- ASC_DBG2(1, "advansys_detect: asc_ioport[%d] 0x%xn",
- ioport, asc_ioport[ioport]);
- if (asc_ioport[ioport] != 0) {
- for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; iop++) {
- if (_asc_def_iop_base[iop] == asc_ioport[ioport]) {
- break;
- }
- }
- if (iop == ASC_IOADR_TABLE_MAX_IX) {
- printk(
- "AdvanSys SCSI: specified I/O Port 0x%X is invalidn",
- asc_ioport[ioport]);
- asc_ioport[ioport] = 0;
- }
- }
- }
- ioport = 0;
- }
- for (bus = 0; bus < ASC_NUM_BUS; bus++) {
- ASC_DBG2(1, "advansys_detect: bus search type %d (%s)n",
- bus, asc_bus_name[bus]);
- iop = 0;
- while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) {
- ASC_DBG1(2, "advansys_detect: asc_board_count %dn",
- asc_board_count);
- switch (asc_bus[bus]) {
- case ASC_IS_ISA:
- case ASC_IS_VL:
- #ifdef CONFIG_ISA
- if (asc_iopflag == ASC_FALSE) {
- iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
- } else {
- /*
- * ISA and VL I/O port scanning has either been
- * eliminated or limited to selected ports on
- * the LILO command line, /etc/lilo.conf, or
- * by setting variables when the module was loaded.
- */
- ASC_DBG(1, "advansys_detect: I/O port scanning modifiedn");
- ioport_try_again:
- iop = 0;
- for (; ioport < ASC_NUM_IOPORT_PROBE; ioport++) {
- if ((iop = asc_ioport[ioport]) != 0) {
- break;
- }
- }
- if (iop) {
- ASC_DBG1(1,
- "advansys_detect: probing I/O port 0x%x...n",
- iop);
- if (check_region(iop, ASC_IOADR_GAP) != 0) {
- printk(
- "AdvanSys SCSI: specified I/O Port 0x%X is busyn", iop);
- /* Don't try this I/O port twice. */
- asc_ioport[ioport] = 0;
- goto ioport_try_again;
- } else if (AscFindSignature(iop) == ASC_FALSE) {
- printk(
- "AdvanSys SCSI: specified I/O Port 0x%X has no adaptern", iop);
- /* Don't try this I/O port twice. */
- asc_ioport[ioport] = 0;
- goto ioport_try_again;
- } else {
- /*
- * If this isn't an ISA board, then it must be
- * a VL board. If currently looking an ISA
- * board is being looked for then try for
- * another ISA board in 'asc_ioport'.
- */
- if (asc_bus[bus] == ASC_IS_ISA &&
- (AscGetChipVersion(iop, ASC_IS_ISA) &
- ASC_CHIP_VER_ISA_BIT) == 0) {
- /*
- * Don't clear 'asc_ioport[ioport]'. Try
- * this board again for VL. Increment
- * 'ioport' past this board.
- */
- ioport++;
- goto ioport_try_again;
- }
- }
- /*
- * This board appears good, don't try the I/O port
- * again by clearing its value. Increment 'ioport'
- * for the next iteration.
- */
- asc_ioport[ioport++] = 0;
- }
- }
- #endif /* CONFIG_ISA */
- break;
- case ASC_IS_EISA:
- #ifdef CONFIG_ISA
- iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
- #endif /* CONFIG_ISA */
- break;
- case ASC_IS_PCI:
- #ifdef CONFIG_PCI
- if (pci_init_search == 0) {
- int i, j;
- pci_init_search = 1;
- /* Find all PCI cards. */
- while (pci_device_id_cnt < ASC_PCI_DEVICE_ID_CNT) {
- if ((pci_devp = pci_find_device(ASC_PCI_VENDORID,
- pci_device_id[pci_device_id_cnt], pci_devp)) ==
- NULL) {
- pci_device_id_cnt++;
- } else {
- #if ASC_LINUX_KERNEL24
- if (pci_enable_device(pci_devp) == 0) {
- pci_devicep[pci_card_cnt_max++] = pci_devp;
- }
- #elif ASC_LINUX_KERNEL22
- pci_devicep[pci_card_cnt_max++] = pci_devp;
- #endif
- }
- }
- /*
- * Sort PCI cards in ascending order by PCI Bus, Slot,
- * and Device Number.
- */
- for (i = 0; i < pci_card_cnt_max - 1; i++)
- {
- for (j = i + 1; j < pci_card_cnt_max; j++) {
- if ((pci_devicep[j]->bus->number <
- pci_devicep[i]->bus->number) ||
- ((pci_devicep[j]->bus->number ==
- pci_devicep[i]->bus->number) &&
- (pci_devicep[j]->devfn <
- pci_devicep[i]->devfn))) {
- pci_devp = pci_devicep[i];
- pci_devicep[i] = pci_devicep[j];
- pci_devicep[j] = pci_devp;
- }
- }
- }
- pci_card_cnt = 0;
- } else {
- pci_card_cnt++;
- }
- if (pci_card_cnt == pci_card_cnt_max) {
- iop = 0;
- } else {
- pci_devp = pci_devicep[pci_card_cnt];
- ASC_DBG2(2,
- "advansys_detect: devfn %d, bus number %dn",
- pci_devp->devfn, pci_devp->bus->number);
- #if ASC_LINUX_KERNEL24
- iop = pci_resource_start(pci_devp, 0);
- #elif ASC_LINUX_KERNEL22
- iop = pci_devp->base_address[0] & PCI_IOADDRESS_MASK;
- #endif
- ASC_DBG2(1,
- "advansys_detect: vendorID %X, deviceID %Xn",
- pci_devp->vendor, pci_devp->device);
- ASC_DBG2(2, "advansys_detect: iop %X, irqLine %dn",
- iop, pci_devp->irq);
- }
- #endif /* CONFIG_PCI */
- break;
- default:
- ASC_PRINT1("advansys_detect: unknown bus type: %dn",
- asc_bus[bus]);
- break;
- }
- ASC_DBG1(1, "advansys_detect: iop 0x%xn", iop);
- /*
- * Adapter not found, try next bus type.
- */
- if (iop == 0) {
- break;
- }
- /*
- * Adapter found.
- *
- * Register the adapter, get its configuration, and
- * initialize it.
- */
- ASC_DBG(2, "advansys_detect: scsi_register()n");
- shp = scsi_register(tpnt, sizeof(asc_board_t));
- if (shp == NULL) {
- continue;
- }
- #ifdef CONFIG_PCI
- scsi_set_pci_device(shp, pci_devp);
- #endif
- /* Save a pointer to the Scsi_host of each board found. */
- asc_host[asc_board_count++] = shp;
- /* Initialize private per board data */
- boardp = ASC_BOARDP(shp);
- memset(boardp, 0, sizeof(asc_board_t));
- boardp->id = asc_board_count - 1;
- /* Initialize spinlock. */
- boardp->lock = SPIN_LOCK_UNLOCKED;
- /*
- * Handle both narrow and wide boards.
- *
- * If a Wide board was detected, set the board structure
- * wide board flag. Set-up the board structure based on
- * the board type.
- */
- #ifdef CONFIG_PCI
- if (asc_bus[bus] == ASC_IS_PCI &&
- (pci_devp->device == ASC_PCI_DEVICE_ID_2300 ||
- pci_devp->device == ASC_PCI_DEVICE_ID_2500 ||
- pci_devp->device == ASC_PCI_DEVICE_ID_2700))
- {
- boardp->flags |= ASC_IS_WIDE_BOARD;
- }
- #endif /* CONFIG_PCI */
- if (ASC_NARROW_BOARD(boardp)) {
- ASC_DBG(1, "advansys_detect: narrow boardn");
- asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
- asc_dvc_varp->bus_type = asc_bus[bus];
- asc_dvc_varp->drv_ptr = boardp;
- asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
- asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
- asc_dvc_varp->iop_base = iop;
- asc_dvc_varp->isr_callback = asc_isr_callback;
- } else {
- ASC_DBG(1, "advansys_detect: wide boardn");
- adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
- adv_dvc_varp->drv_ptr = boardp;
- adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
- adv_dvc_varp->isr_callback = adv_isr_callback;
- adv_dvc_varp->async_callback = adv_async_callback;
- #ifdef CONFIG_PCI
- if (pci_devp->device == ASC_PCI_DEVICE_ID_2300)
- {
- ASC_DBG(1, "advansys_detect: ASC-3550n");
- adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
- } else if (pci_devp->device == ASC_PCI_DEVICE_ID_2500)
- {
- ASC_DBG(1, "advansys_detect: ASC-38C0800n");
- adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
- } else
- {
- ASC_DBG(1, "advansys_detect: ASC-38C1600n");
- adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
- }
- #endif /* CONFIG_PCI */
- /*
- * Map the board's registers into virtual memory for
- * PCI slave access. Only memory accesses are used to
- * access the board's registers.
- *
- * Note: The PCI register base address is not always
- * page aligned, but the address passed to ioremap()
- * must be page aligned. It is guaranteed that the
- * PCI register base address will not cross a page
- * boundary.
- */
- if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
- {
- iolen = ADV_3550_IOLEN;
- } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800)
- {
- iolen = ADV_38C0800_IOLEN;
- } else
- {
- iolen = ADV_38C1600_IOLEN;
- }
- #ifdef CONFIG_PCI
- #if ASC_LINUX_KERNEL24
- pci_memory_address = pci_resource_start(pci_devp, 1);
- #elif ASC_LINUX_KERNEL22
- pci_memory_address = pci_devp->base_address[1];
- #endif
- ASC_DBG1(1, "advansys_detect: pci_memory_address: 0x%lxn",
- (ulong) pci_memory_address);
- if ((boardp->ioremap_addr =
- ioremap(pci_memory_address & PAGE_MASK,
- PAGE_SIZE)) == 0) {
- ASC_PRINT3(
- "advansys_detect: board %d: ioremap(%x, %d) returned NULLn",
- boardp->id, pci_memory_address, iolen);
- scsi_unregister(shp);
- asc_board_count--;
- continue;
- }
- ASC_DBG1(1, "advansys_detect: ioremap_addr: 0x%lxn",
- (ulong) boardp->ioremap_addr);
- adv_dvc_varp->iop_base = (AdvPortAddr)
- (boardp->ioremap_addr +
- (pci_memory_address - (pci_memory_address & PAGE_MASK)));
- ASC_DBG1(1, "advansys_detect: iop_base: 0x%lxn",
- adv_dvc_varp->iop_base);
- #endif /* CONFIG_PCI */
- /*
- * Even though it isn't used to access wide boards, other
- * than for the debug line below, save I/O Port address so
- * that it can be reported.
- */
- boardp->ioport = iop;
- ASC_DBG2(1,
- "advansys_detect: iopb_chip_id_1 0x%x, iopw_chip_id_0 0x%xn",
- (ushort) inp(iop + 1), (ushort) inpw(iop));
- }
- #ifdef CONFIG_PROC_FS
- /*
- * Allocate buffer for printing information from
- * /proc/scsi/advansys/[0...].
- */
- if ((boardp->prtbuf =
- kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) {
- ASC_PRINT3(
- "advansys_detect: board %d: kmalloc(%d, %d) returned NULLn",
- boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC);
- scsi_unregister(shp);
- asc_board_count--;
- continue;
- }
- #endif /* CONFIG_PROC_FS */
- if (ASC_NARROW_BOARD(boardp)) {
- /*
- * Set the board bus type and PCI IRQ before
- * calling AscInitGetConfig().
- */
- switch (asc_dvc_varp->bus_type) {
- #ifdef CONFIG_ISA
- case ASC_IS_ISA:
- shp->unchecked_isa_dma = TRUE;
- share_irq = FALSE;
- break;
- case ASC_IS_VL:
- shp->unchecked_isa_dma = FALSE;
- share_irq = FALSE;
- break;
- case ASC_IS_EISA:
- shp->unchecked_isa_dma = FALSE;
- share_irq = TRUE;
- break;
- #endif /* CONFIG_ISA */
- #ifdef CONFIG_PCI
- case ASC_IS_PCI:
- shp->irq = asc_dvc_varp->irq_no = pci_devp->irq;
- asc_dvc_varp->cfg->pci_device_id = pci_devp->device;
- asc_dvc_varp->cfg->pci_slot_info =
- ASC_PCI_MKID(pci_devp->bus->number,
- PCI_SLOT(pci_devp->devfn),
- PCI_FUNC(pci_devp->devfn));
- shp->unchecked_isa_dma = FALSE;
- share_irq = TRUE;
- break;
- #endif /* CONFIG_PCI */
- default:
- ASC_PRINT2(
- "advansys_detect: board %d: unknown adapter type: %dn",
- boardp->id, asc_dvc_varp->bus_type);
- shp->unchecked_isa_dma = TRUE;
- share_irq = FALSE;
- break;
- }
- } else {
- /*
- * For Wide boards set PCI information before calling
- * AdvInitGetConfig().
- */
- #ifdef CONFIG_PCI
- shp->irq = adv_dvc_varp->irq_no = pci_devp->irq;
- adv_dvc_varp->cfg->pci_device_id = pci_devp->device;
- adv_dvc_varp->cfg->pci_slot_info =
- ASC_PCI_MKID(pci_devp->bus->number,
- PCI_SLOT(pci_devp->devfn),
- PCI_FUNC(pci_devp->devfn));
- shp->unchecked_isa_dma = FALSE;
- share_irq = TRUE;
- #endif /* CONFIG_PCI */
- }
- /*
- * Read the board configuration.
- */
- if (ASC_NARROW_BOARD(boardp)) {
- /*
- * NOTE: AscInitGetConfig() may change the board's
- * bus_type value. The asc_bus[bus] value should no
- * longer be used. If the bus_type field must be
- * referenced only use the bit-wise AND operator "&".
- */
- ASC_DBG(2, "advansys_detect: AscInitGetConfig()n");
- switch(ret = AscInitGetConfig(asc_dvc_varp)) {
- case 0: /* No error */
- break;
- case ASC_WARN_IO_PORT_ROTATE:
- ASC_PRINT1(
- "AscInitGetConfig: board %d: I/O port address modifiedn",
- boardp->id);
- break;
- case ASC_WARN_AUTO_CONFIG:
- ASC_PRINT1(
- "AscInitGetConfig: board %d: I/O port increment switch enabledn",
- boardp->id);
- break;
- case ASC_WARN_EEPROM_CHKSUM:
- ASC_PRINT1(
- "AscInitGetConfig: board %d: EEPROM checksum errorn",
- boardp->id);
- break;
- case ASC_WARN_IRQ_MODIFIED:
- ASC_PRINT1(
- "AscInitGetConfig: board %d: IRQ modifiedn",
- boardp->id);
- break;
- case ASC_WARN_CMD_QNG_CONFLICT:
- ASC_PRINT1(
- "AscInitGetConfig: board %d: tag queuing enabled w/o disconnectsn",
- boardp->id);
- break;
- default:
- ASC_PRINT2(
- "AscInitGetConfig: board %d: unknown warning: 0x%xn",
- boardp->id, ret);
- break;
- }
- if ((err_code = asc_dvc_varp->err_code) != 0) {
- ASC_PRINT3(
- "AscInitGetConfig: board %d error: init_state 0x%x, err_code 0x%xn",
- boardp->id, asc_dvc_varp->init_state,
- asc_dvc_varp->err_code);
- }
- } else {
- ASC_DBG(2, "advansys_detect: AdvInitGetConfig()n");
- if ((ret = AdvInitGetConfig(adv_dvc_varp)) != 0) {
- ASC_PRINT2("AdvInitGetConfig: board %d: warning: 0x%xn",
- boardp->id, ret);
- }
- if ((err_code = adv_dvc_varp->err_code) != 0) {
- ASC_PRINT2(
- "AdvInitGetConfig: board %d error: err_code 0x%xn",
- boardp->id, adv_dvc_varp->err_code);
- }
- }
- if (err_code != 0) {
- #ifdef CONFIG_PROC_FS
- kfree(boardp->prtbuf);
- #endif /* CONFIG_PROC_FS */
- scsi_unregister(shp);
- asc_board_count--;
- continue;
- }
- /*
- * Save the EEPROM configuration so that it can be displayed
- * from /proc/scsi/advansys/[0...].
- */
- if (ASC_NARROW_BOARD(boardp)) {
- ASCEEP_CONFIG *ep;
- /*
- * Set the adapter's target id bit in the 'init_tidmask' field.
- */
- boardp->init_tidmask |=
- ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
- /*
- * Save EEPROM settings for the board.
- */
- ep = &boardp->eep_config.asc_eep;
- ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
- ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
- ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
- ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed);
- ep->start_motor = asc_dvc_varp->start_motor;
- ep->cntl = asc_dvc_varp->dvc_cntl;
- ep->no_scam = asc_dvc_varp->no_scam;
- ep->max_total_qng = asc_dvc_varp->max_total_qng;
- ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id);
- /* 'max_tag_qng' is set to the same value for every device. */
- ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
- ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
- ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
- ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
- ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
- ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
- ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
- ep->adapter_info[6] = asc_dvc_varp->cfg->adapter_info[6];
- /*
- * Modify board configuration.
- */
- ASC_DBG(2, "advansys_detect: AscInitSetConfig()n");
- switch (ret = AscInitSetConfig(asc_dvc_varp)) {
- case 0: /* No error. */
- break;
- case ASC_WARN_IO_PORT_ROTATE:
- ASC_PRINT1(
- "AscInitSetConfig: board %d: I/O port address modifiedn",
- boardp->id);
- break;
- case ASC_WARN_AUTO_CONFIG:
- ASC_PRINT1(
- "AscInitSetConfig: board %d: I/O port increment switch enabledn",
- boardp->id);
- break;
- case ASC_WARN_EEPROM_CHKSUM:
- ASC_PRINT1(
- "AscInitSetConfig: board %d: EEPROM checksum errorn",
- boardp->id);
- break;
- case ASC_WARN_IRQ_MODIFIED:
- ASC_PRINT1(
- "AscInitSetConfig: board %d: IRQ modifiedn",
- boardp->id);
- break;
- case ASC_WARN_CMD_QNG_CONFLICT:
- ASC_PRINT1(
- "AscInitSetConfig: board %d: tag queuing w/o disconnectsn",
- boardp->id);
- break;
- default:
- ASC_PRINT2(
- "AscInitSetConfig: board %d: unknown warning: 0x%xn",
- boardp->id, ret);
- break;
- }
- if (asc_dvc_varp->err_code != 0) {
- ASC_PRINT3(
- "AscInitSetConfig: board %d error: init_state 0x%x, err_code 0x%xn",
- boardp->id, asc_dvc_varp->init_state,
- asc_dvc_varp->err_code);
- #ifdef CONFIG_PROC_FS
- kfree(boardp->prtbuf);
- #endif /* CONFIG_PROC_FS */
- scsi_unregister(shp);
- asc_board_count--;
- continue;
- }
- /*
- * Finish initializing the 'Scsi_Host' structure.
- */
- /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
- if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
- shp->irq = asc_dvc_varp->irq_no;
- }
- } else {
- ADVEEP_3550_CONFIG *ep_3550;
- ADVEEP_38C0800_CONFIG *ep_38C0800;
- ADVEEP_38C1600_CONFIG *ep_38C1600;
- /*
- * Save Wide EEP Configuration Information.
- */
- if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
- {
- ep_3550 = &boardp->eep_config.adv_3550_eep;
- ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
- ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
- ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
- ep_3550->termination = adv_dvc_varp->cfg->termination;
- ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
- ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
- ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
- ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
- ep_3550->ultra_able = adv_dvc_varp->ultra_able;
- ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
- ep_3550->start_motor = adv_dvc_varp->start_motor;
- ep_3550->scsi_reset_delay = adv_dvc_varp->scsi_reset_wait;
- ep_3550->serial_number_word1 =
- adv_dvc_varp->cfg->serial1;
- ep_3550->serial_number_word2 =
- adv_dvc_varp->cfg->serial2;
- ep_3550->serial_number_word3 =
- adv_dvc_varp->cfg->serial3;
- } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800)
- {
- ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
- ep_38C0800->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
- ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
- ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
- ep_38C0800->termination_lvd =
- adv_dvc_varp->cfg->termination;
- ep_38C0800->disc_enable = adv_dvc_varp->cfg->disc_enable;
- ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
- ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
- ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
- ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
- ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
- ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
- ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
- ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
- ep_38C0800->start_motor = adv_dvc_varp->start_motor;
- ep_38C0800->scsi_reset_delay =
- adv_dvc_varp->scsi_reset_wait;
- ep_38C0800->serial_number_word1 =
- adv_dvc_varp->cfg->serial1;
- ep_38C0800->serial_number_word2 =
- adv_dvc_varp->cfg->serial2;
- ep_38C0800->serial_number_word3 =
- adv_dvc_varp->cfg->serial3;
- } else
- {
- ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
- ep_38C1600->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
- ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng;
- ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
- ep_38C1600->termination_lvd =
- adv_dvc_varp->cfg->termination;
- ep_38C1600->disc_enable = adv_dvc_varp->cfg->disc_enable;
- ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl;
- ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able;
- ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
- ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
- ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
- ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
- ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
- ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
- ep_38C1600->start_motor = adv_dvc_varp->start_motor;
- ep_38C1600->scsi_reset_delay =
- adv_dvc_varp->scsi_reset_wait;
- ep_38C1600->serial_number_word1 =
- adv_dvc_varp->cfg->serial1;
- ep_38C1600->serial_number_word2 =
- adv_dvc_varp->cfg->serial2;
- ep_38C1600->serial_number_word3 =
- adv_dvc_varp->cfg->serial3;
- }
- /*
- * Set the adapter's target id bit in the 'init_tidmask' field.
- */
- boardp->init_tidmask |=
- ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
- /*
- * Finish initializing the 'Scsi_Host' structure.
- */
- shp->irq = adv_dvc_varp->irq_no;
- }
- /*
- * Channels are numbered beginning with 0. For AdvanSys one host
- * structure supports one channel. Multi-channel boards have a
- * separate host structure for each channel.
- */
- shp->max_channel = 0;
- if (ASC_NARROW_BOARD(boardp)) {
- shp->max_id = ASC_MAX_TID + 1;
- shp->max_lun = ASC_MAX_LUN + 1;
- shp->io_port = asc_dvc_varp->iop_base;
- boardp->asc_n_io_port = ASC_IOADR_GAP;
- shp->this_id = asc_dvc_varp->cfg->chip_scsi_id;
- /* Set maximum number of queues the adapter can handle. */
- shp->can_queue = asc_dvc_varp->max_total_qng;
- } else {
- shp->max_id = ADV_MAX_TID + 1;
- shp->max_lun = ADV_MAX_LUN + 1;
- /*
- * Save the I/O Port address and length even though
- * I/O ports are not used to access Wide boards.
- * Instead the Wide boards are accessed with
- * PCI Memory Mapped I/O.
- */
- shp->io_port = iop;
- boardp->asc_n_io_port = iolen;
- shp->this_id = adv_dvc_varp->chip_scsi_id;
- /* Set maximum number of queues the adapter can handle. */
- shp->can_queue = adv_dvc_varp->max_host_qng;
- }
- /*
- * 'n_io_port' currently is one byte.
- *
- * Set a value to 'n_io_port', but never referenced it because
- * it may be truncated.
- */
- shp->n_io_port = boardp->asc_n_io_port <= 255 ?
- boardp->asc_n_io_port : 255;
- /*
- * Following v1.3.89, 'cmd_per_lun' is no longer needed
- * and should be set to zero.
- *
- * But because of a bug introduced in v1.3.89 if the driver is
- * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
- * SCSI function 'allocate_device' will panic. To allow the driver
- * to work as a module in these kernels set 'cmd_per_lun' to 1.
- */
- #ifdef MODULE
- shp->cmd_per_lun = 1;
- #else /* MODULE */
- shp->cmd_per_lun = 0;
- #endif /* MODULE */
- /*
- * Use the host 'select_queue_depths' function to determine
- * the number of commands to queue per device.
- */
- shp->select_queue_depths = advansys_select_queue_depths;
- /*
- * Set the maximum number of scatter-gather elements the
- * adapter can handle.
- */
- if (ASC_NARROW_BOARD(boardp)) {
- /*
- * Allow two commands with 'sg_tablesize' scatter-gather
- * elements to be executed simultaneously. This value is
- * the theoretical hardware limit. It may be decreased
- * below.
- */
- shp->sg_tablesize =
- (((asc_dvc_varp->max_total_qng - 2) / 2) *
- ASC_SG_LIST_PER_Q) + 1;
- } else {
- shp->sg_tablesize = ADV_MAX_SG_LIST;
- }
- /*
- * The value of 'sg_tablesize' can not exceed the SCSI
- * mid-level driver definition of SG_ALL. SG_ALL also
- * must not be exceeded, because it is used to define the
- * size of the scatter-gather table in 'struct asc_sg_head'.
- */
- if (shp->sg_tablesize > SG_ALL) {
- shp->sg_tablesize = SG_ALL;
- }
- ASC_DBG1(1, "advansys_detect: sg_tablesize: %dn",
- shp->sg_tablesize);
- /* BIOS start address. */
- if (ASC_NARROW_BOARD(boardp)) {
- #if ASC_LINUX_KERNEL24
- shp->base =
- #elif ASC_LINUX_KERNEL22
- shp->base = (char *)
- #endif
- ((ulong) AscGetChipBiosAddress(
- asc_dvc_varp->iop_base,
- asc_dvc_varp->bus_type));
- } else {
- /*
- * Fill-in BIOS board variables. The Wide BIOS saves
- * information in LRAM that is used by the driver.
- */
- AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_SIGNATURE,
- boardp->bios_signature);
- AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_VERSION,
- boardp->bios_version);
- AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODESEG,
- boardp->bios_codeseg);
- AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODELEN,
- boardp->bios_codelen);
- ASC_DBG2(1,
- "advansys_detect: bios_signature 0x%x, bios_version 0x%xn",
- boardp->bios_signature, boardp->bios_version);
- ASC_DBG2(1,
- "advansys_detect: bios_codeseg 0x%x, bios_codelen 0x%xn",
- boardp->bios_codeseg, boardp->bios_codelen);
- /*
- * If the BIOS saved a valid signature, then fill in
- * the BIOS code segment base address.
- */
- if (boardp->bios_signature == 0x55AA) {
- /*
- * Convert x86 realmode code segment to a linear
- * address by shifting left 4.
- */
- shp->base =
- #if ASC_LINUX_KERNEL22
- (char *)
- #endif
- ((ulong) boardp->bios_codeseg << 4);
- } else {
- shp->base = 0;
- }
- }
- /*
- * Register Board Resources - I/O Port, DMA, IRQ
- */
- /*
- * Register I/O port range.
- *
- * For Wide boards the I/O ports are not used to access
- * the board, but request the region anyway.
- *
- * 'shp->n_io_port' is not referenced, because it may be truncated.
- */
- ASC_DBG2(2,
- "advansys_detect: request_region port 0x%lx, len 0x%xn",
- (ulong) shp->io_port, boardp->asc_n_io_port);
- #if ASC_LINUX_KERNEL24
- if (request_region(shp->io_port, boardp->asc_n_io_port,
- "advansys") == NULL) {
- ASC_PRINT3(
- "advansys_detect: board %d: request_region() failed, port 0x%lx, len 0x%xn",
- boardp->id, (ulong) shp->io_port, boardp->asc_n_io_port);
- #ifdef CONFIG_PROC_FS
- kfree(boardp->prtbuf);
- #endif /* CONFIG_PROC_FS */
- scsi_unregister(shp);
- asc_board_count--;
- continue;
- }
- #elif ASC_LINUX_KERNEL22
- request_region(shp->io_port, boardp->asc_n_io_port, "advansys");
- #endif
- /* Register DMA Channel for Narrow boards. */
- shp->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
- #ifdef CONFIG_ISA
- if (ASC_NARROW_BOARD(boardp)) {
- /* Register DMA channel for ISA bus. */
- if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
- shp->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
- if ((ret =
- request_dma(shp->dma_channel, "advansys")) != 0) {
- ASC_PRINT3(
- "advansys_detect: board %d: request_dma() %d failed %dn",
- boardp->id, shp->dma_channel, ret);
- release_region(shp->io_port, boardp->asc_n_io_port);
- #ifdef CONFIG_PROC_FS
- kfree(boardp->prtbuf);
- #endif /* CONFIG_PROC_FS */
- scsi_unregister(shp);
- asc_board_count--;
- continue;
- }
- AscEnableIsaDma(shp->dma_channel);
- }
- }
- #endif /* CONFIG_ISA */
- /* Register IRQ Number. */
- ASC_DBG1(2, "advansys_detect: request_irq() %dn", shp->irq);
- /*
- * If request_irq() fails with the SA_INTERRUPT flag set,
- * then try again without the SA_INTERRUPT flag set. This
- * allows IRQ sharing to work even with other drivers that
- * do not set the SA_INTERRUPT flag.
- *
- * If SA_INTERRUPT is not set, then interrupts are enabled
- * before the driver interrupt function is called.
- */
- if (((ret = request_irq(shp->irq, advansys_interrupt,
- SA_INTERRUPT | (share_irq == TRUE ? SA_SHIRQ : 0),
- "advansys", boardp)) != 0) &&
- ((ret = request_irq(shp->irq, advansys_interrupt,
- (share_irq == TRUE ? SA_SHIRQ : 0),
- "advansys", boardp)) != 0))
- {
- if (ret == -EBUSY) {
- ASC_PRINT2(
- "advansys_detect: board %d: request_irq(): IRQ 0x%x already in use.n",
- boardp->id, shp->irq);
- } else if (ret == -EINVAL) {
- ASC_PRINT2(
- "advansys_detect: board %d: request_irq(): IRQ 0x%x not valid.n",
- boardp->id, shp->irq);
- } else {
- ASC_PRINT3(
- "advansys_detect: board %d: request_irq(): IRQ 0x%x failed with %dn",
- boardp->id, shp->irq, ret);
- }
- release_region(shp->io_port, boardp->asc_n_io_port);
- iounmap(boardp->ioremap_addr);
- if (shp->dma_channel != NO_ISA_DMA) {
- free_dma(shp->dma_channel);
- }
- #ifdef CONFIG_PROC_FS
- kfree(boardp->prtbuf);
- #endif /* CONFIG_PROC_FS */
- scsi_unregister(shp);
- asc_board_count--;
- continue;
- }
- /*
- * Initialize board RISC chip and enable interrupts.
- */
- if (ASC_NARROW_BOARD(boardp)) {
- ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()n");
- warn_code = AscInitAsc1000Driver(asc_dvc_varp);
- err_code = asc_dvc_varp->err_code;
- if (warn_code || err_code) {
- ASC_PRINT4(
- "advansys_detect: board %d error: init_state 0x%x, warn 0x%x, error 0x%xn",
- boardp->id, asc_dvc_varp->init_state,
- warn_code, err_code);
- }
- } else {
- ADV_CARR_T *carrp;
- int req_cnt;
- adv_req_t *reqp = NULL;
- int sg_cnt = 0;
- /*
- * Allocate buffer carrier structures. The total size
- * is about 4 KB, so allocate all at once.
- */
- carrp =
- (ADV_CARR_T *) kmalloc(ADV_CARRIER_BUFSIZE, GFP_ATOMIC);
- ASC_DBG1(1, "advansys_detect: carrp 0x%lxn", (ulong) carrp);
- if (carrp == NULL) {
- goto kmalloc_error;
- }
- /*
- * Allocate up to 'max_host_qng' request structures for
- * the Wide board. The total size is about 16 KB, so
- * allocate all at once. If the allocation fails decrement
- * and try again.
- */
- for (req_cnt = adv_dvc_varp->max_host_qng;
- req_cnt > 0; req_cnt--) {
- reqp = (adv_req_t *)
- kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC);
- ASC_DBG3(1,
- "advansys_detect: reqp 0x%lx, req_cnt %d, bytes %lun",
- (ulong) reqp, req_cnt,
- (ulong) sizeof(adv_req_t) * req_cnt);
- if (reqp != NULL) {
- break;
- }
- }
- if (reqp == NULL)
- {
- goto kmalloc_error;
- }
- /*
- * Allocate up to ADV_TOT_SG_BLOCK request structures for
- * the Wide board. Each structure is about 136 bytes.
- */
- boardp->adv_sgblkp = NULL;
- for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
- sgp = (adv_sgblk_t *)
- kmalloc(sizeof(adv_sgblk_t), GFP_ATOMIC);
- if (sgp == NULL) {
- break;
- }
- sgp->next_sgblkp = boardp->adv_sgblkp;
- boardp->adv_sgblkp = sgp;
- }
- ASC_DBG3(1,
- "advansys_detect: sg_cnt %d * %u = %u bytesn",
- sg_cnt, sizeof(adv_sgblk_t),
- (unsigned) (sizeof(adv_sgblk_t) * sg_cnt));
- /*
- * If no request structures or scatter-gather structures could
- * be allocated, then return an error. Otherwise continue with
- * initialization.
- */
- kmalloc_error:
- if (carrp == NULL)
- {
- ASC_PRINT1(
- "advansys_detect: board %d error: failed to kmalloc() carrier buffer.n",
- boardp->id);
- err_code = ADV_ERROR;
- } else if (reqp == NULL) {
- kfree(carrp);
- ASC_PRINT1(
- "advansys_detect: board %d error: failed to kmalloc() adv_req_t buffer.n",
- boardp->id);
- err_code = ADV_ERROR;
- } else if (boardp->adv_sgblkp == NULL) {
- kfree(carrp);
- kfree(reqp);
- ASC_PRINT1(
- "advansys_detect: board %d error: failed to kmalloc() adv_sgblk_t buffers.n",
- boardp->id);
- err_code = ADV_ERROR;
- } else {
- /* Save carrier buffer pointer. */
- boardp->orig_carrp = carrp;
- /*
- * Save original pointer for kfree() in case the
- * driver is built as a module and can be unloaded.
- */
- boardp->orig_reqp = reqp;
- adv_dvc_varp->carrier_buf = carrp;
- /*
- * Point 'adv_reqp' to the request structures and
- * link them together.
- */
- req_cnt--;
- reqp[req_cnt].next_reqp = NULL;
- for (; req_cnt > 0; req_cnt--) {
- reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
- }
- boardp->adv_reqp = &reqp[0];
- if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
- {
- ASC_DBG(2,
- "advansys_detect: AdvInitAsc3550Driver()n");
- warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
- } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
- ASC_DBG(2,
- "advansys_detect: AdvInitAsc38C0800Driver()n");
- warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp);
- } else {
- ASC_DBG(2,
- "advansys_detect: AdvInitAsc38C1600Driver()n");
- warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp);
- }
- err_code = adv_dvc_varp->err_code;
- if (warn_code || err_code) {
- ASC_PRINT3(
- "advansys_detect: board %d error: warn 0x%x, error 0x%xn",
- boardp->id, warn_code, err_code);
- }
- }
- }
- if (err_code != 0) {
- release_region(shp->io_port, boardp->asc_n_io_port);
- if (ASC_WIDE_BOARD(boardp)) {
- iounmap(boardp->ioremap_addr);
- if (boardp->orig_carrp) {
- kfree(boardp->orig_carrp);
- boardp->orig_carrp = NULL;
- }
- if (boardp->orig_reqp) {
- kfree(boardp->orig_reqp);
- boardp->orig_reqp = boardp->adv_reqp = NULL;
- }
- while ((sgp = boardp->adv_sgblkp) != NULL)
- {
- boardp->adv_sgblkp = sgp->next_sgblkp;
- kfree(sgp);
- }
- }
- if (shp->dma_channel != NO_ISA_DMA) {
- free_dma(shp->dma_channel);
- }
- #ifdef CONFIG_PROC_FS
- kfree(boardp->prtbuf);
- #endif /* CONFIG_PROC_FS */
- free_irq(shp->irq, boardp);
- scsi_unregister(shp);
- asc_board_count--;
- continue;
- }
- ASC_DBG_PRT_SCSI_HOST(2, shp);
- }
- }
- /*
- * XXX - Remove this comment and the next line when SCSI mid-level
- * no longer acquires 'io_request_lock' before calling the SCSI
- * low-level detect entrypoint.
- */
- ASC_LOCK_IO_REQUEST_LOCK
- ASC_DBG1(1, "advansys_detect: done: asc_board_count %dn", asc_board_count);
- return asc_board_count;
- }
- /*
- * advansys_release()
- *
- * Release resources allocated for a single AdvanSys adapter.
- */
- int
- advansys_release(struct Scsi_Host *shp)
- {
- asc_board_t *boardp;
- ASC_DBG(1, "advansys_release: beginn");
- boardp = ASC_BOARDP(shp);
- free_irq(shp->irq, boardp);
- if (shp->dma_channel != NO_ISA_DMA) {
- ASC_DBG(1, "advansys_release: free_dma()n");
- free_dma(shp->dma_channel);
- }
- release_region(shp->io_port, boardp->asc_n_io_port);
- if (ASC_WIDE_BOARD(boardp)) {
- adv_sgblk_t *sgp = NULL;
- iounmap(boardp->ioremap_addr);
- if (boardp->orig_carrp) {
- kfree(boardp->orig_carrp);
- boardp->orig_carrp = NULL;
- }
- if (boardp->orig_reqp) {
- kfree(boardp->orig_reqp);
- boardp->orig_reqp = boardp->adv_reqp = NULL;
- }
- while ((sgp = boardp->adv_sgblkp) != NULL)
- {
- boardp->adv_sgblkp = sgp->next_sgblkp;
- kfree(sgp);
- }
- }
- #ifdef CONFIG_PROC_FS
- ASC_ASSERT(boardp->prtbuf != NULL);
- kfree(boardp->prtbuf);
- #endif /* CONFIG_PROC_FS */
- scsi_unregister(shp);
- ASC_DBG(1, "advansys_release: endn");
- return 0;
- }
- /*
- * advansys_info()
- *
- * Return suitable for printing on the console with the argument
- * adapter's configuration information.
- *
- * Note: The information line should not exceed ASC_INFO_SIZE bytes,
- * otherwise the static 'info' array will be overrun.
- */
- const char *
- advansys_info(struct Scsi_Host *shp)
- {
- static char info[ASC_INFO_SIZE];
- asc_board_t *boardp;
- ASC_DVC_VAR *asc_dvc_varp;
- ADV_DVC_VAR *adv_dvc_varp;
- char *busname;
- int iolen;
- char *widename = NULL;
- boardp = ASC_BOARDP(shp);
- if (ASC_NARROW_BOARD(boardp)) {
- asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
- ASC_DBG(1, "advansys_info: beginn");
- if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
- if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == ASC_IS_ISAPNP) {
- busname = "ISA PnP";
- } else {
- busname = "ISA";
- }
- /* Don't reference 'shp->n_io_port'; It may be truncated. */
- sprintf(info,
- "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
- ASC_VERSION, busname,
- (ulong) shp->io_port,
- (ulong) shp->io_port + boardp->asc_n_io_port - 1,
- shp->irq, shp->dma_channel);
- } else {
- if (asc_dvc_varp->bus_type & ASC_IS_VL) {
- busname = "VL";
- } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
- busname = "EISA";
- } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
- if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
- == ASC_IS_PCI_ULTRA) {
- busname = "PCI Ultra";
- } else {
- busname = "PCI";
- }
- } else {
- busname = "?";
- ASC_PRINT2( "advansys_info: board %d: unknown bus type %dn",
- boardp->id, asc_dvc_varp->bus_type);
- }
- /* Don't reference 'shp->n_io_port'; It may be truncated. */
- sprintf(info,
- "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
- ASC_VERSION, busname,
- (ulong) shp->io_port,
- (ulong) shp->io_port + boardp->asc_n_io_port - 1,
- shp->irq);
- }
- } else {
- /*
- * Wide Adapter Information
- *
- * Memory-mapped I/O is used instead of I/O space to access
- * the adapter, but display the I/O Port range. The Memory
- * I/O address is displayed through the driver /proc file.
- */
- adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
- if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550)
- {
- iolen = ADV_3550_IOLEN;
- widename = "Ultra-Wide";
- } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800)
- {
- iolen = ADV_38C0800_IOLEN;
- widename = "Ultra2-Wide";
- } else
- {
- iolen = ADV_38C1600_IOLEN;
- widename = "Ultra3-Wide";
- }
- sprintf(info, "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
- ASC_VERSION,
- widename,
- (ulong) adv_dvc_varp->iop_base,
- (ulong) adv_dvc_varp->iop_base + iolen - 1,
- shp->irq);
- }
- ASC_ASSERT(strlen(info) < ASC_INFO_SIZE);
- ASC_DBG(1, "advansys_info: endn");
- return info;
- }
- /*
- * advansys_queuecommand() - interrupt-driven I/O entrypoint.
- *
- * This function always returns 0. Command return status is saved
- * in the 'scp' result field.
- */
- int
- advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
- {
- struct Scsi_Host *shp;
- asc_board_t *boardp;
- ulong flags;
- Scsi_Cmnd *done_scp;
- shp = scp->host;
- boardp = ASC_BOARDP(shp);
- ASC_STATS(shp, queuecommand);
- /*
- * XXX - Remove this comment and the next line when SCSI mid-level
- * no longer acquires 'io_request_lock' before calling the SCSI
- * low-level queuecommand entrypoint.
- */
- ASC_UNLOCK_IO_REQUEST_LOCK
- spin_lock_irqsave(&boardp->lock, flags);
- /*
- * Block new commands while handling a reset or abort request.
- */
- if (boardp->flags & ASC_HOST_IN_RESET) {
- ASC_DBG1(1,
- "advansys_queuecommand: scp 0x%lx blocked for reset requestn",
- (ulong) scp);
- scp->result = HOST_BYTE(DID_RESET);
- /*
- * Add blocked requests to the board's 'done' queue. The queued
- * requests will be completed at the end of the abort or reset
- * handling.
- */
- asc_enqueue(&boardp->done, scp, ASC_BACK);
- spin_unlock_irqrestore(&boardp->lock, flags);
- return 0;
- }
- /*
- * Attempt to execute any waiting commands for the board.
- */
- if (!ASC_QUEUE_EMPTY(&boardp->waiting)) {
- ASC_DBG(1,
- "advansys_queuecommand: before asc_execute_queue() waitingn");
- asc_execute_queue(&boardp->waiting);
- }
- /*
- * Save the function pointer to Linux mid-level 'done' function
- * and attempt to execute the command.
- *
- * If ASC_NOERROR is returned the request has been added to the
- * board's 'active' queue and will be completed by the interrupt
- * handler.
- *
- * If ASC_BUSY is returned add the request to the board's per
- * target waiting list. This is the first time the request has
- * been tried. Add it to the back of the waiting list. It will be
- * retried later.
- *
- * If an error occurred, the request will have been placed on the
- * board's 'done' queue and must be completed before returning.
- */
- scp->scsi_done = done;
- switch (asc_execute_scsi_cmnd(scp)) {
- case ASC_NOERROR:
- break;
- case ASC_BUSY:
- asc_enqueue(&boardp->waiting, scp, ASC_BACK);
- break;
- case ASC_ERROR:
- default:
- done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
- /* Interrupts could be enabled here. */
- asc_scsi_done_list(done_scp);
- break;
- }
- spin_unlock_irqrestore(&boardp->lock, flags);
- /*
- * XXX - Remove this comment and the next line when SCSI mid-level
- * no longer acquires 'io_request_lock' before calling the SCSI
- * low-level queuecommand entrypoint.
- */
- ASC_LOCK_IO_REQUEST_LOCK
- return 0;
- }
- /*
- * advansys_reset()
- *
- * Reset the bus associated with the command 'scp'.
- *
- * This function runs its own thread. Interrupts must be blocked but
- * sleeping is allowed and no locking other than for host structures is
- * required. Returns SUCCESS or FAILED.
- */
- int
- advansys_reset(Scsi_Cmnd *scp)
- {
- struct Scsi_Host *shp;
- asc_board_t *boardp;
- ASC_DVC_VAR *asc_dvc_varp;
- ADV_DVC_VAR *adv_dvc_varp;
- ulong flags;
- Scsi_Cmnd *done_scp = NULL, *last_scp = NULL;
- Scsi_Cmnd *tscp, *new_last_scp;
- int status;
- int ret = SUCCESS;
- ASC_DBG1(1, "advansys_reset: 0x%lxn", (ulong) scp);
- #ifdef ADVANSYS_STATS
- if (scp->host != NULL) {
- ASC_STATS(scp->host, reset);
- }
- #endif /* ADVANSYS_STATS */
- if ((shp = scp->host) == NULL) {
- scp->result = HOST_BYTE(DID_ERROR);
- return FAILED;
- }
- boardp = ASC_BOARDP(shp);
- ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...n",
- boardp->id);
- /*
- * Check for re-entrancy.
- */
- spin_lock_irqsave(&boardp->lock, flags);
- if (boardp->flags & ASC_HOST_IN_RESET) {
- spin_unlock_irqrestore(&boardp->lock, flags);
- return FAILED;
- }
- boardp->flags |= ASC_HOST_IN_RESET;
- spin_unlock_irqrestore(&boardp->lock, flags);
- /*
- * XXX - Remove this comment and the next line when SCSI mid-level
- * no longer acquires 'io_request_lock' before calling the SCSI
- * low-level reset entrypoint.
- */
- ASC_UNLOCK_IO_REQUEST_LOCK
- if (ASC_NARROW_BOARD(boardp)) {
- /*
- * Narrow Board
- */
- asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
- /*
- * Reset the chip and SCSI bus.
- */
- ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()n");
- status = AscInitAsc1000Driver(asc_dvc_varp);
- /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
- if (asc_dvc_varp->err_code) {
- ASC_PRINT2(
- "advansys_reset: board %d: SCSI bus reset error: 0x%xn",
- boardp->id, asc_dvc_varp->err_code);
- ret = FAILED;
- } else if (status) {
- ASC_PRINT2(
- "advansys_reset: board %d: SCSI bus reset warning: 0x%xn",
- boardp->id, status);
- } else {
- ASC_PRINT1(
- "advansys_reset: board %d: SCSI bus reset successful.n",
- boardp->id);
- }
- ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()n");
- /*
- * Acquire the board lock.
- */
- spin_lock_irqsave(&boardp->lock, flags);
- } else {
- /*
- * Wide Board
- *
- * If the suggest reset bus flags are set, then reset the bus.
- * Otherwise only reset the device.
- */
- adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
- /*
- * Reset the target's SCSI bus.
- */
- ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()n");
- switch (AdvResetChipAndSB(adv_dvc_varp)) {
- case ASC_TRUE:
- ASC_PRINT1("advansys_reset: board %d: SCSI bus reset successful.n",
- boardp->id);
- break;
- case ASC_FALSE:
- default:
- ASC_PRINT1("advansys_reset: board %d: SCSI bus reset error.n",
- boardp->id);
- ret = FAILED;
- break;
- }
- /*
- * Acquire the board lock and ensure all requests completed by the
- * microcode have been processed by calling AdvISR().
- */
- spin_lock_irqsave(&boardp->lock, flags);
- (void) AdvISR(adv_dvc_varp);
- }
- /* Board lock is held. */
- /*
- * Dequeue all board 'done' requests. A pointer to the last request
- * is returned in 'last_scp'.
- */
- done_scp = asc_dequeue_list(&boardp->done, &last_scp, ASC_TID_ALL);
- /*
- * Dequeue all board 'active' requests for all devices and set
- * the request status to DID_RESET. A pointer to the last request
- * is returned in 'last_scp'.
- */
- if (done_scp == NULL) {
- done_scp = asc_dequeue_list(&boardp->active, &last_scp, ASC_TID_ALL);
- for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
- tscp->result = HOST_BYTE(DID_RESET);
- }
- } else {
- /* Append to 'done_scp' at the end with 'last_scp'. */
- ASC_ASSERT(last_scp != NULL);
- REQPNEXT(last_scp) = asc_dequeue_list(&boardp->active,
- &new_last_scp, ASC_TID_ALL);
- if (new_last_scp != NULL) {
- ASC_ASSERT(REQPNEXT(last_scp) != NULL);
- for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) {
- tscp->result = HOST_BYTE(DID_RESET);
- }
- last_scp = new_last_scp;
- }
- }
- /*
- * Dequeue all 'waiting' requests and set the request status
- * to DID_RESET.
- */
- if (done_scp == NULL) {
- done_scp = asc_dequeue_list(&boardp->waiting, &last_scp, ASC_TID_ALL);
- for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) {
- tscp->result = HOST_BYTE(DID_RESET);
- }
- } else {
- /* Append to 'done_scp' at the end with 'last_scp'. */
- ASC_ASSERT(last_scp != NULL);
- REQPNEXT(last_scp) = asc_dequeue_list(&boardp->waiting,
- &new_last_scp, ASC_TID_ALL);
- if (new_last_scp != NULL) {
- ASC_ASSERT(REQPNEXT(last_scp) != NULL);
- for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) {
- tscp->result = HOST_BYTE(DID_RESET);
- }
- last_scp = new_last_scp;
- }
- }
- /* Save the time of the most recently completed reset. */
- boardp->last_reset = jiffies;
- /* Clear reset flag. */
- boardp->flags &= ~ASC_HOST_IN_RESET;
- /* Release the board. */
- spin_unlock_irqrestore(&boardp->lock, flags);
- /*
- * Complete all the 'done_scp' requests.
- */
- if (done_scp != NULL) {
- asc_scsi_done_list(done_scp);
- }
- /*
- * XXX - Remove this comment and the next line when SCSI mid-level
- * no longer acquires 'io_request_lock' before calling the SCSI
- * low-level reset entrypoint.
- */
- ASC_LOCK_IO_REQUEST_LOCK
- ASC_DBG1(1, "advansys_reset: ret %dn", ret);
- return ret;
- }
- /*
- * advansys_biosparam()
- *
- * Translate disk drive geometry if the "BIOS greater than 1 GB"
- * support is enabled for a drive.
- *
- * ip (information pointer) is an int array with the following definition:
- * ip[0]: heads
- * ip[1]: sectors
- * ip[2]: cylinders
- */
- int
- advansys_biosparam(Disk *dp, kdev_t dep, int ip[])
- {
- asc_board_t *boardp;
- ASC_DBG(1, "advansys_biosparam: beginn");
- ASC_STATS(dp->device->host, biosparam);
- boardp = ASC_BOARDP(dp->device->host);
- if (ASC_NARROW_BOARD(boardp)) {
- if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
- ASC_CNTL_BIOS_GT_1GB) && dp->capacity > 0x200000) {
- ip[0] = 255;
- ip[1] = 63;
- } else {
- ip[0] = 64;
- ip[1] = 32;
- }
- } else {
- if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
- BIOS_CTRL_EXTENDED_XLAT) && dp->capacity > 0x200000) {
- ip[0] = 255;
- ip[1] = 63;
- } else {
- ip[0] = 64;
- ip[1] = 32;
- }
- }
- ip[2] = dp->capacity / (ip[0] * ip[1]);
- ASC_DBG(1, "advansys_biosparam: endn");
- return 0;
- }
- /*
- * advansys_setup()