qla_init.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,528 行 · 第 1/5 页
C
2,528 行
pci_write_config_word(ha->pdev, PCI_COMMAND, cmd); /* Disable RISC pause on FPM parity error. */ if (!IS_QLA2100(ha)) WRT_REG_WORD(®->hccr, HCCR_DISABLE_PARITY_PAUSE); spin_unlock_irqrestore(&ha->hardware_lock, flags);}/** * qla2x00_chip_diag() - Test chip for proper operation. * @ha: HA context * * Returns 0 on success. */static intqla2x00_chip_diag(scsi_qla_host_t *ha){ int rval; device_reg_t *reg = ha->iobase; unsigned long flags = 0; uint16_t data; uint32_t cnt; uint16_t mb[5]; /* Assume a failed state */ rval = QLA_FUNCTION_FAILED; DEBUG3(printk("scsi(%ld): Testing device at %lx.\n", ha->host_no, (u_long)®->flash_address)); spin_lock_irqsave(&ha->hardware_lock, flags); /* Reset ISP chip. */ WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); /* * We need to have a delay here since the card will not respond while * in reset causing an MCA on some architectures. */ udelay(20); data = qla2x00_debounce_register(®->ctrl_status); for (cnt = 6000000 ; cnt && (data & CSR_ISP_SOFT_RESET); cnt--) { udelay(5); data = RD_REG_WORD(®->ctrl_status); barrier(); } if (!cnt) goto chip_diag_failed; DEBUG3(printk("scsi(%ld): Reset register cleared by chip reset\n", ha->host_no)); /* Reset RISC processor. */ WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC); /* Workaround for QLA2312 PCI parity error */ if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) { data = qla2x00_debounce_register(MAILBOX_REG(ha, reg, 0)); for (cnt = 6000000; cnt && (data == MBS_BUSY); cnt--) { udelay(5); data = RD_MAILBOX_REG(ha, reg, 0); barrier(); } } else udelay(10); if (!cnt) goto chip_diag_failed; /* Check product ID of chip */ DEBUG3(printk("scsi(%ld): Checking product ID of chip\n", ha->host_no)); mb[1] = RD_MAILBOX_REG(ha, reg, 1); mb[2] = RD_MAILBOX_REG(ha, reg, 2); mb[3] = RD_MAILBOX_REG(ha, reg, 3); mb[4] = qla2x00_debounce_register(MAILBOX_REG(ha, reg, 4)); if (mb[1] != PROD_ID_1 || (mb[2] != PROD_ID_2 && mb[2] != PROD_ID_2a) || mb[3] != PROD_ID_3) { qla_printk(KERN_WARNING, ha, "Wrong product ID = 0x%x,0x%x,0x%x\n", mb[1], mb[2], mb[3]); goto chip_diag_failed; } ha->product_id[0] = mb[1]; ha->product_id[1] = mb[2]; ha->product_id[2] = mb[3]; ha->product_id[3] = mb[4]; /* Adjust fw RISC transfer size */ if (ha->request_q_length > 1024) ha->fw_transfer_size = REQUEST_ENTRY_SIZE * 1024; else ha->fw_transfer_size = REQUEST_ENTRY_SIZE * ha->request_q_length; if (IS_QLA2200(ha) && RD_MAILBOX_REG(ha, reg, 7) == QLA2200A_RISC_ROM_VER) { /* Limit firmware transfer size with a 2200A */ DEBUG3(printk("scsi(%ld): Found QLA2200A chip.\n", ha->host_no)); ha->fw_transfer_size = 128; } /* Wrap Incoming Mailboxes Test. */ spin_unlock_irqrestore(&ha->hardware_lock, flags); DEBUG3(printk("scsi(%ld): Checking mailboxes.\n", ha->host_no)); rval = qla2x00_mbx_reg_test(ha); if (rval) { DEBUG(printk("scsi(%ld): Failed mailbox send register test\n", ha->host_no)); qla_printk(KERN_WARNING, ha, "Failed mailbox send register test\n"); } else { /* Flag a successful rval */ rval = QLA_SUCCESS; } spin_lock_irqsave(&ha->hardware_lock, flags);chip_diag_failed: if (rval) DEBUG2_3(printk("scsi(%ld): Chip diagnostics **** FAILED " "****\n", ha->host_no)); spin_unlock_irqrestore(&ha->hardware_lock, flags); return (rval);}/** * qla2x00_setup_chip() - Load and start RISC firmware. * @ha: HA context * * Returns 0 on success. */static intqla2x00_setup_chip(scsi_qla_host_t *ha){ int rval; uint16_t cnt; uint16_t *risc_code; unsigned long risc_address; unsigned long risc_code_size; int num; int i; uint16_t *req_ring; struct qla_fw_info *fw_iter; rval = QLA_SUCCESS; /* Load firmware sequences */ fw_iter = ha->brd_info->fw_info; while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) { risc_code = fw_iter->fwcode; risc_code_size = *fw_iter->fwlen; if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) { risc_address = *fw_iter->fwstart; } else { /* Extended address */ risc_address = *fw_iter->lfwstart; } num = 0; rval = 0; while (risc_code_size > 0 && !rval) { cnt = (uint16_t)(ha->fw_transfer_size >> 1); if (cnt > risc_code_size) cnt = risc_code_size; DEBUG7(printk("scsi(%ld): Loading risc segment@ " "addr %p, number of bytes 0x%x, offset 0x%lx.\n", ha->host_no, risc_code, cnt, risc_address)); req_ring = (uint16_t *)ha->request_ring; for (i = 0; i < cnt; i++) req_ring[i] = cpu_to_le16(risc_code[i]); if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) { rval = qla2x00_load_ram(ha, ha->request_dma, risc_address, cnt); } else { rval = qla2x00_load_ram_ext(ha, ha->request_dma, risc_address, cnt); } if (rval) { DEBUG(printk("scsi(%ld): [ERROR] Failed to " "load segment %d of firmware\n", ha->host_no, num)); qla_printk(KERN_WARNING, ha, "[ERROR] Failed to load " "segment %d of firmware\n", num); qla2x00_dump_regs(ha); break; } risc_code += cnt; risc_address += cnt; risc_code_size -= cnt; num++; } /* Next firmware sequence */ fw_iter++; } /* Verify checksum of loaded RISC code. */ if (!rval) { DEBUG(printk("scsi(%ld): Verifying Checksum of loaded RISC " "code.\n", ha->host_no)); rval = qla2x00_verify_checksum(ha); if (rval == QLA_SUCCESS) { /* Start firmware execution. */ DEBUG(printk("scsi(%ld): Checksum OK, start " "firmware.\n", ha->host_no)); rval = qla2x00_execute_fw(ha); /* Retrieve firmware information. */ if (rval == QLA_SUCCESS && ha->fw_major_version == 0) { qla2x00_get_fw_version(ha, &ha->fw_major_version, &ha->fw_minor_version, &ha->fw_subminor_version, &ha->fw_attributes, &ha->fw_memory_size); } } else { DEBUG2(printk(KERN_INFO "scsi(%ld): ISP Firmware failed checksum.\n", ha->host_no)); } } if (rval) { DEBUG2_3(printk("scsi(%ld): Setup chip **** FAILED ****.\n", ha->host_no)); } return (rval);}/** * qla2x00_init_response_q_entries() - Initializes response queue entries. * @ha: HA context * * Beginning of request ring has initialization control block already built * by nvram config routine. * * Returns 0 on success. */static voidqla2x00_init_response_q_entries(scsi_qla_host_t *ha){ uint16_t cnt; response_t *pkt; pkt = ha->response_ring_ptr; for (cnt = 0; cnt < ha->response_q_length; cnt++) { pkt->signature = RESPONSE_PROCESSED; pkt++; }}/** * qla2x00_update_fw_options() - Read and process firmware options. * @ha: HA context * * Returns 0 on success. */static voidqla2x00_update_fw_options(scsi_qla_host_t *ha){ /* Setup seriallink options */ uint16_t swing, emphasis; memset(ha->fw_options, 0, sizeof(ha->fw_options)); qla2x00_get_fw_options(ha, ha->fw_options); if (IS_QLA2100(ha) || IS_QLA2200(ha)) return; /* Serial Link options. */ DEBUG3(printk("scsi(%ld): Serial link options:\n", ha->host_no)); DEBUG3(qla2x00_dump_buffer((uint8_t *)&ha->fw_seriallink_options, sizeof(ha->fw_seriallink_options))); ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING; if (ha->fw_seriallink_options[1] & BIT_2) ha->fw_options[1] |= FO1_SET_EMPHASIS_SWING; /* 1G settings */ swing = ha->fw_seriallink_options[0] & (BIT_2 | BIT_1 | BIT_0); emphasis = ha->fw_seriallink_options[0] & (BIT_4 | BIT_3); emphasis >>= 3; ha->fw_options[10] = (emphasis << 14) | (swing << 8) | 0x3; /* 2G settings */ swing = ha->fw_seriallink_options[0] & (BIT_7 | BIT_6 | BIT_5); swing >>= 5; emphasis = ha->fw_seriallink_options[1] & (BIT_1 | BIT_0); ha->fw_options[11] = (emphasis << 14) | (swing << 8) | 0x3; /* FCP2 options. */ /* Return command IOCBs without waiting for an ABTS to complete. */ ha->fw_options[3] |= BIT_13; /* Update Serial Link options. */ qla2x00_set_fw_options(ha, ha->fw_options);}/** * 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; device_reg_t *reg = ha->iobase; spin_lock_irqsave(&ha->hardware_lock, flags); /* Clear outstanding commands array. */ for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) ha->outstanding_cmds[cnt] = 0; 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); 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)); spin_unlock_irqrestore(&ha->hardware_lock, flags); DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); rval = qla2x00_init_firmware(ha, sizeof(init_cb_t)); if (rval) { DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n", ha->host_no)); } else { /* Update any ISP specific firmware options. */ qla2x00_update_fw_options(ha); 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 */ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ / 2); 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];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?