📄 qla1280.c
字号:
#define pci_dma_lo32(a) (a & 0xffffffff)#define NVRAM_DELAY() udelay(500) /* 2 microseconds */#if defined(__ia64__) && !defined(ia64_platform_is)#define ia64_platform_is(foo) (!strcmp(x, platform_name))#endif#define IS_ISP1040(ha) (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1020)#define IS_ISP1x40(ha) (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1020 || \ ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1240)#define IS_ISP1x160(ha) (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160 || \ ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160)static int qla1280_probe_one(struct pci_dev *, const struct pci_device_id *);static void qla1280_remove_one(struct pci_dev *);/* * QLogic Driver Support Function Prototypes. */static void qla1280_done(struct scsi_qla_host *);static int qla1280_get_token(char *);static int qla1280_setup(char *s) __init;/* * QLogic ISP1280 Hardware Support Function Prototypes. */static int qla1280_load_firmware(struct scsi_qla_host *);static int qla1280_init_rings(struct scsi_qla_host *);static int qla1280_nvram_config(struct scsi_qla_host *);static int qla1280_mailbox_command(struct scsi_qla_host *, uint8_t, uint16_t *);static int qla1280_bus_reset(struct scsi_qla_host *, int);static int qla1280_device_reset(struct scsi_qla_host *, int, int);static int qla1280_abort_device(struct scsi_qla_host *, int, int, int);static int qla1280_abort_command(struct scsi_qla_host *, struct srb *, int);static int qla1280_abort_isp(struct scsi_qla_host *);#ifdef QLA_64BIT_PTRstatic int qla1280_64bit_start_scsi(struct scsi_qla_host *, struct srb *);#elsestatic int qla1280_32bit_start_scsi(struct scsi_qla_host *, struct srb *);#endifstatic void qla1280_nv_write(struct scsi_qla_host *, uint16_t);static void qla1280_poll(struct scsi_qla_host *);static void qla1280_reset_adapter(struct scsi_qla_host *);static void qla1280_marker(struct scsi_qla_host *, int, int, int, u8);static void qla1280_isp_cmd(struct scsi_qla_host *);static void qla1280_isr(struct scsi_qla_host *, struct list_head *);static void qla1280_rst_aen(struct scsi_qla_host *);static void qla1280_status_entry(struct scsi_qla_host *, struct response *, struct list_head *);static void qla1280_error_entry(struct scsi_qla_host *, struct response *, struct list_head *);static uint16_t qla1280_get_nvram_word(struct scsi_qla_host *, uint32_t);static uint16_t qla1280_nvram_request(struct scsi_qla_host *, uint32_t);static uint16_t qla1280_debounce_register(volatile uint16_t __iomem *);static request_t *qla1280_req_pkt(struct scsi_qla_host *);static int qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *, unsigned int);static void qla1280_get_target_parameters(struct scsi_qla_host *, struct scsi_device *);static int qla1280_set_target_parameters(struct scsi_qla_host *, int, int);static struct qla_driver_setup driver_setup;/* * convert scsi data direction to request_t control flags */static inline uint16_tqla1280_data_direction(struct scsi_cmnd *cmnd){ switch(cmnd->sc_data_direction) { case DMA_FROM_DEVICE: return BIT_5; case DMA_TO_DEVICE: return BIT_6; case DMA_BIDIRECTIONAL: return BIT_5 | BIT_6; /* * We could BUG() on default here if one of the four cases aren't * met, but then again if we receive something like that from the * SCSI layer we have more serious problems. This shuts up GCC. */ case DMA_NONE: default: return 0; }} #if DEBUG_QLA1280static void __qla1280_print_scsi_cmd(struct scsi_cmnd * cmd);static void __qla1280_dump_buffer(char *, int);#endif/* * insmod needs to find the variable and make it point to something */#ifdef MODULEstatic char *qla1280;/* insmod qla1280 options=verbose" */module_param(qla1280, charp, 0);#else__setup("qla1280=", qla1280_setup);#endif/* * We use the scsi_pointer structure that's included with each scsi_command * to overlay our struct srb over it. qla1280_init() checks that a srb is not * bigger than a scsi_pointer. */#define CMD_SP(Cmnd) &Cmnd->SCp#define CMD_CDBLEN(Cmnd) Cmnd->cmd_len#define CMD_CDBP(Cmnd) Cmnd->cmnd#define CMD_SNSP(Cmnd) Cmnd->sense_buffer#define CMD_SNSLEN(Cmnd) sizeof(Cmnd->sense_buffer)#define CMD_RESULT(Cmnd) Cmnd->result#define CMD_HANDLE(Cmnd) Cmnd->host_scribble#define CMD_REQUEST(Cmnd) Cmnd->request->cmd#define CMD_HOST(Cmnd) Cmnd->device->host#define SCSI_BUS_32(Cmnd) Cmnd->device->channel#define SCSI_TCN_32(Cmnd) Cmnd->device->id#define SCSI_LUN_32(Cmnd) Cmnd->device->lun/*****************************************//* ISP Boards supported by this driver *//*****************************************/struct qla_boards { unsigned char name[9]; /* Board ID String */ int numPorts; /* Number of SCSI ports */ unsigned short *fwcode; /* pointer to FW array */ unsigned short *fwlen; /* number of words in array */ unsigned short *fwstart; /* start address for F/W */ unsigned char *fwver; /* Ptr to F/W version array */};/* NOTE: the last argument in each entry is used to index ql1280_board_tbl */static struct pci_device_id qla1280_pci_tbl[] = { {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP12160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1080, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1280, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, {PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP10160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, {0,}};MODULE_DEVICE_TABLE(pci, qla1280_pci_tbl);static struct qla_boards ql1280_board_tbl[] = { /* Name , Number of ports, FW details */ {"QLA12160", 2, &fw12160i_code01[0], &fw12160i_length01, &fw12160i_addr01, &fw12160i_version_str[0]}, {"QLA1040", 1, &risc_code01[0], &risc_code_length01, &risc_code_addr01, &firmware_version[0]}, {"QLA1080", 1, &fw1280ei_code01[0], &fw1280ei_length01, &fw1280ei_addr01, &fw1280ei_version_str[0]}, {"QLA1240", 2, &fw1280ei_code01[0], &fw1280ei_length01, &fw1280ei_addr01, &fw1280ei_version_str[0]}, {"QLA1280", 2, &fw1280ei_code01[0], &fw1280ei_length01, &fw1280ei_addr01, &fw1280ei_version_str[0]}, {"QLA10160", 1, &fw12160i_code01[0], &fw12160i_length01, &fw12160i_addr01, &fw12160i_version_str[0]}, {" ", 0}};static int qla1280_verbose = 1;#if DEBUG_QLA1280static int ql_debug_level = 1;#define dprintk(level, format, a...) \ do { if (ql_debug_level >= level) printk(KERN_ERR format, ##a); } while(0)#define qla1280_dump_buffer(level, buf, size) \ if (ql_debug_level >= level) __qla1280_dump_buffer(buf, size)#define qla1280_print_scsi_cmd(level, cmd) \ if (ql_debug_level >= level) __qla1280_print_scsi_cmd(cmd)#else#define ql_debug_level 0#define dprintk(level, format, a...) do{}while(0)#define qla1280_dump_buffer(a, b, c) do{}while(0)#define qla1280_print_scsi_cmd(a, b) do{}while(0)#endif#define ENTER(x) dprintk(3, "qla1280 : Entering %s()\n", x);#define LEAVE(x) dprintk(3, "qla1280 : Leaving %s()\n", x);#define ENTER_INTR(x) dprintk(4, "qla1280 : Entering %s()\n", x);#define LEAVE_INTR(x) dprintk(4, "qla1280 : Leaving %s()\n", x);static int qla1280_read_nvram(struct scsi_qla_host *ha){ uint16_t *wptr; uint8_t chksum; int cnt, i; struct nvram *nv; ENTER("qla1280_read_nvram"); if (driver_setup.no_nvram) return 1; printk(KERN_INFO "scsi(%ld): Reading NVRAM\n", ha->host_no); wptr = (uint16_t *)&ha->nvram; nv = &ha->nvram; chksum = 0; for (cnt = 0; cnt < 3; cnt++) { *wptr = qla1280_get_nvram_word(ha, cnt); chksum += *wptr & 0xff; chksum += (*wptr >> 8) & 0xff; wptr++; } if (nv->id0 != 'I' || nv->id1 != 'S' || nv->id2 != 'P' || nv->id3 != ' ' || nv->version < 1) { dprintk(2, "Invalid nvram ID or version!\n"); chksum = 1; } else { for (; cnt < sizeof(struct nvram); cnt++) { *wptr = qla1280_get_nvram_word(ha, cnt); chksum += *wptr & 0xff; chksum += (*wptr >> 8) & 0xff; wptr++; } } dprintk(3, "qla1280_read_nvram: NVRAM Magic ID= %c %c %c %02x" " version %i\n", nv->id0, nv->id1, nv->id2, nv->id3, nv->version); if (chksum) { if (!driver_setup.no_nvram) printk(KERN_WARNING "scsi(%ld): Unable to identify or " "validate NVRAM checksum, using default " "settings\n", ha->host_no); ha->nvram_valid = 0; } else ha->nvram_valid = 1; /* The firmware interface is, um, interesting, in that the * actual firmware image on the chip is little endian, thus, * the process of taking that image to the CPU would end up * little endian. However, the firmare interface requires it * to be read a word (two bytes) at a time. * * The net result of this would be that the word (and * doubleword) quantites in the firmware would be correct, but * the bytes would be pairwise reversed. Since most of the * firmware quantites are, in fact, bytes, we do an extra * le16_to_cpu() in the firmware read routine. * * The upshot of all this is that the bytes in the firmware * are in the correct places, but the 16 and 32 bit quantites * are still in little endian format. We fix that up below by * doing extra reverses on them */ nv->isp_parameter = cpu_to_le16(nv->isp_parameter); nv->firmware_feature.w = cpu_to_le16(nv->firmware_feature.w); for(i = 0; i < MAX_BUSES; i++) { nv->bus[i].selection_timeout = cpu_to_le16(nv->bus[i].selection_timeout); nv->bus[i].max_queue_depth = cpu_to_le16(nv->bus[i].max_queue_depth); } dprintk(1, "qla1280_read_nvram: Completed Reading NVRAM\n"); LEAVE("qla1280_read_nvram"); return chksum;}/************************************************************************** * qla1280_info * Return a string describing the driver. **************************************************************************/static const char *qla1280_info(struct Scsi_Host *host){ static char qla1280_scsi_name_buffer[125]; char *bp; struct scsi_qla_host *ha; struct qla_boards *bdp; bp = &qla1280_scsi_name_buffer[0]; ha = (struct scsi_qla_host *)host->hostdata; bdp = &ql1280_board_tbl[ha->devnum]; memset(bp, 0, sizeof(qla1280_scsi_name_buffer)); sprintf (bp, "QLogic %s PCI to SCSI Host Adapter\n" " Firmware version: %2d.%02d.%02d, Driver version %s", &bdp->name[0], bdp->fwver[0], bdp->fwver[1], bdp->fwver[2], QLA1280_VERSION); return bp;}/************************************************************************** * qla1200_queuecommand * Queue a command to the controller. * * Note: * The mid-level driver tries to ensures that queuecommand never gets invoked * concurrently with itself or the interrupt handler (although the * interrupt handler may call this routine as part of request-completion * handling). Unfortunely, it sometimes calls the scheduler in interrupt * context which is a big NO! NO!. **************************************************************************/static intqla1280_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *)){ struct Scsi_Host *host = cmd->device->host; struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata; struct srb *sp = (struct srb *)&cmd->SCp; int status; cmd->scsi_done = fn; sp->cmd = cmd; sp->flags = 0; qla1280_print_scsi_cmd(5, cmd);#ifdef QLA_64BIT_PTR /* * Using 64 bit commands if the PCI bridge doesn't support it is a * bit wasteful, however this should really only happen if one's * PCI controller is completely broken, like the BCM1250. For * sane hardware this is not an issue. */ status = qla1280_64bit_start_scsi(ha, sp);#else status = qla1280_32bit_start_scsi(ha, sp);#endif return status;}enum action { ABORT_COMMAND, ABORT_DEVICE, DEVICE_RESET, BUS_RESET, ADAPTER_RESET, FAIL};/* timer action for error action processor */static void qla1280_error_wait_timeout(unsigned long __data){ struct scsi_cmnd *cmd = (struct scsi_cmnd *)__data; struct srb *sp = (struct srb *)CMD_SP(cmd); complete(sp->wait);}static void qla1280_mailbox_timeout(unsigned long __data){ struct scsi_qla_host *ha = (struct scsi_qla_host *)__data; struct device_reg __iomem *reg; reg = ha->iobase; ha->mailbox_out[0] = RD_REG_WORD(®->mailbox0); printk(KERN_ERR "scsi(%ld): mailbox timed out, mailbox0 %04x, " "ictrl %04x, istatus %04x\n", ha->host_no, ha->mailbox_out[0], RD_REG_WORD(®->ictrl), RD_REG_WORD(®->istatus)); complete(ha->mailbox_wait);}/************************************************************************** * qla1200_error_action * The function will attempt to perform a specified error action and * wait for the results (or time out). * * Input: * cmd = Linux SCSI command packet of the command that cause the * bus reset. * action = error action to take (see action_t) * * Returns: * SUCCESS or FAILED * * Note: * Resetting the bus always succeeds - is has to, otherwise the * kernel will panic! Try a surgical technique - sending a BUS * DEVICE RESET message - on the offending target before pulling * the SCSI bus reset line. **************************************************************************/static intqla1280_error_action(struct scsi_cmnd *cmd, enum action action){ struct scsi_qla_host *ha; int bus, target, lun; struct srb *sp; uint16_t data; unsigned char *handle; int result, i; DECLARE_COMPLETION_ONSTACK(wait); struct timer_list timer; ha = (struct scsi_qla_host *)(CMD_HOST(cmd)->hostdata);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -