16
#include <linux/init.h>
17
20
#include <linux/module.h>
18
#include <linux/kernel.h>
19
#include <linux/vmalloc.h>
20
21
#include <linux/kmod.h>
22
#include <linux/types.h>
24
#include <linux/errno.h>
25
22
#include <linux/miscdevice.h>
26
#include <linux/pci.h>
28
#include <linux/netdevice.h>
29
#include <linux/etherdevice.h>
30
#include <linux/ethtool.h>
31
#include <linux/if_arp.h>
32
#include <net/iw_handler.h>
33
#include <linux/rtnetlink.h>
35
23
#include <asm/uaccess.h>
41
static KSPIN_LOCK loader_lock;
25
KSPIN_LOCK loader_lock;
42
26
static struct ndis_device *ndis_devices;
43
27
static unsigned int num_ndis_devices;
44
struct list_head ndis_drivers;
28
struct nt_list ndis_drivers;
45
29
static struct pci_device_id *ndiswrapper_pci_devices;
30
static struct pci_driver ndiswrapper_pci_driver;
31
#if defined(CONFIG_USB)
46
32
static struct usb_device_id *ndiswrapper_usb_devices;
47
static struct pci_driver ndiswrapper_pci_driver;
48
33
static struct usb_driver ndiswrapper_usb_driver;
50
38
/* load driver for given device, if not already loaded */
51
39
static struct ndis_driver *ndiswrapper_load_driver(struct ndis_device *device)
54
42
struct ndis_driver *ndis_driver;
56
45
TRACEENTER1("device: %04X:%04X:%04X:%04X", device->vendor,
57
46
device->device, device->subvendor, device->subdevice);
59
kspin_lock(&loader_lock);
60
list_for_each_entry(ndis_driver, &ndis_drivers, list) {
49
irql = kspin_lock_irql(&loader_lock, DISPATCH_LEVEL);
50
nt_list_for_each_entry(ndis_driver, &ndis_drivers, list) {
61
51
if (strcmp(ndis_driver->name, device->driver_name) == 0) {
62
52
DBGTRACE1("driver %s already loaded",
63
53
ndis_driver->name);
142
133
pdev->subsystem_vendor, pdev->subsystem_device);
144
135
device = &ndis_devices[ent->driver_data];
146
136
driver = ndiswrapper_load_driver(device);
152
dev = ndis_init_netdev(&handle, device, driver);
140
dev = init_netdev(&wd, device, driver);
154
142
ERROR("couldn't initialize network device");
146
/* first create pdo */
147
drv_obj = find_bus_driver("PCI");
150
wd->dev.dev_type = NDIS_PCI_BUS;
153
pdo = alloc_pdo(drv_obj);
160
DBGTRACE1("driver: %p", pdo->drv_obj);
162
/* this creates (empty) fdo */
163
res = driver->drv_obj->drv_ext->add_device_func(driver->drv_obj,
165
if (res != STATUS_SUCCESS)
167
DBGTRACE1("fdo: %p", wd->nmb->fdo);
159
169
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
160
170
SET_NETDEV_DEV(dev, &pdev->dev);
163
handle->dev.pci = pdev;
164
handle->device = device;
165
pci_set_drvdata(pdev, handle);
166
device->handle = handle;
174
pci_set_drvdata(pdev, wd);
168
175
res = pci_enable_device(pdev);
170
177
ERROR("couldn't enable PCI device: %08x", res);
174
181
res = pci_request_regions(pdev, DRIVER_NAME);
176
183
ERROR("couldn't request PCI regions: %08x", res);
180
pci_set_power_state(pdev, 0);
181
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9)
182
pci_restore_state(pdev, NULL);
187
res = pci_set_power_state(pdev, PCI_D0);
190
/* 64-bit broadcom driver doesn't work if DMA is allocated
192
if (strcmp(device->driver_name, "netbc564") == 0) {
193
if (pci_set_dma_mask(pdev, 0x3fffffff) ||
194
pci_set_consistent_dma_mask(pdev, 0x3fffffff))
195
WARNING("DMA mask couldn't be set; this driver "
196
"may not work with more than 1GB RAM");
185
DBGTRACE1("%s", "calling ndis init routine");
186
if ((res = miniport_init(handle))) {
187
ERROR("Windows driver couldn't initialize the device (%08X)",
193
handle->hw_status = 0;
194
handle->wrapper_work = 0;
196
/* do we need to power up the card explicitly? */
197
miniport_set_int(handle, OID_PNP_SET_POWER, NdisDeviceStateD0);
198
miniport = &handle->driver->miniport_char;
199
/* According NDIS, pnp_event_notify should be called whenever power
201
* Only NDIS 5.1 drivers are required to supply this function; some
202
* drivers don't seem to support it (at least Orinoco)
205
if (miniport->pnp_event_notify) {
206
DBGTRACE3("%s", "calling pnp_event_notify");
207
miniport->pnp_event_notify(handle, NDIS_PNP_PROFILE_CHANGED,
208
&profile_inf, sizeof(profile_inf));
212
/* IPW2200 devices turn off radio if reset is called */
213
if (pdev->vendor != 0x8086)
214
miniport_reset(handle);
216
/* Wait a little to let card power up otherwise ifup might fail after
218
set_current_state(TASK_INTERRUPTIBLE);
219
schedule_timeout(HZ/2);
221
if (setup_dev(handle->net_dev)) {
222
ERROR("couldn't setup network device");
199
if (ndiswrapper_start_device(wd)) {
200
ERROR("couldn't start device");
226
204
atomic_inc(&driver->users);
206
wd->ndis_device = device;
227
207
TRACEEXIT1(return 0);
230
miniport_halt(handle);
232
210
pci_release_regions(pdev);
234
212
pci_disable_device(pdev);
214
pci_set_drvdata(pdev, NULL);
236
215
free_netdev(dev);
238
216
TRACEEXIT1(return res);
242
220
* Remove one PCI-card.
244
static void __devexit ndiswrapper_remove_one_pci_dev(struct pci_dev *pdev)
222
static void __devexit ndiswrapper_remove_pci_device(struct pci_dev *pdev)
246
struct ndis_handle *handle;
224
struct wrapper_dev *wd;
248
226
TRACEENTER1("%p", pdev);
250
handle = (struct ndis_handle *)pci_get_drvdata(pdev);
252
TRACEENTER1("%p", handle);
228
wd = (struct wrapper_dev *)pci_get_drvdata(pdev);
230
TRACEENTER1("%p", wd);
255
233
TRACEEXIT1(return);
257
atomic_dec(&handle->driver->users);
258
ndiswrapper_remove_one_dev(handle);
260
pci_release_regions(pdev);
261
pci_disable_device(pdev);
262
pci_set_drvdata(pdev, NULL);
234
ndiswrapper_stop_device(wd);
265
237
#ifdef CONFIG_USB
266
238
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
267
static int ndiswrapper_add_one_usb_dev(struct usb_interface *intf,
268
const struct usb_device_id *usb_id)
239
static int ndiswrapper_add_usb_device(struct usb_interface *intf,
240
const struct usb_device_id *usb_id)
270
static void *ndiswrapper_add_one_usb_dev(struct usb_device *udev,
272
const struct usb_device_id *usb_id)
242
static void *ndiswrapper_add_usb_device(struct usb_device *udev,
244
const struct usb_device_id *usb_id)
276
248
struct ndis_device *device;
277
249
struct ndis_driver *driver;
278
struct ndis_handle *handle;
250
struct wrapper_dev *wd;
279
251
struct net_device *dev;
280
struct miniport_char *miniport;
281
// unsigned long profile_inf = NDIS_POWER_PROFILE_AC;
252
struct device_object *pdo;
253
struct driver_object *drv_obj;
283
TRACEENTER1("vendor: %04x, product: %04x",
284
usb_id->idVendor, usb_id->idProduct);
255
TRACEENTER1("vendor: %04x, product: %04x, id: %p",
256
usb_id->idVendor, usb_id->idProduct, usb_id);
286
258
device = &ndis_devices[usb_id->driver_info];
259
/* RNDIS devices have two interfaces, so prevent from
260
* initializing the device again, if it has already been
263
DBGTRACE1("device is already loaded");
264
TRACEEXIT1(return 0);
287
267
driver = ndiswrapper_load_driver(device);
292
dev = ndis_init_netdev(&handle, device, driver);
269
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
274
dev = init_netdev(&wd, device, driver);
294
276
ERROR("couldn't initialize network device");
277
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
284
/* first create pdo */
285
drv_obj = find_bus_driver("USB");
288
wd->dev.dev_type = NDIS_USB_BUS;
290
pdo = alloc_pdo(drv_obj);
299
/* this creates (empty) fdo */
300
res = driver->drv_obj->drv_ext->add_device_func(driver->drv_obj,
302
if (res != STATUS_SUCCESS)
299
304
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
300
305
SET_NETDEV_DEV(dev, &intf->dev);
302
handle->dev.usb = interface_to_usbdev(intf);
304
usb_set_intfdata(intf, handle);
307
wd->dev.usb.udev = interface_to_usbdev(intf);
308
usb_set_intfdata(intf, wd);
309
wd->dev.usb.intf = intf;
306
handle->dev.usb = udev;
311
wd->dev.usb.udev = udev;
312
wd->dev.usb.intf = usb_ifnum_to_if(udev, ifnum);
309
315
TRACEENTER1("calling ndis init routine");
310
if ((res = miniport_init(handle))) {
311
ERROR("Windows driver couldn't initialize the device (%08X)",
317
handle->hw_status = 0;
318
handle->wrapper_work = 0;
320
/* do we need to power up the card explicitly? */
321
miniport_set_int(handle, OID_PNP_SET_POWER, NdisDeviceStateD0);
322
miniport = &handle->driver->miniport_char;
324
if (miniport->pnp_event_notify) {
325
DBGTRACE3("%s", "calling pnp_event_notify");
326
miniport->pnp_event_notify(handle->adapter_ctx,
327
NDIS_PNP_PROFILE_CHANGED,
328
&profile_inf, sizeof(profile_inf));
329
DBGTRACE3("%s", "done");
333
miniport_reset(handle);
334
/* wait here seems crucial; without this delay, at least
335
* prism54 driver crashes (why?) */
336
set_current_state(TASK_INTERRUPTIBLE);
337
schedule_timeout(3*HZ);
339
if (setup_dev(handle->net_dev)) {
340
ERROR("couldn't setup network device");
317
if (ndiswrapper_start_device(wd)) {
318
ERROR("couldn't start device");
345
323
atomic_inc(&driver->users);
325
wd->ndis_device = device;
347
327
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
348
328
TRACEEXIT1(return 0);
350
TRACEEXIT1(return handle);
330
TRACEEXIT1(return wd);
354
miniport_halt(handle);
356
338
free_netdev(dev);
358
340
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
359
341
TRACEEXIT1(return res);
608
611
static void unload_ndis_driver(struct ndis_driver *driver)
614
struct driver_object *drv_obj;
612
616
DBGTRACE1("freeing %d images", driver->num_pe_images);
613
if (driver->driver_unload)
614
driver->driver_unload(driver);
617
drv_obj = driver->drv_obj;
615
618
for (i = 0; i < driver->num_pe_images; i++)
616
if (driver->pe_images[i].image)
619
if (driver->pe_images[i].image) {
620
DBGTRACE1("freeing image at %p",
621
driver->pe_images[i].image);
617
622
vfree(driver->pe_images[i].image);
619
625
DBGTRACE1("freeing %d bin files", driver->num_bin_files);
620
for (i = 0; i < driver->num_bin_files; i++)
626
for (i = 0; i < driver->num_bin_files; i++) {
627
DBGTRACE1("freeing image at %p", driver->bin_files[i].data);
621
628
vfree(driver->bin_files[i].data);
622
630
if (driver->bin_files)
623
631
kfree(driver->bin_files);
633
// IoDetachDevice(drv_obj->dev_obj);
634
RtlFreeUnicodeString(&drv_obj->driver_name);
635
/* this frees driver */
636
free_custom_ext(drv_obj->drv_ext);
637
kfree(drv_obj->drv_ext);
626
639
TRACEEXIT1(return);
629
642
/* call the entry point of the driver */
630
643
static int start_driver(struct ndis_driver *driver)
633
struct unicode_string reg_string;
634
char *reg_path = "0/0t0m0p0";
647
struct driver_object *drv_obj;
648
UINT (*entry)(struct driver_object *obj,
649
struct unicode_string *path) STDCALL;
638
reg_string.buf = (wchar_t *)reg_path;
640
reg_string.buflen = reg_string.len = strlen(reg_path);
652
drv_obj = driver->drv_obj;
641
653
for (ret = res = 0, i = 0; i < driver->num_pe_images; i++)
642
654
/* dlls are already started by loader */
643
655
if (driver->pe_images[i].type == IMAGE_FILE_EXECUTABLE_IMAGE) {
644
UINT (*entry)(void *obj,
645
struct unicode_string *p2) STDCALL;
647
656
entry = driver->pe_images[i].entry;
648
DBGTRACE1("entry: %p, %p", entry, *entry);
649
res = LIN2WIN2(entry, (void *)driver, ®_string);
657
drv_obj->driver_start = driver->pe_images[i].entry;
658
drv_obj->driver_size = driver->pe_images[i].size;
659
DBGTRACE1("entry: %p, %p, drv_obj: %p",
660
entry, *entry, drv_obj);
661
res = LIN2WIN2(entry, drv_obj, &drv_obj->driver_name);
651
663
DBGTRACE1("entry returns %08X", res);
652
664
DBGTRACE1("driver version: %d.%d",
653
driver->miniport_char.majorVersion,
654
driver->miniport_char.minorVersion);
655
driver->entry = entry;
665
driver->miniport.major_version,
666
driver->miniport.minor_version);
659
671
ERROR("driver initialization failed: %08X", ret);
672
RtlFreeUnicodeString(&drv_obj->driver_name);
673
/* this frees ndis_driver */
674
free_custom_ext(drv_obj->drv_ext);
675
kfree(drv_obj->drv_ext);
660
677
TRACEEXIT1(return -EINVAL);
689
707
/* load a driver from userspace and initialize it */
690
708
static int load_ndis_driver(struct load_driver *load_driver)
692
struct ndis_driver *ndis_driver;
694
ndis_driver = kmalloc(sizeof(*ndis_driver), GFP_KERNEL);
696
ERROR("couldn't allocate memory");
697
TRACEEXIT1(return -EINVAL);
710
struct driver_object *drv_obj;
711
struct ansi_string ansi_reg;
712
struct ndis_driver *ndis_driver = NULL;
716
drv_obj = kmalloc(sizeof(*drv_obj), GFP_KERNEL);
718
ERROR("couldn't allocate memory");
719
TRACEEXIT1(return -ENOMEM);
721
DBGTRACE1("drv_obj: %p", drv_obj);
722
memset(drv_obj, 0, sizeof(*drv_obj));
723
drv_obj->drv_ext = kmalloc(sizeof(*(drv_obj->drv_ext)), GFP_KERNEL);
724
if (!drv_obj->drv_ext) {
725
ERROR("couldn't allocate memory");
727
TRACEEXIT1(return -ENOMEM);
729
memset(drv_obj->drv_ext, 0, sizeof(*(drv_obj->drv_ext)));
730
drv_obj->drv_ext->add_device_func = AddDevice;
731
InitializeListHead(&drv_obj->drv_ext->custom_ext);
733
if (IoAllocateDriverObjectExtension(drv_obj,
734
(void *)CE_NDIS_DRIVER_CLIENT_ID,
735
sizeof(*ndis_driver),
736
(void **)&ndis_driver) !=
738
TRACEEXIT1(return NDIS_STATUS_RESOURCES);
739
DBGTRACE1("driver: %p", ndis_driver);
740
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
741
drv_obj->major_func[i] = IopPassIrpDown;
742
// drv_obj->major_func[IRP_MJ_PNP] = fdoDispatchPnp;
699
744
memset(ndis_driver, 0, sizeof(*ndis_driver));
700
745
ndis_driver->bustype = -1;
746
ndis_driver->drv_obj = drv_obj;
747
ansi_reg.buf = "/tmp";
748
ansi_reg.length = strlen(ansi_reg.buf);
749
ansi_reg.max_length = ansi_reg.length + 1;
750
if (RtlAnsiStringToUnicodeString(&drv_obj->driver_name,
751
&ansi_reg, 1) != STATUS_SUCCESS) {
752
ERROR("couldn't initialize registry path");
753
free_custom_ext(drv_obj->drv_ext);
754
kfree(drv_obj->drv_ext);
756
TRACEEXIT1(return -EINVAL);
702
759
if (load_sys_files(ndis_driver, load_driver) ||
703
760
load_bin_files(ndis_driver, load_driver) ||
704
761
load_settings(ndis_driver, load_driver) ||