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