1145485Swpaul/*- 2145485Swpaul * Copyright (c) 2005 3145485Swpaul * Bill Paul <wpaul@windriver.com>. All rights reserved. 4145485Swpaul * 5145485Swpaul * Redistribution and use in source and binary forms, with or without 6145485Swpaul * modification, are permitted provided that the following conditions 7145485Swpaul * are met: 8145485Swpaul * 1. Redistributions of source code must retain the above copyright 9145485Swpaul * notice, this list of conditions and the following disclaimer. 10145485Swpaul * 2. Redistributions in binary form must reproduce the above copyright 11145485Swpaul * notice, this list of conditions and the following disclaimer in the 12145485Swpaul * documentation and/or other materials provided with the distribution. 13145485Swpaul * 3. All advertising materials mentioning features or use of this software 14145485Swpaul * must display the following acknowledgement: 15145485Swpaul * This product includes software developed by Bill Paul. 16145485Swpaul * 4. Neither the name of the author nor the names of any co-contributors 17145485Swpaul * may be used to endorse or promote products derived from this software 18145485Swpaul * without specific prior written permission. 19145485Swpaul * 20145485Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21145485Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22145485Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23145485Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24145485Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25145485Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26145485Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27145485Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28145485Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29145485Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30145485Swpaul * THE POSSIBILITY OF SUCH DAMAGE. 31145485Swpaul */ 32145485Swpaul 33145485Swpaul#include <sys/cdefs.h> 34145485Swpaul__FBSDID("$FreeBSD$"); 35145485Swpaul 36145485Swpaul#include <sys/param.h> 37145485Swpaul#include <sys/systm.h> 38145485Swpaul#include <sys/kernel.h> 39145485Swpaul#include <sys/module.h> 40145485Swpaul#include <sys/conf.h> 41145485Swpaul 42145485Swpaul#include <machine/bus.h> 43145485Swpaul#include <machine/resource.h> 44145485Swpaul#include <sys/bus.h> 45145485Swpaul 46145485Swpaul#define NDIS_REGVALS 47145485Swpaul 48145485Swpaulstruct ndis_cfg { 49145485Swpaul char *nc_cfgkey; 50145485Swpaul char *nc_cfgdesc; 51145485Swpaul char nc_val[256]; 52145485Swpaul int nc_idx; 53145485Swpaul}; 54145485Swpaul 55145485Swpaultypedef struct ndis_cfg ndis_cfg; 56145485Swpaul 57145485Swpaul#include "windrv.h" 58145485Swpaul 59145485Swpaulstruct ndis_pci_type { 60145485Swpaul uint16_t ndis_vid; 61145485Swpaul uint16_t ndis_did; 62145485Swpaul uint32_t ndis_subsys; 63145485Swpaul char *ndis_name; 64145485Swpaul}; 65145485Swpaul 66145485Swpaulstruct ndis_pccard_type { 67145485Swpaul const char *ndis_vid; 68145485Swpaul const char *ndis_did; 69145485Swpaul char *ndis_name; 70145485Swpaul}; 71145485Swpaul 72186507Sweongyostruct ndis_usb_type { 73186507Sweongyo uint16_t ndis_vid; 74186507Sweongyo uint16_t ndis_did; 75186507Sweongyo char *ndis_name; 76186507Sweongyo}; 77145485Swpaul 78145485Swpaul#ifdef NDIS_PCI_DEV_TABLE 79146015Swpaulstatic struct ndis_pci_type ndis_devs_pci[] = { 80145485Swpaul NDIS_PCI_DEV_TABLE 81145485Swpaul { 0, 0, 0, NULL } 82145485Swpaul}; 83145485Swpaul#endif 84145485Swpaul 85145485Swpaul#ifdef NDIS_PCMCIA_DEV_TABLE 86146015Swpaulstatic struct ndis_pccard_type ndis_devs_pccard[] = { 87145485Swpaul NDIS_PCMCIA_DEV_TABLE 88145485Swpaul { NULL, NULL, NULL } 89145485Swpaul}; 90145485Swpaul#endif 91145485Swpaul 92186507Sweongyo#ifdef NDIS_USB_DEV_TABLE 93186507Sweongyostatic struct ndis_usb_type ndis_devs_usb[] = { 94186507Sweongyo NDIS_USB_DEV_TABLE 95186507Sweongyo { 0, 0, NULL } 96186507Sweongyo}; 97186507Sweongyo#endif 98186507Sweongyo 99145485Swpaulenum interface_type { 100145485Swpaul InterfaceTypeUndefined = -1, 101145485Swpaul Internal, 102145485Swpaul Isa, 103145485Swpaul Eisa, 104145485Swpaul MicroChannel, 105145485Swpaul TurboChannel, 106145485Swpaul PCIBus, 107145485Swpaul VMEBus, 108145485Swpaul NuBus, 109145485Swpaul PCMCIABus, 110145485Swpaul CBus, 111145485Swpaul MPIBus, 112145485Swpaul MPSABus, 113145485Swpaul ProcessorInternal, 114145485Swpaul InternalPowerBus, 115145485Swpaul PNPISABus, 116145485Swpaul PNPBus, 117145485Swpaul MaximumInterfaceType 118145485Swpaul}; 119145485Swpaul 120145485Swpaultypedef enum interface_type interface_type; 121145485Swpaul 122145485Swpaul/* 123145485Swpaul * XXX 124145485Swpaul * Ordinarily, device_probe_desc is defined in device_if.h, which 125145485Swpaul * is created from device_if.m. The problem is, the latter file 126145485Swpaul * is only available if you have the kernel source code installed, 127145485Swpaul * and not all users choose to install it. I'd like to let people 128145485Swpaul * load Windows driver modules with the minimal amount of hassle 129145485Swpaul * and dependencies. <sys/bus.h> wants both device_if.h and bus_if.h 130145485Swpaul * to be defined, but it turns out the only thing we really need 131145485Swpaul * to get this module compiled is device_probe_desc, so we define 132145485Swpaul * that here, and let the build script create empty copies of 133145485Swpaul * device_if.h and bus_if.h to make the compiler happy. 134145485Swpaul */ 135145485Swpaul 136145485Swpaulextern struct kobjop_desc device_probe_desc; 137145485Swpaultypedef int device_probe_t(device_t dev); 138145485Swpaul 139145485Swpaulextern int windrv_load(module_t, vm_offset_t, size_t, 140145485Swpaul interface_type, void *, void *); 141145485Swpaulextern int windrv_unload(module_t, vm_offset_t, size_t); 142145485Swpaul 143145485Swpaul#ifndef DRV_DATA_START 144145485Swpaul#define DRV_DATA_START UNDEF_START 145145485Swpaul#endif 146145485Swpaul 147145485Swpaul#ifndef DRV_DATA_END 148145485Swpaul#define DRV_DATA_END UNDEF_END 149145485Swpaul#endif 150145485Swpaul 151145485Swpaul#ifndef DRV_NAME 152145485Swpaul#define DRV_NAME UNDEF_NAME 153145485Swpaul#endif 154145485Swpaul 155145485Swpaulextern uint8_t DRV_DATA_START; 156145485Swpaulextern uint8_t DRV_DATA_END; 157145485Swpaul 158145485Swpaul/* 159145485Swpaul * The following is stub code that makes it look as though we want 160145485Swpaul * to be a child device of all the buses that our supported devices 161145485Swpaul * might want to attach to. Our probe routine always fails. The 162145485Swpaul * reason we need this code is so that loading an ELF-ified Windows 163145485Swpaul * driver module will trigger a bus reprobe. 164145485Swpaul */ 165145485Swpaul 166145485Swpaul#define MODULE_DECL(x) \ 167145485Swpaul MODULE_DEPEND(x, ndisapi, 1, 1, 1); \ 168145485Swpaul MODULE_DEPEND(x, ndis, 1, 1, 1) 169145485Swpaul 170145485SwpaulMODULE_DECL(DRV_NAME); 171145485Swpaul 172145485Swpaulstatic int windrv_probe(device_t); 173145485Swpaulstatic int windrv_modevent(module_t, int, void *); 174145485Swpaulstatic int windrv_loaded = 0; 175145485Swpaul 176145485Swpaulstatic device_method_t windrv_methods[] = { 177145485Swpaul /* Device interface */ 178145485Swpaul DEVMETHOD(device_probe, windrv_probe), 179145485Swpaul 180145485Swpaul { 0, 0 } 181145485Swpaul}; 182145485Swpaul 183145485Swpaulstatic driver_t windrv_driver = { 184145485Swpaul "windrv_stub", 185145485Swpaul windrv_methods, 186145485Swpaul 0 187145485Swpaul}; 188145485Swpaul 189145485Swpaulstatic devclass_t windrv_devclass; 190145485Swpaul 191145485Swpaul#define DRIVER_DECL(x) \ 192145485Swpaul DRIVER_MODULE(x, pci, windrv_driver, \ 193145485Swpaul windrv_devclass, windrv_modevent, NULL); \ 194145485Swpaul DRIVER_MODULE(x, cardbus, windrv_driver, \ 195145485Swpaul windrv_devclass, windrv_modevent, NULL); \ 196145485Swpaul DRIVER_MODULE(x, pccard, windrv_driver, \ 197145485Swpaul windrv_devclass, windrv_modevent, NULL); \ 198145485Swpaul DRIVER_MODULE(x, uhub, windrv_driver, \ 199145485Swpaul windrv_devclass, windrv_modevent, NULL); \ 200145485Swpaul MODULE_VERSION(x, 1) 201145485Swpaul 202145485SwpaulDRIVER_DECL(DRV_NAME); 203145485Swpaul 204145485Swpaulstatic int 205145485Swpaulwindrv_probe(dev) 206145485Swpaul device_t dev; 207145485Swpaul{ 208145485Swpaul return (ENXIO); 209145485Swpaul} 210145485Swpaul 211145485Swpaulstatic int 212145485Swpaulwindrv_modevent(mod, cmd, arg) 213145485Swpaul module_t mod; 214145485Swpaul int cmd; 215145485Swpaul void *arg; 216145485Swpaul{ 217145485Swpaul int drv_data_len; 218145485Swpaul int error = 0; 219145485Swpaul vm_offset_t drv_data_start; 220145485Swpaul vm_offset_t drv_data_end; 221145485Swpaul 222145485Swpaul drv_data_start = (vm_offset_t)&DRV_DATA_START; 223145485Swpaul drv_data_end = (vm_offset_t)&DRV_DATA_END; 224145485Swpaul 225145485Swpaul drv_data_len = drv_data_end - drv_data_start; 226145485Swpaul switch (cmd) { 227145485Swpaul case MOD_LOAD: 228145485Swpaul windrv_loaded++; 229145485Swpaul if (windrv_loaded > 1) 230145485Swpaul break; 231146015Swpaul#ifdef NDIS_PCI_DEV_TABLE 232146015Swpaul windrv_load(mod, drv_data_start, drv_data_len, PCIBus, 233146015Swpaul ndis_devs_pci, &ndis_regvals); 234146015Swpaul#endif 235146015Swpaul#ifdef NDIS_PCMCIA_DEV_TABLE 236146015Swpaul windrv_load(mod, drv_data_start, drv_data_len, PCMCIABus, 237146015Swpaul ndis_devs_pccard, &ndis_regvals); 238146015Swpaul#endif 239186507Sweongyo#ifdef NDIS_USB_DEV_TABLE 240186507Sweongyo windrv_load(mod, drv_data_start, drv_data_len, PNPBus, 241186507Sweongyo ndis_devs_usb, &ndis_regvals); 242186507Sweongyo#endif 243145485Swpaul break; 244145485Swpaul case MOD_UNLOAD: 245145485Swpaul windrv_loaded--; 246145485Swpaul if (windrv_loaded > 0) 247145485Swpaul break; 248146015Swpaul#ifdef NDIS_PCI_DEV_TABLE 249145485Swpaul windrv_unload(mod, drv_data_start, drv_data_len); 250146015Swpaul#endif 251146015Swpaul#ifdef NDIS_PCMCIA_DEV_TABLE 252146015Swpaul windrv_unload(mod, drv_data_start, drv_data_len); 253146015Swpaul#endif 254186507Sweongyo#ifdef NDIS_USB_DEV_TABLE 255186507Sweongyo windrv_unload(mod, drv_data_start, drv_data_len); 256186507Sweongyo#endif 257145485Swpaul break; 258145485Swpaul case MOD_SHUTDOWN: 259145485Swpaul break; 260145485Swpaul default: 261145485Swpaul error = EINVAL; 262145485Swpaul break; 263145485Swpaul } 264145485Swpaul 265145485Swpaul return (error); 266145485Swpaul} 267