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 41 #define ISPFW_VERSION 0 42 43 #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 44 #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 45 #define PCI_PRODUCT_QLOGIC_ISP12160 0x1216 46 #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 47 #define PCI_PRODUCT_QLOGIC_ISP1280 0x1280 48 #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 49 #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 50 #define PCI_PRODUCT_QLOGIC_ISP2300 0x2300 51 #define PCI_PRODUCT_QLOGIC_ISP2312 0x2312 52 53 typedef void ispfwfunc(int, int, int, const u_int16_t **); 54 extern ispfwfunc *isp_get_firmware_p; 55 static void isp_get_firmware(int, int, int, const u_int16_t **); 56 57 static int ncallers = 0; 58 static const u_int16_t ***callp = NULL; 59 static int addcaller(const u_int16_t **); 60 61 static int 62 addcaller(const u_int16_t **caller) 63 { 64 const u_int16_t ***newcallp; 65 int i; 66 for (i = 0; i < ncallers; i++) { 67 if (callp[i] == caller) 68 return (1); 69 } 70 newcallp = malloc((ncallers + 1) * sizeof (const u_int16_t ***), 71 M_DEVBUF, M_NOWAIT); 72 if (newcallp == NULL) { 73 return (0); 74 } 75 for (i = 0; i < ncallers; i++) { 76 newcallp[i] = callp[i]; 77 } 78 newcallp[ncallers] = caller; 79 if (ncallers++) 80 free(callp, M_DEVBUF); 81 callp = newcallp; 82 return (1); 83 } 84 85 static void 86 isp_get_firmware(int version, int tgtmode, int devid, const u_int16_t **ptrp) 87 { 88 const u_int16_t *rp = NULL; 89 90 if (version == ISPFW_VERSION) { 91 switch (devid) { 92 case PCI_PRODUCT_QLOGIC_ISP1020: 93 if (tgtmode) 94 rp = isp_1040_risc_code_it; 95 else 96 rp = isp_1040_risc_code; 97 break; 98 case PCI_PRODUCT_QLOGIC_ISP1080: 99 case PCI_PRODUCT_QLOGIC_ISP1240: 100 case PCI_PRODUCT_QLOGIC_ISP1280: 101 if (tgtmode) 102 rp = isp_1080_risc_code_it; 103 else 104 rp = isp_1080_risc_code; 105 break; 106 case PCI_PRODUCT_QLOGIC_ISP12160: 107 if (tgtmode) 108 rp = isp_12160_risc_code_it; 109 else 110 rp = isp_12160_risc_code; 111 break; 112 case PCI_PRODUCT_QLOGIC_ISP2100: 113 rp = isp_2100_risc_code; 114 break; 115 case PCI_PRODUCT_QLOGIC_ISP2200: 116 rp = isp_2200_risc_code; 117 break; 118 case PCI_PRODUCT_QLOGIC_ISP2300: 119 case PCI_PRODUCT_QLOGIC_ISP2312: 120 rp = isp_2300_risc_code; 121 break; 122 default: 123 break; 124 } 125 } 126 if (rp && addcaller(ptrp)) { 127 *ptrp = rp; 128 } 129 } 130 131 static int 132 isp_module_handler(module_t mod, int what, void *arg) 133 { 134 switch (what) { 135 case MOD_LOAD: 136 isp_get_firmware_p = isp_get_firmware; 137 break; 138 case MOD_UNLOAD: 139 isp_get_firmware_p = NULL; 140 if (ncallers) { 141 int i; 142 for (i = 0; i < ncallers; i++) { 143 *callp[i] = NULL; 144 } 145 free(callp, M_DEVBUF); 146 } 147 break; 148 default: 149 break; 150 } 151 return (0); 152 } 153 static moduledata_t ispfw_mod = { 154 "ispfw", isp_module_handler, NULL 155 }; 156 DECLARE_MODULE(ispfw, ispfw_mod, SI_SUB_DRIVERS, SI_ORDER_THIRD); 157 MODULE_VERSION(ispfw, ISPFW_VERSION); 158 MODULE_DEPEND(ispfw, isp, 1, 1, 1); 159