qla_init.c
来自「linux 内核源代码」· C语言 代码 · 共 2,472 行 · 第 1/5 页
C
2,472 行
/* * 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 "qla_devtbl.h"#ifdef CONFIG_SPARC#include <asm/prom.h>#endif/* 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 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 *);static int qla2x00_find_new_loop_id(scsi_qla_host_t *ha, fc_port_t *dev);/****************************************************************************//* 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; /* 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 = DFLG_NO_CABLE; 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); ha->isp_ops->get_flash_version(ha, ha->request_ring); qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); ha->isp_ops->nvram_config(ha); if (ha->flags.disable_serdes) { /* Mask HBA via NVRAM settings? */ qla_printk(KERN_INFO, ha, "Masking HBA WWPN " "%02x%02x%02x%02x%02x%02x%02x%02x (via NVRAM).\n", ha->port_name[0], ha->port_name[1], ha->port_name[2], ha->port_name[3], ha->port_name[4], ha->port_name[5], ha->port_name[6], ha->port_name[7]); return QLA_FUNCTION_FAILED; } qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { rval = ha->isp_ops->chip_diag(ha); if (rval) return (rval); rval = qla2x00_setup_chip(ha); if (rval) return (rval); } rval = qla2x00_init_rings(ha); 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; uint32_t d; unsigned long flags; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; pci_set_master(ha->pdev); pci_try_set_mwi(ha->pdev); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= (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; uint32_t d; unsigned long flags = 0; uint32_t cnt; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; pci_set_master(ha->pdev); pci_try_set_mwi(ha->pdev); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); if (IS_QLA2322(ha) || IS_QLA6322(ha)) w &= ~PCI_COMMAND_INTX_DISABLE; pci_write_config_word(ha->pdev, PCI_COMMAND, w); /* * 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) pci_clear_mwi(ha->pdev); /* 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_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; uint32_t d; unsigned long flags = 0; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; pci_set_master(ha->pdev); pci_try_set_mwi(ha->pdev); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= (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). */ if (pci_find_capability(ha->pdev, PCI_CAP_ID_PCIX)) pcix_set_mmrbc(ha->pdev, 2048); /* PCIe -- adjust Maximum Read Request Size (2048). */ if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP)) pcie_set_readrq(ha->pdev, 2048); /* 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); ha->chip_revision = ha->pdev->revision; /* 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;}/** * qla25xx_pci_config() - Setup ISP25xx PCI configuration registers. * @ha: HA context * * Returns 0 on success. */intqla25xx_pci_config(scsi_qla_host_t *ha){ uint16_t w; uint32_t d; pci_set_master(ha->pdev); pci_try_set_mwi(ha->pdev); pci_read_config_word(ha->pdev, PCI_COMMAND, &w); w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); w &= ~PCI_COMMAND_INTX_DISABLE; pci_write_config_word(ha->pdev, PCI_COMMAND, w); /* PCIe -- adjust Maximum Read Request Size (2048). */ if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP)) pcie_set_readrq(ha->pdev, 2048); /* 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); ha->chip_revision = ha->pdev->revision; 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, ha->fw_srisc_address); } 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; 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); /* Wait for RISC to recover from reset. */ if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) { /* * It is necessary to for a delay here since the card doesn't * respond to PCI reads during a reset. On some architectures * this will result in an MCA. */ udelay(20); for (cnt = 30000; cnt; cnt--) { if ((RD_REG_WORD(®->ctrl_status) & CSR_ISP_SOFT_RESET) == 0) break; udelay(100); } } else udelay(10); /* Reset RISC processor. */ WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); WRT_REG_WORD(®->semaphore, 0); /* Release RISC processor. */ WRT_REG_WORD(®->hccr, HCCR_RELEASE_RISC); RD_REG_WORD(®->hccr); /* PCI Posting. */ if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) { for (cnt = 0; cnt < 30000; cnt++) { if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY) break; udelay(100); } } else udelay(100); /* Turn on master enable */ cmd |= PCI_COMMAND_MASTER; 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); RD_REG_WORD(®->hccr); /* PCI Posting. */ } spin_unlock_irqrestore(&ha->hardware_lock, flags);}/** * qla24xx_reset_risc() - Perform full reset of ISP24xx RISC.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?