📄 qla_init.c
字号:
/* * QLogic Fibre Channel HBA Driver * Copyright (c) 2003-2005 QLogic Corporation * * See LICENSE.qla2xxx for copyright and licensing details. */#include "qla_def.h"#include <linux/delay.h>#include <linux/vmalloc.h>#include <linux/firmware.h>#include <scsi/scsi_transport_fc.h>#include "qla_devtbl.h"/* XXX(hch): this is ugly, but we don't want to pull in exioctl.h */#ifndef EXT_IS_LUN_BIT_SET#define EXT_IS_LUN_BIT_SET(P,L) \ (((P)->mask[L/8] & (0x80 >> (L%8)))?1:0)#define EXT_SET_LUN_BIT(P,L) \ ((P)->mask[L/8] |= (0x80 >> (L%8)))#endif/** QLogic ISP2x00 Hardware Support Function Prototypes.*/static int qla2x00_isp_firmware(scsi_qla_host_t *);static void qla2x00_resize_request_q(scsi_qla_host_t *);static int qla2x00_setup_chip(scsi_qla_host_t *);static void qla2x00_init_response_q_entries(scsi_qla_host_t *);static int qla2x00_init_rings(scsi_qla_host_t *);static int qla2x00_fw_ready(scsi_qla_host_t *);static int qla2x00_configure_hba(scsi_qla_host_t *);static int qla2x00_configure_loop(scsi_qla_host_t *);static int qla2x00_configure_local_loop(scsi_qla_host_t *);static void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);static int qla2x00_configure_fabric(scsi_qla_host_t *);static int qla2x00_find_all_fabric_devs(scsi_qla_host_t *, struct list_head *);static int qla2x00_device_resync(scsi_qla_host_t *);static int qla2x00_fabric_dev_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);static int qla2x00_restart_isp(scsi_qla_host_t *);/****************************************************************************//* QLogic ISP2x00 Hardware Support Functions. *//****************************************************************************//** qla2x00_initialize_adapter* Initialize board.** Input:* ha = adapter block pointer.** Returns:* 0 = success*/intqla2x00_initialize_adapter(scsi_qla_host_t *ha){ int rval; uint8_t restart_risc = 0; uint8_t retry; uint32_t wait_time; /* Clear adapter flags. */ ha->flags.online = 0; ha->flags.reset_active = 0; atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); atomic_set(&ha->loop_state, LOOP_DOWN); ha->device_flags = 0; ha->dpc_flags = 0; ha->flags.management_server_logged_in = 0; ha->marker_needed = 0; ha->mbx_flags = 0; ha->isp_abort_cnt = 0; ha->beacon_blink_led = 0; set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); qla_printk(KERN_INFO, ha, "Configuring PCI space...\n"); rval = ha->isp_ops.pci_config(ha); if (rval) { DEBUG2(printk("scsi(%ld): Unable to configure PCI space=n", ha->host_no)); return (rval); } ha->isp_ops.reset_chip(ha); qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); ha->isp_ops.nvram_config(ha); qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); retry = 10; /* * Try to configure the loop. */ do { restart_risc = 0; /* If firmware needs to be loaded */ if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { if ((rval = ha->isp_ops.chip_diag(ha)) == QLA_SUCCESS) { rval = qla2x00_setup_chip(ha); } } if (rval == QLA_SUCCESS && (rval = qla2x00_init_rings(ha)) == QLA_SUCCESS) {check_fw_ready_again: /* * Wait for a successful LIP up to a maximum * of (in seconds): RISC login timeout value, * RISC retry count value, and port down retry * value OR a minimum of 4 seconds OR If no * cable, only 5 seconds. */ rval = qla2x00_fw_ready(ha); if (rval == QLA_SUCCESS) { clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); /* Issue a marker after FW becomes ready. */ qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); /* * Wait at most MAX_TARGET RSCNs for a stable * link. */ wait_time = 256; do { clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); rval = qla2x00_configure_loop(ha); if (test_and_clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) { restart_risc = 1; break; } /* * If loop state change while we were * discoverying devices then wait for * LIP to complete */ if (atomic_read(&ha->loop_state) != LOOP_READY && retry--) { goto check_fw_ready_again; } wait_time--; } while (!atomic_read(&ha->loop_down_timer) && retry && wait_time && (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))); if (wait_time == 0) rval = QLA_FUNCTION_FAILED; } else if (ha->device_flags & DFLG_NO_CABLE) /* If no cable, then all is good. */ rval = QLA_SUCCESS; } } while (restart_risc && retry--); if (rval == QLA_SUCCESS) { clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); ha->marker_needed = 0; ha->flags.online = 1; } else { DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__)); } return (rval);}/** * qla2100_pci_config() - Setup ISP21xx PCI configuration registers. * @ha: HA context * * Returns 0 on success. */intqla2100_pci_config(scsi_qla_host_t *ha){ uint16_t w, mwi; uint32_t d; unsigned long flags; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; pci_set_master(ha->pdev); mwi = 0; if (pci_set_mwi(ha->pdev)) mwi = PCI_COMMAND_INVALIDATE; pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); pci_write_config_word(ha->pdev, PCI_COMMAND, w); /* Reset expansion ROM address decode enable */ pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); d &= ~PCI_ROM_ADDRESS_ENABLE; pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); ha->pci_attr = RD_REG_WORD(®->ctrl_status); spin_unlock_irqrestore(&ha->hardware_lock, flags); return QLA_SUCCESS;}/** * qla2300_pci_config() - Setup ISP23xx PCI configuration registers. * @ha: HA context * * Returns 0 on success. */intqla2300_pci_config(scsi_qla_host_t *ha){ uint16_t w, mwi; uint32_t d; unsigned long flags = 0; uint32_t cnt; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; pci_set_master(ha->pdev); mwi = 0; if (pci_set_mwi(ha->pdev)) mwi = PCI_COMMAND_INVALIDATE; pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); if (IS_QLA2322(ha) || IS_QLA6322(ha)) w &= ~PCI_COMMAND_INTX_DISABLE; /* * If this is a 2300 card and not 2312, reset the * COMMAND_INVALIDATE due to a bug in the 2300. Unfortunately, * the 2310 also reports itself as a 2300 so we need to get the * fb revision level -- a 6 indicates it really is a 2300 and * not a 2310. */ if (IS_QLA2300(ha)) { spin_lock_irqsave(&ha->hardware_lock, flags); /* Pause RISC. */ WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC); for (cnt = 0; cnt < 30000; cnt++) { if ((RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) != 0) break; udelay(10); } /* Select FPM registers. */ WRT_REG_WORD(®->ctrl_status, 0x20); RD_REG_WORD(®->ctrl_status); /* Get the fb rev level */ ha->fb_rev = RD_FB_CMD_REG(ha, reg); if (ha->fb_rev == FPM_2300) w &= ~PCI_COMMAND_INVALIDATE; /* Deselect FPM registers. */ WRT_REG_WORD(®->ctrl_status, 0x0); RD_REG_WORD(®->ctrl_status); /* Release RISC module. */ WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC); for (cnt = 0; cnt < 30000; cnt++) { if ((RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) == 0) break; udelay(10); } spin_unlock_irqrestore(&ha->hardware_lock, flags); } pci_write_config_word(ha->pdev, PCI_COMMAND, w); pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); /* Reset expansion ROM address decode enable */ pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); d &= ~PCI_ROM_ADDRESS_ENABLE; pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); ha->pci_attr = RD_REG_WORD(®->ctrl_status); spin_unlock_irqrestore(&ha->hardware_lock, flags); return QLA_SUCCESS;}/** * qla24xx_pci_config() - Setup ISP24xx PCI configuration registers. * @ha: HA context * * Returns 0 on success. */intqla24xx_pci_config(scsi_qla_host_t *ha){ uint16_t w, mwi; uint32_t d; unsigned long flags = 0; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; int pcix_cmd_reg, pcie_dctl_reg; pci_set_master(ha->pdev); mwi = 0; if (pci_set_mwi(ha->pdev)) mwi = PCI_COMMAND_INVALIDATE; pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); w &= ~PCI_COMMAND_INTX_DISABLE; pci_write_config_word(ha->pdev, PCI_COMMAND, w); pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); /* PCI-X -- adjust Maximum Memory Read Byte Count (2048). */ pcix_cmd_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_PCIX); if (pcix_cmd_reg) { uint16_t pcix_cmd; pcix_cmd_reg += PCI_X_CMD; pci_read_config_word(ha->pdev, pcix_cmd_reg, &pcix_cmd); pcix_cmd &= ~PCI_X_CMD_MAX_READ; pcix_cmd |= 0x0008; pci_write_config_word(ha->pdev, pcix_cmd_reg, pcix_cmd); } /* PCIe -- adjust Maximum Read Request Size (2048). */ pcie_dctl_reg = pci_find_capability(ha->pdev, PCI_CAP_ID_EXP); if (pcie_dctl_reg) { uint16_t pcie_dctl; pcie_dctl_reg += PCI_EXP_DEVCTL; pci_read_config_word(ha->pdev, pcie_dctl_reg, &pcie_dctl); pcie_dctl &= ~PCI_EXP_DEVCTL_READRQ; pcie_dctl |= 0x4000; pci_write_config_word(ha->pdev, pcie_dctl_reg, pcie_dctl); } /* Reset expansion ROM address decode enable */ pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); d &= ~PCI_ROM_ADDRESS_ENABLE; pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); ha->pci_attr = RD_REG_DWORD(®->ctrl_status); spin_unlock_irqrestore(&ha->hardware_lock, flags); return QLA_SUCCESS;}/** * qla2x00_isp_firmware() - Choose firmware image. * @ha: HA context * * Returns 0 on success. */static intqla2x00_isp_firmware(scsi_qla_host_t *ha){ int rval; /* Assume loading risc code */ rval = QLA_FUNCTION_FAILED; if (ha->flags.disable_risc_code_load) { DEBUG2(printk("scsi(%ld): RISC CODE NOT loaded\n", ha->host_no)); qla_printk(KERN_INFO, ha, "RISC CODE NOT loaded\n"); /* Verify checksum of loaded RISC code. */ rval = qla2x00_verify_checksum(ha, IS_QLA24XX(ha) || IS_QLA25XX(ha) ? RISC_SADDRESS : *ha->brd_info->fw_info[0].fwstart); } if (rval) { DEBUG2_3(printk("scsi(%ld): **** Load RISC code ****\n", ha->host_no)); } return (rval);}/** * qla2x00_reset_chip() - Reset ISP chip. * @ha: HA context * * Returns 0 on success. */voidqla2x00_reset_chip(scsi_qla_host_t *ha){ unsigned long flags = 0; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; uint32_t cnt; unsigned long mbx_flags = 0; uint16_t cmd; ha->isp_ops.disable_intrs(ha); spin_lock_irqsave(&ha->hardware_lock, flags); /* Turn off master enable */ cmd = 0; pci_read_config_word(ha->pdev, PCI_COMMAND, &cmd); cmd &= ~PCI_COMMAND_MASTER; pci_write_config_word(ha->pdev, PCI_COMMAND, cmd); if (!IS_QLA2100(ha)) { /* Pause RISC. */ WRT_REG_WORD(®->hccr, HCCR_PAUSE_RISC); if (IS_QLA2200(ha) || IS_QLA2300(ha)) { for (cnt = 0; cnt < 30000; cnt++) { if ((RD_REG_WORD(®->hccr) & HCCR_RISC_PAUSE) != 0) break; udelay(100); } } else { RD_REG_WORD(®->hccr); /* PCI Posting. */ udelay(10); } /* Select FPM registers. */ WRT_REG_WORD(®->ctrl_status, 0x20); RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ /* FPM Soft Reset. */ WRT_REG_WORD(®->fpm_diag_config, 0x100); RD_REG_WORD(®->fpm_diag_config); /* PCI Posting. */ /* Toggle Fpm Reset. */ if (!IS_QLA2200(ha)) { WRT_REG_WORD(®->fpm_diag_config, 0x0); RD_REG_WORD(®->fpm_diag_config); /* PCI Posting. */ } /* Select frame buffer registers. */ WRT_REG_WORD(®->ctrl_status, 0x10); RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ /* Reset frame buffer FIFOs. */ if (IS_QLA2200(ha)) { WRT_FB_CMD_REG(ha, reg, 0xa000); RD_FB_CMD_REG(ha, reg); /* PCI Posting. */ } else { WRT_FB_CMD_REG(ha, reg, 0x00fc); /* Read back fb_cmd until zero or 3 seconds max */ for (cnt = 0; cnt < 3000; cnt++) { if ((RD_FB_CMD_REG(ha, reg) & 0xff) == 0) break; udelay(100); } } /* Select RISC module registers. */ WRT_REG_WORD(®->ctrl_status, 0); RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ /* Reset RISC processor. */ WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); RD_REG_WORD(®->hccr); /* PCI Posting. */ /* Release RISC processor. */ WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC); RD_REG_WORD(®->hccr); /* PCI Posting. */ } WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); WRT_REG_WORD(®->hccr, HCCR_CLR_HOST_INT); /* Reset ISP chip. */ WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -