ispfw.c revision 129879
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: head/sys/dev/ispfw/ispfw.c 129879 2004-05-30 20:08:47Z phk $"); 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 63typedef void ispfwfunc(int, int, int, const u_int16_t **); 64extern ispfwfunc *isp_get_firmware_p; 65static void isp_get_firmware(int, int, int, const u_int16_t **); 66 67static int ncallers = 0; 68static const u_int16_t ***callp = NULL; 69static int addcaller(const u_int16_t **); 70 71static int 72addcaller(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 95static void 96isp_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 149static int 150isp_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 break; 168 } 169 return (0); 170} 171static moduledata_t ispfw_mod = { 172 "ispfw", isp_module_handler, NULL 173}; 174DECLARE_MODULE(ispfw, ispfw_mod, SI_SUB_DRIVERS, SI_ORDER_THIRD); 175MODULE_VERSION(ispfw, ISPFW_VERSION); 176MODULE_DEPEND(ispfw, isp, 1, 1, 1); 177