1 /* $FreeBSD$ */ 2 /* 3 * ISP Firmware Helper Pseudo Device for FreeBSD 4 * 5 *--------------------------------------- 6 * Copyright (c) 2000, by Matthew Jacob 7 * All rights reserved. 8 *--------------------------------------- 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. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/bio.h> 36 #include <sys/disk.h> 37 #include <sys/kernel.h> 38 #include <sys/malloc.h> 39 #include <sys/linker.h> 40 41 #include <dev/ispfw/asm_1040.h> 42 #include <dev/ispfw/asm_1080.h> 43 #include <dev/ispfw/asm_12160.h> 44 #include <dev/ispfw/asm_2100.h> 45 #include <dev/ispfw/asm_2200.h> 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_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 57 typedef void ispfwfunc __P((int, int, int, const u_int16_t **)); 58 extern ispfwfunc *isp_get_firmware_p; 59 static void isp_get_firmware __P((int, int, int, const u_int16_t **)); 60 61 static int ncallers = 0; 62 static const u_int16_t ***callp = NULL; 63 static int addcaller(const u_int16_t **); 64 65 static int 66 addcaller(const u_int16_t **caller) 67 { 68 const u_int16_t ***newcallp; 69 int i; 70 for (i = 0; i < ncallers; i++) { 71 if (callp[i] == caller) 72 return (1); 73 } 74 newcallp = malloc((ncallers + 1) * sizeof (const u_int16_t ***), 75 M_DEVBUF, M_NOWAIT); 76 if (newcallp == NULL) { 77 return (0); 78 } 79 for (i = 0; i < ncallers; i++) { 80 newcallp[i] = callp[i]; 81 } 82 newcallp[ncallers] = caller; 83 if (ncallers++) 84 free(callp, M_DEVBUF); 85 callp = newcallp; 86 return (1); 87 } 88 89 static void 90 isp_get_firmware(int version, int tgtmode, int devid, const u_int16_t **ptrp) 91 { 92 const u_int16_t *rp = NULL; 93 94 if (version == ISPFW_VERSION) { 95 switch (devid) { 96 case PCI_PRODUCT_QLOGIC_ISP1020: 97 if (tgtmode) 98 rp = isp_1040_risc_code_it; 99 else 100 rp = isp_1040_risc_code; 101 break; 102 case PCI_PRODUCT_QLOGIC_ISP1080: 103 case PCI_PRODUCT_QLOGIC_ISP1240: 104 case PCI_PRODUCT_QLOGIC_ISP1280: 105 if (tgtmode) 106 rp = isp_1080_risc_code_it; 107 else 108 rp = isp_1080_risc_code; 109 break; 110 case PCI_PRODUCT_QLOGIC_ISP12160: 111 rp = isp_12160_risc_code; 112 break; 113 case PCI_PRODUCT_QLOGIC_ISP2100: 114 rp = isp_2100_risc_code; 115 break; 116 case PCI_PRODUCT_QLOGIC_ISP2200: 117 rp = isp_2200_risc_code; 118 default: 119 break; 120 } 121 } 122 if (rp && addcaller(ptrp)) { 123 *ptrp = rp; 124 } 125 } 126 127 static int 128 isp_module_handler(module_t mod, int what, void *arg) 129 { 130 switch (what) { 131 case MOD_LOAD: 132 isp_get_firmware_p = isp_get_firmware; 133 break; 134 case MOD_UNLOAD: 135 isp_get_firmware_p = NULL; 136 if (ncallers) { 137 int i; 138 for (i = 0; i < ncallers; i++) { 139 *callp[i] = NULL; 140 } 141 free(callp, M_DEVBUF); 142 } 143 break; 144 default: 145 break; 146 } 147 return (0); 148 } 149 static moduledata_t ispfw_mod = { 150 "ispfw", isp_module_handler, NULL 151 }; 152 DECLARE_MODULE(ispfw, ispfw_mod, SI_SUB_DRIVERS, SI_ORDER_THIRD); 153 MODULE_VERSION(ispfw, ISPFW_VERSION); 154 MODULE_DEPEND(ispfw, isp, 1, 1, 1); 155