📄 qlogicisp.c
字号:
} hostdata = (struct isp1020_hostdata *) host->hostdata; DEBUG_INTR(printk("qlogicisp : interrupt on line %d\n", irq)); if (!(inw(host->io_port + PCI_INTF_STS) & 0x04)) { /* spurious interrupts can happen legally */ DEBUG_INTR(printk("qlogicisp: got spurious interrupt\n")); return; } in_ptr = inw(host->io_port + MBOX5); outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); if ((inw(host->io_port + PCI_SEMAPHORE) & ASYNC_EVENT_INTERRUPT)) { status = inw(host->io_port + MBOX0); DEBUG_INTR(printk("qlogicisp : mbox completion status: %x\n", status)); switch (status) { case ASYNC_SCSI_BUS_RESET: case EXECUTION_TIMEOUT_RESET: hostdata->send_marker = 1; break; case INVALID_COMMAND: case HOST_INTERFACE_ERROR: case COMMAND_ERROR: case COMMAND_PARAM_ERROR: printk("qlogicisp : bad mailbox return status\n"); break; } outw(0x0, host->io_port + PCI_SEMAPHORE); } out_ptr = hostdata->res_out_ptr; DEBUG_INTR(printk("qlogicisp : response queue update\n")); DEBUG_INTR(printk("qlogicisp : response queue depth %d\n", QUEUE_DEPTH(in_ptr, out_ptr))); while (out_ptr != in_ptr) { sts = (struct Status_Entry *) &hostdata->res[out_ptr][0]; out_ptr = (out_ptr + 1) & RES_QUEUE_LEN; Cmnd = (Scsi_Cmnd *) bus_to_virt(sts->handle); TRACE("done", out_ptr, Cmnd); if (sts->completion_status == CS_RESET_OCCURRED || sts->completion_status == CS_ABORTED || (sts->status_flags & STF_BUS_RESET)) hostdata->send_marker = 1; if (sts->state_flags & SF_GOT_SENSE) memcpy(Cmnd->sense_buffer, sts->req_sense_data, sizeof(Cmnd->sense_buffer)); DEBUG_INTR(isp1020_print_status_entry(sts)); if (sts->hdr.entry_type == ENTRY_STATUS) Cmnd->result = isp1020_return_status(sts); else Cmnd->result = DID_ERROR << 16; outw(out_ptr, host->io_port + MBOX5); (*Cmnd->scsi_done)(Cmnd); } hostdata->res_out_ptr = out_ptr; LEAVE_INTR("isp1020_intr_handler");}static int isp1020_return_status(struct Status_Entry *sts){ int host_status = DID_ERROR;#if DEBUG_ISP1020_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_ISP1020_INTR */ ENTER("isp1020_return_status"); DEBUG(printk("qlogicisp : completion status = 0x%04x\n", sts->completion_status)); switch(sts->completion_status) { case CS_COMPLETE: host_status = DID_OK; break; case CS_INCOMPLETE: if (!(sts->state_flags & SF_GOT_BUS)) host_status = DID_NO_CONNECT; else if (!(sts->state_flags & SF_GOT_TARGET)) host_status = DID_BAD_TARGET; else if (!(sts->state_flags & SF_SENT_CDB)) host_status = DID_ERROR; else if (!(sts->state_flags & SF_TRANSFERRED_DATA)) host_status = DID_ERROR; else if (!(sts->state_flags & SF_GOT_STATUS)) host_status = DID_ERROR; else if (!(sts->state_flags & SF_GOT_SENSE)) host_status = DID_ERROR; break; case CS_DMA_ERROR: case CS_TRANSPORT_ERROR: host_status = DID_ERROR; break; case CS_RESET_OCCURRED: 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: case CS_COMMAND_OVERRUN: case CS_STATUS_OVERRUN: case CS_BAD_MESSAGE: case CS_NO_MESSAGE_OUT: case CS_EXT_ID_FAILED: case CS_IDE_MSG_FAILED: case CS_ABORT_MSG_FAILED: case CS_NOP_MSG_FAILED: case CS_PARITY_ERROR_MSG_FAILED: case CS_DEVICE_RESET_MSG_FAILED: case CS_ID_MSG_FAILED: case CS_UNEXP_BUS_FREE: case CS_INVALID_ENTRY_TYPE: case CS_DEVICE_QUEUE_FULL: case CS_SCSI_PHASE_SKIPPED: case CS_ARS_FAILED: host_status = DID_ERROR; break; case CS_DATA_UNDERRUN: host_status = DID_OK; break; default: printk("qlogicisp : unknown completion status 0x%04x\n", sts->completion_status); host_status = DID_ERROR; break; } DEBUG_INTR(printk("qlogicisp : host status (%s) scsi status %x\n", reason[host_status], sts->scsi_status)); LEAVE("isp1020_return_status"); return (sts->scsi_status & STATUS_MASK) | (host_status << 16);}int isp1020_abort(Scsi_Cmnd *Cmnd){ u_short param[6]; struct Scsi_Host *host; struct isp1020_hostdata *hostdata; int return_status = SCSI_ABORT_SUCCESS; u_int cmdaddr = virt_to_bus(Cmnd); ENTER("isp1020_abort"); host = Cmnd->host; hostdata = (struct isp1020_hostdata *) host->hostdata; isp1020_disable_irqs(host); param[0] = MBOX_ABORT; param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun; param[2] = cmdaddr >> 16; param[3] = cmdaddr & 0xffff; isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { printk("qlogicisp : scsi abort failure: %x\n", param[0]); return_status = SCSI_ABORT_ERROR; } isp1020_enable_irqs(host); LEAVE("isp1020_abort"); return return_status;}int isp1020_reset(Scsi_Cmnd *Cmnd, unsigned int reset_flags){ u_short param[6]; struct Scsi_Host *host; struct isp1020_hostdata *hostdata; int return_status = SCSI_RESET_SUCCESS; ENTER("isp1020_reset"); host = Cmnd->host; hostdata = (struct isp1020_hostdata *) host->hostdata; param[0] = MBOX_BUS_RESET; param[1] = hostdata->host_param.bus_reset_delay; isp1020_disable_irqs(host); isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { printk("qlogicisp : scsi bus reset failure: %x\n", param[0]); return_status = SCSI_RESET_ERROR; } isp1020_enable_irqs(host); LEAVE("isp1020_reset"); return return_status;;}int isp1020_biosparam(Disk *disk, kdev_t n, int ip[]){ int size = disk->capacity; ENTER("isp1020_biosparam"); ip[0] = 64; ip[1] = 32; ip[2] = size >> 11; if (ip[2] > 1024) { ip[0] = 255; ip[1] = 63; ip[2] = size / (ip[0] * ip[1]); if (ip[2] > 1023) ip[2] = 1023; } LEAVE("isp1020_biosparam"); return 0;}static int isp1020_reset_hardware(struct Scsi_Host *host){ u_short param[6]; int loop_count; ENTER("isp1020_reset_hardware"); outw(ISP_RESET, host->io_port + PCI_INTF_CTL); outw(HCCR_RESET, host->io_port + HOST_HCCR); outw(HCCR_RELEASE, host->io_port + HOST_HCCR); outw(HCCR_BIOS_DISABLE, host->io_port + HOST_HCCR); loop_count = DEFAULT_LOOP_COUNT; while (--loop_count && inw(host->io_port + HOST_HCCR) == RISC_BUSY) barrier(); if (!loop_count) printk("qlogicisp: reset_hardware loop timeout\n"); outw(0, host->io_port + ISP_CFG1);#if DEBUG_ISP1020 printk("qlogicisp : mbox 0 0x%04x \n", inw(host->io_port + MBOX0)); printk("qlogicisp : mbox 1 0x%04x \n", inw(host->io_port + MBOX1)); printk("qlogicisp : mbox 2 0x%04x \n", inw(host->io_port + MBOX2)); printk("qlogicisp : mbox 3 0x%04x \n", inw(host->io_port + MBOX3)); printk("qlogicisp : mbox 4 0x%04x \n", inw(host->io_port + MBOX4)); printk("qlogicisp : mbox 5 0x%04x \n", inw(host->io_port + MBOX5));#endif /* DEBUG_ISP1020 */ DEBUG(printk("qlogicisp : loading risc ram\n"));#if RELOAD_FIRMWARE { int i; for (i = 0; i < risc_code_length01; i++) { param[0] = MBOX_WRITE_RAM_WORD; param[1] = risc_code_addr01 + i; param[2] = risc_code01[i]; isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { printk("qlogicisp : firmware load failure\n"); return 1; } } }#endif /* RELOAD_FIRMWARE */ DEBUG(printk("qlogicisp : verifying checksum\n")); param[0] = MBOX_VERIFY_CHECKSUM; param[1] = risc_code_addr01; isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { printk("qlogicisp : ram checksum failure\n"); return 1; } DEBUG(printk("qlogicisp : executing firmware\n")); param[0] = MBOX_EXEC_FIRMWARE; param[1] = risc_code_addr01; isp1020_mbox_command(host, param); param[0] = MBOX_ABOUT_FIRMWARE; isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { printk("qlogicisp : about firmware failure\n"); return 1; } DEBUG(printk("qlogicisp : firmware major revision %d\n", param[1])); DEBUG(printk("qlogicisp : firmware minor revision %d\n", param[2])); LEAVE("isp1020_reset_hardware"); return 0;}static int isp1020_init(struct Scsi_Host *sh){ u_int io_base; struct isp1020_hostdata *hostdata; u_char bus, device_fn, revision, irq; u_short vendor_id, device_id, command; ENTER("isp1020_init"); hostdata = (struct isp1020_hostdata *) sh->hostdata; bus = hostdata->bus; device_fn = hostdata->device_fn; if (pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, &vendor_id) || pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID, &device_id) || pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command) || pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_0, &io_base) || pcibios_read_config_byte(bus, device_fn, PCI_CLASS_REVISION, &revision) || pcibios_read_config_byte(bus, device_fn, PCI_INTERRUPT_LINE, &irq)) { printk("qlogicisp : error reading PCI configuration\n"); return 1; } if (vendor_id != PCI_VENDOR_ID_QLOGIC) { printk("qlogicisp : 0x%04x is not QLogic vendor ID\n", vendor_id); return 1; } if (device_id != PCI_DEVICE_ID_QLOGIC_ISP1020) { printk("qlogicisp : 0x%04x does not match ISP1020 device id\n", device_id); return 1; } if (command & PCI_COMMAND_IO && (io_base & 3) == 1) io_base &= PCI_BASE_ADDRESS_IO_MASK; else { printk("qlogicisp : i/o mapping is disabled\n"); return 1; } if (!(command & PCI_COMMAND_MASTER)) { printk("qlogicisp : bus mastering is disabled\n"); return 1; } if (revision != ISP1020_REV_ID) printk("qlogicisp : new isp1020 revision ID (%d)\n", revision); if (inw(io_base + PCI_ID_LOW) != PCI_VENDOR_ID_QLOGIC || inw(io_base + PCI_ID_HIGH) != PCI_DEVICE_ID_QLOGIC_ISP1020) { printk("qlogicisp : can't decode i/o address space at 0x%x\n", io_base); return 1; } hostdata->revision = revision; sh->irq = irq; sh->io_port = io_base; LEAVE("isp1020_init"); return 0;}#if USE_NVRAM_DEFAULTSstatic int isp1020_get_defaults(struct Scsi_Host *host){ int i; u_short value; struct isp1020_hostdata *hostdata = (struct isp1020_hostdata *) host->hostdata; ENTER("isp1020_get_defaults"); if (!isp1020_verify_nvram(host)) { printk("qlogicisp : nvram checksum failure\n"); printk("qlogicisp : attempting to use default parameters\n"); return isp1020_set_defaults(host); } value = isp1020_read_nvram_word(host, 2); hostdata->host_param.fifo_threshold = (value >> 8) & 0x03; hostdata->host_param.host_adapter_enable = (value >> 11) & 0x01; hostdata->host_param.initiator_scsi_id = (value >> 12) & 0x0f; value = isp1020_read_nvram_word(host, 3); hostdata->host_param.bus_reset_delay = value & 0xff; hostdata->host_param.retry_count = value >> 8; value = isp1020_read_nvram_word(host, 4); hostdata->host_param.retry_delay = value & 0xff; hostdata->host_param.async_data_setup_time = (value >> 8) & 0x0f; hostdata->host_param.req_ack_active_negation = (value >> 12) & 0x01; hostdata->host_param.data_line_active_negation = (value >> 13) & 0x01; hostdata->host_param.data_dma_burst_enable = (value >> 14) & 0x01; hostdata->host_param.command_dma_burst_enable = (value >> 15); value = isp1020_read_nvram_word(host, 5); hostdata->host_param.tag_aging = value & 0xff; value = isp1020_read_nvram_word(host, 6); hostdata->host_param.selection_timeout = value & 0xffff; value = isp1020_read_nvram_word(host, 7);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -