ispfw.c revision 119418
1/*
2
3#include <sys/cdefs.h>
4__FBSDID("$FreeBSD: head/sys/dev/ispfw/ispfw.c 119418 2003-08-24 17:55:58Z obrien $");
5 * ISP Firmware Helper Pseudo Device for FreeBSD
6 *
7 * Copyright (c) 2000, 2001, by Matthew Jacob
8 * All rights reserved.
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. The name of the author may not be used to endorse or promote products
17 *    derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <sys/kernel.h>
34#include <sys/malloc.h>
35
36#include <dev/ispfw/asm_1040.h>
37#include <dev/ispfw/asm_1080.h>
38#include <dev/ispfw/asm_12160.h>
39#include <dev/ispfw/asm_2100.h>
40#include <dev/ispfw/asm_2200.h>
41#include <dev/ispfw/asm_2300.h>
42#if	_MACHINE_ARCH == sparc64
43#include <dev/ispfw/asm_1000.h>
44#endif
45
46#define	ISPFW_VERSION	0
47
48#define	PCI_PRODUCT_QLOGIC_ISP1020	0x1020
49#define	PCI_PRODUCT_QLOGIC_ISP1080	0x1080
50#define	PCI_PRODUCT_QLOGIC_ISP10160	0x1016
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#define	PCI_PRODUCT_QLOGIC_ISP2300	0x2300
57#define	PCI_PRODUCT_QLOGIC_ISP2312	0x2312
58#if	_MACHINE_ARCH == sparc64
59#define	SBUS_PRODUCT_QLOGIC_ISP1000	0x1000
60#endif
61
62typedef void ispfwfunc(int, int, int, const u_int16_t **);
63extern ispfwfunc *isp_get_firmware_p;
64static void isp_get_firmware(int, int, int, const u_int16_t **);
65
66static int ncallers = 0;
67static const u_int16_t ***callp = NULL;
68static int addcaller(const u_int16_t **);
69
70static int
71addcaller(const u_int16_t **caller)
72{
73	const u_int16_t ***newcallp;
74	int i;
75	for (i = 0; i < ncallers; i++) {
76		if (callp[i] == caller)
77			return (1);
78	}
79	newcallp = malloc((ncallers + 1) * sizeof (const u_int16_t ***),
80	    M_DEVBUF, M_NOWAIT);
81	if (newcallp == NULL) {
82		return (0);
83	}
84	for (i = 0; i < ncallers; i++) {
85		newcallp[i] = callp[i];
86	}
87	newcallp[ncallers] = caller;
88	if (ncallers++)
89		free(callp, M_DEVBUF);
90	callp = newcallp;
91	return (1);
92}
93
94static void
95isp_get_firmware(int version, int tgtmode, int devid, const u_int16_t **ptrp)
96{
97	const u_int16_t *rp = NULL;
98
99	if (version == ISPFW_VERSION) {
100		switch (devid) {
101		case PCI_PRODUCT_QLOGIC_ISP1020:
102			if (tgtmode)
103				rp = isp_1040_risc_code_it;
104			else
105				rp = isp_1040_risc_code;
106			break;
107		case PCI_PRODUCT_QLOGIC_ISP1080:
108		case PCI_PRODUCT_QLOGIC_ISP1240:
109		case PCI_PRODUCT_QLOGIC_ISP1280:
110			if (tgtmode)
111				rp = isp_1080_risc_code_it;
112			else
113				rp = isp_1080_risc_code;
114			break;
115		case PCI_PRODUCT_QLOGIC_ISP10160:
116		case PCI_PRODUCT_QLOGIC_ISP12160:
117			if (tgtmode)
118				rp = isp_12160_risc_code_it;
119			else
120				rp = isp_12160_risc_code;
121			break;
122		case PCI_PRODUCT_QLOGIC_ISP2100:
123			rp = isp_2100_risc_code;
124			break;
125		case PCI_PRODUCT_QLOGIC_ISP2200:
126			rp = isp_2200_risc_code;
127			break;
128		case PCI_PRODUCT_QLOGIC_ISP2300:
129		case PCI_PRODUCT_QLOGIC_ISP2312:
130			rp = isp_2300_risc_code;
131			break;
132#if	_MACHINE_ARCH == sparc64
133		case SBUS_PRODUCT_QLOGIC_ISP1000:
134			if (tgtmode)
135				break;
136			rp = isp_1000_risc_code;
137			break;
138#endif
139		default:
140			break;
141		}
142	}
143	if (rp && addcaller(ptrp)) {
144		*ptrp = rp;
145	}
146}
147
148static int
149isp_module_handler(module_t mod, int what, void *arg)
150{
151	switch (what) {
152	case MOD_LOAD:
153		isp_get_firmware_p = isp_get_firmware;
154		break;
155	case MOD_UNLOAD:
156		isp_get_firmware_p = NULL;
157		if (ncallers)  {
158			int i;
159			for (i = 0; i < ncallers; i++) {
160				*callp[i] = NULL;
161			}
162			free(callp, M_DEVBUF);
163		}
164		break;
165	default:
166		break;
167	}
168	return (0);
169}
170static moduledata_t ispfw_mod = {
171	"ispfw", isp_module_handler, NULL
172};
173DECLARE_MODULE(ispfw, ispfw_mod, SI_SUB_DRIVERS, SI_ORDER_THIRD);
174MODULE_VERSION(ispfw, ISPFW_VERSION);
175MODULE_DEPEND(ispfw, isp, 1, 1, 1);
176