📄 qlogicisp.c
字号:
printk("qlogicisp : data line active negation=%d\n", hostdata->host_param.data_line_active_negation); printk("qlogicisp : data DMA burst enable=%d\n", hostdata->host_param.data_dma_burst_enable); printk("qlogicisp : command DMA burst enable=%d\n", hostdata->host_param.command_dma_burst_enable); printk("qlogicisp : tag age limit=%d\n", hostdata->host_param.tag_aging); printk("qlogicisp : selection timeout limit=%d\n", hostdata->host_param.selection_timeout); printk("qlogicisp : max queue depth=%d\n", hostdata->host_param.max_queue_depth);#endif /* DEBUG_ISP1020_SETUP */ for (i = 0; i < MAX_TARGETS; i++) { value = isp1020_read_nvram_word(host, 14 + i * 3); hostdata->dev_param[i].device_flags = value & 0xff; hostdata->dev_param[i].execution_throttle = value >> 8; value = isp1020_read_nvram_word(host, 15 + i * 3); hostdata->dev_param[i].synchronous_period = value & 0xff; hostdata->dev_param[i].synchronous_offset = (value >> 8) & 0x0f; hostdata->dev_param[i].device_enable = (value >> 12) & 0x01;#if DEBUG_ISP1020_SETUP printk("qlogicisp : target 0x%02x\n", i); printk("qlogicisp : device flags=0x%02x\n", hostdata->dev_param[i].device_flags); printk("qlogicisp : execution throttle=%d\n", hostdata->dev_param[i].execution_throttle); printk("qlogicisp : synchronous period=%d\n", hostdata->dev_param[i].synchronous_period); printk("qlogicisp : synchronous offset=%d\n", hostdata->dev_param[i].synchronous_offset); printk("qlogicisp : device enable=%d\n", hostdata->dev_param[i].device_enable);#endif /* DEBUG_ISP1020_SETUP */ } LEAVE("isp1020_get_defaults"); return 0;}#define ISP1020_NVRAM_LEN 0x40#define ISP1020_NVRAM_SIG1 0x5349#define ISP1020_NVRAM_SIG2 0x2050static int isp1020_verify_nvram(struct Scsi_Host *host){ int i; u_short value; u_char checksum = 0; for (i = 0; i < ISP1020_NVRAM_LEN; i++) { value = isp1020_read_nvram_word(host, i); switch (i) { case 0: if (value != ISP1020_NVRAM_SIG1) return 0; break; case 1: if (value != ISP1020_NVRAM_SIG2) return 0; break; case 2: if ((value & 0xff) != 0x02) return 0; break; } checksum += value & 0xff; checksum += value >> 8; } return (checksum == 0);}#define NVRAM_DELAY() udelay(2) /* 2 microsecond delay */u_short isp1020_read_nvram_word(struct Scsi_Host *host, u_short byte){ int i; u_short value, output, input; byte &= 0x3f; byte |= 0x0180; for (i = 8; 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 */static int isp1020_set_defaults(struct Scsi_Host *host){ struct isp1020_hostdata *hostdata = (struct isp1020_hostdata *) host->hostdata; int i; ENTER("isp1020_set_defaults"); hostdata->host_param.fifo_threshold = 2; hostdata->host_param.host_adapter_enable = 1; hostdata->host_param.initiator_scsi_id = 7; hostdata->host_param.bus_reset_delay = 3; hostdata->host_param.retry_count = 0; hostdata->host_param.retry_delay = 1; hostdata->host_param.async_data_setup_time = 6; hostdata->host_param.req_ack_active_negation = 1; hostdata->host_param.data_line_active_negation = 1; hostdata->host_param.data_dma_burst_enable = 1; hostdata->host_param.command_dma_burst_enable = 1; hostdata->host_param.tag_aging = 8; hostdata->host_param.selection_timeout = 250; hostdata->host_param.max_queue_depth = 256; for (i = 0; i < MAX_TARGETS; i++) { hostdata->dev_param[i].device_flags = 0xfd; hostdata->dev_param[i].execution_throttle = 16; hostdata->dev_param[i].synchronous_period = 25; hostdata->dev_param[i].synchronous_offset = 12; hostdata->dev_param[i].device_enable = 1; } LEAVE("isp1020_set_defaults"); return 0;}static int isp1020_load_parameters(struct Scsi_Host *host){ int i, k; u_int queue_addr; u_short param[6]; u_short isp_cfg1; unsigned long flags; struct isp1020_hostdata *hostdata = (struct isp1020_hostdata *) host->hostdata; ENTER("isp1020_load_parameters"); save_flags(flags); cli(); outw(hostdata->host_param.fifo_threshold, host->io_port + ISP_CFG1); param[0] = MBOX_SET_INIT_SCSI_ID; param[1] = hostdata->host_param.initiator_scsi_id; isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { restore_flags(flags); printk("qlogicisp : set initiator id failure\n"); return 1; } param[0] = MBOX_SET_RETRY_COUNT; param[1] = hostdata->host_param.retry_count; param[2] = hostdata->host_param.retry_delay; isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { restore_flags(flags); printk("qlogicisp : set retry count failure\n"); return 1; } param[0] = MBOX_SET_ASYNC_DATA_SETUP_TIME; param[1] = hostdata->host_param.async_data_setup_time; isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { restore_flags(flags); printk("qlogicisp : async data setup time failure\n"); return 1; } param[0] = MBOX_SET_ACTIVE_NEG_STATE; param[1] = (hostdata->host_param.req_ack_active_negation << 4) | (hostdata->host_param.data_line_active_negation << 5); isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { restore_flags(flags); printk("qlogicisp : set active negation state failure\n"); return 1; } param[0] = MBOX_SET_PCI_CONTROL_PARAMS; param[1] = hostdata->host_param.data_dma_burst_enable << 1; param[2] = hostdata->host_param.command_dma_burst_enable << 1; isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { restore_flags(flags); printk("qlogicisp : set pci control parameter failure\n"); return 1; } isp_cfg1 = inw(host->io_port + ISP_CFG1); if (hostdata->host_param.data_dma_burst_enable || hostdata->host_param.command_dma_burst_enable) isp_cfg1 |= 0x0004; else isp_cfg1 &= 0xfffb; outw(isp_cfg1, host->io_port + ISP_CFG1); param[0] = MBOX_SET_TAG_AGE_LIMIT; param[1] = hostdata->host_param.tag_aging; isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { restore_flags(flags); printk("qlogicisp : set tag age limit failure\n"); return 1; } param[0] = MBOX_SET_SELECT_TIMEOUT; param[1] = hostdata->host_param.selection_timeout; isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { restore_flags(flags); printk("qlogicisp : set selection timeout failure\n"); return 1; } for (i = 0; i < MAX_TARGETS; i++) { if (!hostdata->dev_param[i].device_enable) continue; param[0] = MBOX_SET_TARGET_PARAMS; param[1] = i << 8; param[2] = hostdata->dev_param[i].device_flags << 8; param[3] = (hostdata->dev_param[i].synchronous_offset << 8) | hostdata->dev_param[i].synchronous_period; isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { restore_flags(flags); printk("qlogicisp : set target parameter failure\n"); return 1; } for (k = 0; k < MAX_LUNS; k++) { param[0] = MBOX_SET_DEV_QUEUE_PARAMS; param[1] = (i << 8) | k; param[2] = hostdata->host_param.max_queue_depth; param[3] = hostdata->dev_param[i].execution_throttle; isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { restore_flags(flags); printk("qlogicisp : set device queue " "parameter failure\n"); return 1; } } } queue_addr = (u_int) virt_to_bus(&hostdata->res[0][0]); param[0] = MBOX_INIT_RES_QUEUE; param[1] = RES_QUEUE_LEN + 1; param[2] = (u_short) (queue_addr >> 16); param[3] = (u_short) (queue_addr & 0xffff); param[4] = 0; param[5] = 0; isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { restore_flags(flags); printk("qlogicisp : set response queue failure\n"); return 1; } queue_addr = (u_int) virt_to_bus(&hostdata->req[0][0]); param[0] = MBOX_INIT_REQ_QUEUE; param[1] = QLOGICISP_REQ_QUEUE_LEN + 1; param[2] = (u_short) (queue_addr >> 16); param[3] = (u_short) (queue_addr & 0xffff); param[4] = 0; isp1020_mbox_command(host, param); if (param[0] != MBOX_COMMAND_COMPLETE) { restore_flags(flags); printk("qlogicisp : set request queue failure\n"); return 1; } restore_flags(flags); LEAVE("isp1020_load_parameters"); return 0;}/* * currently, this is only called during initialization or abort/reset, * at which times interrupts are disabled, so polling is OK, I guess... */static int isp1020_mbox_command(struct Scsi_Host *host, u_short param[]){ int loop_count; if (mbox_param[param[0]] == 0) return 1; loop_count = DEFAULT_LOOP_COUNT; while (--loop_count && inw(host->io_port + HOST_HCCR) & 0x0080) barrier(); if (!loop_count) printk("qlogicisp: mbox_command loop timeout #1\n"); switch(mbox_param[param[0]] >> 4) { case 6: outw(param[5], host->io_port + MBOX5); case 5: outw(param[4], host->io_port + MBOX4); case 4: outw(param[3], host->io_port + MBOX3); case 3: outw(param[2], host->io_port + MBOX2); case 2: outw(param[1], host->io_port + MBOX1); case 1: outw(param[0], host->io_port + MBOX0); } outw(0x0, host->io_port + PCI_SEMAPHORE); outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); outw(HCCR_SET_HOST_INTR, host->io_port + HOST_HCCR); loop_count = DEFAULT_LOOP_COUNT; while (--loop_count && !(inw(host->io_port + PCI_INTF_STS) & 0x04)) barrier(); if (!loop_count) printk("qlogicisp: mbox_command loop timeout #2\n"); loop_count = DEFAULT_LOOP_COUNT; while (--loop_count && inw(host->io_port + MBOX0) == 0x04) barrier(); if (!loop_count) printk("qlogicisp: mbox_command loop timeout #3\n"); switch(mbox_param[param[0]] & 0xf) { case 6: param[5] = inw(host->io_port + MBOX5); case 5: param[4] = inw(host->io_port + MBOX4); case 4: param[3] = inw(host->io_port + MBOX3); case 3: param[2] = inw(host->io_port + MBOX2); case 2: param[1] = inw(host->io_port + MBOX1); case 1: param[0] = inw(host->io_port + MBOX0); } outw(0x0, host->io_port + PCI_SEMAPHORE); outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); return 0;}#if DEBUG_ISP1020_INTRvoid isp1020_print_status_entry(struct Status_Entry *status){ int i; printk("qlogicisp : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n", status->hdr.entry_cnt, status->hdr.entry_type, status->hdr.flags); printk("qlogicisp : scsi status = 0x%04x, completion status = 0x%04x\n", le16_to_cpu(status->scsi_status), le16_to_cpu(status->completion_status)); printk("qlogicisp : state flags = 0x%04x, status flags = 0x%04x\n", le16_to_cpu(status->state_flags), le16_to_cpu(status->status_flags)); printk("qlogicisp : time = 0x%04x, request sense length = 0x%04x\n", le16_to_cpu(status->time), le16_to_cpu(status->req_sense_len)); printk("qlogicisp : residual transfer length = 0x%08x\n", le32_to_cpu(status->residual)); for (i = 0; i < le16_to_cpu(status->req_sense_len); i++) printk("qlogicisp : sense data = 0x%02x\n", status->req_sense_data[i]);}#endif /* DEBUG_ISP1020_INTR */#if DEBUG_ISP1020void isp1020_print_scsi_cmd(Scsi_Cmnd *cmd){ int i; printk("qlogicisp : target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n", cmd->target, cmd->lun, cmd->cmd_len); printk("qlogicisp : command = "); for (i = 0; i < cmd->cmd_len; i++) printk("0x%02x ", cmd->cmnd[i]); printk("\n");}#endif /* DEBUG_ISP1020 */#ifdef MODULEScsi_Host_Template driver_template = QLOGICISP;#include "scsi_module.c"#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -