FreeBSD/Linux Kernel Cross Reference
sys/dev/ispfw/ispfw.c
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$");
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 #include <dev/ispfw/asm_2322.h>
44 #include <dev/ispfw/asm_2400.h>
45 #if _MACHINE_ARCH == sparc64
46 #include <dev/ispfw/asm_1000.h>
47 #endif
48
49 #define ISPFW_VERSION 0
50
51 #define PCI_PRODUCT_QLOGIC_ISP1020 0x1020
52 #define PCI_PRODUCT_QLOGIC_ISP1080 0x1080
53 #define PCI_PRODUCT_QLOGIC_ISP10160 0x1016
54 #define PCI_PRODUCT_QLOGIC_ISP12160 0x1216
55 #define PCI_PRODUCT_QLOGIC_ISP1240 0x1240
56 #define PCI_PRODUCT_QLOGIC_ISP1280 0x1280
57 #define PCI_PRODUCT_QLOGIC_ISP2100 0x2100
58 #define PCI_PRODUCT_QLOGIC_ISP2200 0x2200
59 #define PCI_PRODUCT_QLOGIC_ISP2300 0x2300
60 #define PCI_PRODUCT_QLOGIC_ISP2312 0x2312
61 #define PCI_PRODUCT_QLOGIC_ISP6312 0x6312
62 #define PCI_PRODUCT_QLOGIC_ISP2322 0x2322
63 #define PCI_PRODUCT_QLOGIC_ISP6322 0x6322
64 #define PCI_PRODUCT_QLOGIC_ISP2422 0x2422
65 #define PCI_PRODUCT_QLOGIC_ISP2432 0x2432
66 #if _MACHINE_ARCH == sparc64
67 #define SBUS_PRODUCT_QLOGIC_ISP1000 0x1000
68 #endif
69
70 typedef void ispfwfunc(int, int, int, const u_int16_t **);
71 extern ispfwfunc *isp_get_firmware_p;
72 static void isp_get_firmware(int, int, int, const u_int16_t **);
73
74 static int ncallers = 0;
75 static const u_int16_t ***callp = NULL;
76 static int addcaller(const u_int16_t **);
77
78 static int
79 addcaller(const u_int16_t **caller)
80 {
81 const u_int16_t ***newcallp;
82 int i;
83 for (i = 0; i < ncallers; i++) {
84 if (callp[i] == caller)
85 return (1);
86 }
87 newcallp = malloc((ncallers + 1) * sizeof (const u_int16_t ***),
88 M_DEVBUF, M_NOWAIT);
89 if (newcallp == NULL) {
90 return (0);
91 }
92 for (i = 0; i < ncallers; i++) {
93 newcallp[i] = callp[i];
94 }
95 newcallp[ncallers] = caller;
96 if (ncallers++)
97 free(callp, M_DEVBUF);
98 callp = newcallp;
99 return (1);
100 }
101
102 static void
103 isp_get_firmware(int version, int tgtmode, int devid, const u_int16_t **ptrp)
104 {
105 const u_int16_t *rp = NULL;
106
107 if (version == ISPFW_VERSION) {
108 switch (devid) {
109 case PCI_PRODUCT_QLOGIC_ISP1020:
110 if (tgtmode)
111 rp = isp_1040_risc_code_it;
112 else
113 rp = isp_1040_risc_code;
114 break;
115 case PCI_PRODUCT_QLOGIC_ISP1080:
116 case PCI_PRODUCT_QLOGIC_ISP1240:
117 case PCI_PRODUCT_QLOGIC_ISP1280:
118 if (tgtmode)
119 rp = isp_1080_risc_code_it;
120 else
121 rp = isp_1080_risc_code;
122 break;
123 case PCI_PRODUCT_QLOGIC_ISP10160:
124 case PCI_PRODUCT_QLOGIC_ISP12160:
125 if (tgtmode)
126 rp = isp_12160_risc_code_it;
127 else
128 rp = isp_12160_risc_code;
129 break;
130 case PCI_PRODUCT_QLOGIC_ISP2100:
131 rp = isp_2100_risc_code;
132 break;
133 case PCI_PRODUCT_QLOGIC_ISP2200:
134 rp = isp_2200_risc_code;
135 break;
136 case PCI_PRODUCT_QLOGIC_ISP2300:
137 case PCI_PRODUCT_QLOGIC_ISP2312:
138 case PCI_PRODUCT_QLOGIC_ISP6312:
139 rp = isp_2300_risc_code;
140 break;
141 case PCI_PRODUCT_QLOGIC_ISP2322:
142 case PCI_PRODUCT_QLOGIC_ISP6322:
143 rp = isp_2322_risc_code;
144 break;
145 case PCI_PRODUCT_QLOGIC_ISP2422:
146 case PCI_PRODUCT_QLOGIC_ISP2432:
147 rp = (const u_int16_t *) isp_2400_risc_code;
148 break;
149 #if _MACHINE_ARCH == sparc64
150 case SBUS_PRODUCT_QLOGIC_ISP1000:
151 if (tgtmode)
152 break;
153 rp = isp_1000_risc_code;
154 break;
155 #endif
156 default:
157 break;
158 }
159 }
160 if (rp && addcaller(ptrp)) {
161 *ptrp = rp;
162 }
163 }
164
165 static int
166 isp_module_handler(module_t mod, int what, void *arg)
167 {
168 switch (what) {
169 case MOD_LOAD:
170 isp_get_firmware_p = isp_get_firmware;
171 break;
172 case MOD_UNLOAD:
173 isp_get_firmware_p = NULL;
174 if (ncallers) {
175 int i;
176 for (i = 0; i < ncallers; i++) {
177 *callp[i] = NULL;
178 }
179 free(callp, M_DEVBUF);
180 }
181 break;
182 default:
183 return (EOPNOTSUPP);
184 break;
185 }
186 return (0);
187 }
188 static moduledata_t ispfw_mod = {
189 "ispfw", isp_module_handler, NULL
190 };
191 DECLARE_MODULE(ispfw, ispfw_mod, SI_SUB_DRIVERS, SI_ORDER_THIRD);
192 MODULE_VERSION(ispfw, ISPFW_VERSION);
193 MODULE_DEPEND(ispfw, isp, 1, 1, 1);
Cache object: eaf6fd94ac5984df481f01136c33735e
|