win-pvdrivers

view xennet/xennet.c @ 95:b55f4ed508b0

Merged and xennet updates
author James Harper <james.harper@bendigoit.com.au>
date Sat Jan 05 14:47:44 2008 +1100 (2008-01-05)
parents 24963c2b7846
children 652ccd25fc7e
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 KEVENT backend_state_change_event;
114 ULONG state;
115 ULONG backend_state;
117 KSPIN_LOCK RxLock;
118 KSPIN_LOCK TxLock;
119 };
121 /* This function copied from linux's lib/vsprintf.c, see it for attribution */
122 static unsigned long
123 simple_strtoul(const char *cp,char **endp,unsigned int base)
124 {
125 unsigned long result = 0,value;
127 if (!base) {
128 base = 10;
129 if (*cp == '0') {
130 base = 8;
131 cp++;
132 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
133 cp++;
134 base = 16;
135 }
136 }
137 } else if (base == 16) {
138 if (cp[0] == '0' && toupper(cp[1]) == 'X')
139 cp += 2;
140 }
141 while (isxdigit(*cp) &&
142 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
143 result = result*base + value;
144 cp++;
145 }
146 if (endp)
147 *endp = (char *)cp;
148 return result;
149 }
151 static void
152 add_id_to_freelist(NDIS_PACKET **list, unsigned short id)
153 {
154 list[id] = list[0];
155 list[0] = (void *)(unsigned long)id;
156 }
158 static unsigned short
159 get_id_from_freelist(NDIS_PACKET **list)
160 {
161 unsigned short id = (unsigned short)(unsigned long)list[0];
162 list[0] = list[id];
163 return id;
164 }
166 // Called at DISPATCH_LEVEL
167 static NDIS_STATUS
168 XenNet_TxBufferGC(struct xennet_info *xi)
169 {
170 RING_IDX cons, prod;
171 unsigned short id;
172 PNDIS_PACKET pkt;
173 PMDL pmdl;
174 KIRQL OldIrql;
176 ASSERT(xi->connected);
178 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
180 KeAcquireSpinLock(&xi->TxLock, &OldIrql);
182 do {
183 prod = xi->tx.sring->rsp_prod;
184 KeMemoryBarrier(); /* Ensure we see responses up to 'rp'. */
186 for (cons = xi->tx.rsp_cons; cons != prod; cons++) {
187 struct netif_tx_response *txrsp;
189 txrsp = RING_GET_RESPONSE(&xi->tx, cons);
190 if (txrsp->status == NETIF_RSP_NULL)
191 continue;
193 id = txrsp->id;
194 pkt = xi->tx_pkts[id];
195 xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
196 xi->grant_tx_ref[id]);
197 xi->grant_tx_ref[id] = GRANT_INVALID_REF;
198 add_id_to_freelist(xi->tx_pkts, id);
200 /* free linearized data page */
201 pmdl = *(PMDL *)pkt->MiniportReservedEx;
202 NdisFreeMemory(MmGetMdlVirtualAddress(pmdl), 0, 0); // <= DISPATCH_LEVEL
203 IoFreeMdl(pmdl);
205 xi->stat_tx_ok++;
206 NdisMSendComplete(xi->adapter_handle, pkt, NDIS_STATUS_SUCCESS);
207 }
209 xi->tx.rsp_cons = prod;
211 /*
212 * Set a new event, then check for race with update of tx_cons.
213 * Note that it is essential to schedule a callback, no matter
214 * how few buffers are pending. Even if there is space in the
215 * transmit ring, higher layers may be blocked because too much
216 * data is outstanding: in such cases notification from Xen is
217 * likely to be the only kick that we'll get.
218 */
219 xi->tx.sring->rsp_event =
220 prod + ((xi->tx.sring->req_prod - prod) >> 1) + 1;
221 KeMemoryBarrier();
222 } while ((cons == prod) && (prod != xi->tx.sring->rsp_prod));
224 /* if queued packets, send them now?
225 network_maybe_wake_tx(dev); */
227 KeReleaseSpinLock(&xi->TxLock, OldIrql);
229 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
231 return NDIS_STATUS_SUCCESS;
232 }
234 // Called at DISPATCH_LEVEL with RxLock held
235 static NDIS_STATUS
236 XenNet_AllocRXBuffers(struct xennet_info *xi)
237 {
238 unsigned short id;
239 PNDIS_PACKET packet;
240 PNDIS_BUFFER buffer;
241 int i, batch_target, notify;
242 RING_IDX req_prod = xi->rx.req_prod_pvt;
243 grant_ref_t ref;
244 netif_rx_request_t *req;
245 NDIS_STATUS status;
246 PVOID start;
248 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
250 batch_target = xi->rx_target - (req_prod - xi->rx.rsp_cons);
251 for (i = 0; i < batch_target; i++)
252 {
253 /*
254 * Allocate a packet, page, and buffer. Hook them up.
255 */
256 status = NdisAllocateMemoryWithTag(&start, PAGE_SIZE, XENNET_POOL_TAG);
257 if (status != NDIS_STATUS_SUCCESS)
258 {
259 KdPrint(("NdisAllocateMemoryWithTag Failed! status = 0x%x\n", status));
260 break;
261 }
262 NdisAllocateBuffer(&status, &buffer, xi->buffer_pool, start, PAGE_SIZE);
263 if (status != NDIS_STATUS_SUCCESS)
264 {
265 KdPrint(("NdisAllocateBuffer Failed! status = 0x%x\n", status));
266 NdisFreeMemory(start, 0, 0);
267 break;
268 }
269 NdisAllocatePacket(&status, &packet, xi->packet_pool);
270 if (status != NDIS_STATUS_SUCCESS)
271 {
272 KdPrint(("NdisAllocatePacket Failed! status = 0x%x\n", status));
273 NdisFreeMemory(start, 0, 0);
274 NdisFreeBuffer(buffer);
275 break;
276 }
277 NdisChainBufferAtBack(packet, buffer);
278 NDIS_SET_PACKET_HEADER_SIZE(packet, XN_HDR_SIZE);
280 /* Give to netback */
281 id = (unsigned short)(req_prod + i) & (NET_RX_RING_SIZE - 1);
282 ASSERT(!xi->rx_pkts[id]);
283 xi->rx_pkts[id] = packet;
284 req = RING_GET_REQUEST(&xi->rx, req_prod + i);
285 /* an NDIS_BUFFER is just a MDL, so we can get its pfn array */
286 ref = xi->XenInterface.GntTbl_GrantAccess(
287 xi->XenInterface.InterfaceHeader.Context, 0,
288 *MmGetMdlPfnArray(buffer), FALSE);
289 ASSERT((signed short)ref >= 0);
290 xi->grant_rx_ref[id] = ref;
292 req->id = id;
293 req->gref = ref;
294 }
296 xi->rx.req_prod_pvt = req_prod + i;
297 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xi->rx, notify);
298 if (notify)
299 {
300 xi->XenInterface.EvtChn_Notify(xi->XenInterface.InterfaceHeader.Context,
301 xi->event_channel);
302 }
304 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
306 return NDIS_STATUS_SUCCESS;
307 }
309 // Called at DISPATCH_LEVEL
310 static NDIS_STATUS
311 XenNet_RxBufferCheck(struct xennet_info *xi)
312 {
313 RING_IDX cons, prod;
315 PNDIS_PACKET pkt;
316 PNDIS_BUFFER buffer;
317 PVOID buff_va;
318 UINT buff_len;
319 UINT tot_buff_len;
320 int moretodo;
321 KIRQL OldIrql;
323 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
325 ASSERT(xi->connected);
327 KeAcquireSpinLock(&xi->RxLock, &OldIrql);
329 do {
330 prod = xi->rx.sring->rsp_prod;
331 KeMemoryBarrier(); /* Ensure we see responses up to 'rp'. */
333 for (cons = xi->rx.rsp_cons; cons != prod; cons++) {
334 struct netif_rx_response *rxrsp;
336 rxrsp = RING_GET_RESPONSE(&xi->rx, cons);
337 if (rxrsp->status == NETIF_RSP_NULL)
338 continue;
340 // KdPrint((__DRIVER_NAME " Got a packet\n"));
342 pkt = xi->rx_pkts[rxrsp->id];
343 xi->rx_pkts[rxrsp->id] = NULL;
344 xi->XenInterface.GntTbl_EndAccess(xi->XenInterface.InterfaceHeader.Context,
345 xi->grant_rx_ref[rxrsp->id]);
346 xi->grant_rx_ref[rxrsp->id] = GRANT_INVALID_REF;
348 NdisGetFirstBufferFromPacketSafe(pkt, &buffer, &buff_va, &buff_len,
349 &tot_buff_len, NormalPagePriority);
350 ASSERT(rxrsp->offset == 0);
351 ASSERT(rxrsp->status > 0);
352 NdisAdjustBufferLength(buffer, rxrsp->status);
354 xi->stat_rx_ok++;
355 NDIS_SET_PACKET_STATUS(pkt, NDIS_STATUS_SUCCESS);
357 /* just indicate 1 packet for now */
358 // KdPrint((__DRIVER_NAME " Indicating Received\n"));
359 NdisMIndicateReceivePacket(xi->adapter_handle, &pkt, 1);
360 // KdPrint((__DRIVER_NAME " Done Indicating Received\n"));
361 }
363 xi->rx.rsp_cons = prod;
365 RING_FINAL_CHECK_FOR_RESPONSES(&xi->rx, moretodo);
366 } while (moretodo);
368 /* Give netback more buffers */
369 XenNet_AllocRXBuffers(xi);
371 KeReleaseSpinLock(&xi->RxLock, OldIrql);
373 //xi->rx.sring->rsp_event = xi->rx.rsp_cons + 1;
375 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
377 return NDIS_STATUS_SUCCESS;
378 }
380 // Called at DISPATCH_LEVEL
381 static BOOLEAN
382 XenNet_Interrupt(
383 PKINTERRUPT Interrupt,
384 PVOID ServiceContext
385 )
386 {
387 struct xennet_info *xi = ServiceContext;
389 UNREFERENCED_PARAMETER(Interrupt);
391 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
393 if (xi->connected)
394 {
395 XenNet_TxBufferGC(xi);
396 XenNet_RxBufferCheck(xi);
397 }
399 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
401 return TRUE;
402 }
404 // Called at <= DISPATCH_LEVEL
406 static VOID
407 XenNet_BackEndStateHandler(char *Path, PVOID Data)
408 {
409 struct xennet_info *xi = Data;
410 char *Value;
411 char TmpPath[128];
412 xenbus_transaction_t xbt = 0;
413 int retry = 0;
414 char *err;
415 int i;
416 int new_backend_state;
418 struct set_params {
419 char *name;
420 int value;
421 } params[] = {
422 {"tx-ring-ref", 0},
423 {"rx-ring-ref", 0},
424 {"event-channel", 0},
425 {"request-rx-copy", 1},
426 #if 0 // these seemed to cause kernel messages about checksums
427 {"feature-rx-notify", 1},
428 {"feature-no-csum-offload", 1},
429 {"feature-sg", 1},
430 {"feature-gso-tcpv4", 0},
431 #endif
432 {NULL, 0},
433 };
435 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
436 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
438 xi->XenInterface.XenBus_Read(xi->XenInterface.InterfaceHeader.Context,
439 XBT_NIL, Path, &Value);
440 new_backend_state = atoi(Value);
441 xi->XenInterface.FreeMem(Value);
443 if (xi->backend_state == new_backend_state)
444 {
445 KdPrint((__DRIVER_NAME " state unchanged\n"));
446 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
447 return;
448 }
450 xi->backend_state = new_backend_state;
452 switch (xi->backend_state)
453 {
454 case XenbusStateUnknown:
455 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
456 break;
458 case XenbusStateInitialising:
459 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
460 break;
462 case XenbusStateInitWait:
463 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
465 xi->event_channel = xi->XenInterface.EvtChn_AllocUnbound(
466 xi->XenInterface.InterfaceHeader.Context, 0);
467 xi->XenInterface.EvtChn_BindDpc(xi->XenInterface.InterfaceHeader.Context,
468 xi->event_channel, XenNet_Interrupt, xi);
470 /* TODO: must free pages in MDL as well as MDL using MmFreePagesFromMdl and ExFreePool */
471 // or, allocate mem and then get mdl, then free mdl
472 xi->tx_mdl = AllocatePage();
473 xi->tx_pgs = MmGetMdlVirtualAddress(xi->tx_mdl); //MmMapLockedPagesSpecifyCache(xi->tx_mdl, KernelMode, MmNonCached, NULL, FALSE, NormalPagePriority);
474 SHARED_RING_INIT(xi->tx_pgs);
475 FRONT_RING_INIT(&xi->tx, xi->tx_pgs, PAGE_SIZE);
476 xi->tx_ring_ref = xi->XenInterface.GntTbl_GrantAccess(
477 xi->XenInterface.InterfaceHeader.Context, 0,
478 *MmGetMdlPfnArray(xi->tx_mdl), FALSE);
480 xi->rx_mdl = AllocatePage();
481 xi->rx_pgs = MmGetMdlVirtualAddress(xi->rx_mdl); //MmMapLockedPagesSpecifyCache(xi->rx_mdl, KernelMode, MmNonCached, NULL, FALSE, NormalPagePriority);
482 SHARED_RING_INIT(xi->rx_pgs);
483 FRONT_RING_INIT(&xi->rx, xi->rx_pgs, PAGE_SIZE);
484 xi->rx_ring_ref = xi->XenInterface.GntTbl_GrantAccess(
485 xi->XenInterface.InterfaceHeader.Context, 0,
486 *MmGetMdlPfnArray(xi->rx_mdl), FALSE);
488 /* fixup array for dynamic values */
489 params[0].value = xi->tx_ring_ref;
490 params[1].value = xi->rx_ring_ref;
491 params[2].value = xi->event_channel;
493 xi->XenInterface.XenBus_StartTransaction(
494 xi->XenInterface.InterfaceHeader.Context, &xbt);
496 for (i = 0; params[i].name; i++)
497 {
498 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/%s",
499 xi->pdoData->Path, params[i].name);
500 err = xi->XenInterface.XenBus_Printf(xi->XenInterface.InterfaceHeader.Context,
501 XBT_NIL, TmpPath, "%d", params[i].value);
502 if (err)
503 {
504 KdPrint(("setting %s failed, err = %s\n", params[i].name, err));
505 goto trouble;
506 }
507 }
509 /* commit transaction */
510 xi->XenInterface.XenBus_EndTransaction(xi->XenInterface.InterfaceHeader.Context,
511 xbt, 0, &retry);
513 XenNet_AllocRXBuffers(xi);
515 xi->state = XenbusStateConnected;
516 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
517 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->pdoData->Path);
518 xi->XenInterface.XenBus_Printf(xi->XenInterface.InterfaceHeader.Context,
519 XBT_NIL, TmpPath, "%d", xi->state);
521 /* send fake arp? */
523 xi->connected = TRUE;
525 break;
527 case XenbusStateInitialised:
528 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
529 break;
531 case XenbusStateConnected:
532 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
533 break;
535 case XenbusStateClosing:
536 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
537 break;
539 case XenbusStateClosed:
540 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
541 break;
543 default:
544 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", xi->backend_state));
545 break;
546 }
548 KeSetEvent(&xi->backend_state_change_event, 1, FALSE);
550 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
552 return;
554 trouble:
555 KdPrint((__DRIVER_NAME __FUNCTION__ ": Should never happen!\n"));
556 xi->XenInterface.XenBus_EndTransaction(xi->XenInterface.InterfaceHeader.Context,
557 xbt, 1, &retry);
558 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
559 }
561 VOID
562 XenNet_Halt(
563 IN NDIS_HANDLE MiniportAdapterContext
564 )
565 {
566 struct xennet_info *xi = MiniportAdapterContext;
567 CHAR TmpPath[128];
569 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
570 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
572 // set frontend state to 'closing'
573 xi->state = XenbusStateClosing;
574 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->pdoData->Path);
575 xi->XenInterface.XenBus_Printf(xi->XenInterface.InterfaceHeader.Context,
576 XBT_NIL, TmpPath, "%d", xi->state);
578 // wait for backend to set 'Closing' state
580 while (xi->backend_state != XenbusStateClosing)
581 KeWaitForSingleObject(&xi->backend_state_change_event, Executive, KernelMode, FALSE, NULL);
583 // set frontend state to 'closed'
584 xi->state = XenbusStateClosed;
585 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->pdoData->Path);
586 xi->XenInterface.XenBus_Printf(xi->XenInterface.InterfaceHeader.Context,
587 XBT_NIL, TmpPath, "%d", xi->state);
589 // wait for backend to set 'Closed' state
590 while (xi->backend_state != XenbusStateClosed)
591 KeWaitForSingleObject(&xi->backend_state_change_event, Executive, KernelMode, FALSE, NULL);
593 // remove event channel xenbus entry
594 // unbind event channel
595 // remove tx/rx ring entries
596 // clean up all grant table entries
597 // free all memory
599 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
600 }
602 static NDIS_STATUS
603 XenNet_Init(
604 OUT PNDIS_STATUS OpenErrorStatus,
605 OUT PUINT SelectedMediumIndex,
606 IN PNDIS_MEDIUM MediumArray,
607 IN UINT MediumArraySize,
608 IN NDIS_HANDLE MiniportAdapterHandle,
609 IN NDIS_HANDLE WrapperConfigurationContext
610 )
611 {
612 NDIS_STATUS status;
613 UINT i;
614 BOOLEAN medium_found = FALSE;
615 struct xennet_info *xi = NULL;
616 ULONG length;
617 WDF_OBJECT_ATTRIBUTES wdf_attrs;
618 char *res;
619 char *Value;
620 char TmpPath[128];
622 UNREFERENCED_PARAMETER(OpenErrorStatus);
623 UNREFERENCED_PARAMETER(WrapperConfigurationContext);
625 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
626 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
628 /* deal with medium stuff */
629 for (i = 0; i < MediumArraySize; i++)
630 {
631 if (MediumArray[i] == NdisMedium802_3)
632 {
633 medium_found = TRUE;
634 break;
635 }
636 }
637 if (!medium_found)
638 {
639 KdPrint(("NIC_MEDIA_TYPE not in MediumArray\n"));
640 return NDIS_STATUS_UNSUPPORTED_MEDIA;
641 }
642 *SelectedMediumIndex = i;
644 /* Alloc memory for adapter private info */
645 status = NdisAllocateMemoryWithTag(&xi, sizeof(*xi), XENNET_POOL_TAG);
646 if (!NT_SUCCESS(status))
647 {
648 KdPrint(("NdisAllocateMemoryWithTag failed with 0x%x\n", status));
649 status = NDIS_STATUS_RESOURCES;
650 goto err;
651 }
652 RtlZeroMemory(xi, sizeof(*xi));
654 /* init xennet_info */
655 xi->adapter_handle = MiniportAdapterHandle;
656 xi->rx_target = RX_DFL_MIN_TARGET;
657 xi->rx_min_target = RX_DFL_MIN_TARGET;
658 xi->rx_max_target = RX_MAX_TARGET;
660 xi->state = XenbusStateUnknown;
661 xi->backend_state = XenbusStateUnknown;
663 KeInitializeSpinLock(&xi->TxLock);
664 KeInitializeSpinLock(&xi->RxLock);
666 NdisAllocatePacketPool(&status, &xi->packet_pool, NET_RX_RING_SIZE,
667 PROTOCOL_RESERVED_SIZE_IN_PACKET);
668 if (status != NDIS_STATUS_SUCCESS)
669 {
670 KdPrint(("NdisAllocatePacketPool failed with 0x%x\n", status));
671 status = NDIS_STATUS_RESOURCES;
672 goto err;
673 }
675 NdisAllocateBufferPool(&status, &xi->buffer_pool, NET_RX_RING_SIZE);
676 if (status != NDIS_STATUS_SUCCESS)
677 {
678 KdPrint(("NdisAllocateBufferPool failed with 0x%x\n", status));
679 status = NDIS_STATUS_RESOURCES;
680 goto err;
681 }
683 NdisMGetDeviceProperty(MiniportAdapterHandle, &xi->pdo, &xi->fdo,
684 &xi->lower_do, NULL, NULL);
685 xi->pdoData = (PXENPCI_XEN_DEVICE_DATA)xi->pdo->DeviceExtension;
687 /* Initialize tx_pkts as a free chain containing every entry. */
688 for (i = 0; i <= NET_TX_RING_SIZE; i++) {
689 xi->tx_pkts[i] = (void *)((unsigned long) i+1);
690 xi->grant_tx_ref[i] = GRANT_INVALID_REF;
691 }
693 for (i = 0; i < NET_RX_RING_SIZE; i++) {
694 xi->rx_pkts[i] = NULL;
695 xi->grant_rx_ref[i] = GRANT_INVALID_REF;
696 }
698 xi->packet_filter = NDIS_PACKET_TYPE_PROMISCUOUS;
700 status = IoGetDeviceProperty(xi->pdo, DevicePropertyDeviceDescription,
701 NAME_SIZE, xi->name, &length);
702 if (!NT_SUCCESS(status))
703 {
704 KdPrint(("IoGetDeviceProperty failed with 0x%x\n", status));
705 status = NDIS_STATUS_FAILURE;
706 goto err;
707 }
709 NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE) xi,
710 0, (NDIS_ATTRIBUTE_DESERIALIZE /*| NDIS_ATTRIBUTE_BUS_MASTER*/),
711 NdisInterfaceInternal);
713 WDF_OBJECT_ATTRIBUTES_INIT(&wdf_attrs);
715 status = WdfDeviceMiniportCreate(WdfGetDriver(), &wdf_attrs, xi->fdo,
716 xi->lower_do, xi->pdo, &xi->wdf_device);
717 if (!NT_SUCCESS(status))
718 {
719 KdPrint(("WdfDeviceMiniportCreate failed with 0x%x\n", status));
720 status = NDIS_STATUS_FAILURE;
721 goto err;
722 }
724 /* get lower (Xen) interfaces */
726 status = WdfFdoQueryForInterface(xi->wdf_device, &GUID_XEN_IFACE,
727 (PINTERFACE) &xi->XenInterface, sizeof(XEN_IFACE), 1, NULL);
728 if(!NT_SUCCESS(status))
729 {
730 KdPrint(("WdfFdoQueryForInterface failed with status 0x%08x\n", status));
731 status = NDIS_STATUS_FAILURE;
732 goto err;
733 }
735 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath),
736 "%s/backend", xi->pdoData->Path);
737 KdPrint(("About to read %s to get backend path\n", TmpPath));
738 res = xi->XenInterface.XenBus_Read(xi->XenInterface.InterfaceHeader.Context,
739 XBT_NIL, TmpPath, &Value);
740 if (res)
741 {
742 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
743 xi->XenInterface.FreeMem(res);
744 status = NDIS_STATUS_FAILURE;
745 goto err;
746 }
747 RtlStringCbCopyA(xi->BackendPath, ARRAY_SIZE(xi->BackendPath), Value);
748 KdPrint((__DRIVER_NAME "backend path = %s\n", xi->BackendPath));
750 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/type", xi->BackendPath);
751 res = xi->XenInterface.XenBus_Read(xi->XenInterface.InterfaceHeader.Context,
752 XBT_NIL, TmpPath, &Value);
753 if (res || strcmp(Value, "netfront") != 0)
754 {
755 KdPrint((__DRIVER_NAME " Backend type is not 'netfront'\n"));
756 status = NDIS_STATUS_FAILURE;
757 goto err;
758 }
761 KeInitializeEvent(&xi->backend_state_change_event, SynchronizationEvent, FALSE);
763 /* Add watch on backend state */
764 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->BackendPath);
765 xi->XenInterface.XenBus_AddWatch(xi->XenInterface.InterfaceHeader.Context,
766 XBT_NIL, TmpPath, XenNet_BackEndStateHandler, xi);
768 // Fire backend state handler here, as we may have missed it
769 XenNet_BackEndStateHandler(TmpPath, xi);
771 KdPrint((__DRIVER_NAME " Waiting for backend to connect\n"));
773 // wait here for signal that we are all set up
774 while (xi->backend_state != XenbusStateConnected)
775 KeWaitForSingleObject(&xi->backend_state_change_event, Executive, KernelMode, FALSE, NULL);
777 KdPrint((__DRIVER_NAME " Connected\n"));
779 /* get mac address */
780 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/mac", xi->BackendPath);
781 xi->XenInterface.XenBus_Read(xi->XenInterface.InterfaceHeader.Context,
782 XBT_NIL, TmpPath, &Value);
783 if (!Value)
784 {
785 KdPrint((__DRIVER_NAME " mac Read Failed\n"));
786 status = NDIS_STATUS_FAILURE;
787 goto err;
788 }
789 else
790 {
791 char *s, *e;
792 int i;
793 s = Value;
794 for (i = 0; i < ETH_ALEN; i++) {
795 xi->perm_mac_addr[i] = (UINT8)simple_strtoul(s, &e, 16);
796 if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
797 KdPrint((__DRIVER_NAME "Error parsing MAC address\n"));
798 xi->XenInterface.FreeMem(Value);
799 status = NDIS_STATUS_FAILURE;
800 goto err;
801 }
802 s = e + 1;
803 }
804 memcpy(xi->curr_mac_addr, xi->perm_mac_addr, ETH_ALEN);
805 xi->XenInterface.FreeMem(Value);
806 }
808 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
810 return NDIS_STATUS_SUCCESS;
812 err:
813 NdisFreeMemory(xi, 0, 0);
814 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
815 return status;
816 }
818 // Q = Query Mandatory, S = Set Mandatory
819 NDIS_OID supported_oids[] =
820 {
821 /* general OIDs */
822 OID_GEN_SUPPORTED_LIST, // Q
823 OID_GEN_HARDWARE_STATUS, // Q
824 OID_GEN_MEDIA_SUPPORTED, // Q
825 OID_GEN_MEDIA_IN_USE, // Q
826 OID_GEN_MAXIMUM_LOOKAHEAD, // Q
827 OID_GEN_MAXIMUM_FRAME_SIZE, // Q
828 OID_GEN_LINK_SPEED, // Q
829 OID_GEN_TRANSMIT_BUFFER_SPACE, // Q
830 OID_GEN_RECEIVE_BUFFER_SPACE, // Q
831 OID_GEN_TRANSMIT_BLOCK_SIZE, // Q
832 OID_GEN_RECEIVE_BLOCK_SIZE, // Q
833 OID_GEN_VENDOR_ID, // Q
834 OID_GEN_VENDOR_DESCRIPTION, // Q
835 OID_GEN_CURRENT_PACKET_FILTER, // QS
836 OID_GEN_CURRENT_LOOKAHEAD, // QS
837 OID_GEN_DRIVER_VERSION, // Q
838 OID_GEN_MAXIMUM_TOTAL_SIZE, // Q
839 OID_GEN_PROTOCOL_OPTIONS, // S
840 OID_GEN_MAC_OPTIONS, // Q
841 OID_GEN_MEDIA_CONNECT_STATUS, // Q
842 OID_GEN_MAXIMUM_SEND_PACKETS, // Q
843 /* stats */
844 OID_GEN_XMIT_OK, // Q
845 OID_GEN_RCV_OK, // Q
846 OID_GEN_XMIT_ERROR, // Q
847 OID_GEN_RCV_ERROR, // Q
848 OID_GEN_RCV_NO_BUFFER, // Q
849 /* media-specific OIDs */
850 OID_802_3_PERMANENT_ADDRESS,
851 OID_802_3_CURRENT_ADDRESS,
852 OID_802_3_MULTICAST_LIST,
853 OID_802_3_MAXIMUM_LIST_SIZE,
854 };
856 NDIS_STATUS
857 XenNet_QueryInformation(
858 IN NDIS_HANDLE MiniportAdapterContext,
859 IN NDIS_OID Oid,
860 IN PVOID InformationBuffer,
861 IN ULONG InformationBufferLength,
862 OUT PULONG BytesWritten,
863 OUT PULONG BytesNeeded)
864 {
865 struct xennet_info *xi = MiniportAdapterContext;
866 UCHAR vendor_desc[] = XN_VENDOR_DESC;
867 ULONG64 temp_data;
868 PVOID data = &temp_data;
869 UINT len = 4;
870 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
872 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
874 switch(Oid)
875 {
876 case OID_GEN_SUPPORTED_LIST:
877 data = supported_oids;
878 len = sizeof(supported_oids);
879 break;
880 case OID_GEN_HARDWARE_STATUS:
881 if (!xi->connected)
882 temp_data = NdisHardwareStatusInitializing;
883 else
884 temp_data = NdisHardwareStatusReady;
885 break;
886 case OID_GEN_MEDIA_SUPPORTED:
887 temp_data = NdisMedium802_3;
888 break;
889 case OID_GEN_MEDIA_IN_USE:
890 temp_data = NdisMedium802_3;
891 break;
892 case OID_GEN_MAXIMUM_LOOKAHEAD:
893 temp_data = XN_DATA_SIZE;
894 break;
895 case OID_GEN_MAXIMUM_FRAME_SIZE:
896 // According to the specs, OID_GEN_MAXIMUM_FRAME_SIZE does not include the header, so
897 // it is XN_DATA_SIZE not XN_MAX_PKT_SIZE
898 temp_data = XN_DATA_SIZE; // XN_MAX_PKT_SIZE;
899 break;
900 case OID_GEN_LINK_SPEED:
901 temp_data = 10000000; /* 1Gb */
902 break;
903 case OID_GEN_TRANSMIT_BUFFER_SPACE:
904 /* pkts times sizeof ring, maybe? */
905 temp_data = XN_MAX_PKT_SIZE * NET_TX_RING_SIZE;
906 break;
907 case OID_GEN_RECEIVE_BUFFER_SPACE:
908 /* pkts times sizeof ring, maybe? */
909 temp_data = XN_MAX_PKT_SIZE * NET_RX_RING_SIZE;
910 break;
911 case OID_GEN_TRANSMIT_BLOCK_SIZE:
912 temp_data = XN_MAX_PKT_SIZE;
913 break;
914 case OID_GEN_RECEIVE_BLOCK_SIZE:
915 temp_data = XN_MAX_PKT_SIZE;
916 break;
917 case OID_GEN_VENDOR_ID:
918 temp_data = 0xFFFFFF; // Not guaranteed to be XENSOURCE_MAC_HDR;
919 break;
920 case OID_GEN_VENDOR_DESCRIPTION:
921 data = vendor_desc;
922 len = sizeof(vendor_desc);
923 break;
924 case OID_GEN_CURRENT_PACKET_FILTER:
925 temp_data = xi->packet_filter;
926 break;
927 case OID_GEN_CURRENT_LOOKAHEAD:
928 // TODO: we should store this...
929 temp_data = XN_MAX_PKT_SIZE;
930 break;
931 case OID_GEN_DRIVER_VERSION:
932 temp_data = (NDIS_MAJOR_VER << 8) | NDIS_MINOR_VER;
933 len = 2;
934 break;
935 case OID_GEN_MAXIMUM_TOTAL_SIZE:
936 temp_data = XN_MAX_PKT_SIZE;
937 break;
938 case OID_GEN_MAC_OPTIONS:
939 temp_data = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
940 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
941 NDIS_MAC_OPTION_NO_LOOPBACK;
942 break;
943 case OID_GEN_MEDIA_CONNECT_STATUS:
944 if (xi->connected)
945 temp_data = NdisMediaStateConnected;
946 else
947 temp_data = NdisMediaStateDisconnected;
948 break;
949 case OID_GEN_MAXIMUM_SEND_PACKETS:
950 temp_data = XN_MAX_SEND_PKTS;
951 break;
952 case OID_GEN_XMIT_OK:
953 temp_data = xi->stat_tx_ok;
954 len = sizeof(ULONG64);
955 break;
956 case OID_GEN_RCV_OK:
957 temp_data = xi->stat_rx_ok;
958 len = sizeof(ULONG64);
959 break;
960 case OID_GEN_XMIT_ERROR:
961 temp_data = xi->stat_tx_error;
962 len = sizeof(ULONG64);
963 break;
964 case OID_GEN_RCV_ERROR:
965 temp_data = xi->stat_rx_error;
966 len = sizeof(ULONG64);
967 break;
968 case OID_GEN_RCV_NO_BUFFER:
969 temp_data = xi->stat_rx_no_buffer;
970 len = sizeof(ULONG64);
971 break;
972 case OID_802_3_PERMANENT_ADDRESS:
973 data = xi->perm_mac_addr;
974 len = ETH_ALEN;
975 break;
976 case OID_802_3_CURRENT_ADDRESS:
977 data = xi->curr_mac_addr;
978 len = ETH_ALEN;
979 break;
980 case OID_802_3_MULTICAST_LIST:
981 data = NULL;
982 len = 0;
983 case OID_802_3_MAXIMUM_LIST_SIZE:
984 temp_data = 0; /* no mcast support */
985 break;
986 default:
987 KdPrint(("Get Unknown OID 0x%x\n", Oid));
988 status = NDIS_STATUS_NOT_SUPPORTED;
989 }
991 if (!NT_SUCCESS(status))
992 {
993 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (returned error)\n"));
994 return status;
995 }
997 if (len > InformationBufferLength)
998 {
999 *BytesNeeded = len;
1000 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (returned error)\n"));
1001 return NDIS_STATUS_BUFFER_TOO_SHORT;
1004 *BytesWritten = len;
1005 if (len)
1007 NdisMoveMemory(InformationBuffer, data, len);
1010 //KdPrint(("Got OID 0x%x\n", Oid));
1011 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1013 return status;
1016 NDIS_STATUS
1017 XenNet_SetInformation(
1018 IN NDIS_HANDLE MiniportAdapterContext,
1019 IN NDIS_OID Oid,
1020 IN PVOID InformationBuffer,
1021 IN ULONG InformationBufferLength,
1022 OUT PULONG BytesRead,
1023 OUT PULONG BytesNeeded
1026 NTSTATUS status;
1027 struct xennet_info *xi = MiniportAdapterContext;
1028 PULONG64 data = InformationBuffer;
1030 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1032 UNREFERENCED_PARAMETER(MiniportAdapterContext);
1033 UNREFERENCED_PARAMETER(InformationBufferLength);
1034 UNREFERENCED_PARAMETER(BytesRead);
1035 UNREFERENCED_PARAMETER(BytesNeeded);
1037 switch(Oid)
1039 case OID_GEN_SUPPORTED_LIST:
1040 status = NDIS_STATUS_NOT_SUPPORTED;
1041 KdPrint(("Unsupported set OID_GEN_SUPPORTED_LIST\n"));
1042 break;
1043 case OID_GEN_HARDWARE_STATUS:
1044 status = NDIS_STATUS_NOT_SUPPORTED;
1045 KdPrint(("Unsupported set OID_GEN_HARDWARE_STATUS\n"));
1046 break;
1047 case OID_GEN_MEDIA_SUPPORTED:
1048 status = NDIS_STATUS_NOT_SUPPORTED;
1049 KdPrint(("Unsupported set OID_GEN_MEDIA_SUPPORTED\n"));
1050 break;
1051 case OID_GEN_MEDIA_IN_USE:
1052 status = NDIS_STATUS_NOT_SUPPORTED;
1053 KdPrint(("Unsupported set OID_GEN_MEDIA_IN_USE\n"));
1054 break;
1055 case OID_GEN_MAXIMUM_LOOKAHEAD:
1056 status = NDIS_STATUS_NOT_SUPPORTED;
1057 KdPrint(("Unsupported set OID_GEN_MAXIMUM_LOOKAHEAD\n"));
1058 break;
1059 case OID_GEN_MAXIMUM_FRAME_SIZE:
1060 status = NDIS_STATUS_NOT_SUPPORTED;
1061 KdPrint(("Unsupported set OID_GEN_MAXIMUM_FRAME_SIZE\n"));
1062 break;
1063 case OID_GEN_LINK_SPEED:
1064 status = NDIS_STATUS_NOT_SUPPORTED;
1065 KdPrint(("Unsupported set OID_GEN_LINK_SPEED\n"));
1066 break;
1067 case OID_GEN_TRANSMIT_BUFFER_SPACE:
1068 status = NDIS_STATUS_NOT_SUPPORTED;
1069 KdPrint(("Unsupported set OID_GEN_TRANSMIT_BUFFER_SPACE\n"));
1070 break;
1071 case OID_GEN_RECEIVE_BUFFER_SPACE:
1072 status = NDIS_STATUS_NOT_SUPPORTED;
1073 KdPrint(("Unsupported set OID_GEN_RECEIVE_BUFFER_SPACE\n"));
1074 break;
1075 case OID_GEN_TRANSMIT_BLOCK_SIZE:
1076 status = NDIS_STATUS_NOT_SUPPORTED;
1077 KdPrint(("Unsupported set OID_GEN_TRANSMIT_BLOCK_SIZE\n"));
1078 break;
1079 case OID_GEN_RECEIVE_BLOCK_SIZE:
1080 status = NDIS_STATUS_NOT_SUPPORTED;
1081 KdPrint(("Unsupported set OID_GEN_RECEIVE_BLOCK_SIZE\n"));
1082 break;
1083 case OID_GEN_VENDOR_ID:
1084 status = NDIS_STATUS_NOT_SUPPORTED;
1085 KdPrint(("Unsupported set OID_GEN_VENDOR_ID\n"));
1086 break;
1087 case OID_GEN_VENDOR_DESCRIPTION:
1088 status = NDIS_STATUS_NOT_SUPPORTED;
1089 KdPrint(("Unsupported set OID_GEN_VENDOR_DESCRIPTION\n"));
1090 break;
1091 case OID_GEN_CURRENT_PACKET_FILTER:
1092 KdPrint(("Set OID_GEN_CURRENT_PACKET_FILTER\n"));
1093 xi->packet_filter = *(ULONG *)data;
1094 status = NDIS_STATUS_SUCCESS;
1095 break;
1096 case OID_GEN_CURRENT_LOOKAHEAD:
1097 KdPrint(("Set OID_GEN_CURRENT_LOOKAHEAD %d\n", *(int *)data));
1098 // TODO: We should do this...
1099 status = NDIS_STATUS_SUCCESS;
1100 break;
1101 case OID_GEN_DRIVER_VERSION:
1102 status = NDIS_STATUS_NOT_SUPPORTED;
1103 KdPrint(("Unsupported set OID_GEN_DRIVER_VERSION\n"));
1104 break;
1105 case OID_GEN_MAXIMUM_TOTAL_SIZE:
1106 status = NDIS_STATUS_NOT_SUPPORTED;
1107 KdPrint(("Unsupported set OID_GEN_MAXIMUM_TOTAL_SIZE\n"));
1108 break;
1109 case OID_GEN_PROTOCOL_OPTIONS:
1110 KdPrint(("Unsupported set OID_GEN_PROTOCOL_OPTIONS\n"));
1111 // TODO - actually do this...
1112 status = NDIS_STATUS_SUCCESS;
1113 break;
1114 case OID_GEN_MAC_OPTIONS:
1115 status = NDIS_STATUS_NOT_SUPPORTED;
1116 KdPrint(("Unsupported set OID_GEN_MAC_OPTIONS\n"));
1117 break;
1118 case OID_GEN_MEDIA_CONNECT_STATUS:
1119 status = NDIS_STATUS_NOT_SUPPORTED;
1120 KdPrint(("Unsupported set OID_GEN_MEDIA_CONNECT_STATUS\n"));
1121 break;
1122 case OID_GEN_MAXIMUM_SEND_PACKETS:
1123 status = NDIS_STATUS_NOT_SUPPORTED;
1124 KdPrint(("Unsupported set OID_GEN_MAXIMUM_SEND_PACKETS\n"));
1125 break;
1126 case OID_GEN_XMIT_OK:
1127 status = NDIS_STATUS_NOT_SUPPORTED;
1128 KdPrint(("Unsupported set OID_GEN_XMIT_OK\n"));
1129 break;
1130 case OID_GEN_RCV_OK:
1131 status = NDIS_STATUS_NOT_SUPPORTED;
1132 KdPrint(("Unsupported set OID_GEN_RCV_OK\n"));
1133 break;
1134 case OID_GEN_XMIT_ERROR:
1135 status = NDIS_STATUS_NOT_SUPPORTED;
1136 KdPrint(("Unsupported set OID_GEN_XMIT_ERROR\n"));
1137 break;
1138 case OID_GEN_RCV_ERROR:
1139 status = NDIS_STATUS_NOT_SUPPORTED;
1140 KdPrint(("Unsupported set OID_GEN_RCV_ERROR\n"));
1141 break;
1142 case OID_GEN_RCV_NO_BUFFER:
1143 status = NDIS_STATUS_NOT_SUPPORTED;
1144 KdPrint(("Unsupported set OID_GEN_RCV_NO_BUFFER\n"));
1145 break;
1146 case OID_802_3_PERMANENT_ADDRESS:
1147 status = NDIS_STATUS_NOT_SUPPORTED;
1148 KdPrint(("Unsupported set OID_802_3_PERMANENT_ADDRESS\n"));
1149 break;
1150 case OID_802_3_CURRENT_ADDRESS:
1151 status = NDIS_STATUS_NOT_SUPPORTED;
1152 KdPrint(("Unsupported set OID_802_3_CURRENT_ADDRESS\n"));
1153 break;
1154 case OID_802_3_MULTICAST_LIST:
1155 status = NDIS_STATUS_NOT_SUPPORTED;
1156 KdPrint(("Unsupported set OID_802_3_MULTICAST_LIST\n"));
1157 break;
1158 case OID_802_3_MAXIMUM_LIST_SIZE:
1159 status = NDIS_STATUS_NOT_SUPPORTED;
1160 KdPrint(("Unsupported set OID_802_3_MAXIMUM_LIST_SIZE\n"));
1161 break;
1162 default:
1163 KdPrint(("Set Unknown OID 0x%x\n", Oid));
1164 status = NDIS_STATUS_NOT_SUPPORTED;
1165 break;
1167 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1168 return status;
1171 VOID
1172 XenNet_ReturnPacket(
1173 IN NDIS_HANDLE MiniportAdapterContext,
1174 IN PNDIS_PACKET Packet
1177 PNDIS_BUFFER buffer;
1178 PVOID buff_va;
1179 UINT buff_len;
1180 UINT tot_buff_len;
1182 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1184 UNREFERENCED_PARAMETER(MiniportAdapterContext);
1186 NdisGetFirstBufferFromPacketSafe(Packet, &buffer, &buff_va, &buff_len,
1187 &tot_buff_len, NormalPagePriority);
1188 ASSERT(buff_len == tot_buff_len);
1190 NdisFreeMemory(buff_va, 0, 0);
1191 NdisFreeBuffer(buffer);
1192 NdisFreePacket(Packet);
1194 //KdPrint((__FUNCTION__ " called\n"));
1195 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1198 PMDL
1199 XenNet_Linearize(PNDIS_PACKET Packet)
1201 NDIS_STATUS status;
1202 PMDL pmdl;
1203 char *start;
1204 PNDIS_BUFFER buffer;
1205 PVOID buff_va;
1206 UINT buff_len;
1207 UINT tot_buff_len;
1209 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1211 NdisGetFirstBufferFromPacketSafe(Packet, &buffer, &buff_va, &buff_len,
1212 &tot_buff_len, NormalPagePriority);
1213 ASSERT(tot_buff_len <= XN_MAX_PKT_SIZE);
1215 status = NdisAllocateMemoryWithTag(&start, tot_buff_len, XENNET_POOL_TAG);
1216 if (!NT_SUCCESS(status))
1218 KdPrint(("Could not allocate memory for linearization\n"));
1219 return NULL;
1221 pmdl = IoAllocateMdl(start, tot_buff_len, FALSE, FALSE, FALSE);
1222 if (!pmdl)
1224 KdPrint(("Could not allocate MDL for linearization\n"));
1225 NdisFreeMemory(start, 0, 0);
1226 return NULL;
1228 MmBuildMdlForNonPagedPool(pmdl);
1230 while (buffer)
1232 NdisQueryBufferSafe(buffer, &buff_va, &buff_len, NormalPagePriority);
1233 RtlCopyMemory(start, buff_va, buff_len);
1234 start += buff_len;
1235 NdisGetNextBuffer(buffer, &buffer);
1238 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1239 return pmdl;
1242 VOID
1243 XenNet_SendPackets(
1244 IN NDIS_HANDLE MiniportAdapterContext,
1245 IN PPNDIS_PACKET PacketArray,
1246 IN UINT NumberOfPackets
1249 struct xennet_info *xi = MiniportAdapterContext;
1250 PNDIS_PACKET curr_packet;
1251 UINT i;
1252 struct netif_tx_request *tx;
1253 unsigned short id;
1254 int notify;
1255 PMDL pmdl;
1256 UINT pkt_size;
1257 KIRQL OldIrql;
1259 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1261 KeAcquireSpinLock(&xi->TxLock, &OldIrql);
1263 for (i = 0; i < NumberOfPackets; i++)
1265 curr_packet = PacketArray[i];
1266 ASSERT(curr_packet);
1268 NdisQueryPacket(curr_packet, NULL, NULL, NULL, &pkt_size);
1270 //KdPrint(("sending pkt, len %d\n", pkt_size));
1272 pmdl = XenNet_Linearize(curr_packet);
1273 if (!pmdl)
1275 KdPrint((__DRIVER_NAME "Couldn't linearize packet!\n"));
1276 NdisMSendComplete(xi, curr_packet, NDIS_STATUS_FAILURE);
1277 break;
1279 *((PMDL *)curr_packet->MiniportReservedEx) = pmdl;
1281 id = get_id_from_freelist(xi->tx_pkts);
1282 xi->tx_pkts[id] = curr_packet;
1284 tx = RING_GET_REQUEST(&xi->tx, xi->tx.req_prod_pvt);
1285 tx->id = id;
1286 tx->gref = xi->XenInterface.GntTbl_GrantAccess(
1287 xi->XenInterface.InterfaceHeader.Context,
1288 0,
1289 *MmGetMdlPfnArray(pmdl),
1290 TRUE);
1291 xi->grant_tx_ref[id] = tx->gref;
1292 tx->offset = (uint16_t)MmGetMdlByteOffset(pmdl);
1293 tx->size = (UINT16)pkt_size;
1294 // NETTXF_csum_blank should only be used for tcp and udp packets...
1295 tx->flags = 0; //NETTXF_csum_blank;
1297 xi->tx.req_prod_pvt++;
1299 // NDIS_SET_PACKET_STATUS(curr_packet, NDIS_STATUS_SUCCESS);
1300 // NdisMSendComplete(xi, curr_packet, NDIS_STATUS_SUCCESS);
1303 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xi->tx, notify);
1304 if (notify)
1306 xi->XenInterface.EvtChn_Notify(xi->XenInterface.InterfaceHeader.Context,
1307 xi->event_channel);
1310 KeReleaseSpinLock(&xi->TxLock, OldIrql);
1312 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1315 VOID
1316 XenNet_PnPEventNotify(
1317 IN NDIS_HANDLE MiniportAdapterContext,
1318 IN NDIS_DEVICE_PNP_EVENT PnPEvent,
1319 IN PVOID InformationBuffer,
1320 IN ULONG InformationBufferLength
1323 UNREFERENCED_PARAMETER(MiniportAdapterContext);
1324 UNREFERENCED_PARAMETER(PnPEvent);
1325 UNREFERENCED_PARAMETER(InformationBuffer);
1326 UNREFERENCED_PARAMETER(InformationBufferLength);
1328 KdPrint((__FUNCTION__ " called\n"));
1331 VOID
1332 XenNet_Shutdown(
1333 IN NDIS_HANDLE MiniportAdapterContext
1336 //struct xennet_info *xi = MiniportAdapterContext;
1337 UNREFERENCED_PARAMETER(MiniportAdapterContext);
1339 // I think all we are supposed to do here is reset the adapter, which for us might be nothing...
1341 KdPrint((__FUNCTION__ " called\n"));
1344 NTSTATUS
1345 DriverEntry(
1346 PDRIVER_OBJECT DriverObject,
1347 PUNICODE_STRING RegistryPath
1350 NTSTATUS status;
1351 WDF_DRIVER_CONFIG config;
1352 NDIS_HANDLE ndis_wrapper_handle;
1353 NDIS_MINIPORT_CHARACTERISTICS mini_chars;
1355 RtlZeroMemory(&mini_chars, sizeof(mini_chars));
1357 WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK);
1358 config.DriverInitFlags |= WdfDriverInitNoDispatchOverride;
1360 status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES,
1361 &config, WDF_NO_HANDLE);
1362 if (!NT_SUCCESS(status))
1364 KdPrint(("WdfDriverCreate failed err = 0x%x\n", status));
1365 return status;
1368 NdisMInitializeWrapper(&ndis_wrapper_handle, DriverObject, RegistryPath, NULL);
1369 if (!ndis_wrapper_handle)
1371 KdPrint(("NdisMInitializeWrapper failed\n"));
1372 return NDIS_STATUS_FAILURE;
1375 /* NDIS 5.1 driver */
1376 mini_chars.MajorNdisVersion = NDIS_MAJOR_VER;
1377 mini_chars.MinorNdisVersion = NDIS_MINOR_VER;
1379 mini_chars.HaltHandler = XenNet_Halt;
1380 mini_chars.InitializeHandler = XenNet_Init;
1381 mini_chars.ISRHandler = NULL; // needed if we register interrupt?
1382 mini_chars.QueryInformationHandler = XenNet_QueryInformation;
1383 mini_chars.ResetHandler = NULL; //TODO: fill in
1384 mini_chars.SetInformationHandler = XenNet_SetInformation;
1385 /* added in v.4 -- use multiple pkts interface */
1386 mini_chars.ReturnPacketHandler = XenNet_ReturnPacket;
1387 mini_chars.SendPacketsHandler = XenNet_SendPackets;
1388 /* added in v.5.1 */
1389 mini_chars.PnPEventNotifyHandler = XenNet_PnPEventNotify;
1390 mini_chars.AdapterShutdownHandler = XenNet_Shutdown;
1392 /* TODO: we don't have hardware, but we have "resources", so do we need to implement fns to handle this? */
1394 /* set up upper-edge interface */
1395 status = NdisMRegisterMiniport(ndis_wrapper_handle, &mini_chars, sizeof(mini_chars));
1396 if (!NT_SUCCESS(status))
1398 KdPrint(("NdisMRegisterMiniport failed, status = 0x%x\n", status));
1399 NdisTerminateWrapper(ndis_wrapper_handle, NULL);
1400 return status;
1403 return status;