+/* Firmware interface routines. */
+
+#define FW_BLOBS 5
+#define FW_ISP21XX 0
+#define FW_ISP22XX 1
+#define FW_ISP2300 2
+#define FW_ISP2322 3
+#define FW_ISP24XX 4
+
+#define FW_FILE_ISP21XX "ql2100_fw.bin"
+#define FW_FILE_ISP22XX "ql2200_fw.bin"
+#define FW_FILE_ISP2300 "ql2300_fw.bin"
+#define FW_FILE_ISP2322 "ql2322_fw.bin"
+#define FW_FILE_ISP24XX "ql2400_fw.bin"
+
+static DECLARE_MUTEX(qla_fw_lock);
+
+extern struct firmware ql2100_fw, ql2200_fw, ql2300_fw, ql2322_fw, ql2400_fw;
+
+static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
+ { .name = FW_FILE_ISP21XX, .segs = { 0x1000, 0 }, .fw = &ql2100_fw },
+ { .name = FW_FILE_ISP22XX, .segs = { 0x1000, 0 }, .fw = &ql2200_fw },
+ { .name = FW_FILE_ISP2300, .segs = { 0x800, 0 }, .fw = &ql2300_fw },
+ { .name = FW_FILE_ISP2322, .segs = { 0x800, 0x1c000, 0x1e000, 0 }, .fw = &ql2322_fw },
+ { .name = FW_FILE_ISP24XX, .fw = &ql2400_fw },
+};
+
+struct fw_blob *
+qla2x00_request_firmware(scsi_qla_host_t *ha)
+{
+ struct fw_blob *blob;
+
+ blob = NULL;
+ if (IS_QLA2100(ha)) {
+ blob = &qla_fw_blobs[FW_ISP21XX];
+ } else if (IS_QLA2200(ha)) {
+ blob = &qla_fw_blobs[FW_ISP22XX];
+ } else if (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA6312(ha)) {
+ blob = &qla_fw_blobs[FW_ISP2300];
+ } else if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
+ blob = &qla_fw_blobs[FW_ISP2322];
+ } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+ blob = &qla_fw_blobs[FW_ISP24XX];
+ }
+
+ down(&qla_fw_lock);
+ if (blob->fw)
+ goto out;
+
+ if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) {
+ DEBUG2(printk("scsi(%ld): Failed to load firmware image "
+ "(%s).\n", ha->host_no, blob->name));
+ blob->fw = NULL;
+ blob = NULL;
+ goto out;
+ }
+
+out:
+ up(&qla_fw_lock);
+ return blob;
+}
+
+static void
+qla2x00_release_firmware(void)
+{
+ int idx;
+
+ down(&qla_fw_lock);
+ for (idx = 0; idx < FW_BLOBS; idx++)
+ if (qla_fw_blobs[idx].fw)
+ release_firmware(qla_fw_blobs[idx].fw);
+ up(&qla_fw_lock);
+}
+
+static struct pci_device_id qla2xxx_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2300) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2312) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2322) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6312) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) },
+ { 0 },
+};
+MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
+
+static struct pci_driver qla2xxx_pci_driver = {
+ .name = QLA2XXX_DRIVER_NAME,
+ .driver = {
+ .owner = THIS_MODULE,
+ },
+ .id_table = qla2xxx_pci_tbl,
+ .probe = qla2x00_probe_one,
+ .remove = __devexit_p(qla2x00_remove_one),
+};
+