diff options
author | mjacob <mjacob@FreeBSD.org> | 2000-06-18 04:37:44 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 2000-06-18 04:37:44 +0000 |
commit | 9330548cbea77d763588ca95e69e3e4bebaa3c7b (patch) | |
tree | 80ddf4e79d94cbdcbe385a9318de0b3f26e5985d /sys/dev/ispfw/ispfw.c | |
parent | 4aba1e74067109378b584b42568dcb790080e27f (diff) | |
download | FreeBSD-src-9330548cbea77d763588ca95e69e3e4bebaa3c7b.zip FreeBSD-src-9330548cbea77d763588ca95e69e3e4bebaa3c7b.tar.gz |
Add in (separate files for different board's firmware) new files for ispfw
loadable module.
Diffstat (limited to 'sys/dev/ispfw/ispfw.c')
-rw-r--r-- | sys/dev/ispfw/ispfw.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/sys/dev/ispfw/ispfw.c b/sys/dev/ispfw/ispfw.c new file mode 100644 index 0000000..752594a --- /dev/null +++ b/sys/dev/ispfw/ispfw.c @@ -0,0 +1,157 @@ +/* $FreeBSD$ */ +/* + * ISP Firmware Helper Pseudo Device for FreeBSD + * + *--------------------------------------- + * Copyright (c) 2000, by Matthew Jacob + * All rights reserved. + *--------------------------------------- + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, without modification, + * this list of conditions, and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bio.h> +#include <sys/disk.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/linker.h> + +#include <dev/ispfw/asm_1040.h> +#include <dev/ispfw/asm_1080.h> +#include <dev/ispfw/asm_12160.h> +#include <dev/ispfw/asm_2100.h> +#include <dev/ispfw/asm_2200.h> + +#define ISPFW_VERSION 0 + +#define PCI_PRODUCT_QLOGIC_ISP1020 0x1020 +#define PCI_PRODUCT_QLOGIC_ISP1080 0x1080 +#define PCI_PRODUCT_QLOGIC_ISP12160 0x1216 +#define PCI_PRODUCT_QLOGIC_ISP1240 0x1240 +#define PCI_PRODUCT_QLOGIC_ISP1280 0x1280 +#define PCI_PRODUCT_QLOGIC_ISP2100 0x2100 +#define PCI_PRODUCT_QLOGIC_ISP2200 0x2200 + +typedef void ispfwfunc __P((int, int, int, const u_int16_t **)); +extern ispfwfunc *isp_get_firmware_p; +static void isp_get_firmware __P((int, int, int, const u_int16_t **)); + +static int ncallers = 0; +static const u_int16_t ***callp = NULL; +static int addcaller(const u_int16_t **); + +static int +addcaller(const u_int16_t **caller) +{ + const u_int16_t ***newcallp; + int i; + for (i = 0; i < ncallers; i++) { + if (callp[i] == caller) + return (1); + } + newcallp = malloc((ncallers + 1) * sizeof (const u_int16_t ***), + M_DEVBUF, M_NOWAIT); + if (newcallp == NULL) { + return (0); + } + for (i = 0; i < ncallers; i++) { + newcallp[i] = callp[i]; + } + newcallp[ncallers] = caller; + if (ncallers++) + free(callp, M_DEVBUF); + callp = newcallp; + return (1); +} + +static void +isp_get_firmware(int version, int tgtmode, int devid, const u_int16_t **ptrp) +{ + const u_int16_t *rp = NULL; + + if (version == ISPFW_VERSION) { + switch (devid) { + case PCI_PRODUCT_QLOGIC_ISP1020: + if (tgtmode) + rp = isp_1040_risc_code_it; + else + rp = isp_1040_risc_code; + break; + case PCI_PRODUCT_QLOGIC_ISP1080: + case PCI_PRODUCT_QLOGIC_ISP1240: + case PCI_PRODUCT_QLOGIC_ISP1280: + if (tgtmode) + rp = isp_1080_risc_code_it; + else + rp = isp_1080_risc_code; + break; + case PCI_PRODUCT_QLOGIC_ISP12160: + if (tgtmode) + rp = isp_12160_risc_code_it; + else + rp = isp_12160_risc_code; + break; + case PCI_PRODUCT_QLOGIC_ISP2100: + rp = isp_2100_risc_code; + break; + case PCI_PRODUCT_QLOGIC_ISP2200: + rp = isp_2200_risc_code; + default: + break; + } + } + if (rp && addcaller(ptrp)) { + *ptrp = rp; + } +} + +static int +isp_module_handler(module_t mod, int what, void *arg) +{ + switch (what) { + case MOD_LOAD: + isp_get_firmware_p = isp_get_firmware; + break; + case MOD_UNLOAD: + isp_get_firmware_p = NULL; + if (ncallers) { + int i; + for (i = 0; i < ncallers; i++) { + *callp[i] = NULL; + } + free(callp, M_DEVBUF); + } + break; + default: + break; + } + return (0); +} +static moduledata_t ispfw_mod = { + "ispfw", isp_module_handler, NULL +}; +DECLARE_MODULE(ispfw, ispfw_mod, SI_SUB_DRIVERS, SI_ORDER_THIRD); +MODULE_VERSION(ispfw, ISPFW_VERSION); +MODULE_DEPEND(ispfw, isp, 1, 1, 1); |