~ubuntu-branches/ubuntu/lucid/ndiswrapper/lucid

« back to all changes in this revision

Viewing changes to driver/loader.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant
  • Date: 2005-11-16 23:39:48 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051116233948-00yddqygl6w65vzg
Tags: 1.5-1ubuntu1
Resynchronise with Debian.  (Totally me!)

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
 *
14
14
 */
15
15
 
16
 
#include <linux/init.h>
 
16
#include "ndis.h"
 
17
#include "loader.h"
 
18
#include "wrapper.h"
 
19
 
17
20
#include <linux/module.h>
18
 
#include <linux/kernel.h>
19
 
#include <linux/vmalloc.h>
20
21
#include <linux/kmod.h>
21
 
 
22
 
#include <linux/types.h>
23
 
#include <linux/fs.h>
24
 
#include <linux/errno.h>
25
22
#include <linux/miscdevice.h>
26
 
#include <linux/pci.h>
27
 
 
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>
34
 
 
35
23
#include <asm/uaccess.h>
36
24
 
37
 
#include "ndis.h"
38
 
#include "loader.h"
39
 
#include "wrapper.h"
40
 
 
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;
 
34
#endif
 
35
 
 
36
extern int debug;
49
37
 
50
38
/* load driver for given device, if not already loaded */
51
39
static struct ndis_driver *ndiswrapper_load_driver(struct ndis_device *device)
52
40
{
53
41
        int err, found;
54
42
        struct ndis_driver *ndis_driver;
 
43
        KIRQL irql;
55
44
 
56
45
        TRACEENTER1("device: %04X:%04X:%04X:%04X", device->vendor,
57
46
                    device->device, device->subvendor, device->subdevice);
58
47
        found = 0;
59
 
        kspin_lock(&loader_lock);
60
 
        list_for_each_entry(ndis_driver, &ndis_drivers, list) {
 
48
        ndis_driver = NULL;
 
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);
65
55
                        break;
66
56
                }
67
57
        }
68
 
        kspin_unlock(&loader_lock);
 
58
        kspin_unlock_irql(&loader_lock, irql);
69
59
 
70
60
        if (found)
71
61
                TRACEEXIT1(return ndis_driver);
76
66
#else
77
67
                                "0",
78
68
#endif
79
 
                                NDISWRAPPER_VERSION, device->driver_name,
 
69
                                UTILS_VERSION, device->driver_name,
80
70
                                device->conf_file_name, NULL};
81
71
                char *env[] = {NULL};
82
72
 
99
89
                schedule_timeout(HZ);
100
90
#endif
101
91
                found = 0;
102
 
                kspin_lock(&loader_lock);
103
 
                list_for_each_entry(ndis_driver, &ndis_drivers, list) {
 
92
                irql = kspin_lock_irql(&loader_lock, DISPATCH_LEVEL);
 
93
                nt_list_for_each_entry(ndis_driver, &ndis_drivers, list) {
104
94
                        if (strcmp(ndis_driver->name,
105
95
                                   device->driver_name) == 0) {
106
96
                                found = 1;
107
97
                                break;
108
98
                        }
109
99
                }
110
 
                kspin_unlock(&loader_lock);
 
100
                kspin_unlock_irql(&loader_lock, irql);
111
101
 
112
102
                if (!found) {
113
103
                        ERROR("couldn't load driver '%s'",
126
116
 * This function should not be marked __devinit because ndiswrapper
127
117
 * adds PCI_id's dynamically.
128
118
 */
129
 
static int ndiswrapper_add_one_pci_dev(struct pci_dev *pdev,
130
 
                                       const struct pci_device_id *ent)
 
119
static int ndiswrapper_add_pci_device(struct pci_dev *pdev,
 
120
                                      const struct pci_device_id *ent)
131
121
{
132
 
        int res;
 
122
        int res = 0;
133
123
        struct ndis_device *device;
134
124
        struct ndis_driver *driver;
135
 
        struct ndis_handle *handle;
 
125
        struct wrapper_dev *wd;
136
126
        struct net_device *dev;
137
 
        struct miniport_char *miniport;
 
127
        struct device_object *pdo;
 
128
        struct driver_object *drv_obj;
138
129
 
139
130
        TRACEENTER1("ent: %p", ent);
140
131
 
142
133
                  pdev->subsystem_vendor, pdev->subsystem_device);
143
134
 
144
135
        device = &ndis_devices[ent->driver_data];
145
 
 
146
136
        driver = ndiswrapper_load_driver(device);
147
 
        if (!driver) {
148
 
                res = -ENODEV;
149
 
                goto out_nodev;
150
 
        }
 
137
        if (!driver)
 
138
                return -ENODEV;
151
139
 
152
 
        dev = ndis_init_netdev(&handle, device, driver);
 
140
        dev = init_netdev(&wd, device, driver);
153
141
        if (!dev) {
154
142
                ERROR("couldn't initialize network device");
155
 
                res = -ENOMEM;
156
 
                goto out_nodev;
157
 
        }
 
143
                return -ENOMEM;
 
144
        }
 
145
        DBGTRACE1("");
 
146
        /* first create pdo */
 
147
        drv_obj = find_bus_driver("PCI");
 
148
        if (!drv_obj)
 
149
                goto err_bus_driver;
 
150
        wd->dev.dev_type = NDIS_PCI_BUS;
 
151
        wd->dev.pci = pdev;
 
152
        DBGTRACE1("");
 
153
        pdo = alloc_pdo(drv_obj);
 
154
        if (!pdo) {
 
155
                res = -ENODEV;
 
156
                goto err_bus_driver;
 
157
        }
 
158
        pdo->reserved = wd;
 
159
        wd->nmb->pdo = pdo;
 
160
        DBGTRACE1("driver: %p", pdo->drv_obj);
 
161
 
 
162
        /* this creates (empty) fdo */
 
163
        res = driver->drv_obj->drv_ext->add_device_func(driver->drv_obj,
 
164
                                                        pdo);
 
165
        if (res != STATUS_SUCCESS)
 
166
                goto err_bus_driver;
 
167
        DBGTRACE1("fdo: %p", wd->nmb->fdo);
158
168
 
159
169
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
160
170
        SET_NETDEV_DEV(dev, &pdev->dev);
161
171
#endif
162
172
 
163
 
        handle->dev.pci = pdev;
164
 
        handle->device = device;
165
 
        pci_set_drvdata(pdev, handle);
166
 
        device->handle = handle;
167
 
 
 
173
        DBGTRACE1("");
 
174
        pci_set_drvdata(pdev, wd);
168
175
        res = pci_enable_device(pdev);
169
176
        if (res) {
170
177
                ERROR("couldn't enable PCI device: %08x", res);
171
 
                goto out_enable;
 
178
                goto err_bus_driver;
172
179
        }
173
180
 
174
181
        res = pci_request_regions(pdev, DRIVER_NAME);
175
182
        if (res) {
176
183
                ERROR("couldn't request PCI regions: %08x", res);
177
 
                goto out_regions;
178
 
        }
179
 
 
180
 
        pci_set_power_state(pdev, 0);
181
 
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9)
182
 
        pci_restore_state(pdev, NULL);
 
184
                goto err_enable;
 
185
        }
 
186
 
 
187
        res = pci_set_power_state(pdev, PCI_D0);
 
188
 
 
189
#ifdef CONFIG_X86_64
 
190
        /* 64-bit broadcom driver doesn't work if DMA is allocated
 
191
         * from over 1GB */
 
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");
 
197
        }
183
198
#endif
184
 
 
185
 
        DBGTRACE1("%s", "calling ndis init routine");
186
 
        if ((res = miniport_init(handle))) {
187
 
                ERROR("Windows driver couldn't initialize the device (%08X)",
188
 
                        res);
189
 
                res = -EINVAL;
190
 
                goto out_start;
191
 
        }
192
 
 
193
 
        handle->hw_status = 0;
194
 
        handle->wrapper_work = 0;
195
 
 
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
200
 
         * is set to D0
201
 
         * Only NDIS 5.1 drivers are required to supply this function; some
202
 
         * drivers don't seem to support it (at least Orinoco)
203
 
         */
204
 
        /*
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));
209
 
        }
210
 
        */
211
 
 
212
 
        /* IPW2200 devices turn off radio if reset is called */
213
 
        if (pdev->vendor != 0x8086)
214
 
                miniport_reset(handle);
215
 
 
216
 
        /* Wait a little to let card power up otherwise ifup might fail after
217
 
           boot */
218
 
        set_current_state(TASK_INTERRUPTIBLE);
219
 
        schedule_timeout(HZ/2);
220
 
 
221
 
        if (setup_dev(handle->net_dev)) {
222
 
                ERROR("couldn't setup network device");
223
 
                res = -EINVAL;
224
 
                goto out_setup;
 
199
        if (ndiswrapper_start_device(wd)) {
 
200
                ERROR("couldn't start device");
 
201
                res = -EINVAL;
 
202
                goto err_regions;
225
203
        }
226
204
        atomic_inc(&driver->users);
 
205
        device->wd = wd;
 
206
        wd->ndis_device = device;
227
207
        TRACEEXIT1(return 0);
228
208
 
229
 
out_setup:
230
 
        miniport_halt(handle);
231
 
out_start:
 
209
err_regions:
232
210
        pci_release_regions(pdev);
233
 
out_regions:
 
211
err_enable:
234
212
        pci_disable_device(pdev);
235
 
out_enable:
 
213
err_bus_driver:
 
214
        pci_set_drvdata(pdev, NULL);
236
215
        free_netdev(dev);
237
 
out_nodev:
238
216
        TRACEEXIT1(return res);
239
217
}
240
218
 
241
219
/*
242
220
 * Remove one PCI-card.
243
221
 */
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)
245
223
{
246
 
        struct ndis_handle *handle;
 
224
        struct wrapper_dev *wd;
247
225
 
248
226
        TRACEENTER1("%p", pdev);
249
227
 
250
 
        handle = (struct ndis_handle *)pci_get_drvdata(pdev);
251
 
 
252
 
        TRACEENTER1("%p", handle);
253
 
 
254
 
        if (!handle)
 
228
        wd = (struct wrapper_dev *)pci_get_drvdata(pdev);
 
229
 
 
230
        TRACEENTER1("%p", wd);
 
231
 
 
232
        if (!wd)
255
233
                TRACEEXIT1(return);
256
 
 
257
 
        atomic_dec(&handle->driver->users);
258
 
        ndiswrapper_remove_one_dev(handle);
259
 
 
260
 
        pci_release_regions(pdev);
261
 
        pci_disable_device(pdev);
262
 
        pci_set_drvdata(pdev, NULL);
 
234
        ndiswrapper_stop_device(wd);
263
235
}
264
236
 
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)
269
241
#else
270
 
static void *ndiswrapper_add_one_usb_dev(struct usb_device *udev,
271
 
                                         unsigned int ifnum,
272
 
                                         const struct usb_device_id *usb_id)
 
242
static void *ndiswrapper_add_usb_device(struct usb_device *udev,
 
243
                                        unsigned int ifnum,
 
244
                                        const struct usb_device_id *usb_id)
273
245
#endif
274
246
{
275
 
        int res;
 
247
        int res = 0;
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;
282
254
 
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);
285
257
 
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
 
261
         * initialized */
 
262
        if (device->wd) {
 
263
                DBGTRACE1("device is already loaded");
 
264
                TRACEEXIT1(return 0);
 
265
        }
 
266
 
287
267
        driver = ndiswrapper_load_driver(device);
288
 
        if (!driver) {
289
 
                res = -ENODEV;
290
 
                goto out_nodev;
291
 
        }
292
 
        dev = ndis_init_netdev(&handle, device, driver);
 
268
        if (!driver)
 
269
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 
270
                return -ENODEV;
 
271
#else
 
272
                return NULL;
 
273
#endif
 
274
        dev = init_netdev(&wd, device, driver);
293
275
        if (!dev) {
294
276
                ERROR("couldn't initialize network device");
295
 
                res = -ENOMEM;
296
 
                goto out_nodev;
297
 
        }
298
 
 
 
277
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 
278
                return -ENOMEM;
 
279
#else
 
280
                return NULL;
 
281
#endif
 
282
        }
 
283
 
 
284
        /* first create pdo */
 
285
        drv_obj = find_bus_driver("USB");
 
286
        if (!drv_obj)
 
287
                goto err_net_dev;
 
288
        wd->dev.dev_type = NDIS_USB_BUS;
 
289
        DBGTRACE1("");
 
290
        pdo = alloc_pdo(drv_obj);
 
291
        if (!pdo) {
 
292
                res = -ENODEV;
 
293
                goto err_net_dev;
 
294
        }
 
295
        pdo->reserved = wd;
 
296
        wd->nmb->pdo = pdo;
 
297
 
 
298
        DBGTRACE1("");
 
299
        /* this creates (empty) fdo */
 
300
        res = driver->drv_obj->drv_ext->add_device_func(driver->drv_obj,
 
301
                                                        pdo);
 
302
        if (res != STATUS_SUCCESS)
 
303
                goto err_pdo;
299
304
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
300
305
        SET_NETDEV_DEV(dev, &intf->dev);
301
306
 
302
 
        handle->dev.usb = interface_to_usbdev(intf);
303
 
        handle->intf    = 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;
305
310
#else
306
 
        handle->dev.usb = udev;
 
311
        wd->dev.usb.udev = udev;
 
312
        wd->dev.usb.intf = usb_ifnum_to_if(udev, ifnum);
307
313
#endif
308
314
 
309
315
        TRACEENTER1("calling ndis init routine");
310
 
        if ((res = miniport_init(handle))) {
311
 
                ERROR("Windows driver couldn't initialize the device (%08X)",
312
 
                        res);
313
 
                res = -EINVAL;
314
 
                goto out_start;
315
 
        }
316
 
 
317
 
        handle->hw_status = 0;
318
 
        handle->wrapper_work = 0;
319
 
 
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;
323
 
        /*
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");
330
 
        }
331
 
        */
332
 
 
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);
338
 
 
339
 
        if (setup_dev(handle->net_dev)) {
340
 
                ERROR("couldn't setup network device");
341
 
                res = -EINVAL;
342
 
                goto out_setup;
 
316
 
 
317
        if (ndiswrapper_start_device(wd)) {
 
318
                ERROR("couldn't start device");
 
319
                res = -EINVAL;
 
320
                goto err_add_dev;
343
321
        }
344
322
 
345
323
        atomic_inc(&driver->users);
 
324
        device->wd = wd;
 
325
        wd->ndis_device = device;
346
326
 
347
327
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
348
328
        TRACEEXIT1(return 0);
349
329
#else
350
 
        TRACEEXIT1(return handle);
 
330
        TRACEEXIT1(return wd);
351
331
#endif
352
332
 
353
 
out_setup:
354
 
        miniport_halt(handle);
355
 
out_start:
 
333
err_add_dev:
 
334
        DeleteDevice(pdo);
 
335
err_pdo:
 
336
        IoDeleteDevice(pdo);
 
337
err_net_dev:
356
338
        free_netdev(dev);
357
 
out_nodev:
 
339
        device->wd = NULL;
358
340
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
359
341
        TRACEEXIT1(return res);
360
342
#else
366
348
#ifdef CONFIG_USB
367
349
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
368
350
static void
369
 
ndiswrapper_remove_one_usb_dev(struct usb_interface *intf)
 
351
ndiswrapper_remove_usb_device(struct usb_interface *intf)
370
352
{
371
 
        struct ndis_handle *handle;
 
353
        struct wrapper_dev *wd;
372
354
 
373
355
        TRACEENTER1("");
374
 
        handle = (struct ndis_handle *)usb_get_intfdata(intf);
375
 
 
376
 
        if (!handle)
 
356
        wd = (struct wrapper_dev *)usb_get_intfdata(intf);
 
357
        if (!wd)
377
358
                TRACEEXIT1(return);
 
359
 
 
360
        if (!test_bit(HW_RMMOD, &wd->hw_status))
 
361
                miniport_surprise_remove(wd);
 
362
        wd->dev.usb.intf = NULL;
378
363
        usb_set_intfdata(intf, NULL);
379
 
        atomic_dec(&handle->driver->users);
380
 
        ndiswrapper_remove_one_dev(handle);
 
364
        ndiswrapper_stop_device(wd);
381
365
}
382
366
#else
383
367
static void
384
 
ndiswrapper_remove_one_usb_dev(struct usb_device *udev, void *ptr)
 
368
ndiswrapper_remove_usb_device(struct usb_device *udev, void *ptr)
385
369
{
386
 
        struct ndis_handle *handle = (struct ndis_handle *)ptr;
 
370
        struct wrapper_dev *wd = (struct wrapper_dev *)ptr;
387
371
 
388
372
        TRACEENTER1("");
389
 
 
390
 
        if (!handle || !handle->dev.usb)
 
373
        if (!wd || !wd->dev.usb.intf)
391
374
                TRACEEXIT1(return);
392
 
        handle->dev.usb = NULL;
393
 
        atomic_dec(&handle->driver->users);
394
 
        ndiswrapper_remove_one_dev(handle);
 
375
        if (!test_bit(HW_RMMOD, &wd->hw_status))
 
376
                miniport_surprise_remove(wd);
 
377
        wd->dev.usb.intf = NULL;
 
378
        atomic_dec(&wd->driver->users);
 
379
        if (wd->ndis_device)
 
380
                wd->ndis_device->wd = NULL;
 
381
        ndiswrapper_stop_device(wd);
395
382
}
396
383
#endif
397
384
#endif /* CONFIG_USB */
422
409
 
423
410
#ifdef CONFIG_X86_64
424
411
#ifdef PAGE_KERNEL_EXECUTABLE
425
 
                pe_image->image = __vmalloc(load_driver->sys_files[i].size,
426
 
                                            GFP_KERNEL | __GFP_HIGHMEM,
427
 
                                            PAGE_KERNEL_EXECUTABLE);
 
412
                pe_image->image =
 
413
                        __vmalloc(load_driver->sys_files[i].size,
 
414
                                  GFP_KERNEL | __GFP_HIGHMEM,
 
415
                                  PAGE_KERNEL_EXECUTABLE);
428
416
#elif defined PAGE_KERNEL_EXEC
429
 
                pe_image->image = __vmalloc(load_driver->sys_files[i].size,
430
 
                                            GFP_KERNEL | __GFP_HIGHMEM,
431
 
                                            PAGE_KERNEL_EXEC);
 
417
                pe_image->image =
 
418
                        __vmalloc(load_driver->sys_files[i].size,
 
419
                                  GFP_KERNEL | __GFP_HIGHMEM,
 
420
                                  PAGE_KERNEL_EXEC);
432
421
#else
433
422
#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC
434
423
#endif
435
424
#else
436
 
                pe_image->image = vmalloc(load_driver->sys_files[i].size);
 
425
                /* hate to play with kernel macros, but PAGE_KERNEL_EXEC is
 
426
                 * not available to modules! */
 
427
#ifdef cpu_has_nx
 
428
                if (cpu_has_nx)
 
429
                        pe_image->image =
 
430
                                __vmalloc(load_driver->sys_files[i].size,
 
431
                                          GFP_KERNEL | __GFP_HIGHMEM,
 
432
                                          __pgprot(__PAGE_KERNEL & ~_PAGE_NX));
 
433
                else
 
434
                        pe_image->image =
 
435
                                vmalloc(load_driver->sys_files[i].size);
 
436
#else
 
437
                        pe_image->image =
 
438
                                vmalloc(load_driver->sys_files[i].size);
 
439
#endif
437
440
#endif
438
441
                if (!pe_image->image) {
439
442
                        ERROR("couldn't allocate memory");
453
456
        }
454
457
 
455
458
        if (load_pe_images(driver->pe_images, driver->num_pe_images)) {
456
 
                ERROR("unable to prepare driver '%s'", load_driver->name);
 
459
                ERROR("couldn't prepare driver '%s'", load_driver->name);
457
460
                err = -EINVAL;
458
461
        }
459
462
 
463
466
                                vfree(driver->pe_images[i].image);
464
467
                driver->num_pe_images = 0;
465
468
                TRACEEXIT1(return -EINVAL);
466
 
        } else {
 
469
        } else
