📄 qlogicfc.c
字号:
if (return_status != SUCCESS){ param[0] = MBOX_GET_FIRMWARE_STATE; isp2x00_mbox_command(host, param); printk("qlogicfc%d : abort failed\n", hostdata->host_id); printk("qlogicfc%d : firmware status is %x %x\n", hostdata->host_id, param[0], param[1]); } isp2x00_enable_irqs(host); LEAVE("isp2x00_abort"); return return_status;}int isp2x00_reset(Scsi_Cmnd * Cmnd, unsigned int reset_flags){ u_short param[8]; struct Scsi_Host *host; struct isp2x00_hostdata *hostdata; int return_status = SCSI_RESET_SUCCESS; ENTER("isp2x00_reset"); host = Cmnd->host; hostdata = (struct isp2x00_hostdata *) host->hostdata; param[0] = MBOX_BUS_RESET; param[1] = 3; isp2x00_disable_irqs(host); isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { printk("qlogicfc%d : scsi bus reset failure: %x\n", hostdata->host_id, param[0]); return_status = SCSI_RESET_ERROR; } isp2x00_enable_irqs(host); LEAVE("isp2x00_reset"); return return_status;;}int isp2x00_biosparam(Disk * disk, kdev_t n, int ip[]){ int size = disk->capacity; ENTER("isp2x00_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]); } LEAVE("isp2x00_biosparam"); return 0;}static int isp2x00_reset_hardware(struct Scsi_Host *host){ u_short param[8]; struct isp2x00_hostdata *hostdata; int loop_count; dma64_addr_t busaddr; ENTER("isp2x00_reset_hardware"); hostdata = (struct isp2x00_hostdata *) host->hostdata; outw(0x01, host->io_port + ISP_CTRL_STATUS); 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("qlogicfc%d : reset_hardware loop timeout\n", hostdata->host_id);#if DEBUG_ISP2x00 printk("qlogicfc%d : mbox 0 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX0)); printk("qlogicfc%d : mbox 1 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX1)); printk("qlogicfc%d : mbox 2 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX2)); printk("qlogicfc%d : mbox 3 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX3)); printk("qlogicfc%d : mbox 4 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX4)); printk("qlogicfc%d : mbox 5 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX5)); printk("qlogicfc%d : mbox 6 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX6)); printk("qlogicfc%d : mbox 7 0x%04x \n", hostdata->host_id, inw(host->io_port + MBOX7));#endif /* DEBUG_ISP2x00 */ DEBUG(printk("qlogicfc%d : verifying checksum\n", hostdata->host_id));#if RELOAD_FIRMWARE { int i; unsigned short * risc_code = NULL; unsigned short risc_code_len = 0; if (hostdata->pci_dev->device == PCI_DEVICE_ID_QLOGIC_ISP2100){ risc_code = risc_code2100; risc_code_len = risc_code_length2100; } else if (hostdata->pci_dev->device == PCI_DEVICE_ID_QLOGIC_ISP2200){ risc_code = risc_code2200; risc_code_len = risc_code_length2200; } for (i = 0; i < risc_code_len; i++) { param[0] = MBOX_WRITE_RAM_WORD; param[1] = risc_code_addr01 + i; param[2] = risc_code[i]; isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { printk("qlogicfc%d : firmware load failure\n", hostdata->host_id); return 1; } } }#endif /* RELOAD_FIRMWARE */ param[0] = MBOX_VERIFY_CHECKSUM; param[1] = risc_code_addr01; isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { printk("qlogicfc%d : ram checksum failure\n", hostdata->host_id); return 1; } DEBUG(printk("qlogicfc%d : executing firmware\n", hostdata->host_id)); param[0] = MBOX_EXEC_FIRMWARE; param[1] = risc_code_addr01; isp2x00_mbox_command(host, param); param[0] = MBOX_ABOUT_FIRMWARE; isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { printk("qlogicfc%d : about firmware failure\n", hostdata->host_id); return 1; } DEBUG(printk("qlogicfc%d : firmware major revision %d\n", hostdata->host_id, param[1])); DEBUG(printk("qlogicfc%d : firmware minor revision %d\n", hostdata->host_id, param[2]));#ifdef USE_NVRAM_DEFAULTS if (isp2x00_get_nvram_defaults(host, &hostdata->control_block) != 0) { printk("qlogicfc%d : Could not read from NVRAM\n", hostdata->host_id); }#endif hostdata->wwn = (u64) (cpu_to_le16(hostdata->control_block.node_name[0])) << 56; hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[0]) & 0xff00) << 48; hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[1]) & 0xff00) << 24; hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[1]) & 0x00ff) << 48; hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[2]) & 0x00ff) << 24; hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[2]) & 0xff00) << 8; hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[3]) & 0x00ff) << 8; hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[3]) & 0xff00) >> 8; /* FIXME: If the DMA transfer goes one way only, this should use PCI_DMA_TODEVICE and below as well. */ busaddr = pci64_map_single(hostdata->pci_dev, &hostdata->control_block, sizeof(hostdata->control_block), PCI_DMA_BIDIRECTIONAL); param[0] = MBOX_INIT_FIRMWARE; param[2] = (u_short) (pci64_dma_lo32(busaddr) >> 16); param[3] = (u_short) (pci64_dma_lo32(busaddr) & 0xffff); param[4] = 0; param[5] = 0; param[6] = (u_short) (pci64_dma_hi32(busaddr) >> 16); param[7] = (u_short) (pci64_dma_hi32(busaddr) & 0xffff); isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { printk("qlogicfc%d.c: Ouch 0x%04x\n", hostdata->host_id, param[0]); pci64_unmap_single(hostdata->pci_dev, busaddr, sizeof(hostdata->control_block), PCI_DMA_BIDIRECTIONAL); return 1; } param[0] = MBOX_GET_FIRMWARE_STATE; isp2x00_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { printk("qlogicfc%d.c: 0x%04x\n", hostdata->host_id, param[0]); pci64_unmap_single(hostdata->pci_dev, busaddr, sizeof(hostdata->control_block), PCI_DMA_BIDIRECTIONAL); return 1; } pci64_unmap_single(hostdata->pci_dev, busaddr, sizeof(hostdata->control_block), PCI_DMA_BIDIRECTIONAL); LEAVE("isp2x00_reset_hardware"); return 0;}#ifdef USE_NVRAM_DEFAULTSstatic int isp2x00_get_nvram_defaults(struct Scsi_Host *host, struct init_cb *control_block){ u_short value; if (isp2x00_read_nvram_word(host, 0) != 0x5349) return 1; value = isp2x00_read_nvram_word(host, 8); control_block->node_name[0] = cpu_to_le16(isp2x00_read_nvram_word(host, 9)); control_block->node_name[1] = cpu_to_le16(isp2x00_read_nvram_word(host, 10)); control_block->node_name[2] = cpu_to_le16(isp2x00_read_nvram_word(host, 11)); control_block->node_name[3] = cpu_to_le16(isp2x00_read_nvram_word(host, 12)); control_block->hard_addr = cpu_to_le16(isp2x00_read_nvram_word(host, 13)); return 0;}#endifstatic int isp2x00_init(struct Scsi_Host *sh){ u_long io_base; struct isp2x00_hostdata *hostdata; u_char revision; u_int irq; u_short command; struct pci_dev *pdev; ENTER("isp2x00_init"); hostdata = (struct isp2x00_hostdata *) sh->hostdata; pdev = hostdata->pci_dev; if (pci_read_config_word(pdev, PCI_COMMAND, &command) || pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision)) { printk("qlogicfc%d : error reading PCI configuration\n", hostdata->host_id); return 1; } io_base = pci_resource_start(pdev, 0); irq = pdev->irq; if (pdev->vendor != PCI_VENDOR_ID_QLOGIC) { printk("qlogicfc%d : 0x%04x is not QLogic vendor ID\n", hostdata->host_id, pdev->vendor); return 1; } if (pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2100 && pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2200) { printk("qlogicfc%d : 0x%04x does not match ISP2100 or ISP2200 device id\n", hostdata->host_id, pdev->device); return 1; } if (!(command & PCI_COMMAND_IO) || !(pdev->resource[0].flags & IORESOURCE_IO)) { printk("qlogicfc%d : i/o mapping is disabled\n", hostdata->host_id); return 1; } if (!(command & PCI_COMMAND_MASTER)) { printk("qlogicfc%d : bus mastering is disabled\n", hostdata->host_id); return 1; } if (revision != ISP2100_REV_ID1 && revision != ISP2100_REV_ID3 && revision != ISP2200_REV_ID5) printk("qlogicfc%d : new isp2x00 revision ID (%d)\n", hostdata->host_id, revision); hostdata->revision = revision; sh->irq = irq; sh->io_port = io_base; LEAVE("isp2x00_init"); return 0;}#if USE_NVRAM_DEFAULTS#define NVRAM_DELAY() udelay(10) /* 10 microsecond delay */u_short isp2x00_read_nvram_word(struct Scsi_Host * host, u_short byte){ int i; u_short value, output, input; outw(0x2, host->io_port + PCI_NVRAM); NVRAM_DELAY(); outw(0x3, host->io_port + PCI_NVRAM); NVRAM_DELAY(); byte &= 0xff; byte |= 0x0600; for (i = 10; i >= 0; i--) { output = ((byte >> i) & 0x1) ? 0x4 : 0x0; outw(output | 0x2, host->io_port + PCI_NVRAM); NVRAM_DELAY(); outw(output | 0x3, host->io_port + PCI_NVRAM); NVRAM_DELAY(); outw(output | 0x2, host->io_port + PCI_NVRAM); NVRAM_DELAY(); } for (i = 0xf, value = 0; i >= 0; i--) { value <<= 1; outw(0x3, host->io_port + PCI_NVRAM); NVRAM_DELAY(); input = inw(host->io_port + PCI_NVRAM); NVRAM_DELAY(); outw(0x2, host->io_port + PCI_NVRAM); NVRAM_DELAY(); if (input & 0x8) value |= 1; } outw(0x0, host->io_port + PCI_NVRAM); NVRAM_DELAY(); return value;}#endif /* USE_NVRAM_DEFAULTS *//* * currently, this is only called during initialization or abort/reset, * at which times interrupts are disabled, so polling is OK, I guess... */static int isp2x00_mbox_command(struct Scsi_Host *host, u_short param[]){ int loop_count; struct isp2x00_hostdata *hostdata = (struct isp2x00_hostdata *) host->hostdata; if (mbox_param[param[0]] == 0 || hostdata->adapter_state == AS_FIRMWARE_DEAD) return 1; loop_count = DEFAULT_LOOP_COUNT; while (--loop_count && inw(host->io_port + HOST_HCCR) & 0x0080) barrier(); if (!loop_count) { printk("qlogicfc%d : mbox_command loop timeout #1\n", hostdata->host_id); param[0] = 0x4006; hostdata->adapter_state = AS_FIRMWARE_DEAD; return 1; } hostdata->mbox_done = 0; if (mbox_param[param[0]] == 0) printk("qlogicfc%d : invalid mbox command\n", hostdata->host_id); if (mbox_param[param[0]] & 0x80) outw(param[7], host->io_port + MBOX7); if (mbox_param[param[0]] & 0x40) outw(param[6], host->io_port + MBOX6); if (mbox_param[param[0]] & 0x20) outw(param[5], host->io_port + MBOX5); if (mbox_param[param[0]] & 0x10) outw(param[4], host->io_port + MBOX4); if (mbox_param[param[0]] & 0x08) outw(param[3], host->io_port + MBOX3); if (mbox_param[param[0]] & 0x04) outw(param[2], host->io_port + MBOX2); if (mbox_param[param[0]] & 0x02) outw(param[1], host->io_port + MBOX1); if (mbox_param[param[0]] & 0x01) outw(param[0], host->io_port + MBOX0); outw(HCCR_SET_HOST_INTR, host->io_port + HOST_HCCR); while (1) { loop_count = DEFAULT_LOOP_COUNT; while (--loop_count && !(inw(host->io_port + PCI_INTER_STS) & 0x08)) { barrier(); } if (!loop_count) { hostdata->adapter_state = AS_FIRMWARE_DEAD; printk("qlogicfc%d : mbox_command loop timeout #2\n", hostdata->host_id); break; } isp2x00_intr_handler(host->irq, host, NULL); if (hostdata->mbox_done == 1) break; } loop_count = DEFAULT_LOOP_COUNT; while (--loop_count && inw(host->io_port + MBOX0) == 0x04) { barrier(); } if (!loop_count) printk("qlogicfc%d : mbox_command loop timeout #3\n", hostdata->host_id); param[7] = inw(host->io_port + MBOX7); param[6] = inw(host->io_port + MBOX6); param[5] = inw(host->io_port + MBOX5); param[4] = inw(host->io_port + MBOX4); param[3] = inw(host->io_port + MBOX3); param[2] = inw(host->io_port + MBOX2); param[1] = inw(host->io_port + MBOX1); param[0] = inw(host->io_port + MBOX0); outw(0x0, host->io_port + PCI_SEMAPHORE); if (inw(host->io_port + HOST_HCCR) & 0x0080) { hostdata->adapter_state = AS_FIRMWARE_DEAD; printk("qlogicfc%d : mbox op is still pending\n", hostdata->host_id); } return 0;}#if DEBUG_ISP2x00_INTRvoid isp2x00_print_status_entry(struct Status_Entry *status){ printk("qlogicfc : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n", status->hdr.entry_cnt, status->hdr.entry_type, status->hdr.flags); printk("qlogicfc : scsi status = 0x%04x, completion status = 0x%04x\n", le16_to_cpu(status->scsi_status), le16_to_cpu(status->completion_status)); printk("qlogicfc : state flags = 0x%04x, status flags = 0x%04x\n", le16_to_cpu(status->state_flags), le16_to_cpu(status->status_flags)); printk("qlogicfc : response info length = 0x%04x, request sense length = 0x%04x\n", le16_to_cpu(status->res_info_len), le16_to_cpu(status->req_sense_len)); printk("qlogicfc : residual transfer length = 0x%08x, response = 0x%02x\n", le32_to_cpu(status->residual), sta
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -