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