467
470
                TRACEEXIT1(return 0);
468
 
        }
469
 
 
470
471
}
471
472
 
472
473
/* load firmware files from userspace */
524
525
static int load_settings(struct ndis_driver *ndis_driver,
525
526
                         struct load_driver *load_driver)
526
527
{
527
 
        int i, found, nr_settings;
 
528
        int i, nr_settings;
528
529
        struct ndis_device *ndis_device;
 
530
        KIRQL irql;
529
531
 
530
532
        TRACEENTER1("");
531
533
 
532
 
        found = 0;
533
 
        kspin_lock(&loader_lock);
 
534
        ndis_device = NULL;
 
535
        irql = kspin_lock_irql(&loader_lock, DISPATCH_LEVEL);
534
536
        for (i = 0; i < num_ndis_devices; i++) {
535
537
                if (strcmp(ndis_devices[i].conf_file_name,
536
538
                           load_driver->conf_file_name) == 0) {
537
 
                        found = 1;
 
539
                        ndis_device = &ndis_devices[i];
538
540
                        break;
539
541
                }
540
542
        }
541
 
        kspin_unlock(&loader_lock);
 
543
        kspin_unlock_irql(&loader_lock, irql);
542
544
 
543
 
        if (!found) {
 
545
        if (!ndis_device) {
544
546
                ERROR("conf file %s not found",
545
547
                      ndis_devices[i].conf_file_name);
546
548
                TRACEEXIT1(return -EINVAL);
547
549
        }
548
550
 
549
551
        nr_settings = 0;
550
 
        ndis_device = &ndis_devices[i];
551
552
        for (i = 0; i < load_driver->nr_settings; i++) {
552
553
                struct load_device_setting *load_setting =
553
554
                        &load_driver->settings[i];
569
570
                if (strcmp(setting->name, "ndis_version") == 0)
570
571
                        memcpy(ndis_driver->version, setting->value,
571
572
                               sizeof(ndis_driver->version));
572
 
                kspin_lock(&loader_lock);
573
 
                list_add(&setting->list, &ndis_device->settings);
574
 
                kspin_unlock(&loader_lock);
 
573
                irql = kspin_lock_irql(&loader_lock, DISPATCH_LEVEL);
 
574
                InsertTailList(&ndis_device->settings, &setting->list);
 
575
                kspin_unlock_irql(&loader_lock, irql);
575
576
                nr_settings++;
576
577
        }
577
578
        /* it is not a fatal error if some settings couldn't be loaded */
584
585
/* this function is called while holding load_lock spinlock */
585
586
static void unload_ndis_device(struct ndis_device *device)
586
587
{
587
 
        TRACEENTER1("unloading device %04X:%04X:%04X:%04X, driver %s",
588
 
                    device->vendor, device->device, device->subvendor,
 
588
        struct nt_list *cur;
 
589
        TRACEENTER1("unloading device %p (%04X:%04X:%04X:%04X), driver %s",
 
590
                    device, device->vendor, device->device, device->subvendor,
589
591
                    device->subdevice, device->driver_name);
590
592
 
591
 
        while (!list_empty(&device->settings)) {
 
593
        DBGTRACE3("%p", device->ndis_driver);
 
594
        if (!device->ndis_driver)
 
595
                TRACEEXIT1(return);
 
596
        while ((cur = RemoveHeadList(&device->settings))) {
592
597
                struct device_setting *setting;
593
598
                struct ndis_config_param *param;
594
599
 
595
 
                setting = list_entry(device->settings.next,
596
 
                                     struct device_setting, list);
 
600
                setting = container_of(cur, struct device_setting, list);
597
601
                param = &setting->config_param;
598
602
                if (param->type == NDIS_CONFIG_PARAM_STRING)
599
603
                        RtlFreeUnicodeString(&param->data.ustring);
600
 
                list_del(&setting->list);
601
604
                kfree(setting);
602
605
        }
603
606
        TRACEEXIT1(return);
608
611
static void unload_ndis_driver(struct ndis_driver *driver)
609
612
{
610
613
        int i;
 
614
        struct driver_object *drv_obj;
611
615
 
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);
 
623
                }
618
624
 
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);
 
629
        }
622
630
        if (driver->bin_files)
623
631
                kfree(driver->bin_files);
624
632
 
625
 
        kfree(driver);
 
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);
 
638
        kfree(drv_obj);
626
639
        TRACEEXIT1(return);
627
640
}
628
641
 
629
642
/* call the entry point of the driver */
630
643
static int start_driver(struct ndis_driver *driver)
631
644
{
632
 
        int i, ret, res;
633
 
        struct unicode_string reg_string;
634
 
        char *reg_path = "0/0t0m0p0";
 
645
        int i;
 
646
        NTSTATUS ret, res;
 
647
        struct driver_object *drv_obj;
 
648
        UINT (*entry)(struct driver_object *obj,
 
649
                      struct unicode_string *path) STDCALL;
635
650
 
636
651
        TRACEENTER1("");
637
 
 
638
 
        reg_string.buf = (wchar_t *)reg_path;
639
 
 
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;
646
 
 
647
656
                        entry = driver->pe_images[i].entry;
648
 
                        DBGTRACE1("entry: %p, %p", entry, *entry);
649
 
                        res = LIN2WIN2(entry, (void *)driver, &reg_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);
650
662
                        ret |= res;
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);
 
667
                        break;
656
668
                }
657
669
 
658
670
        if (ret) {
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);
 
676
                kfree(drv_obj);
660
677
                TRACEEXIT1(return -EINVAL);
661
678
        }
662
679
 
669
686
 */
670
687
static int add_driver(struct ndis_driver *driver)
671
688
{
 
689
        KIRQL irql;
672
690
        struct ndis_driver *tmp;
673
691
 
674
692
        TRACEENTER1("");
675
 
        kspin_lock(&loader_lock);
676
 
        list_for_each_entry(tmp, &ndis_drivers, list) {
 
693
        irql = kspin_lock_irql(&loader_lock, DISPATCH_LEVEL);
 
694
        nt_list_for_each_entry(tmp, &ndis_drivers, list) {
677
695
                if (strcmp(tmp->name, driver->name) == 0) {
678
 
                        kspin_unlock(&loader_lock);
 
696
                        kspin_unlock_irql(&loader_lock, irql);
679
697
                        ERROR("cannot add duplicate driver");
680
698
                        TRACEEXIT1(return -EBUSY);
681
699
                }
682
700
        }
683
 
        list_add(&driver->list, &ndis_drivers);
684
 
        kspin_unlock(&loader_lock);
 
701
        InsertTailList(&ndis_drivers, &driver->list);
 
702
        kspin_unlock_irql(&loader_lock, irql);
685
703
 
686
704
        TRACEEXIT1(return 0);
687
705
}
689
707
/* load a driver from userspace and initialize it */
690
708
static int load_ndis_driver(struct load_driver *load_driver)
691
709
{
692
 
        struct ndis_driver *ndis_driver;
693
 
 
694
 
        ndis_driver = kmalloc(sizeof(*ndis_driver), GFP_KERNEL);
695
 
        if (!ndis_driver) {
696
 
                ERROR("couldn't allocate memory");
697
 
                TRACEEXIT1(return -EINVAL);
698
 
        }
 
710
        struct driver_object *drv_obj;
 
711
        struct ansi_string ansi_reg;
 
712
        struct ndis_driver *ndis_driver = NULL;
 
713
        int i;
 
714
 
 
715
        TRACEENTER1("");
 
716
        drv_obj = kmalloc(sizeof(*drv_obj), GFP_KERNEL);
 
717
        if (!drv_obj) {
 
718
                ERROR("couldn't allocate memory");
 
719
                TRACEEXIT1(return -ENOMEM);
 
720
        }
 
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");
 
726
                kfree(drv_obj);
 
727
                TRACEEXIT1(return -ENOMEM);
 
728
        }
 
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);
 
732
        DBGTRACE1("");
 
733
        if (IoAllocateDriverObjectExtension(drv_obj,
 
734
                                            (void *)CE_NDIS_DRIVER_CLIENT_ID,
 
735
                                            sizeof(*ndis_driver),
 
736
                                            (void **)&ndis_driver) !=
 
737
            STATUS_SUCCESS)
 
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;
 
743
 
699
744
        memset(ndis_driver, 0, sizeof(*ndis_driver));
700
745
        ndis_driver->bustype = -1;
701
 
 
 
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);
 
755
                kfree(drv_obj);
 
756
                TRACEEXIT1(return -EINVAL);
 
757
        }
 
758
        DBGTRACE1("");
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) ||
726
783
 
727
784
        devices = NULL;
728
785
        ndiswrapper_pci_devices = NULL;
 
786
#if defined(CONFIG_USB)
729
787
        ndiswrapper_usb_devices = NULL;
 
788
#endif
730
789
        ndis_devices = NULL;
731
790
        devices = vmalloc(load_devices->count * sizeof(struct load_device));
732
791
        if (!devices) {
762
821
                       (num_pci + 1) * sizeof(struct pci_device_id));
763
822
        }
764
823
 
 
824
#if defined(CONFIG_USB)
765
825
        if (num_usb > 0) {
766
826
                ndiswrapper_usb_devices =
767
827
                        kmalloc((num_usb + 1) * sizeof(struct usb_device_id),
773
833
                memset(ndiswrapper_usb_devices, 0,
774
834
                       (num_usb + 1) * sizeof(struct usb_device_id));
775
835
        }
 
836
#endif
776
837
 
777
838
        ndis_devices = vmalloc(num_ndis_devices * sizeof(*ndis_devices));
778
839
        if (!ndis_devices) {
788
849
 
789
850
                ndis_device = &ndis_devices[num_pci + num_usb];
790
851
 
791
 
                INIT_LIST_HEAD(&ndis_device->settings);
 
852
                InitializeListHead(&ndis_device->settings);
792
853
                memcpy(&ndis_device->driver_name, device->driver_name,
793
854
                       sizeof(ndis_device->driver_name));
794
855
                memcpy(&ndis_device->conf_file_name, device->conf_file_name,
800
861
                ndis_device->subvendor = device->subvendor;
801
862
                ndis_device->subdevice = device->subdevice;
802
863
 
803
 
                memcpy(&ndis_device->driver_name, device->driver_name,
804
 
                       sizeof(ndis_device->driver_name));
805
 
 
806
864
                if (device->bustype == NDIS_PCI_BUS) {
807
865
                        ndiswrapper_pci_devices[num_pci].vendor =
808
866
                                device->vendor;
845
903
                                  device->vendor, device->device);
846
904
#endif
847
905
                } else {
848
 
                        ERROR("system doesn't support bus type %d",
849
 
                              device->bustype);
 
906
                        ERROR("bus type %d not supported", device->bustype);
850
907
                }
851
908
        }
852
909
 
855
912
                               sizeof(ndiswrapper_pci_driver));
