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