[SCSI] qla2xxx: Add support for embedded ISP24xx firmware.
authorAndrew Vasquez <andrew.vasquez@qlogic.com>
Wed, 9 Nov 2005 23:49:19 +0000 (15:49 -0800)
committerJames Bottomley <jejb@mulgrave.(none)>
Wed, 14 Dec 2005 01:11:19 +0000 (18:11 -0700)
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
drivers/scsi/qla2xxx/Makefile
drivers/scsi/qla2xxx/ql2400.c [new file with mode: 0644]
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_os.c

index 549dfe41020889efdf4d838b9367b8faafa0d105..40c0de1258897966413cad237debe24377769aa7 100644 (file)
@@ -10,10 +10,11 @@ qla2200-y := ql2200.o ql2200_fw.o
 qla2300-y := ql2300.o ql2300_fw.o
 qla2322-y := ql2322.o ql2322_fw.o
 qla6312-y := ql6312.o ql6312_fw.o
+qla2400-y := ql2400.o ql2400_fw.o
 
 obj-$(CONFIG_SCSI_QLA21XX) += qla2xxx.o qla2100.o
 obj-$(CONFIG_SCSI_QLA22XX) += qla2xxx.o qla2200.o
 obj-$(CONFIG_SCSI_QLA2300) += qla2xxx.o qla2300.o
 obj-$(CONFIG_SCSI_QLA2322) += qla2xxx.o qla2322.o
 obj-$(CONFIG_SCSI_QLA6312) += qla2xxx.o qla6312.o
-obj-$(CONFIG_SCSI_QLA24XX) += qla2xxx.o
+obj-$(CONFIG_SCSI_QLA24XX) += qla2xxx.o qla2400.o
diff --git a/drivers/scsi/qla2xxx/ql2400.c b/drivers/scsi/qla2xxx/ql2400.c
new file mode 100644 (file)
index 0000000..6c7165f
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * QLogic Fibre Channel HBA Driver
+ * Copyright (c)  2003-2005 QLogic Corporation
+ *
+ * See LICENSE.qla2xxx for copyright and licensing details.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "qla_def.h"
+
+static char qla_driver_name[] = "qla2400";
+
+extern uint32_t fw2400_version_str[];
+extern uint32_t fw2400_addr01;
+extern uint32_t fw2400_code01[];
+extern uint32_t fw2400_length01;
+extern uint32_t fw2400_addr02;
+extern uint32_t fw2400_code02[];
+extern uint32_t fw2400_length02;
+
+static struct qla_fw_info qla_fw_tbl[] = {
+       {
+               .addressing     = FW_INFO_ADDR_EXTENDED,
+               .fwcode         = (unsigned short *)&fw2400_code01[0],
+               .fwlen          = (unsigned short *)&fw2400_length01,
+               .lfwstart       = (unsigned long *)&fw2400_addr01,
+       },
+       {
+               .addressing     = FW_INFO_ADDR_EXTENDED,
+               .fwcode         = (unsigned short *)&fw2400_code02[0],
+               .fwlen          = (unsigned short *)&fw2400_length02,
+               .lfwstart       = (unsigned long *)&fw2400_addr02,
+       },
+       { FW_INFO_ADDR_NOMORE, },
+};
+
+static struct qla_board_info qla_board_tbl[] = {
+       {
+               .drv_name       = qla_driver_name,
+               .isp_name       = "ISP2422",
+               .fw_info        = qla_fw_tbl,
+               .fw_fname       = "ql2400_fw.bin",
+       },
+       {
+               .drv_name       = qla_driver_name,
+               .isp_name       = "ISP2432",
+               .fw_info        = qla_fw_tbl,
+               .fw_fname       = "ql2400_fw.bin",
+       },
+};
+
+static struct pci_device_id qla24xx_pci_tbl[] = {
+       {
+               .vendor         = PCI_VENDOR_ID_QLOGIC,
+               .device         = PCI_DEVICE_ID_QLOGIC_ISP2422,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = (unsigned long)&qla_board_tbl[0],
+       },
+       {
+               .vendor         = PCI_VENDOR_ID_QLOGIC,
+               .device         = PCI_DEVICE_ID_QLOGIC_ISP2432,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = (unsigned long)&qla_board_tbl[1],
+       },
+       {0, 0},
+};
+MODULE_DEVICE_TABLE(pci, qla24xx_pci_tbl);
+
+static int __devinit
+qla24xx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       return qla2x00_probe_one(pdev,
+           (struct qla_board_info *)id->driver_data);
+}
+
+static void __devexit
+qla24xx_remove_one(struct pci_dev *pdev)
+{
+       qla2x00_remove_one(pdev);
+}
+
+static struct pci_driver qla24xx_pci_driver = {
+       .name           = "qla2400",
+       .id_table       = qla24xx_pci_tbl,
+       .probe          = qla24xx_probe_one,
+       .remove         = __devexit_p(qla24xx_remove_one),
+};
+
+static int __init
+qla24xx_init(void)
+{
+       return pci_module_init(&qla24xx_pci_driver);
+}
+
+static void __exit
+qla24xx_exit(void)
+{
+       pci_unregister_driver(&qla24xx_pci_driver);
+}
+
+module_init(qla24xx_init);
+module_exit(qla24xx_exit);
+
+MODULE_AUTHOR("QLogic Corporation");
+MODULE_DESCRIPTION("QLogic ISP24xx FC-SCSI Host Bus Adapter driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
index 13e2aaf567699b9a00da482f2d89ca3e48bec6b5..dadc91bd0ea9b389e3b75024609cd8f7ab8e9510 100644 (file)
@@ -3549,6 +3549,67 @@ qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
        return rval;
 }
 
