qla_init.c
来自「linux2.6.16版本」· C语言 代码 · 共 2,472 行 · 第 1/5 页
C
2,472 行
} else if (IS_QLA2322(ha) || IS_QLA6322(ha)) ha->fw_options[11] |= BIT_5 | ((rx_sens & (BIT_1 | BIT_0)) << 2) | (tx_sens & (BIT_1 | BIT_0)); } /* FCP2 options. */ /* Return command IOCBs without waiting for an ABTS to complete. */ ha->fw_options[3] |= BIT_13; /* LED scheme. */ if (ha->flags.enable_led_scheme) ha->fw_options[2] |= BIT_12; /* Update firmware options. */ qla2x00_set_fw_options(ha, ha->fw_options);}voidqla24xx_update_fw_options(scsi_qla_host_t *ha){ int rval; /* Update Serial Link options. */ if ((le16_to_cpu(ha->fw_seriallink_options24[0]) & BIT_0) == 0) return; rval = qla2x00_set_serdes_params(ha, le16_to_cpu(ha->fw_seriallink_options24[1]), le16_to_cpu(ha->fw_seriallink_options24[2]), le16_to_cpu(ha->fw_seriallink_options24[3])); if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "Unable to update Serial Link options (%x).\n", rval); }}voidqla2x00_config_rings(struct scsi_qla_host *ha){ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; /* Setup ring parameters in initialization control block. */ ha->init_cb->request_q_outpointer = __constant_cpu_to_le16(0); ha->init_cb->response_q_inpointer = __constant_cpu_to_le16(0); ha->init_cb->request_q_length = cpu_to_le16(ha->request_q_length); ha->init_cb->response_q_length = cpu_to_le16(ha->response_q_length); ha->init_cb->request_q_address[0] = cpu_to_le32(LSD(ha->request_dma)); ha->init_cb->request_q_address[1] = cpu_to_le32(MSD(ha->request_dma)); ha->init_cb->response_q_address[0] = cpu_to_le32(LSD(ha->response_dma)); ha->init_cb->response_q_address[1] = cpu_to_le32(MSD(ha->response_dma)); WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), 0); WRT_REG_WORD(ISP_REQ_Q_OUT(ha, reg), 0); WRT_REG_WORD(ISP_RSP_Q_IN(ha, reg), 0); WRT_REG_WORD(ISP_RSP_Q_OUT(ha, reg), 0); RD_REG_WORD(ISP_RSP_Q_OUT(ha, reg)); /* PCI Posting. */}voidqla24xx_config_rings(struct scsi_qla_host *ha){ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; struct init_cb_24xx *icb; /* Setup ring parameters in initialization control block. */ icb = (struct init_cb_24xx *)ha->init_cb; icb->request_q_outpointer = __constant_cpu_to_le16(0); icb->response_q_inpointer = __constant_cpu_to_le16(0); icb->request_q_length = cpu_to_le16(ha->request_q_length); icb->response_q_length = cpu_to_le16(ha->response_q_length); icb->request_q_address[0] = cpu_to_le32(LSD(ha->request_dma)); icb->request_q_address[1] = cpu_to_le32(MSD(ha->request_dma)); icb->response_q_address[0] = cpu_to_le32(LSD(ha->response_dma)); icb->response_q_address[1] = cpu_to_le32(MSD(ha->response_dma)); WRT_REG_DWORD(®->req_q_in, 0); WRT_REG_DWORD(®->req_q_out, 0); WRT_REG_DWORD(®->rsp_q_in, 0); WRT_REG_DWORD(®->rsp_q_out, 0); RD_REG_DWORD(®->rsp_q_out);}/** * qla2x00_init_rings() - Initializes firmware. * @ha: HA context * * Beginning of request ring has initialization control block already built * by nvram config routine. * * Returns 0 on success. */static intqla2x00_init_rings(scsi_qla_host_t *ha){ int rval; unsigned long flags = 0; int cnt; spin_lock_irqsave(&ha->hardware_lock, flags); /* Clear outstanding commands array. */ for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) ha->outstanding_cmds[cnt] = NULL; ha->current_outstanding_cmd = 0; /* Clear RSCN queue. */ ha->rscn_in_ptr = 0; ha->rscn_out_ptr = 0; /* Initialize firmware. */ ha->request_ring_ptr = ha->request_ring; ha->req_ring_index = 0; ha->req_q_cnt = ha->request_q_length; ha->response_ring_ptr = ha->response_ring; ha->rsp_ring_index = 0; /* Initialize response queue entries */ qla2x00_init_response_q_entries(ha); ha->isp_ops.config_rings(ha); spin_unlock_irqrestore(&ha->hardware_lock, flags); /* Update any ISP specific firmware options before initialization. */ ha->isp_ops.update_fw_options(ha); DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); rval = qla2x00_init_firmware(ha, ha->init_cb_size); if (rval) { DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n", ha->host_no)); } else { DEBUG3(printk("scsi(%ld): Init firmware -- success.\n", ha->host_no)); } return (rval);}/** * qla2x00_fw_ready() - Waits for firmware ready. * @ha: HA context * * Returns 0 on success. */static intqla2x00_fw_ready(scsi_qla_host_t *ha){ int rval; unsigned long wtime, mtime; uint16_t min_wait; /* Minimum wait time if loop is down */ uint16_t wait_time; /* Wait time if loop is coming ready */ uint16_t fw_state; rval = QLA_SUCCESS; /* 20 seconds for loop down. */ min_wait = 20; /* * Firmware should take at most one RATOV to login, plus 5 seconds for * our own processing. */ if ((wait_time = (ha->retry_count*ha->login_timeout) + 5) < min_wait) { wait_time = min_wait; } /* Min wait time if loop down */ mtime = jiffies + (min_wait * HZ); /* wait time before firmware ready */ wtime = jiffies + (wait_time * HZ); /* Wait for ISP to finish LIP */ if (!ha->flags.init_done) qla_printk(KERN_INFO, ha, "Waiting for LIP to complete...\n"); DEBUG3(printk("scsi(%ld): Waiting for LIP to complete...\n", ha->host_no)); do { rval = qla2x00_get_firmware_state(ha, &fw_state); if (rval == QLA_SUCCESS) { if (fw_state < FSTATE_LOSS_OF_SYNC) { ha->device_flags &= ~DFLG_NO_CABLE; } if (fw_state == FSTATE_READY) { DEBUG(printk("scsi(%ld): F/W Ready - OK \n", ha->host_no)); qla2x00_get_retry_cnt(ha, &ha->retry_count, &ha->login_timeout, &ha->r_a_tov); rval = QLA_SUCCESS; break; } rval = QLA_FUNCTION_FAILED; if (atomic_read(&ha->loop_down_timer) && (fw_state >= FSTATE_LOSS_OF_SYNC || fw_state == FSTATE_WAIT_AL_PA)) { /* Loop down. Timeout on min_wait for states * other than Wait for Login. */ if (time_after_eq(jiffies, mtime)) { qla_printk(KERN_INFO, ha, "Cable is unplugged...\n"); ha->device_flags |= DFLG_NO_CABLE; break; } } } else { /* Mailbox cmd failed. Timeout on min_wait. */ if (time_after_eq(jiffies, mtime)) break; } if (time_after_eq(jiffies, wtime)) break; /* Delay for a while */ msleep(500); DEBUG3(printk("scsi(%ld): fw_state=%x curr time=%lx.\n", ha->host_no, fw_state, jiffies)); } while (1); DEBUG(printk("scsi(%ld): fw_state=%x curr time=%lx.\n", ha->host_no, fw_state, jiffies)); if (rval) { DEBUG2_3(printk("scsi(%ld): Firmware ready **** FAILED ****.\n", ha->host_no)); } return (rval);}/** qla2x00_configure_hba* Setup adapter context.** Input:* ha = adapter state pointer.** Returns:* 0 = success** Context:* Kernel context.*/static intqla2x00_configure_hba(scsi_qla_host_t *ha){ int rval; uint16_t loop_id; uint16_t topo; uint8_t al_pa; uint8_t area; uint8_t domain; char connect_type[22]; /* Get host addresses. */ rval = qla2x00_get_adapter_id(ha, &loop_id, &al_pa, &area, &domain, &topo); if (rval != QLA_SUCCESS) { if (LOOP_TRANSITION(ha) || atomic_read(&ha->loop_down_timer) || (rval == QLA_COMMAND_ERROR && loop_id == 0x7)) { DEBUG2(printk("%s(%ld) Loop is in a transition state\n", __func__, ha->host_no)); } else { qla_printk(KERN_WARNING, ha, "ERROR -- Unable to get host loop ID.\n"); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); } return (rval); } if (topo == 4) { qla_printk(KERN_INFO, ha, "Cannot get topology - retrying.\n"); return (QLA_FUNCTION_FAILED); } ha->loop_id = loop_id; /* initialize */ ha->min_external_loopid = SNS_FIRST_LOOP_ID; ha->operating_mode = LOOP; switch (topo) { case 0: DEBUG3(printk("scsi(%ld): HBA in NL topology.\n", ha->host_no)); ha->current_topology = ISP_CFG_NL; strcpy(connect_type, "(Loop)"); break; case 1: DEBUG3(printk("scsi(%ld): HBA in FL topology.\n", ha->host_no)); ha->current_topology = ISP_CFG_FL; strcpy(connect_type, "(FL_Port)"); break; case 2: DEBUG3(printk("scsi(%ld): HBA in N P2P topology.\n", ha->host_no)); ha->operating_mode = P2P; ha->current_topology = ISP_CFG_N; strcpy(connect_type, "(N_Port-to-N_Port)"); break; case 3: DEBUG3(printk("scsi(%ld): HBA in F P2P topology.\n", ha->host_no)); ha->operating_mode = P2P; ha->current_topology = ISP_CFG_F; strcpy(connect_type, "(F_Port)"); break; default: DEBUG3(printk("scsi(%ld): HBA in unknown topology %x. " "Using NL.\n", ha->host_no, topo)); ha->current_topology = ISP_CFG_NL; strcpy(connect_type, "(Loop)"); break; } /* Save Host port and loop ID. */ /* byte order - Big Endian */ ha->d_id.b.domain = domain; ha->d_id.b.area = area; ha->d_id.b.al_pa = al_pa; if (!ha->flags.init_done) qla_printk(KERN_INFO, ha, "Topology - %s, Host Loop address 0x%x\n", connect_type, ha->loop_id); if (rval) { DEBUG2_3(printk("scsi(%ld): FAILED.\n", ha->host_no)); } else { DEBUG3(printk("scsi(%ld): exiting normally.\n", ha->host_no)); } return(rval);}/** NVRAM configuration for ISP 2xxx** Input:* ha = adapter block pointer.** Output:* initialization control block in response_ring* host adapters parameters in host adapter block** Returns:* 0 = success.*/intqla2x00_nvram_config(scsi_qla_host_t *ha){ int rval; uint8_t chksum = 0; uint16_t cnt; uint8_t *dptr1, *dptr2; init_cb_t *icb = ha->init_cb; nvram_t *nv = (nvram_t *)ha->request_ring; uint8_t *ptr = (uint8_t *)ha->request_ring; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; rval = QLA_SUCCESS; /* Determine NVRAM starting address. */ ha->nvram_size = sizeof(nvram_t); ha->nvram_base = 0; if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha)) if ((RD_REG_WORD(®->ctrl_status) >> 14) == 1) ha->nvram_base = 0x80; /* Get NVRAM data and calculate checksum. */ ha->isp_ops.read_nvram(ha, ptr, ha->nvram_base, ha->nvram_size); for (cnt = 0, chksum = 0; cnt < ha->nvram_size; cnt++) chksum += *ptr++; DEBUG5(printk("scsi(%ld): Contents of NVRAM\n", ha->host_no)); DEBUG5(qla2x00_dump_buffer((uint8_t *)ha->request_ring, ha->nvram_size)); /* Bad NVRAM data, set defaults parameters. */ if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P' || nv->id[3] != ' ' || nv->nvram_version < 1) { /* Reset NVRAM data. */ qla_printk(KERN_WARNING, ha, "Inconsistent NVRAM detected: " "checksum=0x%x id=%c version=0x%x.\n", chksum, nv->id[0], nv->nvram_version); qla_printk(KERN_WARNING, ha, "Falling back to functioning (yet " "invalid -- WWPN) defaults.\n"); /* * Set default initialization control block. */ memset(nv, 0, ha->nvram_size); nv->parameter_block_version = ICB_VERSION; if (IS_QLA23XX(ha)) { nv->firmware_options[0] = BIT_2 | BIT_1; nv->firmware_options[1] = BIT_7 | BIT_5; nv->add_firmware_options[0] = BIT_5; nv->add_firmware_options[1] = BIT_5 | BIT_4; nv->frame_payload_size = __constant_cpu_to_le16(2048); nv->special_options[1] = BIT_7; } else if (IS_QLA2200(ha)) { nv->firmware_options[0] = BIT_2 | BIT_1; nv->firmware_options[1] = BIT_7 | BIT_5; nv->add_firmware_options[0] = BIT_5; nv->add_firmware_options[1] = BIT_5 | BIT_4; nv->frame_payload_size = __constant_cpu_to_le16(1024); } else if (IS_QLA2100(ha)) { nv->firmware_options[0] = BIT_3 | BIT_1; nv->firmware_options[1] = BIT_5; nv->frame_payload_size = __constant_cpu_to_le16(1024); } nv->max_iocb_allocation = __constant_cpu_to_le16(256); nv->execution_throttle = __constant_cpu_to_le16(16); nv->retry_count = 8; nv->retry_delay = 1; nv->port_name[0] = 33; nv->port_name[3] = 224; nv->port_name[4] = 139; nv->login_timeout = 4; /* * Set default host adapter parameters */ nv->host_p[1] = BIT_2; nv->reset_delay = 5; nv->port_down_retry_count = 8; nv->max_luns_per_target = __constant_cpu_to_le16(8); nv->link_down_timeout = 60; rval = 1; }#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) /* * The SN2 does not provide BIOS emulation which means you can't change * potentially bogus BIOS settings. Force the use of default settings * for link rate and frame size. Hope that the rest of the settings * are valid. */ if (ia64_platform_is("sn2")) { nv->frame_payload_size = __constant_cpu_to_le16(2048); if (IS_QLA23XX(ha)) nv->special_options[1] = BIT_7; }#endif /* Reset Initialization control block */ memset(icb, 0, ha->init_cb_size); /* * Setup driver NVRAM options. */ nv->firmware_options[0] |= (BIT_6 | BIT_1); nv->firmware_options[0] &= ~(BIT_5 | BIT_4); nv->firmware_options[1] |= (BIT_5 | BIT_0); nv->firmware_options[1] &= ~BIT_4; if (IS_QLA23XX(ha)) { nv->firmware_options[0] |= BIT_2; nv->firmware_options[0] &= ~BIT_3; nv->add_firmware_options[1] |= BIT_5 | BIT_4; if (IS_QLA2300(ha)) { if (ha->fb_rev == FPM_2310) { strcpy(ha->model_number, "QLA2310"); } else { strcpy(ha->model_number, "QLA2300"); } } else { if (rval == 0 && memcmp(nv->model_number, BINZERO, sizeof(nv->model_number)) != 0) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?