2
* Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
21
#include <linux/kernel_stat.h>
23
#include "ndis_exports.h"
25
#define MAX_ALLOCATED_NDIS_PACKETS TX_RING_SIZE
26
#define MAX_ALLOCATED_NDIS_BUFFERS TX_RING_SIZE
28
static void ndis_worker(worker_param_t dummy);
29
static work_struct_t ndis_work;
30
static struct nt_list ndis_work_list;
31
static spinlock_t ndis_work_list_lock;
33
workqueue_struct_t *ndis_wq;
34
static struct nt_thread *ndis_worker_thread;
36
static void *ndis_get_routine_address(char *name);
38
wstdcall void WIN_FUNC(NdisInitializeWrapper,4)
39
(void **driver_handle, struct driver_object *driver,
40
struct unicode_string *reg_path, void *unused)
42
ENTER1("handle: %p, driver: %p", driver_handle, driver);
43
*driver_handle = driver;
47
wstdcall void WIN_FUNC(NdisTerminateWrapper,2)
48
(struct device_object *dev_obj, void *system_specific)
53
wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterMiniport,3)
54
(struct driver_object *drv_obj, struct miniport *mp, UINT length)
57
struct wrap_driver *wrap_driver;
58
struct ndis_driver *ndis_driver;
60
min_length = ((char *)&mp->co_create_vc) - ((char *)mp);
62
ENTER1("%p %p %d", drv_obj, mp, length);
64
if (mp->major_version < 4) {
65
ERROR("Driver is using ndis version %d which is too old.",
67
EXIT1(return NDIS_STATUS_BAD_VERSION);
70
if (length < min_length) {
71
ERROR("Characteristics length %d is too small", length);
72
EXIT1(return NDIS_STATUS_BAD_CHARACTERISTICS);
75
TRACE1("%d.%d, %d, %u", mp->major_version, mp->minor_version, length,
76
(u32)sizeof(struct miniport));
77
wrap_driver = IoGetDriverObjectExtension(drv_obj,
78
(void *)WRAP_DRIVER_CLIENT_ID);
80
ERROR("couldn't get wrap_driver");
81
EXIT1(return NDIS_STATUS_RESOURCES);
83
if (IoAllocateDriverObjectExtension(
84
drv_obj, (void *)NDIS_DRIVER_CLIENT_ID,
85
sizeof(*ndis_driver), (void **)&ndis_driver) !=
87
EXIT1(return NDIS_STATUS_RESOURCES);
88
wrap_driver->ndis_driver = ndis_driver;
89
TRACE1("driver: %p", ndis_driver);
90
memcpy(&ndis_driver->mp, mp, min_t(int, sizeof(*mp), length));
96
"queryinfo", "reconfig", "reset", "send", "setinfo",
97
"tx_data", "return_packet", "send_packets",
98
"alloc_complete", "co_create_vc", "co_delete_vc",
99
"co_activate_vc", "co_deactivate_vc",
100
"co_send_packets", "co_request", "cancel_send_packets",
101
"pnp_event_notify", "shutdown",
103
func = (void **)&ndis_driver->mp.queryinfo;
104
for (i = 0; i < (sizeof(mp_funcs) / sizeof(mp_funcs[0])); i++)
105
TRACE2("function '%s' is at %p", mp_funcs[i], func[i]);
107
EXIT1(return NDIS_STATUS_SUCCESS);
110
wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterDevice,6)
111
(struct driver_object *drv_obj, struct unicode_string *dev_name,
112
struct unicode_string *link, void **funcs,
113
struct device_object **dev_obj, void **dev_obj_handle)
116
struct device_object *tmp;
119
ENTER1("%p, %p, %p", drv_obj, dev_name, link);
120
status = IoCreateDevice(drv_obj, 0, dev_name, FILE_DEVICE_NETWORK, 0,
123
if (status != STATUS_SUCCESS)
124
EXIT1(return NDIS_STATUS_RESOURCES);
126
status = IoCreateSymbolicLink(link, dev_name);
127
if (status != STATUS_SUCCESS) {
129
EXIT1(return NDIS_STATUS_RESOURCES);
133
*dev_obj_handle = *dev_obj;
134
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
135
if (funcs[i] && i != IRP_MJ_PNP && i != IRP_MJ_POWER) {
136
drv_obj->major_func[i] = funcs[i];
137
TRACE1("mj_fn for 0x%x is at %p", i, funcs[i]);
139
EXIT1(return NDIS_STATUS_SUCCESS);
142
wstdcall NDIS_STATUS WIN_FUNC(NdisMDeregisterDevice,1)
143
(struct device_object *dev_obj)
145
ENTER2("%p", dev_obj);
146
IoDeleteDevice(dev_obj);
147
return NDIS_STATUS_SUCCESS;
150
wstdcall NDIS_STATUS WIN_FUNC(NdisAllocateMemoryWithTag,3)
151
(void **dest, UINT length, ULONG tag)
155
assert_irql(_irql_ <= DISPATCH_LEVEL);
156
addr = ExAllocatePoolWithTag(NonPagedPool, length, tag);
160
EXIT4(return NDIS_STATUS_SUCCESS);
162
EXIT4(return NDIS_STATUS_FAILURE);
165
wstdcall NDIS_STATUS WIN_FUNC(NdisAllocateMemory,4)
166
(void **dest, UINT length, UINT flags, NDIS_PHY_ADDRESS highest_address)
168
return NdisAllocateMemoryWithTag(dest, length, 0);
171
/* length_tag is either length or tag, depending on if
172
* NdisAllocateMemory or NdisAllocateMemoryTag is used to allocate
174
wstdcall void WIN_FUNC(NdisFreeMemory,3)
175
(void *addr, UINT length_tag, UINT flags)
181
noregparm void WIN_FUNC(NdisWriteErrorLogEntry,12)
182
(struct driver_object *drv_obj, ULONG error, ULONG count, ...)
188
va_start(args, count);
189
ERROR("log: %08X, count: %d, return_address: %p",
190
error, count, __builtin_return_address(0));
191
for (i = 0; i < count; i++) {
192
code = va_arg(args, ULONG);
193
ERROR("code: 0x%x", code);
199
wstdcall void WIN_FUNC(NdisOpenConfiguration,3)
200
(NDIS_STATUS *status, struct ndis_mp_block **conf_handle,
201
struct ndis_mp_block *handle)
203
ENTER2("%p", conf_handle);
204
*conf_handle = handle;
205
*status = NDIS_STATUS_SUCCESS;
209
wstdcall void WIN_FUNC(NdisOpenProtocolConfiguration,3)
210
(NDIS_STATUS *status, void **confhandle,
211
struct unicode_string *section)
213
ENTER2("%p", confhandle);
214
*status = NDIS_STATUS_SUCCESS;
218
wstdcall void WIN_FUNC(NdisOpenConfigurationKeyByName,4)
219
(NDIS_STATUS *status, void *handle,
220
struct unicode_string *key, void **subkeyhandle)
222
struct ansi_string ansi;
224
if (RtlUnicodeStringToAnsiString(&ansi, key, TRUE) == STATUS_SUCCESS) {
225
TRACE2("%s", ansi.buf);
226
RtlFreeAnsiString(&ansi);
228
*subkeyhandle = handle;
229
*status = NDIS_STATUS_SUCCESS;
233
wstdcall void WIN_FUNC(NdisOpenConfigurationKeyByIndex,5)
234
(NDIS_STATUS *status, void *handle, ULONG index,
235
struct unicode_string *key, void **subkeyhandle)
238
// *subkeyhandle = handle;
239
*status = NDIS_STATUS_FAILURE;
243
wstdcall void WIN_FUNC(NdisCloseConfiguration,1)
246
/* instead of freeing all configuration parameters as we are
247
* supposed to do here, we free them when the device is
249
ENTER2("%p", handle);
253
wstdcall void WIN_FUNC(NdisOpenFile,5)
254
(NDIS_STATUS *status, struct wrap_bin_file **file,
255
UINT *filelength, struct unicode_string *filename,
256
NDIS_PHY_ADDRESS highest_address)
258
struct ansi_string ansi;
259
struct wrap_bin_file *bin_file;
261
ENTER2("%p, %d, %llx, %p", status, *filelength, highest_address, *file);
262
if (RtlUnicodeStringToAnsiString(&ansi, filename, TRUE) !=
264
*status = NDIS_STATUS_RESOURCES;
267
TRACE2("%s", ansi.buf);
268
bin_file = get_bin_file(ansi.buf);
271
*filelength = bin_file->size;
272
*status = NDIS_STATUS_SUCCESS;
274
*status = NDIS_STATUS_FILE_NOT_FOUND;
276
RtlFreeAnsiString(&ansi);
280
wstdcall void WIN_FUNC(NdisMapFile,3)
281
(NDIS_STATUS *status, void **mappedbuffer, struct wrap_bin_file *file)
286
*status = NDIS_STATUS_ALREADY_MAPPED;
290
*status = NDIS_STATUS_SUCCESS;
291
*mappedbuffer = file->data;
295
wstdcall void WIN_FUNC(NdisUnmapFile,1)
296
(struct wrap_bin_file *file)
302
wstdcall void WIN_FUNC(NdisCloseFile,1)
303
(struct wrap_bin_file *file)
310
wstdcall void WIN_FUNC(NdisGetSystemUpTime,1)
313
*ms = 1000 * jiffies / HZ;
317
wstdcall ULONG WIN_FUNC(NDIS_BUFFER_TO_SPAN_PAGES,1)
318
(ndis_buffer *buffer)
324
if (MmGetMdlByteCount(buffer) == 0)
327
length = MmGetMdlByteCount(buffer);
328
n = SPAN_PAGES(MmGetMdlVirtualAddress(buffer), length);
329
TRACE4("%p, %p, %d, %d", buffer->startva, buffer->mappedsystemva,
334
wstdcall void WIN_FUNC(NdisGetBufferPhysicalArraySize,2)
335
(ndis_buffer *buffer, UINT *arraysize)
337
ENTER3("%p", buffer);
338
*arraysize = NDIS_BUFFER_TO_SPAN_PAGES(buffer);
342
static struct ndis_configuration_parameter *
343
ndis_encode_setting(struct wrap_device_setting *setting,
344
enum ndis_parameter_type type)
346
struct ansi_string ansi;
347
struct ndis_configuration_parameter *param;
349
param = setting->encoded;
351
if (param->type == type)
353
if (param->type == NdisParameterString)
354
RtlFreeUnicodeString(¶m->data.string);
355
setting->encoded = NULL;
357
param = ExAllocatePoolWithTag(NonPagedPool, sizeof(*param), 0);
359
ERROR("couldn't allocate memory");
363
case NdisParameterInteger:
364
param->data.integer = simple_strtol(setting->value, NULL, 0);
365
TRACE2("0x%x", (ULONG)param->data.integer);
367
case NdisParameterHexInteger:
368
param->data.integer = simple_strtol(setting->value, NULL, 16);
369
TRACE2("0x%x", (ULONG)param->data.integer);
371
case NdisParameterString:
372
RtlInitAnsiString(&ansi, setting->value);
373
TRACE2("'%s'", ansi.buf);
374
if (RtlAnsiStringToUnicodeString(¶m->data.string,
380
case NdisParameterBinary:
381
param->data.integer = simple_strtol(setting->value, NULL, 2);
382
TRACE2("0x%x", (ULONG)param->data.integer);
385
ERROR("unknown type: %d", type);
390
setting->encoded = param;
394
static int ndis_decode_setting(struct wrap_device_setting *setting,
395
struct ndis_configuration_parameter *param)
397
struct ansi_string ansi;
398
struct ndis_configuration_parameter *prev;
400
ENTER2("%p, %p", setting, param);
401
prev = setting->encoded;
402
if (prev && prev->type == NdisParameterString) {
403
RtlFreeUnicodeString(&prev->data.string);
404
setting->encoded = NULL;
406
switch(param->type) {
407
case NdisParameterInteger:
408
snprintf(setting->value, sizeof(u32), "%u",
409
param->data.integer);
410
setting->value[sizeof(ULONG)] = 0;
412
case NdisParameterHexInteger:
413
snprintf(setting->value, sizeof(u32), "%x",
414
param->data.integer);
415
setting->value[sizeof(ULONG)] = 0;
417
case NdisParameterString:
418
ansi.buf = setting->value;
419
ansi.max_length = MAX_SETTING_VALUE_LEN;
420
if ((RtlUnicodeStringToAnsiString(&ansi, ¶m->data.string,
421
FALSE) != STATUS_SUCCESS)
422
|| ansi.length >= MAX_SETTING_VALUE_LEN) {
425
if (ansi.length == ansi.max_length)
427
setting->value[ansi.length] = 0;
429
case NdisParameterBinary:
430
snprintf(setting->value, sizeof(u32), "%u",
431
param->data.integer);
432
setting->value[sizeof(ULONG)] = 0;
435
TRACE2("unknown setting type: %d", param->type);
438
TRACE2("setting changed %s='%s', %d", setting->name, setting->value,
443
static int read_setting(struct nt_list *setting_list, char *keyname, int length,
444
struct ndis_configuration_parameter **param,
445
enum ndis_parameter_type type)
447
struct wrap_device_setting *setting;
448
if (down_interruptible(&loader_mutex))
449
WARNING("couldn't obtain loader_mutex");
450
nt_list_for_each_entry(setting, setting_list, list) {
451
if (strnicmp(keyname, setting->name, length) == 0) {
452
TRACE2("setting %s='%s'", keyname, setting->value);
454
*param = ndis_encode_setting(setting, type);
465
wstdcall void WIN_FUNC(NdisReadConfiguration,5)
466
(NDIS_STATUS *status, struct ndis_configuration_parameter **param,
467
struct ndis_mp_block *nmb, struct unicode_string *key,
468
enum ndis_parameter_type type)
470
struct ansi_string ansi;
473
ENTER2("nmb: %p", nmb);
474
ret = RtlUnicodeStringToAnsiString(&ansi, key, TRUE);
475
if (ret != STATUS_SUCCESS || ansi.buf == NULL) {
477
*status = NDIS_STATUS_FAILURE;
478
RtlFreeAnsiString(&ansi);
481
TRACE2("%d, %s", type, ansi.buf);
483
if (read_setting(&nmb->wnd->wd->settings, ansi.buf,
484
ansi.length, param, type) == 0 ||
485
read_setting(&nmb->wnd->wd->driver->settings, ansi.buf,
486
ansi.length, param, type) == 0)
487
*status = NDIS_STATUS_SUCCESS;
489
TRACE2("setting %s not found (type:%d)", ansi.buf, type);
490
*status = NDIS_STATUS_FAILURE;
492
RtlFreeAnsiString(&ansi);
497
wstdcall void WIN_FUNC(NdisWriteConfiguration,4)
498
(NDIS_STATUS *status, struct ndis_mp_block *nmb,
499
struct unicode_string *key, struct ndis_configuration_parameter *param)
501
struct ansi_string ansi;
503
struct wrap_device_setting *setting;
505
ENTER2("nmb: %p", nmb);
506
if (RtlUnicodeStringToAnsiString(&ansi, key, TRUE)) {
507
*status = NDIS_STATUS_FAILURE;
511
TRACE2("%s", keyname);
513
if (down_interruptible(&loader_mutex))
514
WARNING("couldn't obtain loader_mutex");
515
nt_list_for_each_entry(setting, &nmb->wnd->wd->settings, list) {
516
if (strnicmp(keyname, setting->name, ansi.length) == 0) {
518
if (ndis_decode_setting(setting, param))
519
*status = NDIS_STATUS_FAILURE;
521
*status = NDIS_STATUS_SUCCESS;
522
RtlFreeAnsiString(&ansi);
527
setting = kzalloc(sizeof(*setting), GFP_KERNEL);
529
if (ansi.length == ansi.max_length)
531
memcpy(setting->name, keyname, ansi.length);
532
setting->name[ansi.length] = 0;
533
if (ndis_decode_setting(setting, param))
534
*status = NDIS_STATUS_FAILURE;
536
*status = NDIS_STATUS_SUCCESS;
537
if (down_interruptible(&loader_mutex))
538
WARNING("couldn't obtain loader_mutex");
539
InsertTailList(&nmb->wnd->wd->settings, &setting->list);
543
*status = NDIS_STATUS_RESOURCES;
545
RtlFreeAnsiString(&ansi);
549
wstdcall void WIN_FUNC(NdisReadNetworkAddress,4)
550
(NDIS_STATUS *status, void **addr, UINT *len,
551
struct ndis_mp_block *nmb)
553
struct ndis_device *wnd = nmb->wnd;
554
struct ndis_configuration_parameter *param;
555
struct unicode_string key;
556
struct ansi_string ansi;
557
typeof(wnd->mac) mac;
561
RtlInitAnsiString(&ansi, "NetworkAddress");
562
*status = NDIS_STATUS_FAILURE;
563
if (RtlAnsiStringToUnicodeString(&key, &ansi, TRUE) != STATUS_SUCCESS)
566
NdisReadConfiguration(&ret, ¶m, nmb, &key, NdisParameterString);
567
RtlFreeUnicodeString(&key);
568
if (ret != NDIS_STATUS_SUCCESS)
570
ret = RtlUnicodeStringToAnsiString(&ansi, ¶m->data.string, TRUE);
571
if (ret != STATUS_SUCCESS)
575
if (ansi.length >= 2 * sizeof(mac)) {
576
for (i = 0; i < sizeof(mac); i++) {
579
c[0] = ansi.buf[i*2];
580
c[1] = ansi.buf[i*2+1];
582
ret = sscanf(c, "%x", &x);
588
TRACE2("%s, %d, " MACSTR, ansi.buf, i, MAC2STR(mac));
589
RtlFreeAnsiString(&ansi);
590
if (i == sizeof(mac)) {
591
memcpy(wnd->mac, mac, sizeof(wnd->mac));
594
*status = NDIS_STATUS_SUCCESS;
599
wstdcall void WIN_FUNC(NdisInitializeString,2)
600
(struct unicode_string *dest, UCHAR *src)
602
struct ansi_string ansi;
606
dest->length = dest->max_length = 0;
609
RtlInitAnsiString(&ansi, src);
610
/* the string is freed with NdisFreeMemory */
611
RtlAnsiStringToUnicodeString(dest, &ansi, TRUE);
616
wstdcall void WIN_FUNC(NdisInitAnsiString,2)
617
(struct ansi_string *dst, CHAR *src)
619
RtlInitAnsiString(dst, src);
623
wstdcall void WIN_FUNC(NdisInitUnicodeString,2)
624
(struct unicode_string *dest, const wchar_t *src)
626
RtlInitUnicodeString(dest, src);
630
wstdcall NDIS_STATUS WIN_FUNC(NdisAnsiStringToUnicodeString,2)
631
(struct unicode_string *dst, struct ansi_string *src)
634
if (dst == NULL || src == NULL)
635
EXIT2(return NDIS_STATUS_FAILURE);
636
if (RtlAnsiStringToUnicodeString(dst, src, FALSE) == STATUS_SUCCESS)
637
return NDIS_STATUS_SUCCESS;
639
return NDIS_STATUS_FAILURE;
642
wstdcall NDIS_STATUS WIN_FUNC(NdisUnicodeStringToAnsiString,2)
643
(struct ansi_string *dst, struct unicode_string *src)
646
if (dst == NULL || src == NULL)
647
EXIT2(return NDIS_STATUS_FAILURE);
648
if (RtlUnicodeStringToAnsiString(dst, src, FALSE) == STATUS_SUCCESS)
649
return NDIS_STATUS_SUCCESS;
651
return NDIS_STATUS_FAILURE;
654
wstdcall NTSTATUS WIN_FUNC(NdisUpcaseUnicodeString,2)
655
(struct unicode_string *dst, struct unicode_string *src)
657
EXIT2(return RtlUpcaseUnicodeString(dst, src, FALSE));
660
wstdcall void WIN_FUNC(NdisMSetAttributesEx,5)
661
(struct ndis_mp_block *nmb, void *mp_ctx,
662
UINT hangcheck_interval, UINT attributes, ULONG adaptertype)
664
struct ndis_device *wnd;
666
ENTER1("%p, %p, %d, %08x, %d", nmb, mp_ctx, hangcheck_interval,
667
attributes, adaptertype);
669
nmb->mp_ctx = mp_ctx;
670
wnd->attributes = attributes;
672
if ((attributes & NDIS_ATTRIBUTE_BUS_MASTER) &&
673
wrap_is_pci_bus(wnd->wd->dev_bus))
674
pci_set_master(wnd->wd->pci.pdev);
676
if (hangcheck_interval > 0)
677
wnd->hangcheck_interval = 2 * hangcheck_interval * HZ;
679
wnd->hangcheck_interval = 2 * HZ;
684
wstdcall ULONG WIN_FUNC(NdisReadPciSlotInformation,5)
685
(struct ndis_mp_block *nmb, ULONG slot,
686
ULONG offset, char *buf, ULONG len)
688
struct wrap_device *wd = nmb->wnd->wd;
690
for (i = 0; i < len; i++)
691
if (pci_read_config_byte(wd->pci.pdev, offset + i, &buf[i]) !=
696
WARNING("%u, %u", i, len);
701
wstdcall ULONG WIN_FUNC(NdisImmediateReadPciSlotInformation,5)
702
(struct ndis_mp_block *nmb, ULONG slot,
703
ULONG offset, char *buf, ULONG len)
705
return NdisReadPciSlotInformation(nmb, slot, offset, buf, len);
708
wstdcall ULONG WIN_FUNC(NdisWritePciSlotInformation,5)
709
(struct ndis_mp_block *nmb, ULONG slot,
710
ULONG offset, char *buf, ULONG len)
712
struct wrap_device *wd = nmb->wnd->wd;
714
for (i = 0; i < len; i++)
715
if (pci_write_config_byte(wd->pci.pdev, offset + i, buf[i]) !=
720
WARNING("%u, %u", i, len);
725
wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterIoPortRange,4)
726
(void **virt, struct ndis_mp_block *nmb, UINT start, UINT len)
728
ENTER3("%08x %08x", start, len);
729
*virt = (void *)(ULONG_PTR)start;
730
return NDIS_STATUS_SUCCESS;
733
wstdcall void WIN_FUNC(NdisMDeregisterIoPortRange,4)
734
(struct ndis_mp_block *nmb, UINT start, UINT len, void* virt)
736
ENTER1("%08x %08x", start, len);
739
wstdcall void WIN_FUNC(NdisReadPortUchar,3)
740
(struct ndis_mp_block *nmb, ULONG port, char *data)
745
wstdcall void WIN_FUNC(NdisImmediateReadPortUchar,3)
746
(struct ndis_mp_block *nmb, ULONG port, char *data)
751
wstdcall void WIN_FUNC(NdisWritePortUchar,3)
752
(struct ndis_mp_block *nmb, ULONG port, char data)
757
wstdcall void WIN_FUNC(NdisImmediateWritePortUchar,3)
758
(struct ndis_mp_block *nmb, ULONG port, char data)
763
wstdcall void WIN_FUNC(NdisMQueryAdapterResources,4)
764
(NDIS_STATUS *status, struct ndis_mp_block *nmb,
765
NDIS_RESOURCE_LIST *resource_list, UINT *size)
767
struct ndis_device *wnd = nmb->wnd;
768
NDIS_RESOURCE_LIST *list;
769
UINT resource_length;
771
list = &wnd->wd->resource_list->list->partial_resource_list;
772
resource_length = sizeof(struct cm_partial_resource_list) +
773
sizeof(struct cm_partial_resource_descriptor) *
775
TRACE2("%p, %p,%d (%d), %p %d %d", wnd, resource_list, *size,
776
resource_length, &list->partial_descriptors[list->count-1],
777
list->partial_descriptors[list->count-1].u.interrupt.level,
778
list->partial_descriptors[list->count-1].u.interrupt.vector);
779
if (*size < sizeof(*list)) {
780
*size = resource_length;
781
*status = NDIS_STATUS_BUFFER_TOO_SHORT;
784
if (*size >= resource_length) {
785
*size = resource_length;
788
UINT n = sizeof(*list);
790
while (count++ < list->count && n < *size)
791
n += sizeof(list->partial_descriptors);
794
memcpy(resource_list, list, *size);
795
resource_list->count = count;
796
*status = NDIS_STATUS_SUCCESS;
801
wstdcall NDIS_STATUS WIN_FUNC(NdisMPciAssignResources,3)
802
(struct ndis_mp_block *nmb, ULONG slot_number,
803
NDIS_RESOURCE_LIST **resources)
805
struct ndis_device *wnd = nmb->wnd;
807
ENTER2("%p, %p", wnd, wnd->wd->resource_list);
808
*resources = &wnd->wd->resource_list->list->partial_resource_list;
809
EXIT2(return NDIS_STATUS_SUCCESS);
812
wstdcall NDIS_STATUS WIN_FUNC(NdisMMapIoSpace,4)
813
(void __iomem **virt, struct ndis_mp_block *nmb,
814
NDIS_PHY_ADDRESS phy_addr, UINT len)
816
struct ndis_device *wnd = nmb->wnd;
818
ENTER2("%Lx, %d", phy_addr, len);
819
*virt = MmMapIoSpace(phy_addr, len, MmCached);
821
ERROR("ioremap failed");
822
EXIT2(return NDIS_STATUS_FAILURE);
824
wnd->mem_start = phy_addr;
825
wnd->mem_end = phy_addr + len;
827
EXIT2(return NDIS_STATUS_SUCCESS);
830
wstdcall void WIN_FUNC(NdisMUnmapIoSpace,3)
831
(struct ndis_mp_block *nmb, void __iomem *virt, UINT len)
833
ENTER2("%p, %d", virt, len);
834
MmUnmapIoSpace(virt, len);
838
wstdcall void WIN_FUNC(NdisAllocateSpinLock,1)
839
(struct ndis_spinlock *lock)
841
TRACE4("lock %p, %p", lock, &lock->klock);
842
KeInitializeSpinLock(&lock->klock);
843
lock->irql = PASSIVE_LEVEL;
847
wstdcall void WIN_FUNC(NdisFreeSpinLock,1)
848
(struct ndis_spinlock *lock)
850
TRACE4("lock %p, %p", lock, &lock->klock);
854
wstdcall void WIN_FUNC(NdisAcquireSpinLock,1)
855
(struct ndis_spinlock *lock)
857
ENTER6("lock %p, %p", lock, &lock->klock);
858
// assert_irql(_irql_ <= DISPATCH_LEVEL);
859
lock->irql = nt_spin_lock_irql(&lock->klock, DISPATCH_LEVEL);
863
wstdcall void WIN_FUNC(NdisReleaseSpinLock,1)
864
(struct ndis_spinlock *lock)
866
ENTER6("lock %p, %p", lock, &lock->klock);
867
// assert_irql(_irql_ == DISPATCH_LEVEL);
868
nt_spin_unlock_irql(&lock->klock, lock->irql);
872
wstdcall void WIN_FUNC(NdisDprAcquireSpinLock,1)
873
(struct ndis_spinlock *lock)
875
ENTER6("lock %p", &lock->klock);
876
// assert_irql(_irql_ == DISPATCH_LEVEL);
877
nt_spin_lock(&lock->klock);
881
wstdcall void WIN_FUNC(NdisDprReleaseSpinLock,1)
882
(struct ndis_spinlock *lock)
884
ENTER6("lock %p", &lock->klock);
885
// assert_irql(_irql_ == DISPATCH_LEVEL);
886
nt_spin_unlock(&lock->klock);
890
wstdcall void WIN_FUNC(NdisInitializeReadWriteLock,1)
891
(struct ndis_rw_lock *rw_lock)
893
ENTER3("%p", rw_lock);
894
memset(rw_lock, 0, sizeof(*rw_lock));
895
KeInitializeSpinLock(&rw_lock->klock);
899
/* read/write locks are implemented in a rather simplisitic way - we
900
* should probably use Linux's rw_lock implementation */
902
wstdcall void WIN_FUNC(NdisAcquireReadWriteLock,3)
903
(struct ndis_rw_lock *rw_lock, BOOLEAN write,
904
struct lock_state *lock_state)
908
if (cmpxchg(&rw_lock->count, 0, -1) == 0)
910
while (rw_lock->count)
916
typeof(rw_lock->count) count;
917
while ((count = rw_lock->count) < 0)
919
if (cmpxchg(&rw_lock->count, count, count + 1) == count)
924
wstdcall void WIN_FUNC(NdisReleaseReadWriteLock,2)
925
(struct ndis_rw_lock *rw_lock, struct lock_state *lock_state)
927
if (rw_lock->count > 0)
928
pre_atomic_add(rw_lock->count, -1);
929
else if (rw_lock->count == -1)
932
WARNING("invalid state: %d", rw_lock->count);
935
wstdcall NDIS_STATUS WIN_FUNC(NdisMAllocateMapRegisters,5)
936
(struct ndis_mp_block *nmb, UINT dmachan,
937
NDIS_DMA_SIZE dmasize, ULONG basemap, ULONG max_buf_size)
939
struct ndis_device *wnd = nmb->wnd;
941
ENTER2("%p, %d %d %d %d", wnd, dmachan, dmasize, basemap, max_buf_size);
942
if (wnd->dma_map_count > 0) {
943
WARNING("%s: map registers already allocated: %u",
944
wnd->net_dev->name, wnd->dma_map_count);
945
EXIT2(return NDIS_STATUS_RESOURCES);
947
if (dmasize == NDIS_DMA_24BITS) {
948
if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(24)) ||
949
pci_set_consistent_dma_mask(wnd->wd->pci.pdev,
951
WARNING("setting dma mask failed");
952
} else if (dmasize == NDIS_DMA_32BITS) {
953
/* consistent dma is in low 32-bits by default */
954
if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(32)))
955
WARNING("setting dma mask failed");
957
} else if (dmasize == NDIS_DMA_64BITS) {
958
if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(64)) ||
959
pci_set_consistent_dma_mask(wnd->wd->pci.pdev,
961
WARNING("setting dma mask failed");
963
wnd->net_dev->features |= NETIF_F_HIGHDMA;
966
/* since memory for buffer is allocated with kmalloc, buffer
967
* is physically contiguous, so entire map will fit in one
970
WARNING("Windows driver %s requesting too many (%u) "
971
"map registers", wnd->wd->driver->name, basemap);
972
/* As per NDIS, NDIS_STATUS_RESOURCES should be
973
* returned, but with that Atheros PCI driver fails -
974
* for now tolerate it */
975
// EXIT2(return NDIS_STATUS_RESOURCES);
978
wnd->dma_map_addr = kmalloc(basemap * sizeof(*(wnd->dma_map_addr)),
980
if (!wnd->dma_map_addr)
981
EXIT2(return NDIS_STATUS_RESOURCES);
982
memset(wnd->dma_map_addr, 0, basemap * sizeof(*(wnd->dma_map_addr)));
983
wnd->dma_map_count = basemap;
984
TRACE2("%u", wnd->dma_map_count);
985
EXIT2(return NDIS_STATUS_SUCCESS);
988
wstdcall void WIN_FUNC(NdisMFreeMapRegisters,1)
989
(struct ndis_mp_block *nmb)
991
struct ndis_device *wnd = nmb->wnd;
994
ENTER2("wnd: %p", wnd);
995
if (wnd->dma_map_addr) {
996
for (i = 0; i < wnd->dma_map_count; i++) {
997
if (wnd->dma_map_addr[i])
998
WARNING("%s: dma addr %p not freed by "
999
"Windows driver", wnd->net_dev->name,
1000
(void *)wnd->dma_map_addr[i]);
1002
kfree(wnd->dma_map_addr);
1003
wnd->dma_map_addr = NULL;
1005
WARNING("map registers already freed?");
1006
wnd->dma_map_count = 0;
1010
wstdcall void WIN_FUNC(NdisMStartBufferPhysicalMapping,6)
1011
(struct ndis_mp_block *nmb, ndis_buffer *buf,
1012
ULONG index, BOOLEAN write_to_dev,
1013
struct ndis_phy_addr_unit *phy_addr_array, UINT *array_size)
1015
struct ndis_device *wnd = nmb->wnd;
1017
ENTER3("%p, %p, %u, %u", wnd, buf, index, wnd->dma_map_count);
1018
if (unlikely(wnd->sg_dma_size || !write_to_dev ||
1019
index >= wnd->dma_map_count)) {
1020
WARNING("invalid request: %d, %d, %d, %d", wnd->sg_dma_size,
1021
write_to_dev, index, wnd->dma_map_count);
1022
phy_addr_array[0].phy_addr = 0;
1023
phy_addr_array[0].length = 0;
1027
if (wnd->dma_map_addr[index]) {
1028
TRACE2("buffer %p at %d is already mapped: %lx", buf, index,
1029
(unsigned long)wnd->dma_map_addr[index]);
1033
TRACE3("%p, %p, %u", buf, MmGetSystemAddressForMdl(buf),
1034
MmGetMdlByteCount(buf));
1036
dump_bytes(__func__, MmGetSystemAddressForMdl(buf),
1037
MmGetMdlByteCount(buf));
1039
wnd->dma_map_addr[index] =
1040
PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev,
1041
MmGetSystemAddressForMdl(buf),
1042
MmGetMdlByteCount(buf), PCI_DMA_TODEVICE);
1043
phy_addr_array[0].phy_addr = wnd->dma_map_addr[index];
1044
phy_addr_array[0].length = MmGetMdlByteCount(buf);
1045
TRACE4("%Lx, %d, %d", phy_addr_array[0].phy_addr,
1046
phy_addr_array[0].length, index);
1050
wstdcall void WIN_FUNC(NdisMCompleteBufferPhysicalMapping,3)
1051
(struct ndis_mp_block *nmb, ndis_buffer *buf, ULONG index)
1053
struct ndis_device *wnd = nmb->wnd;
1055
ENTER3("%p, %p %u (%u)", wnd, buf, index, wnd->dma_map_count);
1057
if (unlikely(wnd->sg_dma_size))
1058
WARNING("buffer %p may have been unmapped already", buf);
1059
if (index >= wnd->dma_map_count) {
1060
ERROR("invalid map register (%u >= %u)",
1061
index, wnd->dma_map_count);
1064
TRACE4("%lx", (unsigned long)wnd->dma_map_addr[index]);
1065
if (wnd->dma_map_addr[index]) {
1066
PCI_DMA_UNMAP_SINGLE(wnd->wd->pci.pdev, wnd->dma_map_addr[index],
1067
MmGetMdlByteCount(buf), PCI_DMA_TODEVICE);
1068
wnd->dma_map_addr[index] = 0;
1070
WARNING("map registers at %u not used", index);
1073
wstdcall void WIN_FUNC(NdisMAllocateSharedMemory,5)
1074
(struct ndis_mp_block *nmb, ULONG size,
1075
BOOLEAN cached, void **virt, NDIS_PHY_ADDRESS *phys)
1077
dma_addr_t dma_addr;
1078
struct wrap_device *wd = nmb->wnd->wd;
1080
ENTER3("size: %u, cached: %d", size, cached);
1081
*virt = PCI_DMA_ALLOC_COHERENT(wd->pci.pdev, size, &dma_addr);
1085
WARNING("couldn't allocate %d bytes of %scached DMA memory",
1086
size, cached ? "" : "un-");
1090
wstdcall void WIN_FUNC(NdisMFreeSharedMemory,5)
1091
(struct ndis_mp_block *nmb, ULONG size, BOOLEAN cached,
1092
void *virt, NDIS_PHY_ADDRESS addr)
1094
struct wrap_device *wd = nmb->wnd->wd;
1095
ENTER3("%p, %Lx, %u", virt, addr, size);
1096
PCI_DMA_FREE_COHERENT(wd->pci.pdev, size, virt, addr);
1100
wstdcall void alloc_shared_memory_async(void *arg1, void *arg2)
1102
struct ndis_device *wnd;
1103
struct alloc_shared_mem *alloc_shared_mem;
1104
struct miniport *mp;
1106
NDIS_PHY_ADDRESS phys;
1110
alloc_shared_mem = arg2;
1111
mp = &wnd->wd->driver->ndis_driver->mp;
1112
NdisMAllocateSharedMemory(wnd->nmb, alloc_shared_mem->size,
1113
alloc_shared_mem->cached, &virt, &phys);
1114
irql = serialize_lock_irql(wnd);
1115
assert_irql(_irql_ == DISPATCH_LEVEL);
1116
LIN2WIN5(mp->alloc_complete, wnd->nmb, virt,
1117
&phys, alloc_shared_mem->size, alloc_shared_mem->ctx);
1118
serialize_unlock_irql(wnd, irql);
1119
kfree(alloc_shared_mem);
1121
WIN_FUNC_DECL(alloc_shared_memory_async,2)
1123
wstdcall NDIS_STATUS WIN_FUNC(NdisMAllocateSharedMemoryAsync,4)
1124
(struct ndis_mp_block *nmb, ULONG size, BOOLEAN cached, void *ctx)
1126
struct ndis_device *wnd = nmb->wnd;
1127
struct alloc_shared_mem *alloc_shared_mem;
1129
ENTER3("wnd: %p", wnd);
1130
alloc_shared_mem = kmalloc(sizeof(*alloc_shared_mem), irql_gfp());
1131
if (!alloc_shared_mem) {
1132
WARNING("couldn't allocate memory");
1133
return NDIS_STATUS_FAILURE;
1136
alloc_shared_mem->size = size;
1137
alloc_shared_mem->cached = cached;
1138
alloc_shared_mem->ctx = ctx;
1139
if (schedule_ntos_work_item(WIN_FUNC_PTR(alloc_shared_memory_async,2),
1140
wnd, alloc_shared_mem))
1141
EXIT3(return NDIS_STATUS_FAILURE);
1142
EXIT3(return NDIS_STATUS_PENDING);
1145
/* Some drivers allocate NDIS_BUFFER (aka MDL) very often; instead of
1146
* allocating and freeing with kernel functions, we chain them into
1147
* ndis_buffer_pool. When an MDL is freed, it is added to the list of
1148
* free MDLs. When allocated, we first check if there is one in free
1149
* list and if so just return it; otherwise, we allocate a new one and
1150
* return that. This reduces memory fragmentation. Windows DDK says
1151
* that the driver itself shouldn't check what is returned in
1152
* pool_handle, presumably because buffer pools are not used in
1153
* XP. However, as long as driver follows rest of the semantics - that
1154
* it should indicate maximum number of MDLs used with num_descr and
1155
* pass the same pool_handle in other buffer functions, this should
1156
* work. Sadly, though, NdisFreeBuffer doesn't pass the pool_handle,
1157
* so we use 'process' field of MDL to store pool_handle. */
1159
wstdcall void WIN_FUNC(NdisAllocateBufferPool,3)
1160
(NDIS_STATUS *status, struct ndis_buffer_pool **pool_handle,
1163
struct ndis_buffer_pool *pool;
1165
ENTER1("buffers: %d", num_descr);
1166
pool = kmalloc(sizeof(*pool), irql_gfp());
1168
*status = NDIS_STATUS_RESOURCES;
1171
spin_lock_init(&pool->lock);
1172
pool->max_descr = num_descr;
1173
pool->num_allocated_descr = 0;
1174
pool->free_descr = NULL;
1175
*pool_handle = pool;
1176
*status = NDIS_STATUS_SUCCESS;
1177
TRACE1("pool: %p, num_descr: %d", pool, num_descr);
1181
wstdcall void WIN_FUNC(NdisAllocateBuffer,5)
1182
(NDIS_STATUS *status, ndis_buffer **buffer,
1183
struct ndis_buffer_pool *pool, void *virt, UINT length)
1187
ENTER4("pool: %p (%d)", pool, pool->num_allocated_descr);
1188
/* NDIS drivers should call this at DISPATCH_LEVEL, but
1189
* alloc_tx_packet calls at SOFT_IRQL */
1190
assert_irql(_irql_ <= SOFT_LEVEL);
1192
*status = NDIS_STATUS_FAILURE;
1196
spin_lock_bh(&pool->lock);
1197
if ((descr = pool->free_descr))
1198
pool->free_descr = descr->next;
1199
spin_unlock_bh(&pool->lock);
1201
typeof(descr->flags) flags;
1202
flags = descr->flags;
1203
memset(descr, 0, sizeof(*descr));
1204
MmInitializeMdl(descr, virt, length);
1205
if (flags & MDL_CACHE_ALLOCATED)
1206
descr->flags |= MDL_CACHE_ALLOCATED;
1208
if (pool->num_allocated_descr > pool->max_descr) {
1209
TRACE2("pool %p is full: %d(%d)", pool,
1210
pool->num_allocated_descr, pool->max_descr);
1211
#ifndef ALLOW_POOL_OVERFLOW
1212
*status = NDIS_STATUS_FAILURE;
1217
descr = allocate_init_mdl(virt, length);
1219
WARNING("couldn't allocate buffer");
1220
*status = NDIS_STATUS_FAILURE;
1224
TRACE4("buffer %p for %p, %d", descr, virt, length);
1225
atomic_inc_var(pool->num_allocated_descr);
1227
/* TODO: make sure this mdl can map given buffer */
1228
MmBuildMdlForNonPagedPool(descr);
1229
// descr->flags |= MDL_ALLOCATED_FIXED_SIZE |
1230
// MDL_MAPPED_TO_SYSTEM_VA | MDL_PAGES_LOCKED;
1233
*status = NDIS_STATUS_SUCCESS;
1234
TRACE4("buffer: %p", descr);
1238
wstdcall void WIN_FUNC(NdisFreeBuffer,1)
1239
(ndis_buffer *buffer)
1241
struct ndis_buffer_pool *pool;
1243
ENTER4("%p", buffer);
1244
if (!buffer || !buffer->pool) {
1245
ERROR("invalid buffer");
1248
pool = buffer->pool;
1249
if (pool->num_allocated_descr > MAX_ALLOCATED_NDIS_BUFFERS) {
1250
/* NB NB NB: set mdl's 'pool' field to NULL before
1251
* calling free_mdl; otherwise free_mdl calls
1252
* NdisFreeBuffer back */
1253
atomic_dec_var(pool->num_allocated_descr);
1254
buffer->pool = NULL;
1257
spin_lock_bh(&pool->lock);
1258
buffer->next = pool->free_descr;
1259
pool->free_descr = buffer;
1260
spin_unlock_bh(&pool->lock);
1265
wstdcall void WIN_FUNC(NdisFreeBufferPool,1)
1266
(struct ndis_buffer_pool *pool)
1268
ndis_buffer *cur, *next;
1270
TRACE3("pool: %p", pool);
1272
WARNING("invalid pool");
1275
spin_lock_bh(&pool->lock);
1276
cur = pool->free_descr;
1283
spin_unlock_bh(&pool->lock);
1289
wstdcall void WIN_FUNC(NdisAdjustBufferLength,2)
1290
(ndis_buffer *buffer, UINT length)
1292
ENTER4("%p, %d", buffer, length);
1293
buffer->bytecount = length;
1296
wstdcall void WIN_FUNC(NdisQueryBuffer,3)
1297
(ndis_buffer *buffer, void **virt, UINT *length)
1299
ENTER4("buffer: %p", buffer);
1301
*virt = MmGetSystemAddressForMdl(buffer);
1302
*length = MmGetMdlByteCount(buffer);
1303
TRACE4("%p, %u", virt? *virt : NULL, *length);
1307
wstdcall void WIN_FUNC(NdisQueryBufferSafe,4)
1308
(ndis_buffer *buffer, void **virt, UINT *length,
1309
enum mm_page_priority priority)
1311
ENTER4("%p, %p, %p, %d", buffer, virt, length, priority);
1313
*virt = MmGetSystemAddressForMdlSafe(buffer, priority);
1314
*length = MmGetMdlByteCount(buffer);
1315
TRACE4("%p, %u", virt? *virt : NULL, *length);
1318
wstdcall void *WIN_FUNC(NdisBufferVirtualAddress,1)
1319
(ndis_buffer *buffer)
1321
ENTER3("%p", buffer);
1322
return MmGetSystemAddressForMdl(buffer);
1325
wstdcall ULONG WIN_FUNC(NdisBufferLength,1)
1326
(ndis_buffer *buffer)
1328
ENTER3("%p", buffer);
1329
return MmGetMdlByteCount(buffer);
1332
wstdcall void WIN_FUNC(NdisQueryBufferOffset,3)
1333
(ndis_buffer *buffer, UINT *offset, UINT *length)
1335
ENTER3("%p", buffer);
1336
*offset = MmGetMdlByteOffset(buffer);
1337
*length = MmGetMdlByteCount(buffer);
1338
TRACE3("%d, %d", *offset, *length);
1341
wstdcall void WIN_FUNC(NdisUnchainBufferAtBack,2)
1342
(struct ndis_packet *packet, ndis_buffer **buffer)
1344
ndis_buffer *b, *btail;
1346
ENTER3("%p", packet);
1347
b = packet->private.buffer_head;
1349
/* no buffer in packet */
1353
btail = packet->private.buffer_tail;
1356
/* one buffer in packet */
1357
packet->private.buffer_head = NULL;
1358
packet->private.buffer_tail = NULL;
1360
while (b->next != btail)
1362
packet->private.buffer_tail = b;
1365
packet->private.valid_counts = FALSE;
1369
wstdcall void WIN_FUNC(NdisUnchainBufferAtFront,2)
1370
(struct ndis_packet *packet, ndis_buffer **buffer)
1372
ENTER3("%p", packet);
1373
if (packet->private.buffer_head == NULL) {
1374
/* no buffer in packet */
1379
*buffer = packet->private.buffer_head;
1380
if (packet->private.buffer_head == packet->private.buffer_tail) {
1381
/* one buffer in packet */
1382
packet->private.buffer_head = NULL;
1383
packet->private.buffer_tail = NULL;
1385
packet->private.buffer_head = (*buffer)->next;
1387
packet->private.valid_counts = FALSE;
1391
wstdcall void WIN_FUNC(NdisGetFirstBufferFromPacketSafe,6)
1392
(struct ndis_packet *packet, ndis_buffer **first_buffer,
1393
void **first_buffer_va, UINT *first_buffer_length,
1394
UINT *total_buffer_length, enum mm_page_priority priority)
1396
ndis_buffer *b = packet->private.buffer_head;
1398
ENTER3("%p(%p)", packet, b);
1401
*first_buffer_va = MmGetSystemAddressForMdlSafe(b, priority);
1402
*first_buffer_length = *total_buffer_length =
1403
MmGetMdlByteCount(b);
1404
for (b = b->next; b; b = b->next)
1405
*total_buffer_length += MmGetMdlByteCount(b);
1407
*first_buffer_va = NULL;
1408
*first_buffer_length = 0;
1409
*total_buffer_length = 0;
1411
TRACE3("%p, %d, %d", *first_buffer_va, *first_buffer_length,
1412
*total_buffer_length);
1416
wstdcall void WIN_FUNC(NdisGetFirstBufferFromPacket,6)
1417
(struct ndis_packet *packet, ndis_buffer **first_buffer,
1418
void **first_buffer_va, UINT *first_buffer_length,
1419
UINT *total_buffer_length, enum mm_page_priority priority)
1421
NdisGetFirstBufferFromPacketSafe(packet, first_buffer,
1422
first_buffer_va, first_buffer_length,
1423
total_buffer_length,
1424
NormalPagePriority);
1427
wstdcall void WIN_FUNC(NdisAllocatePacketPoolEx,5)
1428
(NDIS_STATUS *status, struct ndis_packet_pool **pool_handle,
1429
UINT num_descr, UINT overflowsize, UINT proto_rsvd_length)
1431
struct ndis_packet_pool *pool;
1433
ENTER3("buffers: %d, length: %d", num_descr, proto_rsvd_length);
1434
pool = kzalloc(sizeof(*pool), irql_gfp());
1436
*status = NDIS_STATUS_RESOURCES;
1439
spin_lock_init(&pool->lock);
1440
pool->max_descr = num_descr;
1441
pool->num_allocated_descr = 0;
1442
pool->num_used_descr = 0;
1443
pool->free_descr = NULL;
1444
pool->proto_rsvd_length = proto_rsvd_length;
1445
*pool_handle = pool;
1446
*status = NDIS_STATUS_SUCCESS;
1447
TRACE3("pool: %p", pool);
1451
wstdcall void WIN_FUNC(NdisAllocatePacketPool,4)
1452
(NDIS_STATUS *status, struct ndis_packet_pool **pool_handle,
1453
UINT num_descr, UINT proto_rsvd_length)
1455
NdisAllocatePacketPoolEx(status, pool_handle, num_descr, 0,
1460
wstdcall void WIN_FUNC(NdisFreePacketPool,1)
1461
(struct ndis_packet_pool *pool)
1463
struct ndis_packet *packet, *next;
1465
ENTER3("pool: %p", pool);
1467
WARNING("invalid pool");
1470
spin_lock_bh(&pool->lock);
1471
packet = pool->free_descr;
1473
next = (struct ndis_packet *)packet->reserved[0];
1477
pool->num_allocated_descr = 0;
1478
pool->num_used_descr = 0;
1479
pool->free_descr = NULL;
1480
spin_unlock_bh(&pool->lock);
1485
wstdcall UINT WIN_FUNC(NdisPacketPoolUsage,1)
1486
(struct ndis_packet_pool *pool)
1488
EXIT4(return pool->num_used_descr);
1491
wstdcall void WIN_FUNC(NdisAllocatePacket,3)
1492
(NDIS_STATUS *status, struct ndis_packet **ndis_packet,
1493
struct ndis_packet_pool *pool)
1495
struct ndis_packet *packet;
1498
ENTER4("pool: %p", pool);
1500
*status = NDIS_STATUS_RESOURCES;
1501
*ndis_packet = NULL;
1504
assert_irql(_irql_ <= SOFT_LEVEL);
1505
if (pool->num_used_descr > pool->max_descr) {
1506
TRACE3("pool %p is full: %d(%d)", pool,
1507
pool->num_used_descr, pool->max_descr);
1508
#ifndef ALLOW_POOL_OVERFLOW
1509
*status = NDIS_STATUS_RESOURCES;
1510
*ndis_packet = NULL;
1514
/* packet has space for 1 byte in protocol_reserved field */
1515
packet_length = sizeof(*packet) - 1 + pool->proto_rsvd_length +
1516
sizeof(struct ndis_packet_oob_data);
1517
spin_lock_bh(&pool->lock);
1518
if ((packet = pool->free_descr))
1519
pool->free_descr = (void *)packet->reserved[0];
1520
spin_unlock_bh(&pool->lock);
1522
packet = kmalloc(packet_length, irql_gfp());
1524
WARNING("couldn't allocate packet");
1525
*status = NDIS_STATUS_RESOURCES;
1526
*ndis_packet = NULL;
1529
atomic_inc_var(pool->num_allocated_descr);
1531
TRACE4("%p, %p", pool, packet);
1532
atomic_inc_var(pool->num_used_descr);
1533
memset(packet, 0, packet_length);
1534
packet->private.oob_offset =
1535
packet_length - sizeof(struct ndis_packet_oob_data);
1536
packet->private.packet_flags = fPACKET_ALLOCATED_BY_NDIS;
1537
packet->private.pool = pool;
1538
*ndis_packet = packet;
1539
*status = NDIS_STATUS_SUCCESS;
1543
wstdcall void WIN_FUNC(NdisDprAllocatePacket,3)
1544
(NDIS_STATUS *status, struct ndis_packet **packet,
1545
struct ndis_packet_pool *pool)
1547
NdisAllocatePacket(status, packet, pool);
1550
wstdcall void WIN_FUNC(NdisFreePacket,1)
1551
(struct ndis_packet *packet)
1553
struct ndis_packet_pool *pool;
1555
ENTER4("%p, %p", packet, packet->private.pool);
1556
pool = packet->private.pool;
1558
ERROR("invalid pool %p", packet);
1561
assert((int)pool->num_used_descr > 0);
1562
atomic_dec_var(pool->num_used_descr);
1563
if (packet->reserved[1]) {
1564
TRACE3("%p, %p", packet, (void *)packet->reserved[1]);
1565
kfree((void *)packet->reserved[1]);
1566
packet->reserved[1] = 0;
1568
if (pool->num_allocated_descr > MAX_ALLOCATED_NDIS_PACKETS) {
1570
atomic_dec_var(pool->num_allocated_descr);
1573
TRACE4("%p, %p, %p", pool, packet, pool->free_descr);
1574
spin_lock_bh(&pool->lock);
1575
packet->reserved[0] =
1576
(typeof(packet->reserved[0]))pool->free_descr;
1577
pool->free_descr = packet;
1578
spin_unlock_bh(&pool->lock);
1583
wstdcall struct ndis_packet_stack *WIN_FUNC(NdisIMGetCurrentPacketStack,2)
1584
(struct ndis_packet *packet, BOOLEAN *stacks_remain)
1586
struct ndis_packet_stack *stack;
1588
if (!packet->reserved[1]) {
1589
stack = kzalloc(2 * sizeof(*stack), irql_gfp());
1590
TRACE3("%p, %p", packet, stack);
1591
packet->reserved[1] = (typeof(packet->reserved[1]))stack;
1593
stack = (void *)packet->reserved[1];;
1594
if (xchg(&stack->ndis_reserved[0], 1)) {
1596
if (xchg(&stack->ndis_reserved[0], 1))
1599
TRACE3("%p", stack);
1602
*stacks_remain = TRUE;
1604
*stacks_remain = FALSE;
1606
EXIT3(return stack);
1609
wstdcall void WIN_FUNC(NdisCopyFromPacketToPacketSafe,7)
1610
(struct ndis_packet *dst, UINT dst_offset, UINT num_to_copy,
1611
struct ndis_packet *src, UINT src_offset, UINT *num_copied,
1612
enum mm_page_priority priority)
1614
UINT dst_n, src_n, n, left;
1615
ndis_buffer *dst_buf;
1616
ndis_buffer *src_buf;
1624
dst_buf = dst->private.buffer_head;
1625
src_buf = src->private.buffer_head;
1627
if (!dst_buf || !src_buf) {
1631
dst_n = MmGetMdlByteCount(dst_buf) - dst_offset;
1632
src_n = MmGetMdlByteCount(src_buf) - src_offset;
1634
n = min(src_n, dst_n);
1635
n = min(n, num_to_copy);
1636
memcpy(MmGetSystemAddressForMdl(dst_buf) + dst_offset,
1637
MmGetSystemAddressForMdl(src_buf) + src_offset, n);
1639
left = num_to_copy - n;
1646
dst_buf = dst_buf->next;
1649
dst_n = MmGetMdlByteCount(dst_buf);
1653
src_buf = src_buf->next;
1656
src_n = MmGetMdlByteCount(src_buf);
1660
n = min(src_n, dst_n);
1662
memcpy(MmGetSystemAddressForMdl(dst_buf) + dst_offset,
1663
MmGetSystemAddressForMdl(src_buf) + src_offset, n);
1666
*num_copied = num_to_copy - left;
1670
wstdcall void WIN_FUNC(NdisCopyFromPacketToPacket,6)
1671
(struct ndis_packet *dst, UINT dst_offset, UINT num_to_copy,
1672
struct ndis_packet *src, UINT src_offset, UINT *num_copied)
1674
NdisCopyFromPacketToPacketSafe(dst, dst_offset, num_to_copy,
1675
src, src_offset, num_copied,
1676
NormalPagePriority);
1680
wstdcall void WIN_FUNC(NdisIMCopySendPerPacketInfo,2)
1681
(struct ndis_packet *dst, struct ndis_packet *src)
1683
struct ndis_packet_oob_data *dst_oob, *src_oob;
1684
dst_oob = NDIS_PACKET_OOB_DATA(dst);
1685
src_oob = NDIS_PACKET_OOB_DATA(src);
1686
memcpy(&dst_oob->ext, &src_oob->ext, sizeof(dst_oob->ext));
1690
wstdcall void WIN_FUNC(NdisSend,3)
1691
(NDIS_STATUS *status, struct ndis_mp_block *nmb,
1692
struct ndis_packet *packet)
1694
struct ndis_device *wnd = nmb->wnd;
1695
struct miniport *mp;
1698
mp = &wnd->wd->driver->ndis_driver->mp;
1699
if (mp->send_packets) {
1700
irql = serialize_lock_irql(wnd);
1701
assert_irql(_irql_ == DISPATCH_LEVEL);
1702
LIN2WIN3(mp->send_packets, wnd->nmb->mp_ctx, &packet, 1);
1703
serialize_unlock_irql(wnd, irql);
1704
if (deserialized_driver(wnd))
1705
*status = NDIS_STATUS_PENDING;
1707
struct ndis_packet_oob_data *oob_data;
1708
oob_data = NDIS_PACKET_OOB_DATA(packet);
1709
*status = oob_data->status;
1711
case NDIS_STATUS_SUCCESS:
1712
free_tx_packet(wnd, packet, *status);
1714
case NDIS_STATUS_PENDING:
1716
case NDIS_STATUS_RESOURCES:
1719
case NDIS_STATUS_FAILURE:
1721
free_tx_packet(wnd, packet, *status);
1726
irql = serialize_lock_irql(wnd);
1727
assert_irql(_irql_ == DISPATCH_LEVEL);
1728
*status = LIN2WIN3(mp->send, wnd->nmb->mp_ctx, packet, 0);
1729
serialize_unlock_irql(wnd, irql);
1731
case NDIS_STATUS_SUCCESS:
1732
free_tx_packet(wnd, packet, *status);
1734
case NDIS_STATUS_PENDING:
1736
case NDIS_STATUS_RESOURCES:
1739
case NDIS_STATUS_FAILURE:
1741
free_tx_packet(wnd, packet, *status);
1748
/* called for serialized drivers only */
1749
wstdcall void mp_timer_dpc(struct kdpc *kdpc, void *ctx, void *arg1, void *arg2)
1751
struct ndis_mp_timer *timer;
1752
struct ndis_mp_block *nmb;
1755
TIMERENTER("%p, %p, %p, %p", timer, timer->func, timer->ctx, timer->nmb);
1756
assert_irql(_irql_ == DISPATCH_LEVEL);
1758
serialize_lock(nmb->wnd);
1759
LIN2WIN4(timer->func, NULL, timer->ctx, NULL, NULL);
1760
serialize_unlock(nmb->wnd);
1763
WIN_FUNC_DECL(mp_timer_dpc,4)
1765
wstdcall void WIN_FUNC(NdisMInitializeTimer,4)
1766
(struct ndis_mp_timer *timer, struct ndis_mp_block *nmb,
1767
DPC func, void *ctx)
1769
TIMERENTER("%p, %p, %p, %p", timer, func, ctx, nmb);
1770
assert_irql(_irql_ == PASSIVE_LEVEL);
1774
if (deserialized_driver(nmb->wnd))
1775
KeInitializeDpc(&timer->kdpc, func, ctx);
1777
KeInitializeDpc(&timer->kdpc, WIN_FUNC_PTR(mp_timer_dpc,4),
1779
wrap_init_timer(&timer->nt_timer, NotificationTimer, nmb);
1783
wstdcall void WIN_FUNC(NdisMSetPeriodicTimer,2)
1784
(struct ndis_mp_timer *timer, UINT period_ms)
1786
unsigned long expires = MSEC_TO_HZ(period_ms);
1788
TIMERENTER("%p, %u, %ld", timer, period_ms, expires);
1789
assert_irql(_irql_ <= DISPATCH_LEVEL);
1790
wrap_set_timer(&timer->nt_timer, expires, expires, &timer->kdpc);
1794
wstdcall void WIN_FUNC(NdisMCancelTimer,2)
1795
(struct ndis_mp_timer *timer, BOOLEAN *canceled)
1797
TIMERENTER("%p", timer);
1798
assert_irql(_irql_ <= DISPATCH_LEVEL);
1799
*canceled = KeCancelTimer(&timer->nt_timer);
1800
TIMERTRACE("%d", *canceled);
1804
wstdcall void WIN_FUNC(NdisInitializeTimer,3)
1805
(struct ndis_timer *timer, void *func, void *ctx)
1807
TIMERENTER("%p, %p, %p", timer, func, ctx);
1808
assert_irql(_irql_ == PASSIVE_LEVEL);
1809
KeInitializeDpc(&timer->kdpc, func, ctx);
1810
wrap_init_timer(&timer->nt_timer, NotificationTimer, NULL);
1814
/* NdisMSetTimer is a macro that calls NdisSetTimer with
1815
* ndis_mp_timer typecast to ndis_timer */
1817
wstdcall void WIN_FUNC(NdisSetTimer,2)
1818
(struct ndis_timer *timer, UINT duetime_ms)
1820
unsigned long expires = MSEC_TO_HZ(duetime_ms);
1822
TIMERENTER("%p, %p, %u, %ld", timer, timer->nt_timer.wrap_timer,
1823
duetime_ms, expires);
1824
assert_irql(_irql_ <= DISPATCH_LEVEL);
1825
wrap_set_timer(&timer->nt_timer, expires, 0, &timer->kdpc);
1829
wstdcall void WIN_FUNC(NdisCancelTimer,2)
1830
(struct ndis_timer *timer, BOOLEAN *canceled)
1832
TIMERENTER("%p", timer);
1833
assert_irql(_irql_ <= DISPATCH_LEVEL);
1834
*canceled = KeCancelTimer(&timer->nt_timer);
1838
wstdcall void WIN_FUNC(NdisMRegisterAdapterShutdownHandler,3)
1839
(struct ndis_mp_block *nmb, void *ctx, void *func)
1841
struct ndis_device *wnd = nmb->wnd;
1843
wnd->wd->driver->ndis_driver->mp.shutdown = func;
1844
wnd->shutdown_ctx = ctx;
1847
wstdcall void WIN_FUNC(NdisMDeregisterAdapterShutdownHandler,1)
1848
(struct ndis_mp_block *nmb)
1850
struct ndis_device *wnd = nmb->wnd;
1851
wnd->wd->driver->ndis_driver->mp.shutdown = NULL;
1852
wnd->shutdown_ctx = NULL;
1855
/* TODO: rt61 (serialized) driver doesn't want MiniportEnableInterrupt
1856
* to be called in irq handler, but mrv800c (deserialized) driver
1857
* wants. NDIS is confusing about when to call MiniportEnableInterrupt
1858
* For now, handle these cases with two separate irq handlers based on
1859
* observation of these two drivers. However, it is likely not
1861
wstdcall void deserialized_irq_handler(struct kdpc *kdpc, void *ctx,
1862
void *arg1, void *arg2)
1864
struct ndis_device *wnd = ctx;
1865
ndis_interrupt_handler irq_handler = arg1;
1866
struct miniport *mp = arg2;
1868
TRACE6("%p", irq_handler);
1869
assert_irql(_irql_ == DISPATCH_LEVEL);
1870
LIN2WIN1(irq_handler, wnd->nmb->mp_ctx);
1871
if (mp->enable_interrupt)
1872
LIN2WIN1(mp->enable_interrupt, wnd->nmb->mp_ctx);
1875
WIN_FUNC_DECL(deserialized_irq_handler,4)
1877
wstdcall void serialized_irq_handler(struct kdpc *kdpc, void *ctx,
1878
void *arg1, void *arg2)
1880
struct ndis_device *wnd = ctx;
1881
ndis_interrupt_handler irq_handler = arg1;
1883
TRACE6("%p, %p, %p", wnd, irq_handler, arg2);
1884
assert_irql(_irql_ == DISPATCH_LEVEL);
1885
serialize_lock(wnd);
1886
LIN2WIN1(irq_handler, arg2);
1887
serialize_unlock(wnd);
1890
WIN_FUNC_DECL(serialized_irq_handler,4)
1892
wstdcall BOOLEAN ndis_isr(struct kinterrupt *kinterrupt, void *ctx)
1894
struct ndis_mp_interrupt *mp_interrupt = ctx;
1895
struct ndis_device *wnd = mp_interrupt->nmb->wnd;
1896
BOOLEAN recognized = TRUE, queue_handler = TRUE;
1899
/* kernel may call ISR when registering interrupt, in
1900
* the same context if DEBUG_SHIRQ is enabled */
1901
assert_irql(_irql_ == DIRQL || _irql_ == PASSIVE_LEVEL);
1902
if (mp_interrupt->shared)
1903
LIN2WIN3(mp_interrupt->isr, &recognized, &queue_handler,
1906
struct miniport *mp;
1907
mp = &wnd->wd->driver->ndis_driver->mp;
1908
LIN2WIN1(mp->disable_interrupt, wnd->nmb->mp_ctx);
1909
/* it is not shared interrupt, so handler must be called */
1910
recognized = queue_handler = TRUE;
1913
if (queue_handler) {
1914
TRACE5("%p", &wnd->irq_kdpc);
1915
queue_kdpc(&wnd->irq_kdpc);
1919
EXIT6(return FALSE);
1921
WIN_FUNC_DECL(ndis_isr,2)
1923
wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterInterrupt,7)
1924
(struct ndis_mp_interrupt *mp_interrupt,
1925
struct ndis_mp_block *nmb, UINT vector, UINT level,
1926
BOOLEAN req_isr, BOOLEAN shared, enum kinterrupt_mode mode)
1928
struct ndis_device *wnd = nmb->wnd;
1929
struct miniport *mp;
1931
ENTER1("%p, vector:%d, level:%d, req_isr:%d, shared:%d, mode:%d",
1932
mp_interrupt, vector, level, req_isr, shared, mode);
1934
mp = &wnd->wd->driver->ndis_driver->mp;
1935
nt_spin_lock_init(&mp_interrupt->lock);
1936
mp_interrupt->irq = vector;
1937
mp_interrupt->isr = mp->isr;
1938
mp_interrupt->mp_dpc = mp->handle_interrupt;
1939
mp_interrupt->nmb = nmb;
1940
mp_interrupt->req_isr = req_isr;
1941
if (shared && !req_isr)
1942
WARNING("shared but dynamic interrupt!");
1943
mp_interrupt->shared = shared;
1944
wnd->mp_interrupt = mp_interrupt;
1945
if (mp->enable_interrupt)
1946
mp_interrupt->enable = TRUE;
1948
mp_interrupt->enable = FALSE;
1950
if (deserialized_driver(wnd)) {
1951
KeInitializeDpc(&wnd->irq_kdpc,
1952
WIN_FUNC_PTR(deserialized_irq_handler,4),
1954
wnd->irq_kdpc.arg1 = mp->handle_interrupt;
1955
wnd->irq_kdpc.arg2 = mp;
1956
TRACE2("%p, %p, %p, %p", wnd->irq_kdpc.arg1, wnd->irq_kdpc.arg2,
1957
nmb->wnd, nmb->mp_ctx);
1959
KeInitializeDpc(&wnd->irq_kdpc,
1960
WIN_FUNC_PTR(serialized_irq_handler,4),
1962
wnd->irq_kdpc.arg1 = mp->handle_interrupt;
1963
wnd->irq_kdpc.arg2 = nmb->mp_ctx;
1964
TRACE2("%p, %p, %p", wnd->irq_kdpc.arg1, wnd->irq_kdpc.arg2,
1968
if (IoConnectInterrupt(&mp_interrupt->kinterrupt,
1969
WIN_FUNC_PTR(ndis_isr,2), mp_interrupt, NULL,
1970
vector, DIRQL, DIRQL, mode, shared, 0, FALSE) !=
1972
printk(KERN_WARNING "%s: request for IRQ %d failed\n",
1973
DRIVER_NAME, vector);
1974
return NDIS_STATUS_RESOURCES;
1976
printk(KERN_INFO "%s: using IRQ %d\n", DRIVER_NAME, vector);
1977
EXIT1(return NDIS_STATUS_SUCCESS);
1980
wstdcall void WIN_FUNC(NdisMDeregisterInterrupt,1)
1981
(struct ndis_mp_interrupt *mp_interrupt)
1983
struct ndis_mp_block *nmb;
1985
ENTER1("%p", mp_interrupt);
1986
nmb = xchg(&mp_interrupt->nmb, NULL);
1989
WARNING("interrupt already freed?");
1992
nmb->wnd->mp_interrupt = NULL;
1993
if (dequeue_kdpc(&nmb->wnd->irq_kdpc))
1994
TRACE2("interrupt kdpc was pending");
1995
flush_workqueue(wrapndis_wq);
1996
IoDisconnectInterrupt(mp_interrupt->kinterrupt);
2000
wstdcall BOOLEAN WIN_FUNC(NdisMSynchronizeWithInterrupt,3)
2001
(struct ndis_mp_interrupt *mp_interrupt,
2002
PKSYNCHRONIZE_ROUTINE sync_func, void *ctx)
2004
return KeSynchronizeExecution(mp_interrupt->kinterrupt, sync_func, ctx);
2007
/* called via function pointer; but 64-bit RNDIS driver calls directly */
2008
wstdcall void WIN_FUNC(NdisMIndicateStatus,4)
2009
(struct ndis_mp_block *nmb, NDIS_STATUS status, void *buf, UINT len)
2011
struct ndis_device *wnd = nmb->wnd;
2012
struct ndis_status_indication *si;
2014
ENTER2("status=0x%x len=%d", status, len);
2016
case NDIS_STATUS_MEDIA_CONNECT:
2017
set_media_state(wnd, NdisMediaStateConnected);
2019
case NDIS_STATUS_MEDIA_DISCONNECT:
2020
set_media_state(wnd, NdisMediaStateDisconnected);
2022
case NDIS_STATUS_MEDIA_SPECIFIC_INDICATION:
2026
TRACE2("status_type=%d", si->status_type);
2027
switch (si->status_type) {
2028
case Ndis802_11StatusType_MediaStreamMode:
2030
#ifdef CONFIG_WIRELESS_EXT
2031
case Ndis802_11StatusType_Authentication:
2032
buf = (char *)buf + sizeof(*si);
2035
int pairwise_error = 0, group_error = 0;
2036
struct ndis_auth_req *auth_req =
2037
(struct ndis_auth_req *)buf;
2038
TRACE1(MACSTRSEP, MAC2STR(auth_req->bssid));
2039
if (auth_req->flags & 0x01)
2040
TRACE2("reauth request");
2041
if (auth_req->flags & 0x02)
2042
TRACE2("key update request");
2043
if (auth_req->flags & 0x06) {
2045
TRACE2("pairwise_error");
2047
if (auth_req->flags & 0x0E) {
2049
TRACE2("group_error");
2051
if (pairwise_error || group_error) {
2052
union iwreq_data wrqu;
2053
struct iw_michaelmicfailure micfailure;
2055
memset(&micfailure, 0, sizeof(micfailure));
2058
IW_MICFAILURE_PAIRWISE;
2061
IW_MICFAILURE_GROUP;
2062
memcpy(micfailure.src_addr.sa_data,
2063
auth_req->bssid, ETH_ALEN);
2064
memset(&wrqu, 0, sizeof(wrqu));
2065
wrqu.data.length = sizeof(micfailure);
2066
wireless_send_event(wnd->net_dev,
2067
IWEVMICHAELMICFAILURE,
2068
&wrqu, (u8 *)&micfailure);
2070
len -= auth_req->length;
2071
buf = (char *)buf + auth_req->length;
2074
case Ndis802_11StatusType_PMKID_CandidateList:
2078
struct ndis_pmkid_candidate_list *cand;
2080
cand = buf + sizeof(struct ndis_status_indication);
2081
if (len < sizeof(struct ndis_status_indication) +
2082
sizeof(struct ndis_pmkid_candidate_list) ||
2083
cand->version != 1) {
2084
WARNING("unrecognized PMKID ignored");
2088
end = (u8 *)buf + len;
2089
TRACE2("PMKID ver %d num_cand %d",
2090
cand->version, cand->num_candidates);
2091
for (i = 0; i < cand->num_candidates; i++) {
2092
struct iw_pmkid_cand pcand;
2093
union iwreq_data wrqu;
2094
struct ndis_pmkid_candidate *c =
2095
&cand->candidates[i];
2096
if ((u8 *)(c + 1) > end) {
2097
TRACE2("truncated PMKID");
2100
TRACE2("%ld: " MACSTRSEP " 0x%x",
2101
i, MAC2STR(c->bssid), c->flags);
2102
memset(&pcand, 0, sizeof(pcand));
2103
if (c->flags & 0x01)
2104
pcand.flags |= IW_PMKID_CAND_PREAUTH;
2106
memcpy(pcand.bssid.sa_data, c->bssid, ETH_ALEN);
2108
memset(&wrqu, 0, sizeof(wrqu));
2109
wrqu.data.length = sizeof(pcand);
2110
wireless_send_event(wnd->net_dev, IWEVPMKIDCAND,
2111
&wrqu, (u8 *)&pcand);
2115
case Ndis802_11StatusType_RadioState:
2117
struct ndis_radio_status_indication *radio_status = buf;
2118
if (radio_status->radio_state ==
2119
Ndis802_11RadioStatusOn)
2120
INFO("radio is turned on");
2121
else if (radio_status->radio_state ==
2122
Ndis802_11RadioStatusHardwareOff)
2123
INFO("radio is turned off by hardware");
2124
else if (radio_status->radio_state ==
2125
Ndis802_11RadioStatusSoftwareOff)
2126
INFO("radio is turned off by software");
2131
/* is this RSSI indication? */
2132
TRACE2("unknown indication: %x", si->status_type);
2137
TRACE2("unknown status: %08X", status);
2144
/* called via function pointer; but 64-bit RNDIS driver calls directly */
2145
wstdcall void WIN_FUNC(NdisMIndicateStatusComplete,1)
2146
(struct ndis_mp_block *nmb)
2148
struct ndis_device *wnd = nmb->wnd;
2151
schedule_wrapndis_work(&wnd->tx_work);
2154
/* called via function pointer */
2155
wstdcall void NdisMSendComplete(struct ndis_mp_block *nmb,
2156
struct ndis_packet *packet, NDIS_STATUS status)
2158
struct ndis_device *wnd = nmb->wnd;
2159
ENTER4("%p, %08X", packet, status);
2160
assert_irql(_irql_ <= DISPATCH_LEVEL);
2161
if (deserialized_driver(wnd))
2162
free_tx_packet(wnd, packet, status);
2164
struct ndis_packet_oob_data *oob_data;
2165
NDIS_STATUS pkt_status;
2166
TRACE3("%p, %08x", packet, status);
2167
oob_data = NDIS_PACKET_OOB_DATA(packet);
2168
switch ((pkt_status = xchg(&oob_data->status, status))) {
2169
case NDIS_STATUS_NOT_RECOGNIZED:
2170
free_tx_packet(wnd, packet, status);
2172
case NDIS_STATUS_PENDING:
2176
WARNING("%p: invalid status: %08X", packet, pkt_status);
2179
/* In case a serialized driver has earlier requested a
2180
* pause by returning NDIS_STATUS_RESOURCES during
2181
* MiniportSend(Packets), wakeup tx worker now.
2183
if (xchg(&wnd->tx_ok, 1) == 0) {
2184
TRACE3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end);
2185
schedule_wrapndis_work(&wnd->tx_work);
2191
/* called via function pointer */
2192
wstdcall void NdisMSendResourcesAvailable(struct ndis_mp_block *nmb)
2194
struct ndis_device *wnd = nmb->wnd;
2195
ENTER3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end);
2197
schedule_wrapndis_work(&wnd->tx_work);
2201
wstdcall void return_packet(void *arg1, void *arg2)
2203
struct ndis_device *wnd;
2204
struct ndis_packet *packet;
2205
struct miniport *mp;
2210
ENTER4("%p, %p", wnd, packet);
2211
mp = &wnd->wd->driver->ndis_driver->mp;
2212
irql = serialize_lock_irql(wnd);
2213
assert_irql(_irql_ == DISPATCH_LEVEL);
2214
LIN2WIN2(mp->return_packet, wnd->nmb->mp_ctx, packet);
2215
serialize_unlock_irql(wnd, irql);
2218
WIN_FUNC_DECL(return_packet,2)
2220
/* called via function pointer */
2221
wstdcall void NdisMIndicateReceivePacket(struct ndis_mp_block *nmb,
2222
struct ndis_packet **packets,
2225
struct ndis_device *wnd;
2226
ndis_buffer *buffer;
2227
struct ndis_packet *packet;
2228
struct sk_buff *skb;
2229
ULONG i, length, total_length;
2230
struct ndis_packet_oob_data *oob_data;
2232
struct ndis_tcp_ip_checksum_packet_info csum;
2234
ENTER3("%p, %d", nmb, nr_packets);
2235
assert_irql(_irql_ <= DISPATCH_LEVEL);
2237
for (i = 0; i < nr_packets; i++) {
2238
packet = packets[i];
2240
WARNING("empty packet ignored");
2243
wnd->net_dev->last_rx = jiffies;
2244
/* get total number of bytes in packet */
2245
NdisGetFirstBufferFromPacketSafe(packet, &buffer, &virt,
2246
&length, &total_length,
2247
NormalPagePriority);
2248
TRACE3("%d, %d", length, total_length);
2249
oob_data = NDIS_PACKET_OOB_DATA(packet);
2250
TRACE3("0x%x, 0x%x, %Lu", packet->private.flags,
2251
packet->private.packet_flags, oob_data->time_rxed);
2252
skb = dev_alloc_skb(total_length);
2255
memcpy_skb(skb, MmGetSystemAddressForMdl(buffer),
2256
MmGetMdlByteCount(buffer));
2257
buffer = buffer->next;
2259
skb->dev = wnd->net_dev;
2260
skb->protocol = eth_type_trans(skb, wnd->net_dev);
2261
pre_atomic_add(wnd->net_stats.rx_bytes, total_length);
2262
atomic_inc_var(wnd->net_stats.rx_packets);
2263
csum.value = (typeof(csum.value))(ULONG_PTR)
2264
oob_data->ext.info[TcpIpChecksumPacketInfo];
2265
TRACE3("0x%05x", csum.value);
2266
if (wnd->rx_csum.value &&
2267
(csum.rx.tcp_succeeded || csum.rx.udp_succeeded ||
2268
csum.rx.ip_succeeded))
2269
skb->ip_summed = CHECKSUM_UNNECESSARY;
2271
skb->ip_summed = CHECKSUM_NONE;
2278
WARNING("couldn't allocate skb; packet dropped");
2279
atomic_inc_var(wnd->net_stats.rx_dropped);
2282
/* serialized drivers check the status upon return
2283
* from this function */
2284
if (!deserialized_driver(wnd)) {
2285
oob_data->status = NDIS_STATUS_SUCCESS;
2289
/* if a deserialized driver sets
2290
* NDIS_STATUS_RESOURCES, then it reclaims the packet
2291
* upon return from this function */
2292
if (oob_data->status == NDIS_STATUS_RESOURCES)
2295
assert(oob_data->status == NDIS_STATUS_SUCCESS);
2296
/* deserialized driver doesn't check the status upon
2297
* return from this function; we need to call
2298
* MiniportReturnPacket later for this packet. Calling
2299
* MiniportReturnPacket from here is not correct - the
2300
* driver doesn't expect it (at least Centrino driver
2302
schedule_ntos_work_item(WIN_FUNC_PTR(return_packet,2),
2308
/* called via function pointer (by NdisMEthIndicateReceive macro); the
2309
* first argument is nmb->eth_db */
2310
wstdcall void EthRxIndicateHandler(struct ndis_mp_block *nmb, void *rx_ctx,
2311
char *header1, char *header, UINT header_size,
2312
void *look_ahead, UINT look_ahead_size,
2315
struct sk_buff *skb = NULL;
2316
struct ndis_device *wnd;
2317
unsigned int skb_size = 0;
2319
struct ndis_packet_oob_data *oob_data;
2321
ENTER3("nmb = %p, rx_ctx = %p, buf = %p, size = %d, buf = %p, "
2322
"size = %d, packet = %d", nmb, rx_ctx, header, header_size,
2323
look_ahead, look_ahead_size, packet_size);
2326
TRACE3("wnd = %p", wnd);
2328
ERROR("nmb is NULL");
2331
wnd->net_dev->last_rx = jiffies;
2333
if (look_ahead_size < packet_size) {
2334
struct ndis_packet *packet;
2335
struct miniport *mp;
2336
unsigned int bytes_txed;
2339
NdisAllocatePacket(&res, &packet, wnd->tx_packet_pool);
2340
if (res != NDIS_STATUS_SUCCESS) {
2341
atomic_inc_var(wnd->net_stats.rx_dropped);
2344
oob_data = NDIS_PACKET_OOB_DATA(packet);
2345
mp = &wnd->wd->driver->ndis_driver->mp;
2346
irql = serialize_lock_irql(wnd);
2347
assert_irql(_irql_ == DISPATCH_LEVEL);
2348
res = LIN2WIN6(mp->tx_data, packet, &bytes_txed, nmb,
2349
rx_ctx, look_ahead_size, packet_size);
2350
serialize_unlock_irql(wnd, irql);
2351
TRACE3("%d, %d, %d", header_size, look_ahead_size, bytes_txed);
2352
if (res == NDIS_STATUS_SUCCESS) {
2353
ndis_buffer *buffer;
2354
struct ndis_tcp_ip_checksum_packet_info csum;
2355
skb = dev_alloc_skb(header_size + look_ahead_size +
2358
ERROR("couldn't allocate skb; packet dropped");
2359
atomic_inc_var(wnd->net_stats.rx_dropped);
2360
NdisFreePacket(packet);
2363
memcpy_skb(skb, header, header_size);
2364
memcpy_skb(skb, look_ahead, look_ahead_size);
2365
buffer = packet->private.buffer_head;
2368
MmGetSystemAddressForMdl(buffer),
2369
MmGetMdlByteCount(buffer));
2370
buffer = buffer->next;
2372
skb_size = header_size + look_ahead_size + bytes_txed;
2373
csum.value = (typeof(csum.value))(ULONG_PTR)
2374
oob_data->ext.info[TcpIpChecksumPacketInfo];
2375
TRACE3("0x%05x", csum.value);
2376
if (wnd->rx_csum.value &&
2377
(csum.rx.tcp_succeeded || csum.rx.udp_succeeded))
2378
skb->ip_summed = CHECKSUM_UNNECESSARY;
2380
skb->ip_summed = CHECKSUM_NONE;
2381
NdisFreePacket(packet);
2382
} else if (res == NDIS_STATUS_PENDING) {
2383
/* driver will call td_complete */
2384
oob_data->look_ahead = kmalloc(look_ahead_size,
2386
if (!oob_data->look_ahead) {
2387
NdisFreePacket(packet);
2388
ERROR("packet dropped");
2389
atomic_inc_var(wnd->net_stats.rx_dropped);
2392
assert(sizeof(oob_data->header) == header_size);
2393
memcpy(oob_data->header, header,
2394
sizeof(oob_data->header));
2395
memcpy(oob_data->look_ahead, look_ahead,
2397
oob_data->look_ahead_size = look_ahead_size;
2400
WARNING("packet dropped: %08X", res);
2401
atomic_inc_var(wnd->net_stats.rx_dropped);
2402
NdisFreePacket(packet);
2406
skb_size = header_size + packet_size;
2407
skb = dev_alloc_skb(skb_size);
2409
memcpy_skb(skb, header, header_size);
2410
memcpy_skb(skb, look_ahead, packet_size);
2415
skb->dev = wnd->net_dev;
2416
skb->protocol = eth_type_trans(skb, wnd->net_dev);
2417
pre_atomic_add(wnd->net_stats.rx_bytes, skb_size);
2418
atomic_inc_var(wnd->net_stats.rx_packets);
2428
/* called via function pointer */
2429
wstdcall void NdisMTransferDataComplete(struct ndis_mp_block *nmb,
2430
struct ndis_packet *packet,
2431
NDIS_STATUS status, UINT bytes_txed)
2433
struct ndis_device *wnd = nmb->wnd;
2434
struct sk_buff *skb;
2435
unsigned int skb_size;
2436
struct ndis_packet_oob_data *oob_data;
2437
ndis_buffer *buffer;
2438
struct ndis_tcp_ip_checksum_packet_info csum;
2440
ENTER3("wnd = %p, packet = %p, bytes_txed = %d",
2441
wnd, packet, bytes_txed);
2443
WARNING("illegal packet");
2446
wnd->net_dev->last_rx = jiffies;
2447
oob_data = NDIS_PACKET_OOB_DATA(packet);
2448
skb_size = sizeof(oob_data->header) + oob_data->look_ahead_size +
2450
skb = dev_alloc_skb(skb_size);
2452
kfree(oob_data->look_ahead);
2453
NdisFreePacket(packet);
2454
ERROR("couldn't allocate skb; packet dropped");
2455
atomic_inc_var(wnd->net_stats.rx_dropped);
2458
memcpy_skb(skb, oob_data->header, sizeof(oob_data->header));
2459
memcpy_skb(skb, oob_data->look_ahead, oob_data->look_ahead_size);
2460
buffer = packet->private.buffer_head;
2462
memcpy_skb(skb, MmGetSystemAddressForMdl(buffer),
2463
MmGetMdlByteCount(buffer));
2464
buffer = buffer->next;
2466
kfree(oob_data->look_ahead);
2467
NdisFreePacket(packet);
2468
skb->dev = wnd->net_dev;
2469
skb->protocol = eth_type_trans(skb, wnd->net_dev);
2470
pre_atomic_add(wnd->net_stats.rx_bytes, skb_size);
2471
atomic_inc_var(wnd->net_stats.rx_packets);
2473
csum.value = (typeof(csum.value))(ULONG_PTR)
2474
oob_data->ext.info[TcpIpChecksumPacketInfo];
2475
TRACE3("0x%05x", csum.value);
2476
if (wnd->rx_csum.value &&
2477
(csum.rx.tcp_succeeded || csum.rx.udp_succeeded))
2478
skb->ip_summed = CHECKSUM_UNNECESSARY;
2480
skb->ip_summed = CHECKSUM_NONE;
2488
/* called via function pointer */
2489
wstdcall void EthRxComplete(struct ndis_mp_block *nmb)
2494
/* called via function pointer */
2495
wstdcall void NdisMQueryInformationComplete(struct ndis_mp_block *nmb,
2498
struct ndis_device *wnd = nmb->wnd;
2499
typeof(wnd->ndis_req_task) task;
2501
ENTER2("nmb: %p, wnd: %p, %08X", nmb, wnd, status);
2502
wnd->ndis_req_status = status;
2503
wnd->ndis_req_done = 1;
2504
if ((task = xchg(&wnd->ndis_req_task, NULL)))
2505
wake_up_process(task);
2507
WARNING("invalid task");
2511
/* called via function pointer */
2512
wstdcall void NdisMSetInformationComplete(struct ndis_mp_block *nmb,
2515
struct ndis_device *wnd = nmb->wnd;
2516
typeof(wnd->ndis_req_task) task;
2518
ENTER2("status = %08X", status);
2519
wnd->ndis_req_status = status;
2520
wnd->ndis_req_done = 1;
2521
if ((task = xchg(&wnd->ndis_req_task, NULL)))
2522
wake_up_process(task);
2524
WARNING("invalid task");
2528
/* called via function pointer */
2529
wstdcall void NdisMResetComplete(struct ndis_mp_block *nmb,
2530
NDIS_STATUS status, BOOLEAN address_reset)
2532
struct ndis_device *wnd = nmb->wnd;
2533
typeof(wnd->ndis_req_task) task;
2535
ENTER2("status: %08X, %u", status, address_reset);
2536
wnd->ndis_req_status = status;
2537
wnd->ndis_req_done = address_reset + 1;
2538
if ((task = xchg(&wnd->ndis_req_task, NULL)))
2539
wake_up_process(task);
2541
WARNING("invalid task");
2545
wstdcall void WIN_FUNC(NdisMSleep,1)
2548
unsigned long delay;
2550
ENTER4("%p: us: %u", current, us);
2551
delay = USEC_TO_HZ(us);
2553
TRACE4("%p: done", current);
2556
wstdcall void WIN_FUNC(NdisGetCurrentSystemTime,1)
2557
(LARGE_INTEGER *time)
2559
*time = ticks_1601();
2560
TRACE5("%Lu, %lu", *time, jiffies);
2563
wstdcall LONG WIN_FUNC(NdisInterlockedDecrement,1)
2566
return InterlockedDecrement(val);
2569
wstdcall LONG WIN_FUNC(NdisInterlockedIncrement,1)
2572
return InterlockedIncrement(val);
2575
wstdcall struct nt_list *WIN_FUNC(NdisInterlockedInsertHeadList,3)
2576
(struct nt_list *head, struct nt_list *entry,
2577
struct ndis_spinlock *lock)
2579
return ExInterlockedInsertHeadList(head, entry, &lock->klock);
2582
wstdcall struct nt_list *WIN_FUNC(NdisInterlockedInsertTailList,3)
2583
(struct nt_list *head, struct nt_list *entry,
2584
struct ndis_spinlock *lock)
2586
return ExInterlockedInsertTailList(head, entry, &lock->klock);
2589
wstdcall struct nt_list *WIN_FUNC(NdisInterlockedRemoveHeadList,2)
2590
(struct nt_list *head, struct ndis_spinlock *lock)
2592
return ExInterlockedRemoveHeadList(head, &lock->klock);
2595
wstdcall NDIS_STATUS WIN_FUNC(NdisMInitializeScatterGatherDma,3)
2596
(struct ndis_mp_block *nmb, BOOLEAN dma_size, ULONG max_phy_map)
2598
struct ndis_device *wnd = nmb->wnd;
2599
ENTER2("dma_size=%d, maxtransfer=%u", dma_size, max_phy_map);
2600
#ifdef CONFIG_X86_64
2601
if (dma_size != NDIS_DMA_64BITS) {
2602
TRACE1("DMA size is not 64-bits");
2603
if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(32)) ||
2604
pci_set_consistent_dma_mask(wnd->wd->pci.pdev,
2606
WARNING("setting dma mask failed");
2609
if ((wnd->attributes & NDIS_ATTRIBUTE_BUS_MASTER) &&
2610
wrap_is_pci_bus(wnd->wd->dev_bus)) {
2611
wnd->sg_dma_size = max_phy_map;
2612
return NDIS_STATUS_SUCCESS;
2614
EXIT1(return NDIS_STATUS_NOT_SUPPORTED);
2617
wstdcall ULONG WIN_FUNC(NdisMGetDmaAlignment,1)
2618
(struct ndis_mp_block *nmb)
2621
return dma_get_cache_alignment();
2624
wstdcall CHAR WIN_FUNC(NdisSystemProcessorCount,0)
2627
return (CHAR)NR_CPUS;
2630
wstdcall void WIN_FUNC(NdisGetCurrentProcessorCounts,3)
2631
(ULONG *idle, ULONG *kernel_user, ULONG *index)
2633
int cpu = smp_processor_id();
2634
*idle = kstat_cpu(cpu).cpustat.idle;
2635
*kernel_user = kstat_cpu(cpu).cpustat.system +
2636
kstat_cpu(cpu).cpustat.user;
2640
wstdcall void WIN_FUNC(NdisInitializeEvent,1)
2641
(struct ndis_event *ndis_event)
2643
EVENTENTER("%p", ndis_event);
2644
KeInitializeEvent(&ndis_event->nt_event, NotificationEvent, 0);
2647
wstdcall BOOLEAN WIN_FUNC(NdisWaitEvent,2)
2648
(struct ndis_event *ndis_event, UINT ms)
2650
LARGE_INTEGER ticks;
2653
EVENTENTER("%p %u", ndis_event, ms);
2654
ticks = -((LARGE_INTEGER)ms * TICKSPERMSEC);
2655
res = KeWaitForSingleObject(&ndis_event->nt_event, 0, 0, TRUE,
2656
ms == 0 ? NULL : &ticks);
2657
if (res == STATUS_SUCCESS)
2660
EXIT3(return FALSE);
2663
wstdcall void WIN_FUNC(NdisSetEvent,1)
2664
(struct ndis_event *ndis_event)
2666
EVENTENTER("%p", ndis_event);
2667
KeSetEvent(&ndis_event->nt_event, 0, 0);
2670
wstdcall void WIN_FUNC(NdisResetEvent,1)
2671
(struct ndis_event *ndis_event)
2673
EVENTENTER("%p", ndis_event);
2674
KeResetEvent(&ndis_event->nt_event);
2677
static void ndis_worker(worker_param_t dummy)
2679
struct nt_list *ent;
2680
struct ndis_work_item *ndis_work_item;
2684
spin_lock_bh(&ndis_work_list_lock);
2685
ent = RemoveHeadList(&ndis_work_list);
2686
spin_unlock_bh(&ndis_work_list_lock);
2689
ndis_work_item = container_of(ent, struct ndis_work_item, list);
2690
WORKTRACE("%p: %p, %p", ndis_work_item,
2691
ndis_work_item->func, ndis_work_item->ctx);
2692
LIN2WIN2(ndis_work_item->func, ndis_work_item,
2693
ndis_work_item->ctx);
2694
WORKTRACE("%p done", ndis_work_item);
2699
wstdcall NDIS_STATUS WIN_FUNC(NdisScheduleWorkItem,1)
2700
(struct ndis_work_item *ndis_work_item)
2702
ENTER3("%p", ndis_work_item);
2703
spin_lock_bh(&ndis_work_list_lock);
2704
InsertTailList(&ndis_work_list, &ndis_work_item->list);
2705
spin_unlock_bh(&ndis_work_list_lock);
2706
WORKTRACE("scheduling %p", ndis_work_item);
2707
schedule_ndis_work(&ndis_work);
2708
EXIT3(return NDIS_STATUS_SUCCESS);
2711
wstdcall void WIN_FUNC(NdisMGetDeviceProperty,6)
2712
(struct ndis_mp_block *nmb, void **phy_dev, void **func_dev,
2713
void **next_dev, void **alloc_res, void**trans_res)
2715
ENTER2("nmb: %p, phy_dev = %p, func_dev = %p, next_dev = %p, "
2716
"alloc_res = %p, trans_res = %p", nmb, phy_dev, func_dev,
2717
next_dev, alloc_res, trans_res);
2719
*phy_dev = nmb->pdo;
2721
*func_dev = nmb->fdo;
2723
*next_dev = nmb->next_device;
2726
wstdcall void WIN_FUNC(NdisMRegisterUnloadHandler,2)
2727
(struct driver_object *drv_obj, void *unload)
2730
drv_obj->unload = unload;
2734
wstdcall UINT WIN_FUNC(NdisGetVersion,0)
2740
wstdcall NDIS_STATUS WIN_FUNC(NdisMQueryAdapterInstanceName,2)
2741
(struct unicode_string *name, struct ndis_mp_block *nmb)
2743
struct ndis_device *wnd = nmb->wnd;
2744
struct ansi_string ansi;
2746
if (wrap_is_pci_bus(wnd->wd->dev_bus))
2747
RtlInitAnsiString(&ansi, "PCI Ethernet Adapter");
2749
RtlInitAnsiString(&ansi, "USB Ethernet Adapter");
2751
if (RtlAnsiStringToUnicodeString(name, &ansi, TRUE))
2752
EXIT2(return NDIS_STATUS_RESOURCES);
2754
EXIT2(return NDIS_STATUS_SUCCESS);
2757
wstdcall NDIS_STATUS WIN_FUNC(NdisWriteEventLogEntry,7)
2758
(void *handle, NDIS_STATUS code, ULONG value, USHORT n,
2759
void *strings, ULONG datasize, void *data)
2761
TRACE1("0x%x, 0x%x, %u, %u", code, value, n, datasize);
2762
return NDIS_STATUS_SUCCESS;
2765
wstdcall void *WIN_FUNC(NdisGetRoutineAddress,1)
2766
(struct unicode_string *unicode_string)
2768
struct ansi_string ansi_string;
2771
if (RtlUnicodeStringToAnsiString(&ansi_string, unicode_string, TRUE) !=
2774
INFO("%s", ansi_string.buf);
2775
address = ndis_get_routine_address(ansi_string.buf);
2776
RtlFreeAnsiString(&ansi_string);
2780
wstdcall ULONG WIN_FUNC(NdisReadPcmciaAttributeMemory,4)
2781
(struct ndis_mp_block *nmb, ULONG offset, void *buffer,
2788
wstdcall ULONG WIN_FUNC(NdisWritePcmciaAttributeMemory,4)
2789
(struct ndis_mp_block *nmb, ULONG offset, void *buffer,
2796
wstdcall void WIN_FUNC(NdisMCoIndicateReceivePacket,3)
2797
(struct ndis_mp_block *nmb, struct ndis_packet **packets,
2800
ENTER3("nmb = %p", nmb);
2801
NdisMIndicateReceivePacket(nmb, packets, nr_packets);
2805
wstdcall void WIN_FUNC(NdisMCoSendComplete,3)
2806
(NDIS_STATUS status, struct ndis_mp_block *nmb,
2807
struct ndis_packet *packet)
2809
ENTER3("%08x", status);
2810
NdisMSendComplete(nmb, packet, status);
2814
wstdcall void WIN_FUNC(NdisMCoRequestComplete,3)
2815
(NDIS_STATUS status, struct ndis_mp_block *nmb,
2816
struct ndis_request *ndis_request)
2818
struct ndis_device *wnd = nmb->wnd;
2819
typeof(wnd->ndis_req_task) task;
2821
ENTER3("%08X", status);
2822
wnd->ndis_req_status = status;
2823
wnd->ndis_req_done = 1;
2824
if ((task = xchg(&wnd->ndis_req_task, NULL)))
2825
wake_up_process(task);
2827
WARNING("invalid task");
2831
wstdcall NDIS_STATUS WIN_FUNC(NdisIMNotifiyPnPEvent,2)
2832
(struct ndis_mp_block *nmb, struct net_pnp_event *event)
2834
ENTER2("%p, %d", nmb, event->code);
2835
/* NdisWrapper never calls protocol's pnp event notifier, so
2836
* nothing to do here */
2837
EXIT2(return NDIS_STATUS_SUCCESS);
2840
wstdcall void WIN_FUNC(NdisCompletePnPEvent,2)
2841
(NDIS_STATUS status, void *handle, struct net_pnp_event *event)
2843
ENTER2("%d, %p, %d", status, handle, event->code);
2844
/* NdisWrapper never calls protocol's pnp event notifier, so
2845
* nothing to do here */
2849
wstdcall NDIS_STATUS WIN_FUNC(NdisMSetMiniportSecondary,2)
2850
(struct ndis_mp_block *nmb2, struct ndis_mp_block *nmb1)
2852
ENTER3("%p, %p", nmb1, nmb2);
2854
EXIT3(return NDIS_STATUS_SUCCESS);
2857
wstdcall NDIS_STATUS WIN_FUNC(NdisMPromoteMiniport,1)
2858
(struct ndis_mp_block *nmb)
2862
EXIT3(return NDIS_STATUS_SUCCESS);
2865
wstdcall void WIN_FUNC(NdisMCoActivateVcComplete,3)
2866
(NDIS_STATUS status, void *handle, void *params)
2871
wstdcall void WIN_FUNC(NdisMCoDeactivateVcComplete,2)
2872
(NDIS_STATUS status, void *handle)
2877
wstdcall void WIN_FUNC(NdisMRemoveMiniport,1)
2883
static void *ndis_get_routine_address(char *name)
2887
for (i = 0; i < sizeof(ndis_exports) / sizeof(ndis_exports[0]); i++) {
2888
if (strcmp(name, ndis_exports[i].name) == 0) {
2889
TRACE2("%p", ndis_exports[i].func);
2890
return ndis_exports[i].func;
2896
/* ndis_init_device is called for each device */
2897
int ndis_init_device(struct ndis_device *wnd)
2899
struct ndis_mp_block *nmb = wnd->nmb;
2901
KeInitializeSpinLock(&nmb->lock);
2902
wnd->mp_interrupt = NULL;
2903
wnd->wrap_timer_slist.next = NULL;
2904
if (wnd->wd->driver->ndis_driver)
2905
wnd->wd->driver->ndis_driver->mp.shutdown = NULL;
2907
nmb->filterdbs.eth_db = nmb;
2908
nmb->filterdbs.tr_db = nmb;
2909
nmb->filterdbs.fddi_db = nmb;
2910
nmb->filterdbs.arc_db = nmb;
2912
nmb->rx_packet = WIN_FUNC_PTR(NdisMIndicateReceivePacket,3);
2913
nmb->send_complete = WIN_FUNC_PTR(NdisMSendComplete,3);
2914
nmb->send_resource_avail = WIN_FUNC_PTR(NdisMSendResourcesAvailable,1);
2915
nmb->status = WIN_FUNC_PTR(NdisMIndicateStatus,4);
2916
nmb->status_complete = WIN_FUNC_PTR(NdisMIndicateStatusComplete,1);
2917
nmb->queryinfo_complete = WIN_FUNC_PTR(NdisMQueryInformationComplete,2);
2918
nmb->setinfo_complete = WIN_FUNC_PTR(NdisMSetInformationComplete,2);
2919
nmb->reset_complete = WIN_FUNC_PTR(NdisMResetComplete,3);
2920
nmb->eth_rx_indicate = WIN_FUNC_PTR(EthRxIndicateHandler,8);
2921
nmb->eth_rx_complete = WIN_FUNC_PTR(EthRxComplete,1);
2922
nmb->td_complete = WIN_FUNC_PTR(NdisMTransferDataComplete,4);
2926
/* ndis_exit_device is called for each device */
2927
void ndis_exit_device(struct ndis_device *wnd)
2929
struct wrap_device_setting *setting;
2931
if (down_interruptible(&loader_mutex))
2932
WARNING("couldn't obtain loader_mutex");
2933
nt_list_for_each_entry(setting, &wnd->wd->settings, list) {
2934
struct ndis_configuration_parameter *param;
2935
param = setting->encoded;
2937
if (param->type == NdisParameterString)
2938
RtlFreeUnicodeString(¶m->data.string);
2940
setting->encoded = NULL;
2946
/* ndis_init is called once when module is loaded */
2949
InitializeListHead(&ndis_work_list);
2950
spin_lock_init(&ndis_work_list_lock);
2951
initialize_work(&ndis_work, ndis_worker, NULL);
2953
ndis_wq = create_singlethread_workqueue("ndis_wq");
2955
WARNING("couldn't create worker thread");
2956
EXIT1(return -ENOMEM);
2959
ndis_worker_thread = wrap_worker_init(ndis_wq);
2960
TRACE1("%p", ndis_worker_thread);
2964
/* ndis_exit is called once when module is removed */
2965
void ndis_exit(void)
2969
destroy_workqueue(ndis_wq);
2970
TRACE1("%p", ndis_worker_thread);
2971
if (ndis_worker_thread)
2972
ObDereferenceObject(ndis_worker_thread);