📄 qla1280.c
字号:
if (qla1280_check_for_dead_scsi_bus(ha, bus)) return 1; if (device->tagged_supported && (ha->bus_settings[bus].qtag_enables & (BIT_0 << target))) { scsi_adjust_queue_depth(device, MSG_ORDERED_TAG, ha->bus_settings[bus].hiwat); } else { scsi_adjust_queue_depth(device, 0, default_depth); } nv->bus[bus].target[target].parameter.enable_sync = device->sdtr; nv->bus[bus].target[target].parameter.enable_wide = device->wdtr; nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = device->ppr; if (driver_setup.no_sync || (driver_setup.sync_mask && (~driver_setup.sync_mask & (1 << target)))) nv->bus[bus].target[target].parameter.enable_sync = 0; if (driver_setup.no_wide || (driver_setup.wide_mask && (~driver_setup.wide_mask & (1 << target)))) nv->bus[bus].target[target].parameter.enable_wide = 0; if (IS_ISP1x160(ha)) { if (driver_setup.no_ppr || (driver_setup.ppr_mask && (~driver_setup.ppr_mask & (1 << target)))) nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 0; } spin_lock_irqsave(ha->host->host_lock, flags); if (nv->bus[bus].target[target].parameter.enable_sync) status = qla1280_set_target_parameters(ha, bus, target); qla1280_get_target_parameters(ha, device); spin_unlock_irqrestore(ha->host->host_lock, flags); return status;}/* * qla1280_done * Process completed commands. * * Input: * ha = adapter block pointer. */static voidqla1280_done(struct scsi_qla_host *ha){ struct srb *sp; struct list_head *done_q; int bus, target, lun; struct scsi_cmnd *cmd; ENTER("qla1280_done"); done_q = &ha->done_q; while (!list_empty(done_q)) { sp = list_entry(done_q->next, struct srb, list); list_del(&sp->list); cmd = sp->cmd; bus = SCSI_BUS_32(cmd); target = SCSI_TCN_32(cmd); lun = SCSI_LUN_32(cmd); switch ((CMD_RESULT(cmd) >> 16)) { case DID_RESET: /* Issue marker command. */ qla1280_marker(ha, bus, target, 0, MK_SYNC_ID); break; case DID_ABORT: sp->flags &= ~SRB_ABORT_PENDING; sp->flags |= SRB_ABORTED; if (sp->flags & SRB_TIMEOUT) CMD_RESULT(sp->cmd) = DID_TIME_OUT << 16; break; default: break; } /* Release memory used for this I/O */ scsi_dma_unmap(cmd); /* Call the mid-level driver interrupt handler */ CMD_HANDLE(sp->cmd) = (unsigned char *)INVALID_HANDLE; ha->actthreads--; (*(cmd)->scsi_done)(cmd); if(sp->wait != NULL) complete(sp->wait); } LEAVE("qla1280_done");}/* * Translates a ISP error to a Linux SCSI error */static intqla1280_return_status(struct response * sts, struct scsi_cmnd *cp){ int host_status = DID_ERROR; uint16_t comp_status = le16_to_cpu(sts->comp_status); uint16_t state_flags = le16_to_cpu(sts->state_flags); uint32_t residual_length = le32_to_cpu(sts->residual_length); uint16_t scsi_status = le16_to_cpu(sts->scsi_status);#if DEBUG_QLA1280_INTR static char *reason[] = { "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR" };#endif /* DEBUG_QLA1280_INTR */ ENTER("qla1280_return_status");#if DEBUG_QLA1280_INTR /* dprintk(1, "qla1280_return_status: compl status = 0x%04x\n", comp_status); */#endif switch (comp_status) { case CS_COMPLETE: host_status = DID_OK; break; case CS_INCOMPLETE: if (!(state_flags & SF_GOT_BUS)) host_status = DID_NO_CONNECT; else if (!(state_flags & SF_GOT_TARGET)) host_status = DID_BAD_TARGET; else if (!(state_flags & SF_SENT_CDB)) host_status = DID_ERROR; else if (!(state_flags & SF_TRANSFERRED_DATA)) host_status = DID_ERROR; else if (!(state_flags & SF_GOT_STATUS)) host_status = DID_ERROR; else if (!(state_flags & SF_GOT_SENSE)) host_status = DID_ERROR; break; case CS_RESET: host_status = DID_RESET; break; case CS_ABORTED: host_status = DID_ABORT; break; case CS_TIMEOUT: host_status = DID_TIME_OUT; break; case CS_DATA_OVERRUN: dprintk(2, "Data overrun 0x%x\n", residual_length); dprintk(2, "qla1280_return_status: response packet data\n"); qla1280_dump_buffer(2, (char *)sts, RESPONSE_ENTRY_SIZE); host_status = DID_ERROR; break; case CS_DATA_UNDERRUN: if ((scsi_bufflen(cp) - residual_length) < cp->underflow) { printk(KERN_WARNING "scsi: Underflow detected - retrying " "command.\n"); host_status = DID_ERROR; } else { scsi_set_resid(cp, residual_length); host_status = DID_OK; } break; default: host_status = DID_ERROR; break; }#if DEBUG_QLA1280_INTR dprintk(1, "qla1280 ISP status: host status (%s) scsi status %x\n", reason[host_status], scsi_status);#endif LEAVE("qla1280_return_status"); return (scsi_status & 0xff) | (host_status << 16);}/****************************************************************************//* QLogic ISP1280 Hardware Support Functions. *//****************************************************************************//* * qla1280_initialize_adapter * Initialize board. * * Input: * ha = adapter block pointer. * * Returns: * 0 = success */static int __devinitqla1280_initialize_adapter(struct scsi_qla_host *ha){ struct device_reg __iomem *reg; int status; int bus; unsigned long flags; ENTER("qla1280_initialize_adapter"); /* Clear adapter flags. */ ha->flags.online = 0; ha->flags.disable_host_adapter = 0; ha->flags.reset_active = 0; ha->flags.abort_isp_active = 0;#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) if (ia64_platform_is("sn2")) { printk(KERN_INFO "scsi(%li): Enabling SN2 PCI DMA " "dual channel lockup workaround\n", ha->host_no); ha->flags.use_pci_vchannel = 1; driver_setup.no_nvram = 1; }#endif /* TODO: implement support for the 1040 nvram format */ if (IS_ISP1040(ha)) driver_setup.no_nvram = 1; dprintk(1, "Configure PCI space for adapter...\n"); reg = ha->iobase; /* Insure mailbox registers are free. */ WRT_REG_WORD(®->semaphore, 0); WRT_REG_WORD(®->host_cmd, HC_CLR_RISC_INT); WRT_REG_WORD(®->host_cmd, HC_CLR_HOST_INT); RD_REG_WORD(®->host_cmd); if (qla1280_read_nvram(ha)) { dprintk(2, "qla1280_initialize_adapter: failed to read " "NVRAM\n"); } /* * It's necessary to grab the spin here as qla1280_mailbox_command * needs to be able to drop the lock unconditionally to wait * for completion. */ spin_lock_irqsave(ha->host->host_lock, flags); status = qla1280_load_firmware(ha); if (status) { printk(KERN_ERR "scsi(%li): initialize: pci probe failed!\n", ha->host_no); goto out; } /* Setup adapter based on NVRAM parameters. */ dprintk(1, "scsi(%ld): Configure NVRAM parameters\n", ha->host_no); qla1280_nvram_config(ha); if (ha->flags.disable_host_adapter) { status = 1; goto out; } status = qla1280_init_rings(ha); if (status) goto out; /* Issue SCSI reset, if we can't reset twice then bus is dead */ for (bus = 0; bus < ha->ports; bus++) { if (!ha->bus_settings[bus].disable_scsi_reset && qla1280_bus_reset(ha, bus) && qla1280_bus_reset(ha, bus)) ha->bus_settings[bus].scsi_bus_dead = 1; } ha->flags.online = 1; out: spin_unlock_irqrestore(ha->host->host_lock, flags); if (status) dprintk(2, "qla1280_initialize_adapter: **** FAILED ****\n"); LEAVE("qla1280_initialize_adapter"); return status;}/* * Chip diagnostics * Test chip for proper operation. * * Input: * ha = adapter block pointer. * * Returns: * 0 = success. */static intqla1280_chip_diag(struct scsi_qla_host *ha){ uint16_t mb[MAILBOX_REGISTER_COUNT]; struct device_reg __iomem *reg = ha->iobase; int status = 0; int cnt; uint16_t data; dprintk(3, "qla1280_chip_diag: testing device at 0x%p \n", ®->id_l); dprintk(1, "scsi(%ld): Verifying chip\n", ha->host_no); /* Soft reset chip and wait for it to finish. */ WRT_REG_WORD(®->ictrl, ISP_RESET); /* * We can't do a traditional PCI write flush here by reading * back the register. The card will not respond once the reset * is in action and we end up with a machine check exception * instead. Nothing to do but wait and hope for the best. * A portable pci_write_flush(pdev) call would be very useful here. */ udelay(20); data = qla1280_debounce_register(®->ictrl); /* * Yet another QLogic gem ;-( */ for (cnt = 1000000; cnt && data & ISP_RESET; cnt--) { udelay(5); data = RD_REG_WORD(®->ictrl); } if (!cnt) goto fail; /* Reset register cleared by chip reset. */ dprintk(3, "qla1280_chip_diag: reset register cleared by chip reset\n"); WRT_REG_WORD(®->cfg_1, 0); /* Reset RISC and disable BIOS which allows RISC to execute out of RAM. */ WRT_REG_WORD(®->host_cmd, HC_RESET_RISC | HC_RELEASE_RISC | HC_DISABLE_BIOS); RD_REG_WORD(®->id_l); /* Flush PCI write */ data = qla1280_debounce_register(®->mailbox0); /* * I *LOVE* this code! */ for (cnt = 1000000; cnt && data == MBS_BUSY; cnt--) { udelay(5); data = RD_REG_WORD(®->mailbox0); } if (!cnt) goto fail; /* Check product ID of chip */ dprintk(3, "qla1280_chip_diag: Checking product ID of chip\n"); if (RD_REG_WORD(®->mailbox1) != PROD_ID_1 || (RD_REG_WORD(®->mailbox2) != PROD_ID_2 && RD_REG_WORD(®->mailbox2) != PROD_ID_2a) || RD_REG_WORD(®->mailbox3) != PROD_ID_3 || RD_REG_WORD(®->mailbox4) != PROD_ID_4) { printk(KERN_INFO "qla1280: Wrong product ID = " "0x%x,0x%x,0x%x,0x%x\n", RD_REG_WORD(®->mailbox1), RD_REG_WORD(®->mailbox2), RD_REG_WORD(®->mailbox3), RD_REG_WORD(®->mailbox4)); goto fail; } /* * Enable ints early!!! */ qla1280_enable_intrs(ha); dprintk(1, "qla1280_chip_diag: Checking mailboxes of chip\n"); /* Wrap Incoming Mailboxes Test. */ mb[0] = MBC_MAILBOX_REGISTER_TEST; mb[1] = 0xAAAA; mb[2] = 0x5555; mb[3] = 0xAA55; mb[4] = 0x55AA; mb[5] = 0xA5A5; mb[6] = 0x5A5A; mb[7] = 0x2525; status = qla1280_mailbox_command(ha, 0xff, mb); if (status)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -