win-pvdrivers

view xennet/xennet.c @ 80:43f57f42508c

Removed hiding code from xenhide - use 'type=netfront' instead.
Added spinlock to xennet to avoid crash.
author James Harper <james.harper@bendigoit.com.au>
date Mon Dec 31 12:46:47 2007 +1100 (2007-12-31)
parents 17319a4920eb
children 9afafc0eae1d 449304b11e61
line source
1 /*
2 PV Net Driver for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
4 Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
21 #include <stdlib.h>
22 #include <io/xenbus.h>
23 #include "xennet.h"
25 /* Xen macros use these, so they need to be redefined to Win equivs */
26 #define wmb() KeMemoryBarrier()
27 #define mb() KeMemoryBarrier()
29 #if !defined (NDIS51_MINIPORT)
30 #error requires NDIS 5.1 compilation environment
31 #endif
33 #define GRANT_INVALID_REF 0
35 /* couldn't get regular xen ring macros to work...*/
36 #define __NET_RING_SIZE(type, _sz) \
37 (__RD32( \
38 (_sz - sizeof(struct type##_sring) + sizeof(union type##_sring_entry)) \
39 / sizeof(union type##_sring_entry)))
41 #define NET_TX_RING_SIZE __NET_RING_SIZE(netif_tx, PAGE_SIZE)
42 #define NET_RX_RING_SIZE __NET_RING_SIZE(netif_rx, PAGE_SIZE)
44 #pragma warning(disable: 4127) // conditional expression is constant
46 struct xennet_info
47 {
48 PDEVICE_OBJECT pdo;
49 PDEVICE_OBJECT fdo;
50 PDEVICE_OBJECT lower_do;
51 WDFDEVICE wdf_device;
52 PXENPCI_XEN_DEVICE_DATA pdoData;
54 WCHAR name[NAME_SIZE];
55 NDIS_HANDLE adapter_handle;
56 ULONG packet_filter;
57 int connected;
58 UINT8 perm_mac_addr[ETH_ALEN];
59 UINT8 curr_mac_addr[ETH_ALEN];
61 // char Path[128];
62 char BackendPath[128];
63 XEN_IFACE XenInterface;
65 /* ring control structures */
66 struct netif_tx_front_ring tx;
67 struct netif_rx_front_ring rx;
69 /* ptrs to the actual rings themselvves */
70 struct netif_tx_sring *tx_pgs;
71 struct netif_rx_sring *rx_pgs;
73 /* MDLs for the above */
74 PMDL tx_mdl;
75 PMDL rx_mdl;
77 /* Outstanding packets. The first entry in tx_pkts
78 * is an index into a chain of free entries. */
79 PNDIS_PACKET tx_pkts[NET_TX_RING_SIZE];
80 PNDIS_PACKET rx_pkts[NET_RX_RING_SIZE];
82 grant_ref_t gref_tx_head;
83 grant_ref_t grant_tx_ref[NET_TX_RING_SIZE];
84 grant_ref_t gref_rx_head;
85 grant_ref_t grant_rx_ref[NET_TX_RING_SIZE];
87 UINT irq;
88 evtchn_port_t event_channel;
90 grant_ref_t tx_ring_ref;
91 grant_ref_t rx_ring_ref;
93 /* Receive-ring batched refills. */
94 #define RX_MIN_TARGET 8
95 #define RX_DFL_MIN_TARGET 64
96 #define RX_MAX_TARGET min(NET_RX_RING_SIZE, 256)
97 ULONG rx_target;
98 ULONG rx_max_target;
99 ULONG rx_min_target;
101 NDIS_HANDLE packet_pool;
102 NDIS_HANDLE buffer_pool;
104 /* stats */
105 ULONG64 stat_tx_ok;
106 ULONG64 stat_rx_ok;
107 ULONG64 stat_tx_error;
108 ULONG64 stat_rx_error;
109 ULONG64 stat_rx_no_buffer;
111 KEVENT backend_ready_event;
112 KSPIN_LOCK Lock;
113 };
115 /* This function copied from linux's lib/vsprintf.c, see it for attribution */
116 static unsigned long
117 simple_strtoul(const char *cp,char **endp,unsigned int base)
118 {
119 unsigned long result = 0,value;
121 if (!base) {
122 base = 10;
123 if (*cp == '0') {
124 base = 8;
125 cp++;
126 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
127 cp++;
128 base = 16;
129 }
130 }
131 } else if (base == 16) {
132 if (cp[0] == '0' && toupper(cp[1]) == 'X')
133 cp += 2;
134 }
135 while (isxdigit(*cp) &&
136 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
137 result = result*base + value;
138 cp++;
139 }
140 if (endp)
141 *endp = (char *)cp;
142 return result;
143 }
145 static void
146 add_id_to_freelist(NDIS_PACKET **list, unsigned short id)
147 {
148 list[id] = list[0];
149 list[0] = (void *)(unsigned long)id;
150 }
152 static unsigned short
153 get_id_from_freelist(NDIS_PACKET **list)
154 {
155 unsigned short id = (unsigned short)(unsigned long)list[0];
156 list[0] = list[id];
157 return id;
158 }
160 // Called at DISPATCH_LEVEL with spinlock held
161 static NDIS_STATUS
162 XenNet_TxBufferGC(struct xennet_info *xi)
163 {
164 RING_IDX cons, prod;
165 unsigned short id;
166 PNDIS_PACKET pkt;
167 PMDL pmdl;
168 int notify;
170 ASSERT(xi->connected);
172 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
174 do {
175 prod = xi->tx.sring->rsp_prod;
176 KeMemoryBarrier(); /* Ensure we see responses up to 'rp'. */
178 for (cons = xi->tx.rsp_cons; cons != prod; cons++) {
179 struct netif_tx_response *txrsp;
181 txrsp = RING_GET_RESPONSE(&xi->tx, cons);
182 if (txrsp->status == NETIF_RSP_NULL)
183 continue;
185 id = txrsp->id;
186 pkt = xi->tx_pkts[id];
187 xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
188 xi->grant_tx_ref[id]);
189 xi->grant_tx_ref[id] = GRANT_INVALID_REF;
190 add_id_to_freelist(xi->tx_pkts, id);
192 /* free linearized data page */
193 pmdl = *(PMDL *)pkt->MiniportReservedEx;
194 NdisFreeMemory(MmGetMdlVirtualAddress(pmdl), 0, 0); // <= DISPATCH_LEVEL
195 IoFreeMdl(pmdl);
197 xi->stat_tx_ok++;
198 NdisMSendComplete(xi->adapter_handle, pkt, NDIS_STATUS_SUCCESS);
199 }
201 xi->tx.rsp_cons = prod;
203 /*
204 * Set a new event, then check for race with update of tx_cons.
205 * Note that it is essential to schedule a callback, no matter
206 * how few buffers are pending. Even if there is space in the
207 * transmit ring, higher layers may be blocked because too much
208 * data is outstanding: in such cases notification from Xen is
209 * likely to be the only kick that we'll get.
210 */
211 xi->tx.sring->rsp_event =
212 prod + ((xi->tx.sring->req_prod - prod) >> 1) + 1;
213 KeMemoryBarrier();
214 } while ((cons == prod) && (prod != xi->tx.sring->rsp_prod));
215 /*
216 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xi->tx, notify);
217 if (notify)
218 {
219 xi->XenInterface.EvtChn_Notify(xi->XenInterface.InterfaceHeader.Context,
220 xi->event_channel);
221 }
222 */
223 /* if queued packets, send them now?
224 network_maybe_wake_tx(dev); */
226 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
228 return NDIS_STATUS_SUCCESS;
229 }
231 static NDIS_STATUS
232 XenNet_AllocRXBuffers(struct xennet_info *xi)
233 {
234 unsigned short id;
235 PNDIS_PACKET packet;
236 PNDIS_BUFFER buffer;
237 int i, batch_target, notify;
238 RING_IDX req_prod = xi->rx.req_prod_pvt;
239 grant_ref_t ref;
240 netif_rx_request_t *req;
241 NDIS_STATUS status;
242 PVOID start;
244 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
246 batch_target = xi->rx_target - (req_prod - xi->rx.rsp_cons);
247 for (i = 0; i < batch_target; i++)
248 {
249 /*
250 * Allocate a packet, page, and buffer. Hook them up.
251 */
252 status = NdisAllocateMemoryWithTag(&start, PAGE_SIZE, XENNET_POOL_TAG);
253 if (status != NDIS_STATUS_SUCCESS)
254 {
255 KdPrint(("NdisAllocateMemoryWithTag Failed! status = 0x%x\n", status));
256 break;
257 }
258 NdisAllocateBuffer(&status, &buffer, xi->buffer_pool, start, PAGE_SIZE);
259 if (status != NDIS_STATUS_SUCCESS)
260 {
261 KdPrint(("NdisAllocateBuffer Failed! status = 0x%x\n", status));
262 NdisFreeMemory(start, 0, 0);
263 break;
264 }
265 NdisAllocatePacket(&status, &packet, xi->packet_pool);
266 if (status != NDIS_STATUS_SUCCESS)
267 {
268 KdPrint(("NdisAllocatePacket Failed! status = 0x%x\n", status));
269 NdisFreeMemory(start, 0, 0);
270 NdisFreeBuffer(buffer);
271 break;
272 }
273 NdisChainBufferAtBack(packet, buffer);
274 NDIS_SET_PACKET_HEADER_SIZE(packet, XN_HDR_SIZE);
276 /* Give to netback */
277 id = (unsigned short)(req_prod + i) & (NET_RX_RING_SIZE - 1);
278 ASSERT(!xi->rx_pkts[id]);
279 xi->rx_pkts[id] = packet;
280 req = RING_GET_REQUEST(&xi->rx, req_prod + i);
281 /* an NDIS_BUFFER is just a MDL, so we can get its pfn array */
282 ref = xi->XenInterface.GntTbl_GrantAccess(
283 xi->XenInterface.InterfaceHeader.Context, 0,
284 *MmGetMdlPfnArray(buffer), FALSE);
285 ASSERT((signed short)ref >= 0);
286 xi->grant_rx_ref[id] = ref;
288 req->id = id;
289 req->gref = ref;
290 }
292 xi->rx.req_prod_pvt = req_prod + i;
293 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xi->rx, notify);
294 if (notify)
295 {
296 xi->XenInterface.EvtChn_Notify(xi->XenInterface.InterfaceHeader.Context,
297 xi->event_channel);
298 }
300 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
302 return NDIS_STATUS_SUCCESS;
303 }
305 // Called at DISPATCH_LEVEL with spinlock held
306 static NDIS_STATUS
307 XenNet_RxBufferCheck(struct xennet_info *xi)
308 {
309 RING_IDX cons, prod;
311 PNDIS_PACKET pkt;
312 PNDIS_BUFFER buffer;
313 PVOID buff_va;
314 UINT buff_len;
315 UINT tot_buff_len;
316 int moretodo;
318 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
320 ASSERT(xi->connected);
322 do {
323 prod = xi->rx.sring->rsp_prod;
324 KeMemoryBarrier(); /* Ensure we see responses up to 'rp'. */
326 for (cons = xi->rx.rsp_cons; cons != prod; cons++) {
327 struct netif_rx_response *rxrsp;
329 rxrsp = RING_GET_RESPONSE(&xi->rx, cons);
330 if (rxrsp->status == NETIF_RSP_NULL)
331 continue;
333 // KdPrint((__DRIVER_NAME " Got a packet\n"));
335 pkt = xi->rx_pkts[rxrsp->id];
336 xi->rx_pkts[rxrsp->id] = NULL;
337 xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
338 xi->grant_rx_ref[rxrsp->id]);
339 xi->grant_rx_ref[rxrsp->id] = GRANT_INVALID_REF;
341 NdisGetFirstBufferFromPacketSafe(pkt, &buffer, &buff_va, &buff_len,
342 &tot_buff_len, NormalPagePriority);
343 ASSERT(rxrsp->offset == 0);
344 ASSERT(rxrsp->status > 0);
345 NdisAdjustBufferLength(buffer, rxrsp->status);
347 xi->stat_rx_ok++;
348 NDIS_SET_PACKET_STATUS(pkt, NDIS_STATUS_SUCCESS);
350 /* just indicate 1 packet for now */
351 // KdPrint((__DRIVER_NAME " Indicating Received\n"));
352 NdisMIndicateReceivePacket(xi->adapter_handle, &pkt, 1);
353 // KdPrint((__DRIVER_NAME " Done Indicating Received\n"));
354 }
356 xi->rx.rsp_cons = prod;
358 RING_FINAL_CHECK_FOR_RESPONSES(&xi->rx, moretodo);
359 #if 0
360 /*
361 * Set a new event, then check for race with update of rx_cons.
362 * Note that it is essential to schedule a callback, no matter
363 * how few buffers are pending. Even if there is space in the
364 * transmit ring, higher layers may be blocked because too much
365 * data is outstanding: in such cases notification from Xen is
366 * likely to be the only kick that we'll get.
367 */
368 xi->rx.sring->rsp_event =
369 prod + ((xi->rx.sring->req_prod - prod) >> 1) + 1;
370 KeMemoryBarrier();
371 } while ((cons == prod) && (prod != xi->rx.sring->rsp_prod));
372 #endif
373 } while (moretodo);
375 /* Give netback more buffers */
376 XenNet_AllocRXBuffers(xi);
378 //xi->rx.sring->rsp_event = xi->rx.rsp_cons + 1;
380 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
382 return NDIS_STATUS_SUCCESS;
383 }
385 // Called at DISPATCH_LEVEL
386 static BOOLEAN
387 XenNet_Interrupt(
388 PKINTERRUPT Interrupt,
389 PVOID ServiceContext
390 )
391 {
392 struct xennet_info *xi = ServiceContext;
393 KIRQL OldIrql;
395 UNREFERENCED_PARAMETER(Interrupt);
397 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
399 KeAcquireSpinLock(xi->Lock, &OldIrql);
401 //KdPrint((__DRIVER_NAME " ***XenNet Interrupt***\n"));
403 if (xi->connected)
404 {
405 XenNet_TxBufferGC(xi);
406 XenNet_RxBufferCheck(xi);
407 }
409 KeReleaseSpinLock(xi->Lock, OldIrql);
411 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
413 return TRUE;
414 }
416 static VOID
417 XenNet_BackEndStateHandler(char *Path, PVOID Data)
418 {
419 struct xennet_info *xi = Data;
420 char *Value;
421 int be_state;
422 char TmpPath[128];
423 xenbus_transaction_t xbt = 0;
424 int retry = 0;
425 char *err;
426 int i;
428 struct set_params {
429 char *name;
430 int value;
431 } params[] = {
432 {"tx-ring-ref", 0},
433 {"rx-ring-ref", 0},
434 {"event-channel", 0},
435 {"request-rx-copy", 1},
436 #if 0 // these seemed to cause kernel messages about checksums
437 {"feature-rx-notify", 1},
438 {"feature-no-csum-offload", 1},
439 {"feature-sg", 1},
440 {"feature-gso-tcpv4", 0},
441 #endif
442 {NULL, 0},
443 };
445 xi->XenInterface.XenBus_Read(xi->XenInterface.InterfaceHeader.Context,
446 XBT_NIL, Path, &Value);
447 be_state = atoi(Value);
448 xi->XenInterface.FreeMem(Value);
450 switch (be_state)
451 {
452 case XenbusStateUnknown:
453 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
454 break;
456 case XenbusStateInitialising:
457 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
458 break;
460 case XenbusStateInitWait:
461 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
463 xi->event_channel = xi->XenInterface.EvtChn_AllocUnbound(
464 xi->XenInterface.InterfaceHeader.Context, 0);
465 xi->XenInterface.EvtChn_BindDpc(xi->XenInterface.InterfaceHeader.Context,
466 xi->event_channel, XenNet_Interrupt, xi);
468 /* TODO: must free pages in MDL as well as MDL using MmFreePagesFromMdl and ExFreePool */
469 // or, allocate mem and then get mdl, then free mdl
470 xi->tx_mdl = AllocatePage();
471 xi->tx_pgs = MmGetMdlVirtualAddress(xi->tx_mdl); //MmMapLockedPagesSpecifyCache(xi->tx_mdl, KernelMode, MmNonCached, NULL, FALSE, NormalPagePriority);
472 SHARED_RING_INIT(xi->tx_pgs);
473 FRONT_RING_INIT(&xi->tx, xi->tx_pgs, PAGE_SIZE);
474 xi->tx_ring_ref = xi->XenInterface.GntTbl_GrantAccess(
475 xi->XenInterface.InterfaceHeader.Context, 0,
476 *MmGetMdlPfnArray(xi->tx_mdl), FALSE);
478 xi->rx_mdl = AllocatePage();
479 xi->rx_pgs = MmGetMdlVirtualAddress(xi->rx_mdl); //MmMapLockedPagesSpecifyCache(xi->rx_mdl, KernelMode, MmNonCached, NULL, FALSE, NormalPagePriority);
480 SHARED_RING_INIT(xi->rx_pgs);
481 FRONT_RING_INIT(&xi->rx, xi->rx_pgs, PAGE_SIZE);
482 xi->rx_ring_ref = xi->XenInterface.GntTbl_GrantAccess(
483 xi->XenInterface.InterfaceHeader.Context, 0,
484 *MmGetMdlPfnArray(xi->rx_mdl), FALSE);
486 /* fixup array for dynamic values */
487 params[0].value = xi->tx_ring_ref;
488 params[1].value = xi->rx_ring_ref;
489 params[2].value = xi->event_channel;
491 xi->XenInterface.XenBus_StartTransaction(
492 xi->XenInterface.InterfaceHeader.Context, &xbt);
494 for (i = 0; params[i].name; i++)
495 {
496 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/%s",
497 xi->pdoData->Path, params[i].name);
498 err = xi->XenInterface.XenBus_Printf(xi->XenInterface.InterfaceHeader.Context,
499 XBT_NIL, TmpPath, "%d", params[i].value);
500 if (err)
501 {
502 KdPrint(("setting %s failed, err = %s\n", params[i].name, err));
503 goto trouble;
504 }
505 }
507 /* commit transaction */
508 xi->XenInterface.XenBus_EndTransaction(xi->XenInterface.InterfaceHeader.Context,
509 xbt, 0, &retry);
511 XenNet_AllocRXBuffers(xi);
513 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
514 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->pdoData->Path);
515 xi->XenInterface.XenBus_Printf(xi->XenInterface.InterfaceHeader.Context,
516 XBT_NIL, TmpPath, "%d", XenbusStateConnected);
518 /* send fake arp? */
520 xi->connected = TRUE;
522 break;
524 case XenbusStateInitialised:
525 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
526 break;
528 case XenbusStateConnected:
529 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
530 KeSetEvent(&xi->backend_ready_event, 1, FALSE);
531 break;
533 case XenbusStateClosing:
534 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
535 break;
537 case XenbusStateClosed:
538 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
539 break;
541 default:
542 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", be_state));
543 break;
544 }
546 return;
548 trouble:
549 KdPrint((__DRIVER_NAME __FUNCTION__ ": Should never happen!\n"));
550 xi->XenInterface.XenBus_EndTransaction(xi->XenInterface.InterfaceHeader.Context,
551 xbt, 1, &retry);
553 }
555 VOID
556 XenNet_Halt(
557 IN NDIS_HANDLE MiniportAdapterContext
558 )
559 {
560 UNREFERENCED_PARAMETER(MiniportAdapterContext);
561 }
563 static NDIS_STATUS
564 XenNet_Init(
565 OUT PNDIS_STATUS OpenErrorStatus,
566 OUT PUINT SelectedMediumIndex,
567 IN PNDIS_MEDIUM MediumArray,
568 IN UINT MediumArraySize,
569 IN NDIS_HANDLE MiniportAdapterHandle,
570 IN NDIS_HANDLE WrapperConfigurationContext
571 )
572 {
573 NDIS_STATUS status;
574 UINT i;
575 BOOLEAN medium_found = FALSE;
576 struct xennet_info *xi = NULL;
577 ULONG length;
578 WDF_OBJECT_ATTRIBUTES wdf_attrs;
579 char *msg;
580 char *Value;
581 char TmpPath[128];
583 UNREFERENCED_PARAMETER(OpenErrorStatus);
584 UNREFERENCED_PARAMETER(WrapperConfigurationContext);
586 /* deal with medium stuff */
587 for (i = 0; i < MediumArraySize; i++)
588 {
589 if (MediumArray[i] == NdisMedium802_3)
590 {
591 medium_found = TRUE;
592 break;
593 }
594 }
595 if (!medium_found)
596 {
597 KdPrint(("NIC_MEDIA_TYPE not in MediumArray\n"));
598 return NDIS_STATUS_UNSUPPORTED_MEDIA;
599 }
600 *SelectedMediumIndex = i;
602 /* Alloc memory for adapter private info */
603 status = NdisAllocateMemoryWithTag(&xi, sizeof(*xi), XENNET_POOL_TAG);
604 if (!NT_SUCCESS(status))
605 {
606 KdPrint(("NdisAllocateMemoryWithTag failed with 0x%x\n", status));
607 status = NDIS_STATUS_RESOURCES;
608 goto err;
609 }
610 RtlZeroMemory(xi, sizeof(*xi));
612 /* init xennet_info */
613 xi->adapter_handle = MiniportAdapterHandle;
614 xi->rx_target = RX_DFL_MIN_TARGET;
615 xi->rx_min_target = RX_DFL_MIN_TARGET;
616 xi->rx_max_target = RX_MAX_TARGET;
618 KeInitializeSpinLock(&xi->Lock);
620 NdisAllocatePacketPool(&status, &xi->packet_pool, NET_RX_RING_SIZE,
621 PROTOCOL_RESERVED_SIZE_IN_PACKET);
622 if (status != NDIS_STATUS_SUCCESS)
623 {
624 KdPrint(("NdisAllocatePacketPool failed with 0x%x\n", status));
625 status = NDIS_STATUS_RESOURCES;
626 goto err;
627 }
629 NdisAllocateBufferPool(&status, &xi->buffer_pool, NET_RX_RING_SIZE);
630 if (status != NDIS_STATUS_SUCCESS)
631 {
632 KdPrint(("NdisAllocateBufferPool failed with 0x%x\n", status));
633 status = NDIS_STATUS_RESOURCES;
634 goto err;
635 }
637 NdisMGetDeviceProperty(MiniportAdapterHandle, &xi->pdo, &xi->fdo,
638 &xi->lower_do, NULL, NULL);
639 xi->pdoData = (PXENPCI_XEN_DEVICE_DATA)xi->pdo->DeviceExtension;
641 /* Initialize tx_pkts as a free chain containing every entry. */
642 for (i = 0; i <= NET_TX_RING_SIZE; i++) {
643 xi->tx_pkts[i] = (void *)((unsigned long) i+1);
644 xi->grant_tx_ref[i] = GRANT_INVALID_REF;
645 }
647 for (i = 0; i < NET_RX_RING_SIZE; i++) {
648 xi->rx_pkts[i] = NULL;
649 xi->grant_rx_ref[i] = GRANT_INVALID_REF;
650 }
652 xi->packet_filter = NDIS_PACKET_TYPE_PROMISCUOUS;
654 status = IoGetDeviceProperty(xi->pdo, DevicePropertyDeviceDescription,
655 NAME_SIZE, xi->name, &length);
656 if (!NT_SUCCESS(status))
657 {
658 KdPrint(("IoGetDeviceProperty failed with 0x%x\n", status));
659 status = NDIS_STATUS_FAILURE;
660 goto err;
661 }
663 NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE) xi,
664 0, (NDIS_ATTRIBUTE_DESERIALIZE /*| NDIS_ATTRIBUTE_BUS_MASTER*/),
665 NdisInterfaceInternal);
667 WDF_OBJECT_ATTRIBUTES_INIT(&wdf_attrs);
669 status = WdfDeviceMiniportCreate(WdfGetDriver(), &wdf_attrs, xi->fdo,
670 xi->lower_do, xi->pdo, &xi->wdf_device);
671 if (!NT_SUCCESS(status))
672 {
673 KdPrint(("WdfDeviceMiniportCreate failed with 0x%x\n", status));
674 status = NDIS_STATUS_FAILURE;
675 goto err;
676 }
678 /* get lower (Xen) interfaces */
680 status = WdfFdoQueryForInterface(xi->wdf_device, &GUID_XEN_IFACE,
681 (PINTERFACE) &xi->XenInterface, sizeof(XEN_IFACE), 1, NULL);
682 if(!NT_SUCCESS(status))
683 {
684 KdPrint(("WdfFdoQueryForInterface failed with status 0x%08x\n", status));
685 status = NDIS_STATUS_FAILURE;
686 goto err;
687 }
689 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath),
690 "%s/backend", xi->pdoData->Path);
691 KdPrint(("About to read %s to get backend path\n", TmpPath));
692 xi->XenInterface.XenBus_Read(xi->XenInterface.InterfaceHeader.Context,
693 XBT_NIL, TmpPath, &Value);
694 if (!Value)
695 {
696 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
697 status = NDIS_STATUS_FAILURE;
698 goto err;
699 }
700 // Check for Value == NULL here
701 RtlStringCbCopyA(xi->BackendPath, ARRAY_SIZE(xi->BackendPath), Value);
702 KdPrint((__DRIVER_NAME "backend path = %s\n", xi->BackendPath));
704 KeInitializeEvent(&xi->backend_ready_event, SynchronizationEvent, FALSE);
706 /* Add watch on backend state */
707 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->BackendPath);
708 xi->XenInterface.XenBus_AddWatch(xi->XenInterface.InterfaceHeader.Context,
709 XBT_NIL, TmpPath, XenNet_BackEndStateHandler, xi);
711 // wait here for signal that we are all set up
712 KeWaitForSingleObject(&xi->backend_ready_event, Executive, KernelMode, FALSE, NULL);
714 /* get mac address */
715 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/mac", xi->BackendPath);
716 xi->XenInterface.XenBus_Read(xi->XenInterface.InterfaceHeader.Context,
717 XBT_NIL, TmpPath, &Value);
718 if (!Value)
719 {
720 KdPrint((__DRIVER_NAME " mac Read Failed\n"));
721 status = NDIS_STATUS_FAILURE;
722 goto err;
723 }
724 else
725 {
726 char *s, *e;
727 int i;
728 s = Value;
729 for (i = 0; i < ETH_ALEN; i++) {
730 xi->perm_mac_addr[i] = (UINT8)simple_strtoul(s, &e, 16);
731 if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
732 KdPrint((__DRIVER_NAME "Error parsing MAC address\n"));
733 xi->XenInterface.FreeMem(Value);
734 status = NDIS_STATUS_FAILURE;
735 goto err;
736 }
737 s = e + 1;
738 }
739 memcpy(xi->curr_mac_addr, xi->perm_mac_addr, ETH_ALEN);
740 xi->XenInterface.FreeMem(Value);
741 }
743 return NDIS_STATUS_SUCCESS;
745 err:
746 NdisFreeMemory(xi, 0, 0);
747 return status;
748 }
750 // Q = Query Mandatory, S = Set Mandatory
751 NDIS_OID supported_oids[] =
752 {
753 /* general OIDs */
754 OID_GEN_SUPPORTED_LIST, // Q
755 OID_GEN_HARDWARE_STATUS, // Q
756 OID_GEN_MEDIA_SUPPORTED, // Q
757 OID_GEN_MEDIA_IN_USE, // Q
758 OID_GEN_MAXIMUM_LOOKAHEAD, // Q
759 OID_GEN_MAXIMUM_FRAME_SIZE, // Q
760 OID_GEN_LINK_SPEED, // Q
761 OID_GEN_TRANSMIT_BUFFER_SPACE, // Q
762 OID_GEN_RECEIVE_BUFFER_SPACE, // Q
763 OID_GEN_TRANSMIT_BLOCK_SIZE, // Q
764 OID_GEN_RECEIVE_BLOCK_SIZE, // Q
765 OID_GEN_VENDOR_ID, // Q
766 OID_GEN_VENDOR_DESCRIPTION, // Q
767 OID_GEN_CURRENT_PACKET_FILTER, // QS
768 OID_GEN_CURRENT_LOOKAHEAD, // QS
769 OID_GEN_DRIVER_VERSION, // Q
770 OID_GEN_MAXIMUM_TOTAL_SIZE, // Q
771 OID_GEN_PROTOCOL_OPTIONS, // S
772 OID_GEN_MAC_OPTIONS, // Q
773 OID_GEN_MEDIA_CONNECT_STATUS, // Q
774 OID_GEN_MAXIMUM_SEND_PACKETS, // Q
775 /* stats */
776 OID_GEN_XMIT_OK, // Q
777 OID_GEN_RCV_OK, // Q
778 OID_GEN_XMIT_ERROR, // Q
779 OID_GEN_RCV_ERROR, // Q
780 OID_GEN_RCV_NO_BUFFER, // Q
781 /* media-specific OIDs */
782 OID_802_3_PERMANENT_ADDRESS,
783 OID_802_3_CURRENT_ADDRESS,
784 OID_802_3_MULTICAST_LIST,
785 OID_802_3_MAXIMUM_LIST_SIZE,
786 };
788 NDIS_STATUS
789 XenNet_QueryInformation(
790 IN NDIS_HANDLE MiniportAdapterContext,
791 IN NDIS_OID Oid,
792 IN PVOID InformationBuffer,
793 IN ULONG InformationBufferLength,
794 OUT PULONG BytesWritten,
795 OUT PULONG BytesNeeded)
796 {
797 struct xennet_info *xi = MiniportAdapterContext;
798 UCHAR vendor_desc[] = XN_VENDOR_DESC;
799 ULONG64 temp_data;
800 PVOID data = &temp_data;
801 UINT len = 4;
802 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
804 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
806 switch(Oid)
807 {
808 case OID_GEN_SUPPORTED_LIST:
809 data = supported_oids;
810 len = sizeof(supported_oids);
811 break;
812 case OID_GEN_HARDWARE_STATUS:
813 if (!xi->connected)
814 temp_data = NdisHardwareStatusInitializing;
815 else
816 temp_data = NdisHardwareStatusReady;
817 break;
818 case OID_GEN_MEDIA_SUPPORTED:
819 temp_data = NdisMedium802_3;
820 break;
821 case OID_GEN_MEDIA_IN_USE:
822 temp_data = NdisMedium802_3;
823 break;
824 case OID_GEN_MAXIMUM_LOOKAHEAD:
825 temp_data = XN_DATA_SIZE;
826 break;
827 case OID_GEN_MAXIMUM_FRAME_SIZE:
828 temp_data = XN_MAX_PKT_SIZE;
829 break;
830 case OID_GEN_LINK_SPEED:
831 temp_data = 10000000; /* 1Gb */
832 break;
833 case OID_GEN_TRANSMIT_BUFFER_SPACE:
834 /* pkts times sizeof ring, maybe? */
835 temp_data = XN_MAX_PKT_SIZE * NET_TX_RING_SIZE;
836 break;
837 case OID_GEN_RECEIVE_BUFFER_SPACE:
838 /* pkts times sizeof ring, maybe? */
839 temp_data = XN_MAX_PKT_SIZE * NET_TX_RING_SIZE;
840 break;
841 case OID_GEN_TRANSMIT_BLOCK_SIZE:
842 temp_data = XN_MAX_PKT_SIZE;
843 break;
844 case OID_GEN_RECEIVE_BLOCK_SIZE:
845 temp_data = XN_MAX_PKT_SIZE;
846 break;
847 case OID_GEN_VENDOR_ID:
848 temp_data = 0xFFFFFF; // Not guaranteed to be XENSOURCE_MAC_HDR;
849 break;
850 case OID_GEN_VENDOR_DESCRIPTION:
851 data = vendor_desc;
852 len = sizeof(vendor_desc);
853 break;
854 case OID_GEN_CURRENT_PACKET_FILTER:
855 temp_data = xi->packet_filter;
856 break;
857 case OID_GEN_CURRENT_LOOKAHEAD:
858 // TODO: we should store this...
859 temp_data = XN_MAX_PKT_SIZE;
860 break;
861 case OID_GEN_DRIVER_VERSION:
862 temp_data = (NDIS_MAJOR_VER << 8) | NDIS_MINOR_VER;
863 len = 2;
864 break;
865 case OID_GEN_MAXIMUM_TOTAL_SIZE:
866 temp_data = XN_MAX_PKT_SIZE;
867 break;
868 case OID_GEN_MAC_OPTIONS:
869 temp_data = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
870 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
871 NDIS_MAC_OPTION_NO_LOOPBACK;
872 break;
873 case OID_GEN_MEDIA_CONNECT_STATUS:
874 if (xi->connected)
875 temp_data = NdisMediaStateConnected;
876 else
877 temp_data = NdisMediaStateDisconnected;
878 break;
879 case OID_GEN_MAXIMUM_SEND_PACKETS:
880 temp_data = XN_MAX_SEND_PKTS;
881 break;
882 case OID_GEN_XMIT_OK:
883 temp_data = xi->stat_tx_ok;
884 len = sizeof(ULONG64);
885 break;
886 case OID_GEN_RCV_OK:
887 temp_data = xi->stat_rx_ok;
888 len = sizeof(ULONG64);
889 break;
890 case OID_GEN_XMIT_ERROR:
891 temp_data = xi->stat_tx_error;
892 len = sizeof(ULONG64);
893 break;
894 case OID_GEN_RCV_ERROR:
895 temp_data = xi->stat_rx_error;
896 len = sizeof(ULONG64);
897 break;
898 case OID_GEN_RCV_NO_BUFFER:
899 temp_data = xi->stat_rx_no_buffer;
900 len = sizeof(ULONG64);
901 break;
902 case OID_802_3_PERMANENT_ADDRESS:
903 data = xi->perm_mac_addr;
904 len = ETH_ALEN;
905 break;
906 case OID_802_3_CURRENT_ADDRESS:
907 data = xi->curr_mac_addr;
908 len = ETH_ALEN;
909 break;
910 case OID_802_3_MULTICAST_LIST:
911 data = NULL;
912 len = 0;
913 case OID_802_3_MAXIMUM_LIST_SIZE:
914 temp_data = 0; /* no mcast support */
915 break;
916 default:
917 KdPrint(("Get Unknown OID 0x%x\n", Oid));
918 status = NDIS_STATUS_NOT_SUPPORTED;
919 }
921 if (!NT_SUCCESS(status))
922 {
923 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (returned error)\n"));
924 return status;
925 }
927 if (len > InformationBufferLength)
928 {
929 *BytesNeeded = len;
930 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (returned error)\n"));
931 return NDIS_STATUS_BUFFER_TOO_SHORT;
932 }
934 *BytesWritten = len;
935 if (len)
936 {
937 NdisMoveMemory(InformationBuffer, data, len);
938 }
940 //KdPrint(("Got OID 0x%x\n", Oid));
941 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
943 return status;
944 }
946 NDIS_STATUS
947 XenNet_SetInformation(
948 IN NDIS_HANDLE MiniportAdapterContext,
949 IN NDIS_OID Oid,
950 IN PVOID InformationBuffer,
951 IN ULONG InformationBufferLength,
952 OUT PULONG BytesRead,
953 OUT PULONG BytesNeeded
954 )
955 {
956 NTSTATUS status;
957 struct xennet_info *xi = MiniportAdapterContext;
958 PULONG64 data = InformationBuffer;
960 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
962 UNREFERENCED_PARAMETER(MiniportAdapterContext);
963 UNREFERENCED_PARAMETER(InformationBufferLength);
964 UNREFERENCED_PARAMETER(BytesRead);
965 UNREFERENCED_PARAMETER(BytesNeeded);
967 switch(Oid)
968 {
969 case OID_GEN_SUPPORTED_LIST:
970 status = NDIS_STATUS_NOT_SUPPORTED;
971 KdPrint(("Unsupported set OID_GEN_SUPPORTED_LIST\n"));
972 break;
973 case OID_GEN_HARDWARE_STATUS:
974 status = NDIS_STATUS_NOT_SUPPORTED;
975 KdPrint(("Unsupported set OID_GEN_HARDWARE_STATUS\n"));
976 break;
977 case OID_GEN_MEDIA_SUPPORTED:
978 status = NDIS_STATUS_NOT_SUPPORTED;
979 KdPrint(("Unsupported set OID_GEN_MEDIA_SUPPORTED\n"));
980 break;
981 case OID_GEN_MEDIA_IN_USE:
982 status = NDIS_STATUS_NOT_SUPPORTED;
983 KdPrint(("Unsupported set OID_GEN_MEDIA_IN_USE\n"));
984 break;
985 case OID_GEN_MAXIMUM_LOOKAHEAD:
986 status = NDIS_STATUS_NOT_SUPPORTED;
987 KdPrint(("Unsupported set OID_GEN_MAXIMUM_LOOKAHEAD\n"));
988 break;
989 case OID_GEN_MAXIMUM_FRAME_SIZE:
990 status = NDIS_STATUS_NOT_SUPPORTED;
991 KdPrint(("Unsupported set OID_GEN_MAXIMUM_FRAME_SIZE\n"));
992 break;
993 case OID_GEN_LINK_SPEED:
994 status = NDIS_STATUS_NOT_SUPPORTED;
995 KdPrint(("Unsupported set OID_GEN_LINK_SPEED\n"));
996 break;
997 case OID_GEN_TRANSMIT_BUFFER_SPACE:
998 status = NDIS_STATUS_NOT_SUPPORTED;
999 KdPrint(("Unsupported set OID_GEN_TRANSMIT_BUFFER_SPACE\n"));
1000 break;
1001 case OID_GEN_RECEIVE_BUFFER_SPACE:
1002 status = NDIS_STATUS_NOT_SUPPORTED;
1003 KdPrint(("Unsupported set OID_GEN_RECEIVE_BUFFER_SPACE\n"));
1004 break;
1005 case OID_GEN_TRANSMIT_BLOCK_SIZE:
1006 status = NDIS_STATUS_NOT_SUPPORTED;
1007 KdPrint(("Unsupported set OID_GEN_TRANSMIT_BLOCK_SIZE\n"));
1008 break;
1009 case OID_GEN_RECEIVE_BLOCK_SIZE:
1010 status = NDIS_STATUS_NOT_SUPPORTED;
1011 KdPrint(("Unsupported set OID_GEN_RECEIVE_BLOCK_SIZE\n"));
1012 break;
1013 case OID_GEN_VENDOR_ID:
1014 status = NDIS_STATUS_NOT_SUPPORTED;
1015 KdPrint(("Unsupported set OID_GEN_VENDOR_ID\n"));
1016 break;
1017 case OID_GEN_VENDOR_DESCRIPTION:
1018 status = NDIS_STATUS_NOT_SUPPORTED;
1019 KdPrint(("Unsupported set OID_GEN_VENDOR_DESCRIPTION\n"));
1020 break;
1021 case OID_GEN_CURRENT_PACKET_FILTER:
1022 KdPrint(("Set OID_GEN_CURRENT_PACKET_FILTER\n"));
1023 xi->packet_filter = *(ULONG *)data;
1024 status = NDIS_STATUS_SUCCESS;
1025 break;
1026 case OID_GEN_CURRENT_LOOKAHEAD:
1027 KdPrint(("Set OID_GEN_CURRENT_LOOKAHEAD %d\n", *(int *)data));
1028 // TODO: We should do this...
1029 status = NDIS_STATUS_SUCCESS;
1030 break;
1031 case OID_GEN_DRIVER_VERSION:
1032 status = NDIS_STATUS_NOT_SUPPORTED;
1033 KdPrint(("Unsupported set OID_GEN_DRIVER_VERSION\n"));
1034 break;
1035 case OID_GEN_MAXIMUM_TOTAL_SIZE:
1036 status = NDIS_STATUS_NOT_SUPPORTED;
1037 KdPrint(("Unsupported set OID_GEN_MAXIMUM_TOTAL_SIZE\n"));
1038 break;
1039 case OID_GEN_PROTOCOL_OPTIONS:
1040 KdPrint(("Unsupported set OID_GEN_PROTOCOL_OPTIONS\n"));
1041 // TODO - actually do this...
1042 status = NDIS_STATUS_SUCCESS;
1043 break;
1044 case OID_GEN_MAC_OPTIONS:
1045 status = NDIS_STATUS_NOT_SUPPORTED;
1046 KdPrint(("Unsupported set OID_GEN_MAC_OPTIONS\n"));
1047 break;
1048 case OID_GEN_MEDIA_CONNECT_STATUS:
1049 status = NDIS_STATUS_NOT_SUPPORTED;
1050 KdPrint(("Unsupported set OID_GEN_MEDIA_CONNECT_STATUS\n"));
1051 break;
1052 case OID_GEN_MAXIMUM_SEND_PACKETS:
1053 status = NDIS_STATUS_NOT_SUPPORTED;
1054 KdPrint(("Unsupported set OID_GEN_MAXIMUM_SEND_PACKETS\n"));
1055 break;
1056 case OID_GEN_XMIT_OK:
1057 status = NDIS_STATUS_NOT_SUPPORTED;
1058 KdPrint(("Unsupported set OID_GEN_XMIT_OK\n"));
1059 break;
1060 case OID_GEN_RCV_OK:
1061 status = NDIS_STATUS_NOT_SUPPORTED;
1062 KdPrint(("Unsupported set OID_GEN_RCV_OK\n"));
1063 break;
1064 case OID_GEN_XMIT_ERROR:
1065 status = NDIS_STATUS_NOT_SUPPORTED;
1066 KdPrint(("Unsupported set OID_GEN_XMIT_ERROR\n"));
1067 break;
1068 case OID_GEN_RCV_ERROR:
1069 status = NDIS_STATUS_NOT_SUPPORTED;
1070 KdPrint(("Unsupported set OID_GEN_RCV_ERROR\n"));
1071 break;
1072 case OID_GEN_RCV_NO_BUFFER:
1073 status = NDIS_STATUS_NOT_SUPPORTED;
1074 KdPrint(("Unsupported set OID_GEN_RCV_NO_BUFFER\n"));
1075 break;
1076 case OID_802_3_PERMANENT_ADDRESS:
1077 status = NDIS_STATUS_NOT_SUPPORTED;
1078 KdPrint(("Unsupported set OID_802_3_PERMANENT_ADDRESS\n"));
1079 break;
1080 case OID_802_3_CURRENT_ADDRESS:
1081 status = NDIS_STATUS_NOT_SUPPORTED;
1082 KdPrint(("Unsupported set OID_802_3_CURRENT_ADDRESS\n"));
1083 break;
1084 case OID_802_3_MULTICAST_LIST:
1085 status = NDIS_STATUS_NOT_SUPPORTED;
1086 KdPrint(("Unsupported set OID_802_3_MULTICAST_LIST\n"));
1087 break;
1088 case OID_802_3_MAXIMUM_LIST_SIZE:
1089 status = NDIS_STATUS_NOT_SUPPORTED;
1090 KdPrint(("Unsupported set OID_802_3_MAXIMUM_LIST_SIZE\n"));
1091 break;
1092 default:
1093 KdPrint(("Set Unknown OID 0x%x\n", Oid));
1094 status = NDIS_STATUS_NOT_SUPPORTED;
1095 break;
1097 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1098 return status;
1101 VOID
1102 XenNet_ReturnPacket(
1103 IN NDIS_HANDLE MiniportAdapterContext,
1104 IN PNDIS_PACKET Packet
1107 PNDIS_BUFFER buffer;
1108 PVOID buff_va;
1109 UINT buff_len;
1110 UINT tot_buff_len;
1112 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1114 UNREFERENCED_PARAMETER(MiniportAdapterContext);
1116 NdisGetFirstBufferFromPacketSafe(Packet, &buffer, &buff_va, &buff_len,
1117 &tot_buff_len, NormalPagePriority);
1118 ASSERT(buff_len == tot_buff_len);
1120 NdisFreeMemory(buff_va, 0, 0);
1121 NdisFreeBuffer(buffer);
1122 NdisFreePacket(Packet);
1124 //KdPrint((__FUNCTION__ " called\n"));
1125 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1128 PMDL
1129 XenNet_Linearize(PNDIS_PACKET Packet)
1131 NDIS_STATUS status;
1132 PMDL pmdl;
1133 char *start;
1134 PNDIS_BUFFER buffer;
1135 PVOID buff_va;
1136 UINT buff_len;
1137 UINT tot_buff_len;
1139 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1141 NdisGetFirstBufferFromPacketSafe(Packet, &buffer, &buff_va, &buff_len,
1142 &tot_buff_len, NormalPagePriority);
1143 ASSERT(tot_buff_len <= XN_MAX_PKT_SIZE);
1145 status = NdisAllocateMemoryWithTag(&start, tot_buff_len, XENNET_POOL_TAG);
1146 if (!NT_SUCCESS(status))
1148 KdPrint(("Could not allocate memory for linearization\n"));
1149 return NULL;
1151 pmdl = IoAllocateMdl(start, tot_buff_len, FALSE, FALSE, FALSE);
1152 if (!pmdl)
1154 KdPrint(("Could not allocate MDL for linearization\n"));
1155 NdisFreeMemory(start, 0, 0);
1156 return NULL;
1158 MmBuildMdlForNonPagedPool(pmdl);
1160 while (buffer)
1162 NdisQueryBufferSafe(buffer, &buff_va, &buff_len, NormalPagePriority);
1163 RtlCopyMemory(start, buff_va, buff_len);
1164 start += buff_len;
1165 NdisGetNextBuffer(buffer, &buffer);
1168 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1169 return pmdl;
1172 VOID
1173 XenNet_SendPackets(
1174 IN NDIS_HANDLE MiniportAdapterContext,
1175 IN PPNDIS_PACKET PacketArray,
1176 IN UINT NumberOfPackets
1179 struct xennet_info *xi = MiniportAdapterContext;
1180 PNDIS_PACKET curr_packet;
1181 UINT i;
1182 struct netif_tx_request *tx;
1183 unsigned short id;
1184 int notify;
1185 PMDL pmdl;
1186 UINT pkt_size;
1187 PKIRQL OldIrql;
1189 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1191 KeAcquireSpinLock(xi->Lock, &OldIrql);
1193 for (i = 0; i < NumberOfPackets; i++)
1195 curr_packet = PacketArray[i];
1196 ASSERT(curr_packet);
1198 NdisQueryPacket(curr_packet, NULL, NULL, NULL, &pkt_size);
1200 //KdPrint(("sending pkt, len %d\n", pkt_size));
1202 pmdl = XenNet_Linearize(curr_packet);
1203 if (!pmdl)
1205 KdPrint((__DRIVER_NAME "Couldn't linearize packet!\n"));
1206 NdisMSendComplete(xi, curr_packet, NDIS_STATUS_FAILURE);
1207 break;
1209 *((PMDL *)curr_packet->MiniportReservedEx) = pmdl;
1211 id = get_id_from_freelist(xi->tx_pkts);
1212 xi->tx_pkts[id] = curr_packet;
1214 tx = RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
1215 tx->id = id;
1216 tx->gref = xi->XenInterface.GntTbl_GrantAccess(
1217 xi->XenInterface.InterfaceHeader.Context,
1218 0,
1219 *MmGetMdlPfnArray(pmdl),
1220 TRUE);
1221 xi->grant_tx_ref[id] = tx->gref;
1222 tx->offset = (uint16_t)MmGetMdlByteOffset(pmdl);
1223 tx->size = (UINT16)pkt_size;
1224 // NETTXF_csum_blank should only be used for tcp and udp packets...
1225 tx->flags = 0; //NETTXF_csum_blank;
1227 xi->tx.req_prod_pvt++;
1229 // NDIS_SET_PACKET_STATUS(curr_packet, NDIS_STATUS_SUCCESS);
1230 // NdisMSendComplete(xi, curr_packet, NDIS_STATUS_SUCCESS);
1233 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xi->tx, notify);
1234 if (notify)
1236 xi->XenInterface.EvtChn_Notify(xi->XenInterface.InterfaceHeader.Context,
1237 xi->event_channel);
1240 KeReleaseSpinLock(xi->Lock, OldIrql);
1242 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1245 VOID
1246 XenNet_PnPEventNotify(
1247 IN NDIS_HANDLE MiniportAdapterContext,
1248 IN NDIS_DEVICE_PNP_EVENT PnPEvent,
1249 IN PVOID InformationBuffer,
1250 IN ULONG InformationBufferLength
1253 UNREFERENCED_PARAMETER(MiniportAdapterContext);
1254 UNREFERENCED_PARAMETER(PnPEvent);
1255 UNREFERENCED_PARAMETER(InformationBuffer);
1256 UNREFERENCED_PARAMETER(InformationBufferLength);
1258 KdPrint((__FUNCTION__ " called\n"));
1261 VOID
1262 XenNet_Shutdown(
1263 IN NDIS_HANDLE MiniportAdapterContext
1266 UNREFERENCED_PARAMETER(MiniportAdapterContext);
1268 KdPrint((__FUNCTION__ " called\n"));
1271 NTSTATUS
1272 DriverEntry(
1273 PDRIVER_OBJECT DriverObject,
1274 PUNICODE_STRING RegistryPath
1277 NTSTATUS status;
1278 WDF_DRIVER_CONFIG config;
1279 NDIS_HANDLE ndis_wrapper_handle;
1280 NDIS_MINIPORT_CHARACTERISTICS mini_chars;
1282 RtlZeroMemory(&mini_chars, sizeof(mini_chars));
1284 WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK);
1285 config.DriverInitFlags |= WdfDriverInitNoDispatchOverride;
1287 status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES,
1288 &config, WDF_NO_HANDLE);
1289 if (!NT_SUCCESS(status))
1291 KdPrint(("WdfDriverCreate failed err = 0x%x\n", status));
1292 return status;
1295 NdisMInitializeWrapper(&ndis_wrapper_handle, DriverObject, RegistryPath, NULL);
1296 if (!ndis_wrapper_handle)
1298 KdPrint(("NdisMInitializeWrapper failed\n"));
1299 return NDIS_STATUS_FAILURE;
1302 /* NDIS 5.1 driver */
1303 mini_chars.MajorNdisVersion = NDIS_MAJOR_VER;
1304 mini_chars.MinorNdisVersion = NDIS_MINOR_VER;
1306 mini_chars.HaltHandler = XenNet_Halt;
1307 mini_chars.InitializeHandler = XenNet_Init;
1308 mini_chars.ISRHandler = NULL; // needed if we register interrupt?
1309 mini_chars.QueryInformationHandler = XenNet_QueryInformation;
1310 mini_chars.ResetHandler = NULL; //TODO: fill in
1311 mini_chars.SetInformationHandler = XenNet_SetInformation;
1312 /* added in v.4 -- use multiple pkts interface */
1313 mini_chars.ReturnPacketHandler = XenNet_ReturnPacket;
1314 mini_chars.SendPacketsHandler = XenNet_SendPackets;
1315 /* added in v.5.1 */
1316 mini_chars.PnPEventNotifyHandler = XenNet_PnPEventNotify;
1317 mini_chars.AdapterShutdownHandler = XenNet_Shutdown;
1319 /* TODO: we don't have hardware, but we have "resources", so do we need to implement fns to handle this? */
1321 /* set up upper-edge interface */
1322 status = NdisMRegisterMiniport(ndis_wrapper_handle, &mini_chars, sizeof(mini_chars));
1323 if (!NT_SUCCESS(status))
1325 KdPrint(("NdisMRegisterMiniport failed, status = 0x%x\n", status));
1326 NdisTerminateWrapper(ndis_wrapper_handle, NULL);
1327 return status;
1330 return status;