windrv_stub.c revision 145485
1/*-
2 * Copyright (c) 2005
3 *      Bill Paul <wpaul@windriver.com>.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *      This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/usr.sbin/ndiscvt/windrv_stub.c 145485 2005-04-24 20:21:22Z wpaul $");
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/kernel.h>
39#include <sys/module.h>
40#include <sys/conf.h>
41
42#include <machine/bus.h>
43#include <machine/resource.h>
44#include <sys/bus.h>
45
46#define NDIS_REGVALS
47
48struct ndis_cfg {
49	char			*nc_cfgkey;
50	char			*nc_cfgdesc;
51	char			nc_val[256];
52	int			nc_idx;
53};
54
55typedef struct ndis_cfg ndis_cfg;
56
57#include "windrv.h"
58
59struct ndis_pci_type {
60        uint16_t                ndis_vid;
61        uint16_t                ndis_did;
62        uint32_t                ndis_subsys;
63        char                    *ndis_name;
64};
65
66struct ndis_pccard_type {
67        const char              *ndis_vid;
68        const char              *ndis_did;
69        char                    *ndis_name;
70};
71
72
73#ifdef NDIS_PCI_DEV_TABLE
74static struct ndis_pci_type ndis_devs[] = {
75        NDIS_PCI_DEV_TABLE
76        { 0, 0, 0, NULL }
77};
78#endif
79
80#ifdef NDIS_PCMCIA_DEV_TABLE
81static struct ndis_pccard_type ndis_devs[] = {
82        NDIS_PCMCIA_DEV_TABLE
83        { NULL, NULL, NULL }
84};
85#endif
86
87enum interface_type {
88	InterfaceTypeUndefined = -1,
89	Internal,
90	Isa,
91	Eisa,
92	MicroChannel,
93	TurboChannel,
94	PCIBus,
95	VMEBus,
96	NuBus,
97	PCMCIABus,
98	CBus,
99	MPIBus,
100	MPSABus,
101	ProcessorInternal,
102	InternalPowerBus,
103	PNPISABus,
104	PNPBus,
105	MaximumInterfaceType
106};
107
108typedef enum interface_type interface_type;
109
110/*
111 * XXX
112 * Ordinarily, device_probe_desc is defined in device_if.h, which
113 * is created from device_if.m. The problem is, the latter file
114 * is only available if you have the kernel source code installed,
115 * and not all users choose to install it. I'd like to let people
116 * load Windows driver modules with the minimal amount of hassle
117 * and dependencies. <sys/bus.h> wants both device_if.h and bus_if.h
118 * to be defined, but it turns out the only thing we really need
119 * to get this module compiled is device_probe_desc, so we define
120 * that here, and let the build script create empty copies of
121 * device_if.h and bus_if.h to make the compiler happy.
122 */
123
124extern struct kobjop_desc device_probe_desc;
125typedef int device_probe_t(device_t dev);
126
127extern int windrv_load(module_t, vm_offset_t, size_t,
128	interface_type, void *, void *);
129extern int windrv_unload(module_t, vm_offset_t, size_t);
130
131#ifndef DRV_DATA_START
132#define DRV_DATA_START UNDEF_START
133#endif
134
135#ifndef DRV_DATA_END
136#define DRV_DATA_END UNDEF_END
137#endif
138
139#ifndef DRV_NAME
140#define DRV_NAME UNDEF_NAME
141#endif
142
143extern uint8_t DRV_DATA_START;
144extern uint8_t DRV_DATA_END;
145
146/*
147 * The following is stub code that makes it look as though we want
148 * to be a child device of all the buses that our supported devices
149 * might want to attach to. Our probe routine always fails. The
150 * reason we need this code is so that loading an ELF-ified Windows
151 * driver module will trigger a bus reprobe.
152 */
153
154#define MODULE_DECL(x)				\
155	MODULE_DEPEND(x, ndisapi, 1, 1, 1);	\
156	MODULE_DEPEND(x, ndis, 1, 1, 1)
157
158MODULE_DECL(DRV_NAME);
159
160static int windrv_probe(device_t);
161static int windrv_modevent(module_t, int, void *);
162static int windrv_loaded = 0;
163
164static device_method_t windrv_methods[] = {
165	/* Device interface */
166	DEVMETHOD(device_probe,         windrv_probe),
167
168	{ 0, 0 }
169};
170
171static driver_t windrv_driver = {
172	"windrv_stub",
173	windrv_methods,
174	0
175};
176
177static devclass_t windrv_devclass;
178
179#define DRIVER_DECL(x)					\
180	DRIVER_MODULE(x, pci, windrv_driver,		\
181	    windrv_devclass, windrv_modevent, NULL);	\
182	DRIVER_MODULE(x, cardbus, windrv_driver,	\
183	    windrv_devclass, windrv_modevent, NULL);	\
184	DRIVER_MODULE(x, pccard, windrv_driver,		\
185	    windrv_devclass, windrv_modevent, NULL);	\
186	DRIVER_MODULE(x, uhub, windrv_driver,		\
187	    windrv_devclass, windrv_modevent, NULL);	\
188	MODULE_VERSION(x, 1)
189
190DRIVER_DECL(DRV_NAME);
191
192static int
193windrv_probe(dev)
194	device_t		dev;
195{
196	return (ENXIO);
197}
198
199static int
200windrv_modevent(mod, cmd, arg)
201	module_t		mod;
202	int			cmd;
203	void			*arg;
204{
205	int			drv_data_len;
206	int			error = 0;
207	vm_offset_t		drv_data_start;
208	vm_offset_t		drv_data_end;
209	interface_type		drv_type;
210
211#ifdef NDIS_PCI_DEV_TABLE
212	drv_type = PCIBus;
213#endif
214
215#ifdef NDIS_PCMCIA_DEV_TABLE
216	drv_type = PCMCIABus;
217#endif
218
219	drv_data_start = (vm_offset_t)&DRV_DATA_START;
220	drv_data_end = (vm_offset_t)&DRV_DATA_END;
221
222	drv_data_len = drv_data_end - drv_data_start;
223	switch (cmd) {
224	case MOD_LOAD:
225		windrv_loaded++;
226		if (windrv_loaded > 1)
227			break;
228		windrv_load(mod, drv_data_start, drv_data_len, drv_type,
229		    ndis_devs, &ndis_regvals);
230		break;
231	case MOD_UNLOAD:
232		windrv_loaded--;
233		if (windrv_loaded > 0)
234			break;
235		windrv_unload(mod, drv_data_start, drv_data_len);
236		break;
237	case MOD_SHUTDOWN:
238		break;
239	default:
240		error = EINVAL;
241		break;
242	}
243
244	return (error);
245}
246