+int
+qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
+{
+       int     rval, num, i;
+       uint32_t cnt;
+       uint32_t *risc_code;
+       uint32_t risc_addr, risc_size;
+       uint32_t *req_ring;
+       struct qla_fw_info *fw_iter;
+
+       rval = QLA_SUCCESS;
+
+       /* Load firmware sequences */
+       fw_iter = ha->brd_info->fw_info;
+       *srisc_addr = *((uint32_t *)fw_iter->lfwstart);
+       while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) {
+               risc_code = (uint32_t *)fw_iter->fwcode;
+               risc_size = *((uint32_t *)fw_iter->fwlen);
+               risc_addr = *((uint32_t *)fw_iter->lfwstart);
+
+               num = 0;
+               rval = 0;
+               while (risc_size > 0 && !rval) {
+                       cnt = (uint32_t)(ha->fw_transfer_size >> 2);
+                       if (cnt > risc_size)
+                               cnt = risc_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_addr));
+
+                       req_ring = (uint32_t *)ha->request_ring;
+                       for (i = 0; i < cnt; i++)
+                               req_ring[i] = cpu_to_le32(risc_code[i]);
+
+                       rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
+                           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_addr += cnt;
+                       risc_size -= cnt;
+                       num++;
+               }
+
+               /* Next firmware sequence */
+               fw_iter++;
+       }
+       return rval;
+}
+
 int
 qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
 {
index 47db029b2fce151c794d47eb199f329b9a3a8daf..41d2aeee096395073ea1396ff5c1153e8f210a51 100644 (file)
@@ -54,6 +54,13 @@ module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xloginretrycount,
                "Specify an alternate value for the NVRAM login retry count.");
 
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
+int ql2xfwloadflash;
+module_param(ql2xfwloadflash, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xfwloadflash,
+               "Load ISP24xx firmware image from FLASH (onboard memory).");
+#endif
+
 static void qla2x00_free_device(scsi_qla_host_t *);
 
 static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha);
@@ -1367,10 +1374,10 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
                ha->isp_ops.reset_adapter = qla24xx_reset_adapter;
                ha->isp_ops.nvram_config = qla24xx_nvram_config;
                ha->isp_ops.update_fw_options = qla24xx_update_fw_options;
