ispfw.c revision 66169
1/* $FreeBSD: head/sys/dev/ispfw/ispfw.c 66169 2000-09-21 16:32:38Z mjacob $ */ 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/kernel.h> 35#include <sys/malloc.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 43#define ISPFW_VERSION 0 44 45#define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 46#define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 47#define PCI_PRODUCT_QLOGIC_ISP12160 0x1216 48#define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 49#define PCI_PRODUCT_QLOGIC_ISP1280 0x1280 50#define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 51#define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 52 53typedef void ispfwfunc __P((int, int, int, const u_int16_t **)); 54extern ispfwfunc *isp_get_firmware_p; 55static void isp_get_firmware __P((int, int, int, const u_int16_t **)); 56 57static int ncallers = 0; 58static const u_int16_t ***callp = NULL; 59static int addcaller(const u_int16_t **); 60 61static int 62addcaller(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 85static void 86isp_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 rp = isp_12160_risc_code; 108 break; 109 case PCI_PRODUCT_QLOGIC_ISP2100: 110 rp = isp_2100_risc_code; 111 break; 112 case PCI_PRODUCT_QLOGIC_ISP2200: 113 rp = isp_2200_risc_code; 114 default: 115 break; 116 } 117 } 118 if (rp && addcaller(ptrp)) { 119 *ptrp = rp; 120 } 121} 122 123static int 124isp_module_handler(module_t mod, int what, void *arg) 125{ 126 switch (what) { 127 case MOD_LOAD: 128 isp_get_firmware_p = isp_get_firmware; 129 break; 130 case MOD_UNLOAD: 131 isp_get_firmware_p = NULL; 132 if (ncallers) { 133 int i; 134 for (i = 0; i < ncallers; i++) { 135 *callp[i] = NULL; 136 } 137 free(callp, M_DEVBUF); 138 } 139 break; 140 default: 141 break; 142 } 143 return (0); 144} 145static moduledata_t ispfw_mod = { 146 "ispfw", isp_module_handler, NULL 147}; 148DECLARE_MODULE(ispfw, ispfw_mod, SI_SUB_DRIVERS, SI_ORDER_THIRD); 149MODULE_VERSION(ispfw, ISPFW_VERSION); 150MODULE_DEPEND(ispfw, isp, 1, 1, 1); 151