212
185
return miniport_set_info(wnd, oid, &data, sizeof(data));
188
/* MiniportPnPEventNotify */
189
static NDIS_STATUS miniport_pnp_event(struct wrap_ndis_device *wnd,
190
enum ndis_device_pnp_event event)
192
struct miniport_char *miniport;
193
enum ndis_power_profile power_profile;
195
TRACEENTER1("%p, %d", wnd, event);
196
/* RNDIS driver doesn't like to be notified if device is
198
if (!test_bit(HW_INITIALIZED, &wnd->hw_status))
199
TRACEEXIT1(return NDIS_STATUS_SUCCESS);
200
miniport = &wnd->wd->driver->ndis_driver->miniport;
202
case NdisDevicePnPEventSurpriseRemoved:
204
(wnd->attributes & NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK),
205
miniport->pnp_event_notify);
206
if ((wnd->attributes & NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK) &&
207
miniport->pnp_event_notify) {
208
DBGTRACE1("calling surprise_removed");
209
LIN2WIN4(miniport->pnp_event_notify,
210
wnd->nmb->adapter_ctx,
211
NdisDevicePnPEventSurpriseRemoved, NULL, 0);
213
DBGTRACE1("Windows driver %s doesn't support "
214
"MiniportPnpEventNotify for safe unplugging",
215
wnd->wd->driver->name);
216
return NDIS_STATUS_SUCCESS;
217
case NdisDevicePnPEventPowerProfileChanged:
218
if (!miniport->pnp_event_notify) {
219
DBGTRACE1("Windows driver %s doesn't support "
220
"MiniportPnpEventNotify",
221
wnd->wd->driver->name);
222
return NDIS_STATUS_FAILURE;
224
power_profile = NdisPowerProfileAcOnLine;
225
LIN2WIN4(miniport->pnp_event_notify, wnd->nmb->adapter_ctx,
226
NdisDevicePnPEventPowerProfileChanged,
227
&power_profile, (ULONG)sizeof(power_profile));
228
return NDIS_STATUS_SUCCESS;
230
WARNING("event %d not yet implemented", event);
231
return NDIS_STATUS_SUCCESS;
235
/* MiniportInitialize */
215
236
static NDIS_STATUS miniport_init(struct wrap_ndis_device *wnd)
217
238
NDIS_STATUS error_status, status;
218
239
UINT medium_index;
219
240
UINT medium_array[] = {NdisMedium802_3};
220
241
struct miniport_char *miniport;
242
struct ndis_pnp_capabilities pnp_capa;
222
244
TRACEENTER1("irql: %d", current_irql());
223
245
if (test_bit(HW_INITIALIZED, &wnd->hw_status)) {
224
ERROR("device %p already initialized!", wnd);
246
WARNING("device %p already initialized!", wnd);
225
247
return NDIS_STATUS_FAILURE;
228
250
if (!wnd->wd->driver->ndis_driver ||
229
251
!wnd->wd->driver->ndis_driver->miniport.init) {
230
ERROR("assuming WDM (non-NDIS) driver");
231
TRACEEXIT1(return NDIS_STATUS_SUCCESS);
252
WARNING("assuming WDM (non-NDIS) driver");
253
TRACEEXIT1(return NDIS_STATUS_NOT_RECOGNIZED);
233
255
miniport = &wnd->wd->driver->ndis_driver->miniport;
234
256
status = LIN2WIN6(miniport->init, &error_status,
244
266
/* Wait a little to let card power up otherwise ifup might
245
* fail after boot; USB devices seem to need long delays */
246
set_current_state(TASK_INTERRUPTIBLE);
247
schedule_timeout(HZ);
250
status = miniport_set_pm_state(wnd, NdisDeviceStateD0);
252
DBGTRACE1("setting power state to device %s returns %08X",
253
wnd->net_dev->name, status);
255
269
set_bit(HW_INITIALIZED, &wnd->hw_status);
256
set_bit(HW_AVAILABLE, &wnd->hw_status);
257
270
hangcheck_add(wnd);
258
stats_timer_add(wnd);
271
up(&wnd->ndis_comm_mutex);
272
up(&wnd->tx_ring_mutex);
273
/* the description about NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND is
274
* misleading/confusing; we just ignore it */
275
status = miniport_query_info(wnd, OID_PNP_CAPABILITIES,
276
&pnp_capa, sizeof(pnp_capa));
277
if (status == NDIS_STATUS_SUCCESS)
280
wnd->pm_capa = FALSE;
281
DBGTRACE1("%d", pnp_capa.wakeup_capa.min_magic_packet_wakeup);
259
282
TRACEEXIT1(return NDIS_STATUS_SUCCESS);
262
286
static void miniport_halt(struct wrap_ndis_device *wnd)
264
288
struct miniport_char *miniport;
266
290
TRACEENTER1("%p", wnd);
267
clear_bit(HW_AVAILABLE, &wnd->hw_status);
269
stats_timer_del(wnd);
270
if (!test_bit(HW_INITIALIZED, &wnd->hw_status)) {
291
/* semaphores may already be locked, e.g., during suspend or
292
* if device is suspended, but resume failed */
293
down_trylock(&wnd->ndis_comm_mutex);
294
down_trylock(&wnd->tx_ring_mutex);
295
if (test_bit(HW_INITIALIZED, &wnd->hw_status)) {
297
del_stats_timer(wnd);
298
miniport = &wnd->wd->driver->ndis_driver->miniport;
299
DBGTRACE1("halt: %p", miniport->miniport_halt);
300
LIN2WIN1(miniport->miniport_halt, wnd->nmb->adapter_ctx);
301
clear_bit(HW_INITIALIZED, &wnd->hw_status);
271
303
WARNING("device %p is not initialized - not halting", wnd);
274
miniport = &wnd->wd->driver->ndis_driver->miniport;
275
DBGTRACE1("driver halt is at %p", miniport->miniport_halt);
277
DBGTRACE2("task: %p, pid: %d", get_current(), get_current()->pid);
278
LIN2WIN1(miniport->miniport_halt, wnd->nmb->adapter_ctx);
279
clear_bit(HW_INITIALIZED, &wnd->hw_status);
281
304
TRACEEXIT1(return);
284
static NDIS_STATUS miniport_pnp_event(struct wrap_ndis_device *wnd,
285
enum ndis_device_pnp_event event)
307
static NDIS_STATUS miniport_set_power_state(struct wrap_ndis_device *wnd,
308
enum ndis_power_state state)
287
struct miniport_char *miniport;
290
miniport = &wnd->wd->driver->ndis_driver->miniport;
292
case NdisDevicePnPEventSurpriseRemoved:
294
test_bit(ATTR_SURPRISE_REMOVE, &wnd->attributes),
295
miniport->pnp_event_notify);
296
if (test_bit(ATTR_SURPRISE_REMOVE, &wnd->attributes) &&
297
miniport->pnp_event_notify) {
298
DBGTRACE1("calling surprise_removed");
299
LIN2WIN4(miniport->pnp_event_notify,
300
wnd->nmb->adapter_ctx,
301
NdisDevicePnPEventSurpriseRemoved, NULL, 0);
312
DBGTRACE1("%d", state);
313
if (state == NdisDeviceStateD0) {
314
status = NDIS_STATUS_SUCCESS;
315
if (test_and_clear_bit(HW_HALTED, &wnd->hw_status)) {
316
status = miniport_init(wnd);
317
if (status == NDIS_STATUS_SUCCESS) {
318
set_packet_filter(wnd, wnd->packet_filter);
319
set_multicast_list(wnd);
321
} else if (test_and_clear_bit(HW_SUSPENDED, &wnd->hw_status)) {
322
up(&wnd->ndis_comm_mutex);
323
status = miniport_set_int(wnd, OID_PNP_SET_POWER,
325
if (status == NDIS_STATUS_SUCCESS)
326
up(&wnd->tx_ring_mutex);
328
down_interruptible(&wnd->ndis_comm_mutex);
329
WARNING("%s: setting power to state %d failed? "
330
"%08X", wnd->net_dev->name, state,
333
if (wnd->ndis_wolopts &&
334
wrap_is_pci_bus(wnd->wd->dev_bus_type))
335
pci_enable_wake(wnd->wd->pci.pdev, PCI_D0, 0);
303
DBGTRACE1("Windows driver %s doesn't support "
304
"MiniportPnpEventNotify for safe unplugging",
305
wnd->wd->driver->name);
306
return NDIS_STATUS_SUCCESS;
307
case NdisDevicePnPEventPowerProfileChanged:
308
if (!miniport->pnp_event_notify) {
309
DBGTRACE1("Windows driver %s doesn't support "
310
"MiniportPnpEventNotify",
311
wnd->wd->driver->name);
312
337
return NDIS_STATUS_FAILURE;
314
pnp_info = NdisPowerProfileAcOnLine;
315
DBGTRACE2("calling pnp_event_notify");
316
LIN2WIN4(miniport->pnp_event_notify, wnd->nmb->adapter_ctx,
317
NdisDevicePnPEventPowerProfileChanged,
318
&pnp_info, (ULONG)sizeof(pnp_info));
319
return NDIS_STATUS_SUCCESS;
321
WARNING("event %d not yet implemented", event);
322
return NDIS_STATUS_SUCCESS;
339
if (status == NDIS_STATUS_SUCCESS) {
341
add_stats_timer(wnd);
343
if (netif_running(wnd->net_dev)) {
344
netif_device_attach(wnd->net_dev);
345
netif_wake_queue(wnd->net_dev);
347
netif_poll_enable(wnd->net_dev);
349
WARNING("%s: couldn't set power to state %d; device not"
350
" resumed", wnd->net_dev->name, state);
352
TRACEEXIT1(return status);
354
netif_poll_disable(wnd->net_dev);
355
if (netif_running(wnd->net_dev)) {
356
netif_tx_disable(wnd->net_dev);
357
netif_device_detach(wnd->net_dev);
359
if (down_interruptible(&wnd->tx_ring_mutex))
360
WARNING("couldn't lock tx_ring_mutex");
362
del_stats_timer(wnd);
363
status = NDIS_STATUS_NOT_SUPPORTED;
364
if (wnd->pm_capa == TRUE) {
365
enum ndis_power_state pm_state = state;
366
if (wnd->ndis_wolopts) {
367
status = miniport_set_int(wnd,
368
OID_PNP_ENABLE_WAKE_UP,
370
if (status == NDIS_STATUS_SUCCESS) {
371
if (wrap_is_pci_bus(wnd->wd->dev_bus_type))
372
pci_enable_wake(wnd->wd->pci.pdev,
375
WARNING("%s: couldn't enable WOL: %08x",
376
wnd->net_dev->name, status);
378
status = miniport_set_int(wnd, OID_PNP_SET_POWER,
380
if (status == NDIS_STATUS_SUCCESS) {
381
set_bit(HW_SUSPENDED, &wnd->hw_status);
382
if (down_interruptible(&wnd->ndis_comm_mutex))
383
WARNING("couldn't lock ndis_comm_mutex");
385
WARNING("suspend failed: %08X", status);
387
if (status != NDIS_STATUS_SUCCESS) {
388
WARNING("%s does not support power management; "
389
"halting the device", wnd->net_dev->name);
390
/* TODO: should we use pnp_stop_device instead? */
392
set_bit(HW_HALTED, &wnd->hw_status);
393
status = STATUS_SUCCESS;
395
TRACEEXIT1(return status);
327
* query functions may not be called from this function as they might
328
* sleep which is not allowed from the context this function is
331
static struct net_device_stats *ndis_get_stats(struct net_device *dev)
333
struct wrap_ndis_device *wnd = netdev_priv(dev);
337
static int ndis_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
344
* This function is called fom BH context
346
static void ndis_set_multicast_list(struct net_device *dev)
348
struct wrap_ndis_device *wnd = netdev_priv(dev);
349
set_bit(SET_MULTICAST_LIST, &wnd->wrap_ndis_work);
350
schedule_work(&wnd->wrap_ndis_worker);
353
399
static int ndis_set_mac_addr(struct net_device *dev, void *p)
355
401
struct wrap_ndis_device *wnd = netdev_priv(dev);
400
440
TRACEEXIT1(return 0);
403
static void show_supported_oids(struct wrap_ndis_device *wnd)
412
res = miniport_query_info_needed(wnd, OID_GEN_SUPPORTED_LIST, NULL, 0,
414
if (!(res == NDIS_STATUS_BUFFER_TOO_SHORT ||
415
res == NDIS_STATUS_INVALID_LENGTH))
417
oids = kmalloc(needed, GFP_KERNEL);
419
DBGTRACE1("couldn't allocate memory");
422
res = miniport_query_info(wnd, OID_GEN_SUPPORTED_LIST, oids, needed);
424
DBGTRACE1("failed: %08X", res);
428
for (i = 0, n = needed / sizeof(*oids); i < n; i++)
429
DBGTRACE1("oid: %08X", oids[i]);
434
static struct ndis_packet *
435
allocate_send_packet(struct wrap_ndis_device *wnd, ndis_buffer *buffer)
443
static struct ndis_packet *alloc_tx_packet(struct wrap_ndis_device *wnd,
437
446
struct ndis_packet *packet;
438
448
struct ndis_packet_oob_data *oob_data;
439
449
NDIS_STATUS status;
441
NdisAllocatePacket(&status, &packet, wnd->wrapper_packet_pool);
451
NdisAllocatePacket(&status, &packet, wnd->tx_packet_pool);
442
452
if (status != NDIS_STATUS_SUCCESS)
454
NdisAllocateBuffer(&status, &buffer, wnd->tx_buffer_pool,
455
skb->data, skb->len);
456
if (status != NDIS_STATUS_SUCCESS) {
457
NdisFreePacket(packet);
445
460
packet->private.buffer_head = buffer;
446
461
packet->private.buffer_tail = buffer;
448
463
oob_data = NDIS_PACKET_OOB_DATA(packet);
449
465
if (wnd->use_sg_dma) {
450
466
oob_data->ndis_sg_element.address =
451
PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev,
452
MmGetMdlVirtualAddress(buffer),
453
MmGetMdlByteCount(buffer),
456
oob_data->ndis_sg_element.length = MmGetMdlByteCount(buffer);
467
PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev, skb->data,
468
skb->len, PCI_DMA_TODEVICE);
469
oob_data->ndis_sg_element.length = skb->len;
457
470
oob_data->ndis_sg_list.nent = 1;
458
471
oob_data->ndis_sg_list.elements = &oob_data->ndis_sg_element;
459
472
oob_data->extension.info[ScatterGatherListPacketInfo] =
460
473
&oob_data->ndis_sg_list;
476
if (wnd->tx_csum_info.value)
477
oob_data->extension.info[TcpIpChecksumPacketInfo] =
481
dump_bytes(__FUNCTION__, skb->data, skb->len);
483
DBGTRACE4("packet: %p, buffer: %p, skb: %p", packet, buffer, skb);
465
static void free_send_packet(struct wrap_ndis_device *wnd,
466
struct ndis_packet *packet)
487
void free_tx_packet(struct wrap_ndis_device *wnd, struct ndis_packet *packet,
468
490
ndis_buffer *buffer;
469
491
struct ndis_packet_oob_data *oob_data;
471
TRACEENTER3("packet: %p", packet);
473
ERROR("illegal packet from %p", wnd);
494
TRACEENTER3("%p, %08X", packet, status);
495
irql = nt_spin_lock_irql(&wnd->tx_stats_lock, DISPATCH_LEVEL);
496
if (status == NDIS_STATUS_SUCCESS) {
497
wnd->stats.tx_bytes += packet->private.len;
498
wnd->stats.tx_packets++;
500
DBGTRACE1("packet dropped: %08X", status);
501
wnd->stats.tx_dropped++;
477
buffer = packet->private.buffer_head;
503
nt_spin_unlock_irql(&wnd->tx_stats_lock, irql);
478
504
oob_data = NDIS_PACKET_OOB_DATA(packet);
479
505
if (wnd->use_sg_dma)
480
506
PCI_DMA_UNMAP_SINGLE(wnd->wd->pci.pdev,
481
507
oob_data->ndis_sg_element.address,
482
508
oob_data->ndis_sg_element.length,
483
509
PCI_DMA_TODEVICE);
510
buffer = packet->private.buffer_head;
485
511
DBGTRACE3("freeing buffer %p", buffer);
486
512
NdisFreeBuffer(buffer);
487
dev_kfree_skb(oob_data->skb);
514
dev_kfree_skb_any(oob_data->skb);
489
515
DBGTRACE3("freeing packet %p", packet);
490
516
NdisFreePacket(packet);
491
517
TRACEEXIT3(return);
495
* MiniportSend and MiniportSendPackets
496
* this function is called with lock held in DISPATCH_LEVEL, so no need
497
* to raise irql to DISPATCH_LEVEL during MiniportSend(Packets)
499
static int send_packets(struct wrap_ndis_device *wnd, unsigned int start,
500
unsigned int pending)
520
/* MiniportSend and MiniportSendPackets */
521
/* this function is called holding tx_ring_mutex, so safe to read
522
* tx_ring_start (tx_ring_end is not updated in tx_worker or here, so
523
* safe to read tx_ring_end, too) without lock */
524
static int miniport_tx_packets(struct wrap_ndis_device *wnd)
503
527
struct miniport_char *miniport;
504
unsigned int sent, n;
528
int n, sent, start, end;
505
529
struct ndis_packet *packet;
507
TRACEENTER3("start: %d, pending: %d", start, pending);
508
532
miniport = &wnd->wd->driver->ndis_driver->miniport;
509
if (pending > wnd->max_send_packets)
510
n = wnd->max_send_packets;
533
start = wnd->tx_ring_start;
534
end = wnd->tx_ring_end;
535
/* end == start when ring is full: (TX_RING_SIZE - 1) number
536
* of packets are pending */
541
assert(wnd->is_tx_ring_full == 1);
542
n = TX_RING_SIZE - 1;
544
if (unlikely(n > wnd->max_tx_packets))
545
n = wnd->max_tx_packets;
546
DBGTRACE3("%d, %d, %d", n, start, end);
514
547
if (miniport->send_packets) {
516
/* copy packets from xmit ring to linear xmit array */
549
/* copy packets from tx ring to linear tx array */
517
550
for (i = 0; i < n; i++) {
518
int j = (start + i) % XMIT_RING_SIZE;
519
wnd->xmit_array[i] = wnd->xmit_ring[j];
551
int j = (start + i) % TX_RING_SIZE;
552
wnd->tx_array[i] = wnd->tx_ring[j];
521
LIN2WIN3(miniport->send_packets, wnd->nmb->adapter_ctx,
524
if (test_bit(ATTR_SERIALIZED, &wnd->attributes)) {
525
for (sent = 0; sent < n && wnd->send_ok; sent++) {
526
struct ndis_packet_oob_data *oob_data;
527
packet = wnd->xmit_array[sent];
554
if (wnd->attributes & NDIS_ATTRIBUTE_DESERIALIZE) {
555
LIN2WIN3(miniport->send_packets, wnd->nmb->adapter_ctx,
559
struct ndis_packet_oob_data *oob_data;
560
irql = raise_irql(DISPATCH_LEVEL);
561
LIN2WIN3(miniport->send_packets, wnd->nmb->adapter_ctx,
564
for (sent = 0; sent < n && wnd->tx_ok; sent++) {
565
packet = wnd->tx_array[sent];
528
566
oob_data = NDIS_PACKET_OOB_DATA(packet);
529
switch(oob_data->status) {
567
switch (xchg(&oob_data->status,
568
NDIS_STATUS_NOT_RECOGNIZED)) {
530
569
case NDIS_STATUS_SUCCESS:
531
sendpacket_done(wnd, packet);
570
free_tx_packet(wnd, packet,
571
NDIS_STATUS_SUCCESS);
533
573
case NDIS_STATUS_PENDING:
535
575
case NDIS_STATUS_RESOURCES:
577
/* resubmit this packet and
578
* the rest when resources
579
* become available */
538
582
case NDIS_STATUS_FAILURE:
583
free_tx_packet(wnd, packet,
584
NDIS_STATUS_FAILURE);
540
free_send_packet(wnd, packet);
587
ERROR("packet %p: invalid status",
589
free_tx_packet(wnd, packet,
595
DBGTRACE3("sent: %d(%d)", sent, n);
548
packet = wnd->xmit_ring[start];
549
res = LIN2WIN3(miniport->send, wnd->nmb->adapter_ctx,
553
case NDIS_STATUS_SUCCESS:
554
sendpacket_done(wnd, packet);
556
case NDIS_STATUS_PENDING:
558
case NDIS_STATUS_RESOURCES:
562
case NDIS_STATUS_FAILURE:
563
free_send_packet(wnd, packet);
598
irql = PASSIVE_LEVEL;
599
for (i = 0; i < n && wnd->tx_ok; i++) {
600
struct ndis_packet_oob_data *oob_data;
601
packet = wnd->tx_ring[(start + i) % TX_RING_SIZE];
602
oob_data = NDIS_PACKET_OOB_DATA(packet);
603
oob_data->status = NDIS_STATUS_NOT_RECOGNIZED;
604
if (!(wnd->attributes & NDIS_ATTRIBUTE_DESERIALIZE))
605
irql = raise_irql(DISPATCH_LEVEL);
606
res = LIN2WIN3(miniport->send, wnd->nmb->adapter_ctx,
607
packet, packet->private.flags);
608
if (!(wnd->attributes & NDIS_ATTRIBUTE_DESERIALIZE))
611
case NDIS_STATUS_SUCCESS:
612
free_tx_packet(wnd, packet, res);
614
case NDIS_STATUS_PENDING:
616
case NDIS_STATUS_RESOURCES:
618
/* resend this packet when resources
619
* become available */
622
case NDIS_STATUS_FAILURE:
623
free_tx_packet(wnd, packet, res);
626
ERROR("packet %p: invalid status: %08X",
567
633
TRACEEXIT3(return sent);
570
static void xmit_worker(void *param)
636
static void tx_worker(void *param)
572
638
struct wrap_ndis_device *wnd = (struct wrap_ndis_device *)param;
576
TRACEENTER3("send_ok %d", wnd->send_ok);
578
/* some drivers e.g., new RT2500 driver, crash if any packets
579
* are sent when the card is not associated */
580
irql = kspin_lock_irql(&wnd->xmit_lock, DISPATCH_LEVEL);
581
while (wnd->send_ok) {
582
if (wnd->xmit_ring_pending == 0)
584
n = send_packets(wnd, wnd->xmit_ring_start,
585
wnd->xmit_ring_pending);
586
wnd->xmit_ring_start =
587
(wnd->xmit_ring_start + n) % XMIT_RING_SIZE;
588
wnd->xmit_ring_pending -= n;
589
if (netif_queue_stopped(wnd->net_dev) && n > 0)
590
netif_wake_queue(wnd->net_dev);
641
TRACEENTER3("tx_ok %d", wnd->tx_ok);
643
if (down_interruptible(&wnd->tx_ring_mutex))
645
/* end == start if either ring is empty or full; in
646
* the latter case is_tx_ring_full is set */
647
if (wnd->tx_ring_end == wnd->tx_ring_start &&
648
!wnd->is_tx_ring_full) {
649
up(&wnd->tx_ring_mutex);
652
n = miniport_tx_packets(wnd);
655
(wnd->tx_ring_start + n) % TX_RING_SIZE;
656
wnd->is_tx_ring_full = 0;
657
if (netif_queue_stopped(wnd->net_dev))
658
netif_wake_queue(wnd->net_dev);
660
up(&wnd->tx_ring_mutex);
661
DBGTRACE3("%d, %d, %d", n, wnd->tx_ring_start,
592
kspin_unlock_irql(&wnd->xmit_lock, irql);
598
* Free and unmap packet created in xmit
600
void sendpacket_done(struct wrap_ndis_device *wnd, struct ndis_packet *packet)
604
TRACEENTER3("%p", packet);
605
irql = kspin_lock_irql(&wnd->send_packet_done_lock, DISPATCH_LEVEL);
606
wnd->stats.tx_bytes += packet->private.len;
607
wnd->stats.tx_packets++;
608
free_send_packet(wnd, packet);
609
kspin_unlock_irql(&wnd->send_packet_done_lock, irql);
614
* This function is called in BH disabled context and ndis drivers
615
* must have their send-functions called from sleepeable context so we
616
* just queue the packets up here and schedule a workqueue to run
619
static int start_xmit(struct sk_buff *skb, struct net_device *dev)
667
static int tx_skbuff(struct sk_buff *skb, struct net_device *dev)
621
669
struct wrap_ndis_device *wnd = netdev_priv(dev);
623
670
struct ndis_packet *packet;
624
struct ndis_packet_oob_data *oob_data;
625
unsigned int xmit_ring_next_slot;
628
NdisAllocateBuffer(&res, &buffer, wnd->wrapper_buffer_pool,
629
skb->data, skb->len);
630
if (res != NDIS_STATUS_SUCCESS)
632
packet = allocate_send_packet(wnd, buffer);
672
packet = alloc_tx_packet(wnd, skb);
634
NdisFreeBuffer(buffer);
674
WARNING("couldn't allocate packet");
675
return NETDEV_TX_BUSY;
637
oob_data = NDIS_PACKET_OOB_DATA(packet);
639
kspin_lock(&wnd->xmit_lock);
640
xmit_ring_next_slot = (wnd->xmit_ring_start +
641
wnd->xmit_ring_pending) % XMIT_RING_SIZE;
642
wnd->xmit_ring[xmit_ring_next_slot] = packet;
643
wnd->xmit_ring_pending++;
644
if (wnd->xmit_ring_pending == XMIT_RING_SIZE)
677
/* no need for lock here - already called holding
678
* net_dev->xmit_lock and tx_ring_end is not updated
680
wnd->tx_ring[wnd->tx_ring_end++] = packet;
681
if (wnd->tx_ring_end == TX_RING_SIZE)
682
wnd->tx_ring_end = 0;
683
if (wnd->tx_ring_end == wnd->tx_ring_start) {
684
wnd->is_tx_ring_full = 1;
645
685
netif_stop_queue(wnd->net_dev);
646
kspin_unlock(&wnd->xmit_lock);
648
schedule_work(&wnd->xmit_work);
687
DBGTRACE3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end);
688
schedule_wrap_work(&wnd->tx_work);
653
692
static int set_packet_filter(struct wrap_ndis_device *wnd, ULONG packet_filter)
656
ULONG filter = packet_filter;
658
TRACEENTER3("%x", packet_filter);
659
res = miniport_set_info(wnd, OID_GEN_CURRENT_PACKET_FILTER,
660
&filter, sizeof(filter));
662
DBGTRACE1("couldn't set packet filter: %08X", res);
663
TRACEEXIT3(return res);
697
res = miniport_set_int(wnd, OID_GEN_CURRENT_PACKET_FILTER,
699
if (res == NDIS_STATUS_SUCCESS)
701
DBGTRACE2("couldn't set filter 0x%08x", packet_filter);
702
/* NDIS_PACKET_TYPE_PROMISCUOUS may not work with 802.11 */
703
if (packet_filter & NDIS_PACKET_TYPE_PROMISCUOUS) {
704
packet_filter &= ~NDIS_PACKET_TYPE_PROMISCUOUS;
707
if (packet_filter & NDIS_PACKET_TYPE_ALL_LOCAL) {
708
packet_filter &= ~NDIS_PACKET_TYPE_ALL_LOCAL;
711
if (packet_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL) {
712
packet_filter &= ~NDIS_PACKET_TYPE_ALL_FUNCTIONAL;
715
if (packet_filter & NDIS_PACKET_TYPE_MULTICAST) {
716
packet_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
717
packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
720
if (packet_filter & NDIS_PACKET_TYPE_ALL_MULTICAST) {
721
packet_filter &= ~NDIS_PACKET_TYPE_ALL_MULTICAST;
665
727
wnd->packet_filter = packet_filter;
666
TRACEEXIT3(return 0);
669
static int get_packet_filter(struct wrap_ndis_device *wnd,
670
ULONG *packet_filter)
674
TRACEENTER3("%p", wnd);
675
res = miniport_query_info(wnd, OID_GEN_CURRENT_PACKET_FILTER,
676
packet_filter, sizeof(*packet_filter));
678
DBGTRACE1("couldn't get packet filter: %08X", res);
679
TRACEEXIT3(return res);
728
res = miniport_query_int(wnd, OID_GEN_CURRENT_PACKET_FILTER,
730
if (packet_filter != wnd->packet_filter) {
731
WARNING("filter not set: 0x%08x, 0x%08x",
732
packet_filter, wnd->packet_filter);
733
wnd->packet_filter = packet_filter;
681
TRACEEXIT3(return 0);
735
if (wnd->packet_filter)
736
TRACEEXIT3(return 0);
738
TRACEEXIT3(return -1);
684
741
static int ndis_open(struct net_device *dev)
767
#ifdef CONFIG_NET_POLL_CONTROLLER
768
static void ndis_poll_controller(struct net_device *dev)
770
struct wrap_ndis_device *wnd = netdev_priv(dev);
772
disable_irq(dev->irq);
773
if (wnd->ndis_irq->req_isr)
774
ndis_isr_shared(dev->irq, wnd, NULL);
776
ndis_isr_dynamic(dev->irq, wnd, NULL);
777
enable_irq(dev->irq);
781
/* this function is called fom BH context */
782
static struct net_device_stats *ndis_get_stats(struct net_device *dev)
784
struct wrap_ndis_device *wnd = netdev_priv(dev);
788
/* this function is called fom BH context */
789
static void ndis_set_multicast_list(struct net_device *dev)
791
struct wrap_ndis_device *wnd = netdev_priv(dev);
792
set_bit(SET_MULTICAST_LIST, &wnd->wrap_ndis_pending_work);
793
schedule_wrap_work(&wnd->wrap_ndis_work);
796
/* this function is called fom BH context */
797
struct iw_statistics *get_wireless_stats(struct net_device *dev)
799
struct wrap_ndis_device *wnd = netdev_priv(dev);
800
return &wnd->wireless_stats;
803
#if defined(HAVE_ETHTOOL)
804
static void ndis_get_drvinfo(struct net_device *dev,
805
struct ethtool_drvinfo *info)
807
struct wrap_ndis_device *wnd = netdev_priv(dev);
808
strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1);
809
strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);
810
strncpy(info->fw_version, wnd->wd->driver->version,
811
sizeof(info->fw_version) - 1);
812
if (wrap_is_pci_bus(wnd->wd->dev_bus_type))
813
strncpy(info->bus_info, pci_name(wnd->wd->pci.pdev),
814
sizeof(info->bus_info) - 1);
817
usb_make_path(wnd->wd->usb.udev, info->bus_info,
818
sizeof(info->bus_info) - 1);
823
static u32 ndis_get_link(struct net_device *dev)
825
struct wrap_ndis_device *wnd = netdev_priv(dev);
826
return wnd->link_status;
829
static void ndis_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
831
struct wrap_ndis_device *wnd = netdev_priv(dev);
832
if (wnd->ndis_wolopts & NDIS_PNP_WAKE_UP_MAGIC_PACKET)
833
wol->wolopts |= WAKE_MAGIC;
834
/* no other options supported */
838
static int ndis_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
840
struct wrap_ndis_device *wnd = netdev_priv(dev);
841
struct ndis_pnp_capabilities pnp_capa;
844
if (!(wol->wolopts & WAKE_MAGIC))
848
status = miniport_query_info(wnd, OID_PNP_CAPABILITIES,
849
&pnp_capa, sizeof(pnp_capa));
850
if (status != NDIS_STATUS_SUCCESS)
852
/* we always suspend to D3 */
853
DBGTRACE1("%d, %d", pnp_capa.wakeup_capa.min_magic_packet_wakeup,
854
pnp_capa.wakeup_capa.min_pattern_wakeup);
855
if (pnp_capa.wakeup_capa.min_magic_packet_wakeup != NdisDeviceStateD3)
857
/* no other options supported */
858
wnd->ndis_wolopts = NDIS_PNP_WAKE_UP_MAGIC_PACKET;
862
static struct ethtool_ops ndis_ethtool_ops = {
863
.get_drvinfo = ndis_get_drvinfo,
864
.get_link = ndis_get_link,
865
.get_wol = ndis_get_wol,
866
.set_wol = ndis_set_wol,
718
870
static void update_wireless_stats(struct wrap_ndis_device *wnd)
720
872
struct iw_statistics *iw_stats = &wnd->wireless_stats;
761
913
struct net_device *net_dev;
762
914
ULONG packet_filter;
765
917
net_dev = wnd->net_dev;
766
if (!(net_dev->mc_count > 0 ||
767
net_dev->flags & IFF_ALLMULTI))
918
packet_filter = wnd->packet_filter;
770
res = get_packet_filter(wnd, &packet_filter);
772
// WARNING("couldn't get packet filter: %08X", res);
920
DBGTRACE2("0x%08x", packet_filter);
921
if (net_dev->flags & IFF_PROMISC) {
922
packet_filter |= NDIS_PACKET_TYPE_PROMISCUOUS |
923
NDIS_PACKET_TYPE_ALL_LOCAL;
924
} else if (net_dev->flags & IFF_ALLMULTI ||
925
net_dev->mc_count > wnd->multicast_size) {
926
packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
927
DBGTRACE2("0x%08x", packet_filter);
928
} else if (net_dev->mc_count > 0) {
931
struct dev_mc_list *mclist;
932
size = min(wnd->multicast_size, net_dev->mc_count);
933
DBGTRACE2("%d, %d", wnd->multicast_size, net_dev->mc_count);
934
buf = kmalloc(size * ETH_ALEN, GFP_KERNEL);
936
WARNING("couldn't allocate memory");
939
mclist = net_dev->mc_list;
940
for (i = 0; i < size && mclist; mclist = mclist->next) {
941
if (mclist->dmi_addrlen != ETH_ALEN)
943
memcpy(buf + i * ETH_ALEN, mclist->dmi_addr, ETH_ALEN);
944
DBGTRACE2(MACSTR, MAC2STR(mclist->dmi_addr));
947
res = miniport_set_info(wnd, OID_802_3_MULTICAST_LIST,
949
if (res == NDIS_STATUS_SUCCESS && i > 0)
950
packet_filter |= NDIS_PACKET_TYPE_MULTICAST;
952
packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
776
packet_filter |= NDIS_PACKET_TYPE_MULTICAST;
777
packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
778
DBGTRACE2("packet filter: %08x", packet_filter);
955
DBGTRACE2("0x%08x", packet_filter);
779
956
res = set_packet_filter(wnd, packet_filter);
781
958
DBGTRACE1("couldn't set packet filter (%08X)", res);
783
959
TRACEEXIT2(return);
786
962
static void link_status_handler(struct wrap_ndis_device *wnd)
788
964
struct ndis_assoc_info *ndis_assoc_info;
789
#if WIRELESS_EXT < 18
965
union iwreq_data wrqu;
967
const int assoc_size = sizeof(*ndis_assoc_info) + IW_CUSTOM_MAX + 32;
968
#if WIRELESS_EXT <= 17
790
969
unsigned char *wpa_assoc_info, *ies;
791
970
unsigned char *p;
794
unsigned char *assoc_info;
795
union iwreq_data wrqu;
797
const int assoc_size = sizeof(*ndis_assoc_info) + IW_CUSTOM_MAX;
799
TRACEENTER2("link status: %d", wnd->link_status);
974
TRACEENTER2("link: %d", wnd->link_status);
975
if (wnd->physical_medium != NdisPhysicalMediumWirelessLan)
800
977
if (wnd->link_status == 0) {
803
struct encr_info *encr_info = &wnd->encr_info;
805
if (wnd->encr_mode == Ndis802_11Encryption1Enabled ||
806
wnd->infrastructure_mode == Ndis802_11IBSS) {
807
for (i = 0; i < MAX_ENCR_KEYS; i++) {
808
if (encr_info->keys[i].length == 0)
810
add_wep_key(wnd, encr_info->keys[i].key,
811
encr_info->keys[i].length, i);
814
set_bit(SET_ESSID, &wnd->wrap_ndis_work);
815
schedule_work(&wnd->wrap_ndis_worker);
818
/* TODO: not clear if NDIS says keys should
820
for (i = 0; i < MAX_ENCR_KEYS; i++)
821
wnd->encr_info.keys[i].length = 0;
824
979
memset(&wrqu, 0, sizeof(wrqu));
825
980
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
826
981
wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL);
827
982
TRACEEXIT2(return);
830
if (!(test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr) ||
831
test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr)))
834
assoc_info = kmalloc(assoc_size, GFP_KERNEL);
986
ndis_assoc_info = kmalloc(assoc_size, GFP_KERNEL);
987
if (!ndis_assoc_info) {
836
988
ERROR("couldn't allocate memory");
837
989
TRACEEXIT2(return);
839
memset(assoc_info, 0, assoc_size);
991
memset(ndis_assoc_info, 0, assoc_size);
841
ndis_assoc_info = (struct ndis_assoc_info *)assoc_info;
843
ndis_assoc_info->length = sizeof(*ndis_assoc_info);
844
ndis_assoc_info->offset_req_ies = sizeof(*ndis_assoc_info);
845
ndis_assoc_info->req_ie_length = IW_CUSTOM_MAX / 2;
846
ndis_assoc_info->offset_resp_ies = sizeof(*ndis_assoc_info) +
847
ndis_assoc_info->req_ie_length;
848
ndis_assoc_info->resp_ie_length = IW_CUSTOM_MAX / 2;
850
993
res = miniport_query_info(wnd, OID_802_11_ASSOCIATION_INFORMATION,
851
assoc_info, assoc_size);
994
ndis_assoc_info, assoc_size);
853
996
DBGTRACE2("query assoc_info failed (%08X)", res);
997
kfree(ndis_assoc_info);
855
998
TRACEEXIT2(return);
859
* TODO: backwards compatibility would require that IWEVCUSTOM
860
* is sent even if WIRELESS_EXT > 17. This version does not do
861
* this in order to allow wpa_supplicant to be tested with
864
1001
#if WIRELESS_EXT > 17
865
1002
memset(&wrqu, 0, sizeof(wrqu));
866
1003
wrqu.data.length = ndis_assoc_info->req_ie_length;
867
1004
wireless_send_event(wnd->net_dev, IWEVASSOCREQIE, &wrqu,
868
((char *) ndis_assoc_info) +
1005
((char *)ndis_assoc_info) +
869
1006
ndis_assoc_info->offset_req_ies);
870
1007
wrqu.data.length = ndis_assoc_info->resp_ie_length;
871
1008
wireless_send_event(wnd->net_dev, IWEVASSOCRESPIE, &wrqu,
872
((char *) ndis_assoc_info) +
1009
((char *)ndis_assoc_info) +
873
1010
ndis_assoc_info->offset_resp_ies);
875
1012
/* we need 28 extra bytes for the format strings */
1242
1309
NTSTATUS status;
1243
1310
NDIS_STATUS ndis_status;
1245
1314
irp_sl = IoGetCurrentIrpStackLocation(irp);
1246
1315
wnd = fdo->reserved;
1247
1316
IOTRACE("fdo: %p, fn: %d:%d, wnd: %p", fdo, irp_sl->major_fn,
1248
1317
irp_sl->minor_fn, wnd);
1249
if (irp_sl->params.power.state.device_state == PowerDeviceD0)
1318
if ((irp_sl->params.power.type == SystemPowerState &&
1319
irp_sl->params.power.state.system_state > PowerSystemWorking) ||
1320
(irp_sl->params.power.type == DevicePowerState &&
1321
irp_sl->params.power.state.device_state > PowerDeviceD0))
1322
state = NdisDeviceStateD3;
1250
1324
state = NdisDeviceStateD0;
1252
state = NdisDeviceStateD3;
1253
1325
switch (irp_sl->minor_fn) {
1254
1326
case IRP_MN_SET_POWER:
1255
1327
if (state == NdisDeviceStateD0) {
1256
IoCopyCurrentIrpStackLocationToNext(irp);
1257
IoSetCompletionRoutine(irp, IrpStopCompletion, wnd,
1258
TRUE, FALSE, FALSE);
1259
status = IoCallDriver(wnd->nmb->pdo, irp);
1328
status = LIN2WIN2(IoSyncForwardIrp, wnd->nmb->pdo, irp);
1260
1329
if (status != STATUS_SUCCESS)
1262
1331
ndis_status = miniport_set_power_state(wnd, state);
1263
1332
if (ndis_status != NDIS_STATUS_SUCCESS)
1264
WARNING("setting power to %d failed: %08X",
1333
WARNING("couldn't set power to %d: %08X",
1265
1334
state, ndis_status);
1267
stats_timer_add(wnd);
1269
set_bit(SET_ESSID, &wnd->wrap_ndis_work);
1270
if (netif_running(wnd->net_dev)) {
1271
netif_device_attach(wnd->net_dev);
1272
netif_wake_queue(wnd->net_dev);
1274
netif_poll_enable(wnd->net_dev);
1275
1335
DBGTRACE2("%s: device resumed", wnd->net_dev->name);
1276
TRACEEXIT2(return STATUS_SUCCESS);
1336
irp->io_status.status = status = STATUS_SUCCESS;
1337
IoCompleteRequest(irp, IO_NO_INCREMENT);
1278
if (test_bit(HW_SUSPENDED, &wnd->hw_status) ||
1279
test_bit(HW_HALTED, &wnd->hw_status))
1280
return STATUS_FAILURE;
1281
DBGTRACE2("irql: %d", current_irql());
1282
netif_poll_disable(wnd->net_dev);
1283
if (netif_running(wnd->net_dev)) {
1284
netif_tx_disable(wnd->net_dev);
1285
netif_device_detach(wnd->net_dev);
1288
stats_timer_del(wnd);
1289
1340
ndis_status = miniport_set_power_state(wnd, state);
1290
/* TODO: we need to send the IRP back with
1291
* error so that pdo can restart device */
1341
/* TODO: handle error case */
1292
1342
if (ndis_status != NDIS_STATUS_SUCCESS)
1293
1343
WARNING("setting power to %d failed: %08X",
1294
1344
state, ndis_status);
1295
return IopPassIrpDown(wnd->nmb->pdo, irp);
1345
status = LIN2WIN2(IoAsyncForwardIrp, wnd->nmb->pdo, irp);
1297
status = STATUS_SUCCESS;
1299
1348
case IRP_MN_QUERY_POWER:
1300
ndis_status = miniport_query_int(wnd, OID_PNP_QUERY_POWER,
1302
DBGTRACE2("query_power to state %d returns %08X",
1303
state, ndis_status);
1304
if (ndis_status == NDIS_STATUS_SUCCESS)
1305
status = STATUS_SUCCESS;
1307
status = STATUS_FAILURE;
1350
ndis_status = miniport_query_info(wnd,
1351
OID_PNP_QUERY_POWER,
1352
&state, sizeof(state));
1353
DBGTRACE2("%d, %08X", state, ndis_status);
1354
/* this OID must always succeed */
1355
if (ndis_status != NDIS_STATUS_SUCCESS)
1356
DBGTRACE1("query power returns %08X",
1358
irp->io_status.status = STATUS_SUCCESS;
1360
irp->io_status.status = STATUS_SUCCESS;
1361
status = LIN2WIN2(IoPassIrpDown, wnd->nmb->pdo, irp);
1309
1363
case IRP_MN_WAIT_WAKE:
1310
1364
case IRP_MN_POWER_SEQUENCE:
1311
1365
/* TODO: implement WAIT_WAKE */
1312
status = STATUS_NOT_SUPPORTED;
1366
status = LIN2WIN2(IoPassIrpDown, wnd->nmb->pdo, irp);
1315
return IopPassIrpDown(wnd->nmb->pdo, irp);
1369
status = LIN2WIN2(IoPassIrpDown, wnd->nmb->pdo, irp);
1317
irp->io_status.status_info = 0;
1318
irp->io_status.status = status;
1319
IoCompleteRequest(irp, IO_NO_INCREMENT);
1372
IOEXIT(return status);
1323
STDCALL NTSTATUS NdisDispatchPnp(struct device_object *fdo,
1375
/* called as Windows function, so call WIN2LIN2 before accessing
1377
wstdcall NTSTATUS NdisDispatchPnp(struct device_object *fdo, struct irp *irp)
1326
1379
struct io_stack_location *irp_sl;
1327
1380
struct wrap_ndis_device *wnd;
1328
1381
struct device_object *pdo;
1329
1382
NTSTATUS status;
1331
IOENTER("fdo: %p, irp: %p", fdo, irp);
1386
IOTRACE("fdo: %p, irp: %p", fdo, irp);
1332
1387
irp_sl = IoGetCurrentIrpStackLocation(irp);
1333
1388
wnd = fdo->reserved;
1334
1389
pdo = wnd->nmb->pdo;
1335
IOTRACE("fn %d:%d, wnd: %p, fdo: %p, pdo: %p",
1336
irp_sl->major_fn, irp_sl->minor_fn, wnd, fdo, pdo);
1337
1390
switch (irp_sl->minor_fn) {
1338
1391
case IRP_MN_START_DEVICE:
1339
IoCopyCurrentIrpStackLocationToNext(irp);
1340
IoSetCompletionRoutine(irp, IrpStopCompletion, wnd, TRUE,
1342
status = IoCallDriver(pdo, irp);
1392
status = LIN2WIN2(IoSyncForwardIrp, pdo, irp);
1343
1393
if (status != STATUS_SUCCESS)
1345
1395
if (ndis_start_device(wnd) == NDIS_STATUS_SUCCESS)
1346
1396
status = STATUS_SUCCESS;
1348
1398
status = STATUS_FAILURE;
1399
irp->io_status.status = status;
1400
IoCompleteRequest(irp, IO_NO_INCREMENT);
1350
1402
case IRP_MN_QUERY_STOP_DEVICE:
1351
return IopPassIrpDown(pdo, irp);
1403
/* TODO: implement in NDIS */
1404
status = LIN2WIN2(IoPassIrpDown, wnd->nmb->pdo, irp);
1352
1406
case IRP_MN_STOP_DEVICE:
1353
1407
miniport_halt(wnd);
1354
return IopPassIrpDown(pdo, irp);
1408
irp->io_status.status = STATUS_SUCCESS;
1409
status = LIN2WIN2(IoAsyncForwardIrp, pdo, irp);
1355
1411
case IRP_MN_REMOVE_DEVICE:
1356
1412
DBGTRACE1("%s", wnd->net_dev->name);
1357
if (ndis_remove_device(wnd) != NDIS_STATUS_SUCCESS) {
1413
if (wnd->wd->surprise_removed == TRUE)
1414
miniport_pnp_event(wnd,
1415
NdisDevicePnPEventSurpriseRemoved);
1416
if (ndis_remove_device(wnd)) {
1358
1417
status = STATUS_FAILURE;
1361
return IopPassIrpDown(pdo, irp);
1420
/* wnd is already freed */
1421
status = LIN2WIN2(IoAsyncForwardIrp, pdo, irp);
1422
IoDetachDevice(fdo);
1423
IoDeleteDevice(fdo);
1363
return IopPassIrpDown(pdo, irp);
1365
irp->io_status.status = status;
1366
IOTRACE("res: %08X", status);
1367
IoCompleteRequest(irp, IO_NO_INCREMENT);
1426
status = LIN2WIN2(IoAsyncForwardIrp, pdo, irp);
1429
IOTRACE("status: %08X", status);
1430
IOEXIT(return status);
1433
static int set_task_offload(struct wrap_ndis_device *wnd, void *buf,
1437
struct ndis_task_offload_header *task_offload_header;
1438
struct ndis_task_offload *task_offload;
1439
struct ndis_task_tcp_ip_checksum *task_tcp_ip_csum = NULL;
1440
struct ndis_task_tcp_ip_checksum csum;
1443
memset(buf, 0, buf_size);
1444
task_offload_header = buf;
1445
task_offload_header->version = NDIS_TASK_OFFLOAD_VERSION;
1446
task_offload_header->size = sizeof(*task_offload_header);
1447
task_offload_header->encapsulation_format.encapsulation =
1448
IEEE_802_3_Encapsulation;
1449
status = miniport_query_info(wnd, OID_TCP_TASK_OFFLOAD, buf, buf_size);
1450
DBGTRACE1("%08X", status);
1451
if (status != NDIS_STATUS_SUCCESS)
1452
TRACEEXIT1(return -1);
1453
if (task_offload_header->offset_first_task == 0)
1454
TRACEEXIT1(return -1);
1455
task_offload = ((void *)task_offload_header +
1456
task_offload_header->offset_first_task);
1458
DBGTRACE1("%d, %d", task_offload->version, task_offload->task);
1459
switch(task_offload->task) {
1460
case TcpIpChecksumNdisTask:
1461
task_tcp_ip_csum = (void *)task_offload->task_buf;
1464
DBGTRACE1("%d", task_offload->task);
1467
if (task_offload->offset_next_task == 0)
1469
task_offload = (void *)task_offload +
1470
task_offload->offset_next_task;
1472
if (!task_tcp_ip_csum)
1473
TRACEEXIT1(return -1);
1474
memcpy(&csum, task_tcp_ip_csum, sizeof(csum));
1476
task_offload_header->encapsulation_format.flags.fixed_header_size = 1;
1477
task_offload_header->encapsulation_format.header_size =
1478
sizeof(struct ethhdr);
1479
task_offload_header->offset_first_task = sizeof(*task_offload_header);
1480
task_offload = ((void *)task_offload_header +
1481
task_offload_header->offset_first_task);
1482
memcpy(task_offload->task_buf, &csum, sizeof(csum));
1483
task_offload->offset_next_task = 0;
1484
task_offload->size = sizeof(*task_offload);
1485
task_offload->task = TcpIpChecksumNdisTask;
1486
task_offload->task_buf_length = sizeof(csum);
1487
status = miniport_set_info(wnd, OID_TCP_TASK_OFFLOAD,
1488
task_offload_header,
1489
sizeof(*task_offload_header) +
1490
sizeof(*task_offload) + sizeof(csum));
1491
DBGTRACE1("%08X", status);
1492
if (status != NDIS_STATUS_SUCCESS)
1493
TRACEEXIT2(return -1);
1494
DBGTRACE1("%08x, %08x", csum.v4_tx.value, csum.v4_rx.value);
1495
if (csum.v4_tx.ip_csum) {
1496
wnd->tx_csum_info.tx.v4 = 1;
1497
if (csum.v4_tx.tcp_csum && csum.v4_tx.udp_csum) {
1498
wnd->net_dev->features |= NETIF_F_HW_CSUM;
1499
wnd->tx_csum_info.tx.tcp = 1;
1500
wnd->tx_csum_info.tx.ip = 1;
1501
wnd->tx_csum_info.tx.udp = 1;
1502
DBGTRACE1("hw_csum");
1504
wnd->net_dev->features |= NETIF_F_IP_CSUM;
1505
wnd->tx_csum_info.tx.ip = 1;
1506
DBGTRACE1("ip_csum");
1509
wnd->rx_csum = csum.v4_rx;
1511
TRACEEXIT1(return 0);
1514
static void get_supported_oids(struct wrap_ndis_device *wnd)
1520
res = miniport_query_info_needed(wnd, OID_GEN_SUPPORTED_LIST, NULL, 0,
1522
if (!(res == NDIS_STATUS_BUFFER_TOO_SHORT ||
1523
res == NDIS_STATUS_INVALID_LENGTH))
1525
oids = kmalloc(needed, GFP_KERNEL);
1527
DBGTRACE1("couldn't allocate memory");
1530
res = miniport_query_info(wnd, OID_GEN_SUPPORTED_LIST, oids, needed);
1532
DBGTRACE1("failed: %08X", res);
1536
for (i = 0, n = needed / sizeof(*oids); i < n; i++) {
1537
DBGTRACE1("oid: %08X", oids[i]);
1538
/* if a wireless device didn't say so for
1539
* OID_GEN_PHYSICAL_MEDIUM (they should, but in case) */
1540
if (wnd->physical_medium != NdisPhysicalMediumWirelessLan &&
1541
oids[i] == OID_802_11_SSID)
1542
wnd->physical_medium = NdisPhysicalMediumWirelessLan;
1371
1548
static NDIS_STATUS ndis_start_device(struct wrap_ndis_device *wnd)
1373
1550
struct wrap_device *wd;
1374
1551
struct net_device *net_dev;
1375
1552
NDIS_STATUS ndis_status;
1554
const int buf_size = 256;
1376
1555
mac_address mac;
1379
if (miniport_init(wnd) != NDIS_STATUS_SUCCESS)
1380
return NDIS_STATUS_FAILURE;
1381
/* NB: xmit_array is used to recognize if device is being
1557
ndis_status = miniport_init(wnd);
1558
if (ndis_status == NDIS_STATUS_NOT_RECOGNIZED)
1559
TRACEEXIT1(return NDIS_STATUS_SUCCESS);
1560
if (ndis_status != NDIS_STATUS_SUCCESS)
1561
TRACEEXIT1(return ndis_status);
1562
/* NB: tx_array is used to recognize if device is being
1382
1563
* started for the first time or being re-started */
1383
if (wnd->xmit_array)
1384
1565
TRACEEXIT2(return NDIS_STATUS_SUCCESS);
1386
1567
net_dev = wnd->net_dev;
1387
show_supported_oids(wnd);
1388
strncpy(net_dev->name, if_name, IFNAMSIZ-1);
1389
net_dev->name[IFNAMSIZ-1] = '\0';
1391
DBGTRACE1("%s: querying for mac", DRIVER_NAME);
1569
ndis_status = miniport_query_int(wnd, OID_GEN_PHYSICAL_MEDIUM,
1570
&wnd->physical_medium);
1571
if (ndis_status != NDIS_STATUS_SUCCESS)
1572
wnd->physical_medium = NdisPhysicalMediumUnspecified;
1574
get_supported_oids(wnd);
1575
strncpy(net_dev->name, if_name, IFNAMSIZ - 1);
1576
net_dev->name[IFNAMSIZ - 1] = '\0';
1392
1578
ndis_status = miniport_query_info(wnd, OID_802_3_CURRENT_ADDRESS,
1393
1579
mac, sizeof(mac));
1394
1580
if (ndis_status) {
1395
1581
ERROR("couldn't get mac address: %08X", ndis_status);
1398
1584
DBGTRACE1("mac:" MACSTR, MAC2STR(mac));
1399
1585
memcpy(&net_dev->dev_addr, mac, ETH_ALEN);
1401
1587
net_dev->open = ndis_open;
1402
net_dev->hard_start_xmit = start_xmit;
1588
net_dev->hard_start_xmit = tx_skbuff;
1403
1589
net_dev->stop = ndis_close;
1404
1590
net_dev->get_stats = ndis_get_stats;
1405
net_dev->do_ioctl = ndis_ioctl;
1591
net_dev->do_ioctl = NULL;
1592
if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {
1406
1593
#if WIRELESS_EXT < 19
1407
net_dev->get_wireless_stats = get_wireless_stats;
1594
net_dev->get_wireless_stats = get_wireless_stats;
1409
net_dev->wireless_handlers =
1410
(struct iw_handler_def *)&ndis_handler_def;
1596
net_dev->wireless_handlers = &ndis_handler_def;
1411
1599
net_dev->set_multicast_list = ndis_set_multicast_list;
1412
1600
net_dev->set_mac_address = ndis_set_mac_addr;
1601
#if defined(HAVE_ETHTOOL)
1414
1602
net_dev->ethtool_ops = &ndis_ethtool_ops;
1416
1604
if (wnd->ndis_irq)
1417
1605
net_dev->irq = wnd->ndis_irq->irq.irq;
1418
1606
net_dev->mem_start = wnd->mem_start;
1419
1607
net_dev->mem_end = wnd->mem_end;
1608
ndis_status = miniport_query_int(wnd, OID_802_3_MAXIMUM_LIST_SIZE,
1609
&wnd->multicast_size);
1610
if (ndis_status != NDIS_STATUS_SUCCESS || wnd->multicast_size < 0)
1611
wnd->multicast_size = 0;
1612
if (wnd->multicast_size > 0)
1613
net_dev->flags |= IFF_MULTICAST;
1615
net_dev->flags &= ~IFF_MULTICAST;
1616
#ifdef CONFIG_NET_POLL_CONTROLLER
1617
net_dev->poll_controller = ndis_poll_controller;
1620
buf = kmalloc(buf_size, GFP_KERNEL);
1622
WARNING("couldn't allocate memory");
1626
set_task_offload(wnd, buf, buf_size);
1420
1627
if (register_netdev(net_dev)) {
1421
1628
ERROR("cannot register net device %s", net_dev->name);
1425
memset(buf, 0, sizeof(buf));
1632
memset(buf, 0, buf_size);
1426
1633
ndis_status = miniport_query_info(wnd, OID_GEN_VENDOR_DESCRIPTION,
1428
1635
if (ndis_status == NDIS_STATUS_SUCCESS)
1429
1636
printk(KERN_INFO "%s: vendor: '%s'\n", net_dev->name, buf);
1431
printk(KERN_INFO "%s: %s ethernet device " MACSTR " using driver %s,"
1638
printk(KERN_INFO "%s: %s ethernet device " MACSTR " using %sdriver %s,"
1432
1639
" %s\n", net_dev->name, DRIVER_NAME, MAC2STR(net_dev->dev_addr),
1640
wnd->attributes & NDIS_ATTRIBUTE_DESERIALIZE ? "" : "serialized ",
1433
1641
wnd->wd->driver->name, wnd->wd->conf_file_name);
1436
DBGTRACE1("capbilities = %ld", wnd->capa.encr);
1437
printk(KERN_INFO "%s: encryption modes supported: %s%s%s%s%s%s%s\n",
1439
test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr) ?
1442
test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr) ?
1443
"; TKIP with WPA" : "",
1444
test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ?
1446
test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ?
1449
test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr) ?
1450
"; AES/CCMP with WPA" : "",
1451
test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ?
1453
test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ?
1456
if (test_bit(ATTR_SERIALIZED, &wnd->attributes)) {
1643
if (wnd->attributes & NDIS_ATTRIBUTE_DESERIALIZE) {
1644
/* deserialized drivers don't have a limit, but we
1645
* keep max at TX_RING_SIZE to allocate tx_array
1647
wnd->max_tx_packets = TX_RING_SIZE;
1458
1650
miniport_query_int(wnd, OID_GEN_MAXIMUM_SEND_PACKETS,
1459
&wnd->max_send_packets);
1651
&wnd->max_tx_packets);
1460
1652
if (ndis_status == NDIS_STATUS_NOT_SUPPORTED)
1461
wnd->max_send_packets = 1;
1462
if (wnd->max_send_packets > XMIT_RING_SIZE)
1463
wnd->max_send_packets = XMIT_RING_SIZE;
1465
/* deserialized drivers don't have a limit, but we
1466
* keep max at XMIT_RING_SIZE to allocate xmit_array
1468
wnd->max_send_packets = XMIT_RING_SIZE;
1653
wnd->max_tx_packets = 1;
1654
if (wnd->max_tx_packets > TX_RING_SIZE)
1655
wnd->max_tx_packets = TX_RING_SIZE;
1471
DBGTRACE1("maximum send packets: %d", wnd->max_send_packets);
1473
kmalloc(sizeof(struct ndis_packet *) * wnd->max_send_packets,
1657
DBGTRACE1("maximum send packets: %d", wnd->max_tx_packets);
1659
kmalloc(sizeof(struct ndis_packet *) * wnd->max_tx_packets,
1475
if (!wnd->xmit_array) {
1661
if (!wnd->tx_array) {
1476
1662
ERROR("couldn't allocate memory for tx_packets");
1477
1663
goto err_start;
1480
1666
/* we need at least one extra packet for
1481
1667
* EthRxIndicateHandler */
1482
NdisAllocatePacketPoolEx(&ndis_status, &wnd->wrapper_packet_pool,
1483
wnd->max_send_packets + 1, 0,
1668
NdisAllocatePacketPoolEx(&ndis_status, &wnd->tx_packet_pool,
1669
wnd->max_tx_packets + 1, 0,
1484
1670
PROTOCOL_RESERVED_SIZE_IN_PACKET);
1485
1671
if (ndis_status != NDIS_STATUS_SUCCESS) {
1486
1672
ERROR("couldn't allocate packet pool");
1487
1673
goto packet_pool_err;
1489
NdisAllocateBufferPool(&ndis_status, &wnd->wrapper_buffer_pool,
1490
wnd->max_send_packets + 4);
1675
NdisAllocateBufferPool(&ndis_status, &wnd->tx_buffer_pool,
1676
wnd->max_tx_packets + 4);
1491
1677
if (ndis_status != NDIS_STATUS_SUCCESS) {
1492
1678
ERROR("couldn't allocate buffer pool");
1493
1679
goto buffer_pool_err;
1495
DBGTRACE1("pool: %p", wnd->wrapper_buffer_pool);
1496
miniport_set_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE,
1497
Ndis802_11Automode);
1498
// miniport_set_int(wnd, OID_802_11_POWER_MODE, NDIS_POWER_OFF);
1499
/* check_capa changes auth_mode and encr_mode, so set them again */
1500
set_infra_mode(wnd, Ndis802_11Infrastructure);
1501
set_auth_mode(wnd, Ndis802_11AuthModeOpen);
1502
set_encr_mode(wnd, Ndis802_11EncryptionDisabled);
1504
set_privacy_filter(wnd, Ndis802_11PrivFilterAcceptAll);
1505
set_essid(wnd, "", 0);
1681
DBGTRACE1("pool: %p", wnd->tx_buffer_pool);
1682
if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) {
1683
miniport_set_int(wnd, OID_802_11_POWER_MODE, NDIS_POWER_OFF);
1684
miniport_set_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE,
1685
Ndis802_11Automode);
1686
get_encryption_capa(wnd);
1687
DBGTRACE1("capbilities = %ld", wnd->capa.encr);
1688
printk(KERN_INFO "%s: encryption modes supported: "
1689
"%s%s%s%s%s%s%s\n", net_dev->name,
1690
test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr) ?
1693
test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr) ?
1694
"; TKIP with WPA" : "",
1695
test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ?
1697
test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ?
1700
test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr) ?
1701
"; AES/CCMP with WPA" : "",
1702
test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ?
1704
test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ?
1707
set_infra_mode(wnd, Ndis802_11Infrastructure);
1709
set_priv_filter(wnd, Ndis802_11PrivFilterAcceptAll);
1710
set_auth_mode(wnd, Ndis802_11AuthModeOpen);
1711
set_encr_mode(wnd, Ndis802_11EncryptionDisabled);
1712
set_essid(wnd, "", 0);
1507
1715
wrap_procfs_add_ndis_device(wnd);
1716
add_stats_timer(wnd);
1508
1717
TRACEEXIT1(return NDIS_STATUS_SUCCESS);
1510
1719
buffer_pool_err:
1511
wnd->wrapper_buffer_pool = NULL;
1512
if (wnd->wrapper_packet_pool) {
1513
NdisFreePacketPool(wnd->wrapper_packet_pool);
1514
wnd->wrapper_packet_pool = NULL;
1720
wnd->tx_buffer_pool = NULL;
1721
if (wnd->tx_packet_pool) {
1722
NdisFreePacketPool(wnd->tx_packet_pool);
1723
wnd->tx_packet_pool = NULL;
1516
1725
packet_pool_err:
1517
kfree(wnd->xmit_array);
1518
wnd->xmit_array = NULL;
1726
kfree(wnd->tx_array);
1727
wnd->tx_array = NULL;
1520
1731
ndis_remove_device(wnd);
1521
1732
TRACEEXIT1(return NDIS_STATUS_FAILURE);
1524
static NDIS_STATUS ndis_remove_device(struct wrap_ndis_device *wnd)
1735
static int ndis_remove_device(struct wrap_ndis_device *wnd)
1528
set_bit(SHUTDOWN, &wnd->wrap_ndis_work);
1529
miniport_pnp_event(wnd, NdisDevicePnPEventSurpriseRemoved);
1739
set_bit(SHUTDOWN, &wnd->wrap_ndis_pending_work);
1530
1741
ndis_close(wnd->net_dev);
1531
1742
netif_carrier_off(wnd->net_dev);
1532
wrap_procfs_remove_ndis_device(wnd);
1743
cancel_delayed_work(&wnd->wrap_ndis_work);
1744
/* In 2.4 kernels, this function is called in atomic context,
1745
* so we can't (don't need to?) wait on mutex. */
1746
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
1747
/* if device is suspended, but resume failed, tx_ring_mutex is
1749
down_trylock(&wnd->tx_ring_mutex);
1751
tx_pending = wnd->tx_ring_end - wnd->tx_ring_start;
1753
tx_pending += TX_RING_SIZE;
1754
else if (tx_pending == 0 && wnd->is_tx_ring_full)
1755
tx_pending = TX_RING_SIZE - 1;
1756
wnd->is_tx_ring_full = 0;
1533
1757
/* throw away pending packets */
1534
irql = kspin_lock_irql(&wnd->xmit_lock, DISPATCH_LEVEL);
1535
while (wnd->xmit_ring_pending) {
1758
while (tx_pending > 0) {
1536
1759
struct ndis_packet *packet;
1538
packet = wnd->xmit_ring[wnd->xmit_ring_start];
1539
free_send_packet(wnd, packet);
1540
wnd->xmit_ring_start =
1541
(wnd->xmit_ring_start + 1) % XMIT_RING_SIZE;
1542
wnd->xmit_ring_pending--;
1761
packet = wnd->tx_ring[wnd->tx_ring_start];
1762
free_tx_packet(wnd, packet, NDIS_STATUS_CLOSING);
1763
wnd->tx_ring_start = (wnd->tx_ring_start + 1) % TX_RING_SIZE;
1544
kspin_unlock_irql(&wnd->xmit_lock, irql);
1766
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
1767
up(&wnd->tx_ring_mutex);
1769
wrap_procfs_remove_ndis_device(wnd);
1545
1770
miniport_halt(wnd);
1546
1771
ndis_exit_device(wnd);
1547
/* flush_scheduled_work here causes crash with 2.4 kernels */
1548
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
1549
flush_scheduled_work();
1551
if (wnd->wrapper_packet_pool) {
1552
NdisFreePacketPool(wnd->wrapper_packet_pool);
1553
wnd->wrapper_packet_pool = NULL;
1555
if (wnd->wrapper_buffer_pool) {
1556
NdisFreeBufferPool(wnd->wrapper_buffer_pool);
1557
wnd->wrapper_buffer_pool = NULL;
1559
IoDetachDevice(wnd->nmb->next_device);
1560
IoDeleteDevice(wnd->nmb->fdo);
1561
if (wnd->xmit_array)
1562
kfree(wnd->xmit_array);
1773
if (wnd->tx_packet_pool) {
1774
NdisFreePacketPool(wnd->tx_packet_pool);
1775
wnd->tx_packet_pool = NULL;
1777
if (wnd->tx_buffer_pool) {
1778
NdisFreeBufferPool(wnd->tx_buffer_pool);
1779
wnd->tx_buffer_pool = NULL;
1782
kfree(wnd->tx_array);
1563
1783
printk(KERN_INFO "%s: device %s removed\n", DRIVER_NAME,
1564
1784
wnd->net_dev->name);
1565
1785
unregister_netdev(wnd->net_dev);
1566
1786
free_netdev(wnd->net_dev);
1567
TRACEEXIT2(return NDIS_STATUS_SUCCESS);
1787
TRACEEXIT2(return 0);
1570
static STDCALL NTSTATUS NdisAddDevice(struct driver_object *drv_obj,
1790
static wstdcall NTSTATUS NdisAddDevice(struct driver_object *drv_obj,
1571
1791
struct device_object *pdo)
1573
1793
struct device_object *fdo;
1620
1847
init_nmb_functions(nmb);
1621
1848
wnd->net_dev = net_dev;
1622
1849
wnd->ndis_irq = NULL;
1623
kspin_lock_init(&wnd->xmit_lock);
1624
init_MUTEX(&wnd->ndis_comm_mutex);
1850
init_MUTEX_LOCKED(&wnd->tx_ring_mutex);
1851
init_MUTEX_LOCKED(&wnd->ndis_comm_mutex);
1625
1852
init_waitqueue_head(&wnd->ndis_comm_wq);
1626
1853
wnd->ndis_comm_done = 0;
1627
/* don't send packets until the card is associated */
1629
INIT_WORK(&wnd->xmit_work, xmit_worker, wnd);
1630
wnd->xmit_ring_start = 0;
1631
wnd->xmit_ring_pending = 0;
1632
kspin_lock_init(&wnd->send_packet_done_lock);
1855
INIT_WORK(&wnd->tx_work, tx_worker, wnd);
1856
wnd->tx_ring_start = 0;
1857
wnd->tx_ring_end = 0;
1858
wnd->is_tx_ring_full = 0;
1859
nt_spin_lock_init(&wnd->tx_stats_lock);
1633
1860
wnd->encr_mode = Ndis802_11EncryptionDisabled;
1634
1861
wnd->auth_mode = Ndis802_11AuthModeOpen;
1635
1862
wnd->capa.encr = 0;
1636
1863
wnd->capa.auth = 0;
1637
1864
wnd->attributes = 0;
1639
wnd->map_dma_addr = NULL;
1865
wnd->dma_map_count = 0;
1866
wnd->dma_map_addr = NULL;
1640
1867
wnd->nick[0] = 0;
1641
wnd->hangcheck_interval = hangcheck_interval;
1642
1868
init_timer(&wnd->hangcheck_timer);
1643
1869
wnd->scan_timestamp = 0;
1644
1870
init_timer(&wnd->stats_timer);
1645
wnd->wrap_ndis_work = 0;
1871
wnd->wrap_ndis_pending_work = 0;
1646
1872
memset(&wnd->essid, 0, sizeof(wnd->essid));
1647
1873
memset(&wnd->encr_info, 0, sizeof(wnd->encr_info));
1648
1874
wnd->infrastructure_mode = Ndis802_11Infrastructure;
1649
INIT_WORK(&wnd->wrap_ndis_worker, wrap_ndis_worker_proc, wnd);
1875
INIT_WORK(&wnd->wrap_ndis_work, wrap_ndis_worker, wnd);
1650
1876
wnd->hw_status = 0;
1651
set_bit(HW_AVAILABLE, &wnd->hw_status);
1652
1877
if (wd->driver->ndis_driver)
1653
1878
wd->driver->ndis_driver->miniport.shutdown = NULL;
1654
/* ZyDas driver doesn't call completion function when
1655
* querying for stats or rssi, so disable stats */
1656
if (stricmp(wd->driver->name, "zd1211u") == 0)
1657
wnd->stats_enabled = FALSE;
1659
wnd->stats_enabled = TRUE;
1879
wnd->stats_enabled = TRUE;
1880
wnd->rx_csum.value = 0;
1661
1882
fdo->reserved = wnd;
1663
1883
nmb->fdo = fdo;
1664
1884
nmb->next_device = IoAttachDeviceToDeviceStack(fdo, pdo);
1665
1885
DBGTRACE1("nmb: %p, pdo: %p, fdo: %p, attached: %p, next: %p",
1666
1886
nmb, pdo, fdo, fdo->attached, nmb->next_device);
1668
1888
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1669
drv_obj->major_func[i] = IopPassIrpDown;
1889
drv_obj->major_func[i] = IoPassIrpDown;
1670
1890
drv_obj->major_func[IRP_MJ_PNP] = NdisDispatchPnp;
1671
1891
drv_obj->major_func[IRP_MJ_POWER] = NdisDispatchPower;
1672
1892
drv_obj->major_func[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
1673
1893
NdisDispatchDeviceControl;
1674
drv_obj->major_func[IRP_MJ_DEVICE_CONTROL] =
1675
NdisDispatchDeviceControl;
1894
drv_obj->major_func[IRP_MJ_DEVICE_CONTROL] = NdisDispatchDeviceControl;
1676
1895
TRACEEXIT2(return STATUS_SUCCESS);