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