856
913
                ndiswrapper_pci_driver.name = DRIVER_NAME;
857
914
                ndiswrapper_pci_driver.id_table = ndiswrapper_pci_devices;
858
 
                ndiswrapper_pci_driver.probe = ndiswrapper_add_one_pci_dev;
 
915
                ndiswrapper_pci_driver.probe = ndiswrapper_add_pci_device;
859
916
                ndiswrapper_pci_driver.remove =
860
 
                        __devexit_p(ndiswrapper_remove_one_pci_dev);
 
917
                        __devexit_p(ndiswrapper_remove_pci_device);
861
918
                ndiswrapper_pci_driver.suspend = ndiswrapper_suspend_pci;
862
919
                ndiswrapper_pci_driver.resume = ndiswrapper_resume_pci;
863
920
                res = pci_register_driver(&ndiswrapper_pci_driver);
873
930
                ndiswrapper_usb_driver.owner = THIS_MODULE;
874
931
                ndiswrapper_usb_driver.name = DRIVER_NAME;
875
932
                ndiswrapper_usb_driver.id_table = ndiswrapper_usb_devices;
876
 
                ndiswrapper_usb_driver.probe = ndiswrapper_add_one_usb_dev;
 
933
                ndiswrapper_usb_driver.probe = ndiswrapper_add_usb_device;
877
934
                ndiswrapper_usb_driver.disconnect =
878
 
                        ndiswrapper_remove_one_usb_dev;
 
935
                        ndiswrapper_remove_usb_device;
 
936
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 
937
                ndiswrapper_usb_driver.suspend = ndiswrapper_suspend_usb;
 
938
                ndiswrapper_usb_driver.resume = ndiswrapper_resume_usb;
 
939
#endif
879
940
                res = usb_register(&ndiswrapper_usb_driver);
880
941
                if (res < 0) {
881
942
                        ERROR("couldn't register ndiswrapper usb driver");
891
952
        if (ndis_devices)
892
953
                vfree(ndis_devices);
893
954
        ndis_devices = NULL;
 
955
#if defined(CONFIG_USB)
894
956
        if (ndiswrapper_usb_devices)
895
957
                kfree(ndiswrapper_usb_devices);
896
958
        ndiswrapper_usb_devices = NULL;
 
959
#endif
897
960
        if (ndiswrapper_pci_devices)
898
961
                kfree(ndiswrapper_pci_devices);
899
962
        ndiswrapper_pci_devices = NULL;
962
1025
 
963
1026
static struct miscdevice wrapper_misc = {
964
1027
        .name   = DRIVER_NAME,
 
1028
        .minor  = MISC_DYNAMIC_MINOR,
965
1029
        .fops   = &wrapper_fops
966
1030
};
967
1031
 
969
1033
{
970
1034
        int err;
971
1035
 
972
 
        INIT_LIST_HEAD(&ndis_drivers);
 
1036
        InitializeListHead(&ndis_drivers);
973
1037
        kspin_lock_init(&loader_lock);
974
1038
        if ((err = misc_register(&wrapper_misc)) < 0 ) {
975
1039
                ERROR("couldn't register module (%d)", err);
981
1045
void loader_exit(void)
982
1046
{
983
1047
        int i;
 
1048
        struct nt_list *cur;
984
1049
 
985
1050
        TRACEENTER1("");
986
1051
        misc_deregister(&wrapper_misc);
987
1052
 
 
1053
        for (i = 0; i < num_ndis_devices; i++)
 
1054
                if (ndis_devices[i].wd)
 
1055
                        set_bit(HW_RMMOD, &ndis_devices[i].wd->hw_status);
988
1056
#ifdef CONFIG_USB
989
1057
        if (ndiswrapper_usb_devices) {
990
1058
                usb_deregister(&ndiswrapper_usb_driver);
1006
1074
                ndis_devices = NULL;
1007
1075
        }
1008
1076
 
1009
 
        while (!list_empty(&ndis_drivers)) {
 
1077
        while ((cur = RemoveHeadList(&ndis_drivers))) {
1010
1078
                struct ndis_driver *driver;
1011
1079
 
1012
 
                driver = list_entry(ndis_drivers.next,
1013
 
                                    struct ndis_driver, list);
1014
 
                list_del(&driver->list);
 
1080
                driver = container_of(cur, struct ndis_driver, list);
1015
1081
                unload_ndis_driver(driver);
1016
1082
        }
1017
1083
        kspin_unlock(&loader_lock);