1 /* 2 3 #include <sys/cdefs.h> 4 __FBSDID("$FreeBSD$"); 5 * ISP Firmware Helper Pseudo Device for FreeBSD 6 * 7 * Copyright (c) 2000, 2001, by Matthew Jacob 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice immediately at the beginning of the file, without modification, 15 * this list of conditions, and the following disclaimer. 16 * 2. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/param.h> 33 #include <sys/kernel.h> 34 #include <sys/malloc.h> 35 36 #include <dev/ispfw/asm_1040.h> 37 #include <dev/ispfw/asm_1080.h> 38 #include <dev/ispfw/asm_12160.h> 39 #include <dev/ispfw/asm_2100.h> 40 #include <dev/ispfw/asm_2200.h> 41 #include <dev/ispfw/asm_2300.h> 42 #if _MACHINE_ARCH == sparc64 43 #include <dev/ispfw/asm_1000.h> 44 #endif 45 46 #define ISPFW_VERSION 0 47 48 #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 49 #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 50 #define PCI_PRODUCT_QLOGIC_ISP10160 0x1016 51 #define PCI_PRODUCT_QLOGIC_ISP12160 0x1216 52 #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 53 #define PCI_PRODUCT_QLOGIC_ISP1280 0x1280 54 #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 55 #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 56 #define PCI_PRODUCT_QLOGIC_ISP2300 0x2300 57 #define PCI_PRODUCT_QLOGIC_ISP2312 0x2312 58 #if _MACHINE_ARCH == sparc64 59 #define SBUS_PRODUCT_QLOGIC_ISP1000 0x1000 60 #endif 61 62 typedef void ispfwfunc(int, int, int, const u_int16_t **); 63 extern ispfwfunc *isp_get_firmware_p; 64 static void isp_get_firmware(int, int, int, const u_int16_t **); 65 66 static int ncallers = 0; 67 static const u_int16_t ***callp = NULL; 68 static int addcaller(const u_int16_t **); 69 70 static int 71 addcaller(const u_int16_t **caller) 72 { 73 const u_int16_t ***newcallp; 74 int i; 75 for (i = 0; i < ncallers; i++) { 76 if (callp[i] == caller) 77 return (1); 78 } 79 newcallp = malloc((ncallers + 1) * sizeof (const u_int16_t ***), 80 M_DEVBUF, M_NOWAIT); 81 if (newcallp == NULL) { 82 return (0); 83 } 84 for (i = 0; i < ncallers; i++) { 85 newcallp[i] = callp[i]; 86 } 87 newcallp[ncallers] = caller; 88 if (ncallers++) 89 free(callp, M_DEVBUF); 90 callp = newcallp; 91 return (1); 92 } 93 94 static void 95 isp_get_firmware(int version, int tgtmode, int devid, const u_int16_t **ptrp) 96 { 97 const u_int16_t *rp = NULL; 98 99 if (version == ISPFW_VERSION) { 100 switch (devid) { 101 case PCI_PRODUCT_QLOGIC_ISP1020: 102 if (tgtmode) 103 rp = isp_1040_risc_code_it; 104 else 105 rp = isp_1040_risc_code; 106 break; 107 case PCI_PRODUCT_QLOGIC_ISP1080: 108 case PCI_PRODUCT_QLOGIC_ISP1240: 109 case PCI_PRODUCT_QLOGIC_ISP1280: 110 if (tgtmode) 111 rp = isp_1080_risc_code_it; 112 else 113 rp = isp_1080_risc_code; 114 break; 115 case PCI_PRODUCT_QLOGIC_ISP10160: 116 case PCI_PRODUCT_QLOGIC_ISP12160: 117 if (tgtmode) 118 rp = isp_12160_risc_code_it; 119 else 120 rp = isp_12160_risc_code; 121 break; 122 case PCI_PRODUCT_QLOGIC_ISP2100: 123 rp = isp_2100_risc_code; 124 break; 125 case PCI_PRODUCT_QLOGIC_ISP2200: 126 rp = isp_2200_risc_code; 127 break; 128 case PCI_PRODUCT_QLOGIC_ISP2300: 129 case PCI_PRODUCT_QLOGIC_ISP2312: 130 rp = isp_2300_risc_code; 131 break; 132 #if _MACHINE_ARCH == sparc64 133 case SBUS_PRODUCT_QLOGIC_ISP1000: 134 if (tgtmode) 135 break; 136 rp = isp_1000_risc_code; 137 break; 138 #endif 139 default: 140 break; 141 } 142 } 143 if (rp && addcaller(ptrp)) { 144 *ptrp = rp; 145 } 146 } 147 148 static int 149 isp_module_handler(module_t mod, int what, void *arg) 150 { 151 switch (what) { 152 case MOD_LOAD: 153 isp_get_firmware_p = isp_get_firmware; 154 break; 155 case MOD_UNLOAD: 156 isp_get_firmware_p = NULL; 157 if (ncallers) { 158 int i; 159 for (i = 0; i < ncallers; i++) { 160 *callp[i] = NULL; 161 } 162 free(callp, M_DEVBUF); 163 } 164 break; 165 default: 166 break; 167 } 168 return (0); 169 } 170 static moduledata_t ispfw_mod = { 171 "ispfw", isp_module_handler, NULL 172 }; 173 DECLARE_MODULE(ispfw, ispfw_mod, SI_SUB_DRIVERS, SI_ORDER_THIRD); 174 MODULE_VERSION(ispfw, ISPFW_VERSION); 175 MODULE_DEPEND(ispfw, isp, 1, 1, 1); 176