-#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
-               ha->isp_ops.load_risc = qla24xx_load_risc_flash;
-#else
                ha->isp_ops.load_risc = qla24xx_load_risc;
+#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
+               if (ql2xfwloadflash)
+                       ha->isp_ops.load_risc = qla24xx_load_risc_flash;
 #endif
                ha->isp_ops.pci_info_str = qla24xx_pci_info_str;
                ha->isp_ops.fw_version_str = qla24xx_fw_version_str;
@@ -2488,53 +2495,8 @@ qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout)
 #if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
 
 #define qla2x00_release_firmware()     do { } while (0)
-
-static struct qla_board_info qla_board_tbl[] = {
-       {
-               .drv_name       = "qla2400",
-               .isp_name       = "ISP2422",
-               .fw_fname       = "ql2400_fw.bin",
-               .sht            = &qla24xx_driver_template,
-       },
-       {
-               .drv_name       = "qla2400",
-               .isp_name       = "ISP2432",
-               .fw_fname       = "ql2400_fw.bin",
-               .sht            = &qla24xx_driver_template,
-       },
-};
-
-static struct pci_device_id qla2xxx_pci_tbl[] = {
-       {
-               .vendor         = PCI_VENDOR_ID_QLOGIC,
-               .device         = PCI_DEVICE_ID_QLOGIC_ISP2422,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .driver_data    = (unsigned long)&qla_board_tbl[0],
-       },
-       {
-               .vendor         = PCI_VENDOR_ID_QLOGIC,
-               .device         = PCI_DEVICE_ID_QLOGIC_ISP2432,
-               .subvendor      = PCI_ANY_ID,
-               .subdevice      = PCI_ANY_ID,
-               .driver_data    = (unsigned long)&qla_board_tbl[1],
-       },
-       {0, 0},
-};
-MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
-
-static int __devinit
-qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-       return qla2x00_probe_one(pdev,
-           (struct qla_board_info *)id->driver_data);
-}
-
-static void __devexit
-qla2xxx_remove_one(struct pci_dev *pdev)
-{
-       qla2x00_remove_one(pdev);
-}
+#define qla2x00_pci_module_init()      (0)
+#define qla2x00_pci_module_exit()      do { } while (0)
 
 #else  /* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
 
@@ -2647,8 +2609,6 @@ qla2xxx_remove_one(struct pci_dev *pdev)
        qla2x00_remove_one(pdev);
 }
 
-#endif
-
 static struct pci_driver qla2xxx_pci_driver = {
        .name           = "qla2xxx",
        .owner          = THIS_MODULE,
@@ -2657,6 +2617,20 @@ static struct pci_driver qla2xxx_pci_driver = {
        .remove         = __devexit_p(qla2xxx_remove_one),
 };
 
+static inline int
+qla2x00_pci_module_init(void)
+{
+       return pci_module_init(&qla2xxx_pci_driver);
+}
+
+static inline void
+qla2x00_pci_module_exit(void)
+{
+       pci_unregister_driver(&qla2xxx_pci_driver);
+}
+
+#endif
+
 /**
  * qla2x00_module_init - Module initialization.
  **/
@@ -2688,7 +2662,7 @@ qla2x00_module_init(void)
                return -ENODEV;
 
        printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n");
-       ret = pci_module_init(&qla2xxx_pci_driver);
+       ret = qla2x00_pci_module_init();
        if (ret) {
                kmem_cache_destroy(srb_cachep);
                fc_release_transport(qla2xxx_transport_template);
@@ -2702,7 +2676,7 @@ qla2x00_module_init(void)
 static void __exit
 qla2x00_module_exit(void)
 {
-       pci_unregister_driver(&qla2xxx_pci_driver);
+       qla2x00_pci_module_exit();
        qla2x00_release_firmware();
        kmem_cache_destroy(srb_cachep);
        fc_release_transport(qla2xxx_transport_template);