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 #if _MACHINE_ARCH == sparc64 60 #define SBUS_PRODUCT_QLOGIC_ISP1000 0x1000 61 #endif 62 63 typedef void ispfwfunc(int, int, int, const u_int16_t **); 64 extern ispfwfunc *isp_get_firmware_p; 65 static void isp_get_firmware(int, int, int, const u_int16_t **); 66 67 static int ncallers = 0; 68 static const u_int16_t ***callp = NULL; 69 static int addcaller(const u_int16_t **); 70 71 static int 72 addcaller(const u_int16_t **caller) 73 { 74 const u_int16_t ***newcallp; 75 int i; 76 for (i = 0; i < ncallers; i++) { 77 if (callp[i] == caller) 78 return (1); 79 } 80 newcallp = malloc((ncallers + 1) * sizeof (const u_int16_t ***), 81 M_DEVBUF, M_NOWAIT); 82 if (newcallp == NULL) { 83 return (0); 84 } 85 for (i = 0; i < ncallers; i++) { 86 newcallp[i] = callp[i]; 87 } 88 newcallp[ncallers] = caller; 89 if (ncallers++) 90 free(callp, M_DEVBUF); 91 callp = newcallp; 92 return (1); 93 } 94 95 static void 96 isp_get_firmware(int version, int tgtmode, int devid, const u_int16_t **ptrp) 97 { 98 const u_int16_t *rp = NULL; 99 100 if (version == ISPFW_VERSION) { 101 switch (devid) { 102 case PCI_PRODUCT_QLOGIC_ISP1020: 103 if (tgtmode) 104 rp = isp_1040_risc_code_it; 105 else 106 rp = isp_1040_risc_code; 107 break; 108 case PCI_PRODUCT_QLOGIC_ISP1080: 109 case PCI_PRODUCT_QLOGIC_ISP1240: 110 case PCI_PRODUCT_QLOGIC_ISP1280: 111 if (tgtmode) 112 rp = isp_1080_risc_code_it; 113 else 114 rp = isp_1080_risc_code; 115 break; 116 case PCI_PRODUCT_QLOGIC_ISP10160: 117 case PCI_PRODUCT_QLOGIC_ISP12160: 118 if (tgtmode) 119 rp = isp_12160_risc_code_it; 120 else 121 rp = isp_12160_risc_code; 122 break; 123 case PCI_PRODUCT_QLOGIC_ISP2100: 124 rp = isp_2100_risc_code; 125 break; 126 case PCI_PRODUCT_QLOGIC_ISP2200: 127 rp = isp_2200_risc_code; 128 break; 129 case PCI_PRODUCT_QLOGIC_ISP2300: 130 case PCI_PRODUCT_QLOGIC_ISP2312: 131 rp = isp_2300_risc_code; 132 break; 133 #if _MACHINE_ARCH == sparc64 134 case SBUS_PRODUCT_QLOGIC_ISP1000: 135 if (tgtmode) 136 break; 137 rp = isp_1000_risc_code; 138 break; 139 #endif 140 default: 141 break; 142 } 143 } 144 if (rp && addcaller(ptrp)) { 145 *ptrp = rp; 146 } 147 } 148 149 static int 150 isp_module_handler(module_t mod, int what, void *arg) 151 { 152 switch (what) { 153 case MOD_LOAD: 154 isp_get_firmware_p = isp_get_firmware; 155 break; 156 case MOD_UNLOAD: 157 isp_get_firmware_p = NULL; 158 if (ncallers) { 159 int i; 160 for (i = 0; i < ncallers; i++) { 161 *callp[i] = NULL; 162 } 163 free(callp, M_DEVBUF); 164 } 165 break; 166 default: 167 return (EOPNOTSUPP); 168 break; 169 } 170 return (0); 171 } 172 static moduledata_t ispfw_mod = { 173 "ispfw", isp_module_handler, NULL 174 }; 175 DECLARE_MODULE(ispfw, ispfw_mod, SI_SUB_DRIVERS, SI_ORDER_THIRD); 176 MODULE_VERSION(ispfw, ISPFW_VERSION); 177 MODULE_DEPEND(ispfw, isp, 1, 1, 1); 178