win-pvdrivers

view xennet/xennet.c @ 22:2e1ad5552529

xennet: get mac from backend; watch backend for state changes
author Andy Grover <andy@groveronline.com>
date Fri Nov 30 10:21:12 2007 -0800 (2007-11-30)
parents e2d29b60b744
children e4f0a0a21488
line source
1 /*
2 PV Net Driver for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
4 Copyright (C) 2007 Andrew Grover
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 #if !defined (NDIS51_MINIPORT)
26 #error requires NDIS 5.1 compilation environment
27 #endif
29 #define GRANT_INVALID_REF 0
31 #define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE)
32 #define NET_RX_RING_SIZE __RING_SIZE((struct netif_rx_sring *)0, PAGE_SIZE)
34 #pragma warning(disable: 4127)
36 struct xennet_info
37 {
38 PDEVICE_OBJECT pdo;
39 PDEVICE_OBJECT fdo;
40 PDEVICE_OBJECT lower_do;
41 WDFDEVICE wdf_device;
43 WCHAR name[NAME_SIZE];
44 NDIS_HANDLE adapter_handle;
45 ULONG packet_filter;
46 UINT8 perm_mac_addr[ETH_ALEN];
47 UINT8 curr_mac_addr[ETH_ALEN];
49 char Path[128];
50 char BackendPath[128];
51 XEN_IFACE_EVTCHN EvtChnInterface;
52 XEN_IFACE_XENBUS XenBusInterface;
53 XEN_IFACE_XEN XenInterface;
54 XEN_IFACE_GNTTBL GntTblInterface;
56 struct netif_tx_front_ring tx;
57 struct netif_rx_front_ring rx;
59 PMDL tx_mdl;
60 PMDL rx_mdl;
61 struct netif_tx_sring *tx_pgs;
62 struct netif_rx_sring *rx_pgs;
64 UINT irq;
65 evtchn_port_t event_channel;
67 grant_ref_t tx_ring_ref;
68 grant_ref_t rx_ring_ref;
69 };
71 /* need to do typedef so the DECLARE below works */
72 typedef struct _wdf_device_info
73 {
74 struct xennet_info *xennet_info;
75 } wdf_device_info;
77 WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(wdf_device_info, GetWdfDeviceInfo)
79 /* This function copied from linux's lib/vsprintf.c, see it for attribution */
80 static unsigned long
81 simple_strtoul(const char *cp,char **endp,unsigned int base)
82 {
83 unsigned long result = 0,value;
85 if (!base) {
86 base = 10;
87 if (*cp == '0') {
88 base = 8;
89 cp++;
90 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
91 cp++;
92 base = 16;
93 }
94 }
95 } else if (base == 16) {
96 if (cp[0] == '0' && toupper(cp[1]) == 'X')
97 cp += 2;
98 }
99 while (isxdigit(*cp) &&
100 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
101 result = result*base + value;
102 cp++;
103 }
104 if (endp)
105 *endp = (char *)cp;
106 return result;
107 }
109 static PMDL
110 AllocatePages(int Pages)
111 {
112 PHYSICAL_ADDRESS Min;
113 PHYSICAL_ADDRESS Max;
114 PHYSICAL_ADDRESS Align;
115 PMDL Mdl;
117 KdPrint((__DRIVER_NAME " --> Allocate Pages\n"));
119 Min.QuadPart = 0;
120 Max.QuadPart = 0xFFFFFFFF;
121 Align.QuadPart = PAGE_SIZE;
123 Mdl = MmAllocatePagesForMdl(Min, Max, Align, Pages * PAGE_SIZE);
125 KdPrint((__DRIVER_NAME " <-- Allocate Pages (mdl = %08x)\n", Mdl));
127 return Mdl;
128 }
130 static PMDL
131 AllocatePage()
132 {
133 return AllocatePages(1);
134 }
136 static BOOLEAN
137 XenNet_Interrupt(
138 PKINTERRUPT Interrupt,
139 PVOID ServiceContext
140 )
141 {
142 // struct xennet_info *xennet_info = ServiceContext;
143 // KIRQL KIrql;
145 UNREFERENCED_PARAMETER(Interrupt);
146 UNREFERENCED_PARAMETER(ServiceContext);
148 // KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
149 // KdPrint((__DRIVER_NAME " --> Setting Dpc Event\n"));
150 // KeSetEvent(&ChildDeviceData->DpcThreadEvent, 1, FALSE);
151 // KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
152 // KdPrint((__DRIVER_NAME " --> Dpc Event Set\n"));
154 /* do something */
156 return TRUE;
157 }
159 static VOID
160 XenNet_BackEndStateHandler(char *Path, PVOID Data)
161 {
162 struct xennet_info *xi = Data;
163 char *Value;
164 int be_state;
166 xi->XenBusInterface.Read(xi->XenBusInterface.InterfaceHeader.Context,
167 XBT_NIL, Path, &Value);
168 be_state = atoi(Value);
169 ExFreePool(Value);
171 switch (be_state)
172 {
173 case XenbusStateUnknown:
174 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
175 break;
177 case XenbusStateInitialising:
178 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
179 break;
181 case XenbusStateInitWait:
182 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
184 /* do stuff here */
186 KdPrint((__DRIVER_NAME " Set Frontend state to Initialised\n"));
187 break;
189 case XenbusStateInitialised:
190 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
191 // create the device
192 break;
194 case XenbusStateConnected:
195 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
197 /* do more stuff here */
199 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
200 break;
202 case XenbusStateClosing:
203 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
204 break;
206 case XenbusStateClosed:
207 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
208 break;
210 default:
211 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", be_state));
212 break;
213 }
215 }
218 VOID
219 XenNet_Halt(
220 IN NDIS_HANDLE MiniportAdapterContext
221 )
222 {
223 UNREFERENCED_PARAMETER(MiniportAdapterContext);
224 }
226 static NDIS_STATUS
227 XenNet_Init(
228 OUT PNDIS_STATUS OpenErrorStatus,
229 OUT PUINT SelectedMediumIndex,
230 IN PNDIS_MEDIUM MediumArray,
231 IN UINT MediumArraySize,
232 IN NDIS_HANDLE MiniportAdapterHandle,
233 IN NDIS_HANDLE WrapperConfigurationContext
234 )
235 {
236 NDIS_STATUS status;
237 UINT i;
238 BOOLEAN medium_found = FALSE;
239 struct xennet_info *xi = NULL;
240 ULONG length;
241 WDF_OBJECT_ATTRIBUTES wdf_attrs;
242 char *msg;
243 char *Value;
244 char **vif_devs;
245 char TmpPath[128];
247 UNREFERENCED_PARAMETER(OpenErrorStatus);
248 UNREFERENCED_PARAMETER(WrapperConfigurationContext);
250 /* deal with medium stuff */
251 for (i = 0; i < MediumArraySize; i++)
252 {
253 if (MediumArray[i] == NdisMedium802_3)
254 {
255 medium_found = TRUE;
256 break;
257 }
258 }
259 if (!medium_found)
260 {
261 KdPrint(("NIC_MEDIA_TYPE not in MediumArray\n"));
262 return NDIS_STATUS_UNSUPPORTED_MEDIA;
263 }
264 *SelectedMediumIndex = i;
266 /* Alloc memory for adapter private info */
267 status = NdisAllocateMemoryWithTag(&xi, sizeof(*xi), XENNET_POOL_TAG);
268 if (!NT_SUCCESS(status))
269 {
270 KdPrint(("NdisAllocateMemoryWithTag failed with 0x%x\n", status));
271 status = NDIS_STATUS_RESOURCES;
272 goto err;
273 }
274 RtlZeroMemory(xi, sizeof(*xi));
276 /* init xennet_info */
277 xi->adapter_handle = MiniportAdapterHandle;
278 NdisMGetDeviceProperty(MiniportAdapterHandle, &xi->pdo, &xi->fdo,
279 &xi->lower_do, NULL, NULL);
281 status = IoGetDeviceProperty(xi->pdo, DevicePropertyDeviceDescription,
282 NAME_SIZE, xi->name, &length);
283 if (!NT_SUCCESS(status))
284 {
285 KdPrint(("IoGetDeviceProperty failed with 0x%x\n", status));
286 status = NDIS_STATUS_FAILURE;
287 goto err;
288 }
290 NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE) xi,
291 0, NDIS_ATTRIBUTE_DESERIALIZE, NdisInterfaceInternal);
293 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&wdf_attrs, wdf_device_info);
295 status = WdfDeviceMiniportCreate(WdfGetDriver(), &wdf_attrs, xi->fdo,
296 xi->lower_do, xi->pdo, &xi->wdf_device);
297 if (!NT_SUCCESS(status))
298 {
299 KdPrint(("WdfDeviceMiniportCreate failed with 0x%x\n", status));
300 status = NDIS_STATUS_FAILURE;
301 goto err;
302 }
304 GetWdfDeviceInfo(xi->wdf_device)->xennet_info = xi;
306 /* get lower (Xen) interfaces */
308 status = WdfFdoQueryForInterface(xi->wdf_device, &GUID_XEN_IFACE_EVTCHN,
309 (PINTERFACE) &xi->EvtChnInterface, sizeof(XEN_IFACE_EVTCHN), 1, NULL);
310 if(!NT_SUCCESS(status))
311 {
312 KdPrint(("WdfFdoQueryForInterface (EvtChn) failed with status 0x%08x\n", status));
313 status = NDIS_STATUS_FAILURE;
314 goto err;
315 }
317 status = WdfFdoQueryForInterface(xi->wdf_device, &GUID_XEN_IFACE_XENBUS,
318 (PINTERFACE) &xi->XenBusInterface, sizeof(XEN_IFACE_XENBUS), 1, NULL);
319 if(!NT_SUCCESS(status))
320 {
321 KdPrint(("WdfFdoQueryForInterface (XenBus) failed with status 0x%08x\n", status));
322 status = NDIS_STATUS_FAILURE;
323 goto err;
324 }
326 #if 0
327 status = WdfFdoQueryForInterface(xi->wdf_device, &GUID_XEN_IFACE_XEN,
328 (PINTERFACE) &xi->XenInterface, sizeof(XEN_IFACE_XEN), 1, NULL);
329 if(!NT_SUCCESS(status))
330 {
331 KdPrint(("WdfFdoQueryForInterface (Xen) failed with status 0x%08x\n", status));
332 status = NDIS_STATUS_FAILURE;
333 goto err;
334 }
335 #endif
337 status = WdfFdoQueryForInterface(xi->wdf_device, &GUID_XEN_IFACE_GNTTBL,
338 (PINTERFACE) &xi->GntTblInterface, sizeof(XEN_IFACE_GNTTBL), 1, NULL);
339 if(!NT_SUCCESS(status))
340 {
341 KdPrint(("WdfFdoQueryForInterface (GntTbl) failed with status 0x%08x\n", status));
342 status = NDIS_STATUS_FAILURE;
343 goto err;
344 }
346 xi->event_channel = xi->EvtChnInterface.AllocUnbound(
347 xi->EvtChnInterface.InterfaceHeader.Context, 0);
348 xi->EvtChnInterface.Bind(xi->EvtChnInterface.InterfaceHeader.Context,
349 xi->event_channel, XenNet_Interrupt, xi);
351 /* TODO: must free pages in MDL as well as MDL using MmFreePagesFromMdl and ExFreePool */
352 // or, allocate mem and then get mdl, then free mdl
353 xi->tx_mdl = AllocatePage();
354 xi->tx_pgs = MmMapLockedPagesSpecifyCache(xi->tx_mdl, KernelMode, MmNonCached,
355 NULL, FALSE, NormalPagePriority);
356 SHARED_RING_INIT(xi->tx_pgs);
357 FRONT_RING_INIT(&xi->tx, xi->tx_pgs, PAGE_SIZE);
358 xi->tx_ring_ref = xi->GntTblInterface.GrantAccess(
359 xi->GntTblInterface.InterfaceHeader.Context, 0,
360 *MmGetMdlPfnArray(xi->tx_mdl), FALSE);
362 xi->rx_mdl = AllocatePage();
363 xi->rx_pgs = MmMapLockedPagesSpecifyCache(xi->rx_mdl, KernelMode, MmNonCached,
364 NULL, FALSE, NormalPagePriority);
365 SHARED_RING_INIT(xi->rx_pgs);
366 FRONT_RING_INIT(&xi->rx, xi->rx_pgs, PAGE_SIZE);
367 xi->rx_ring_ref = xi->GntTblInterface.GrantAccess(
368 xi->GntTblInterface.InterfaceHeader.Context, 0,
369 *MmGetMdlPfnArray(xi->rx_mdl), FALSE);
371 msg = xi->XenBusInterface.List(xi->EvtChnInterface.InterfaceHeader.Context,
372 XBT_NIL, "device/vif", &vif_devs);
373 if (msg)
374 {
375 KdPrint((__DRIVER_NAME ": " __FUNCTION__ ": List retval is nonzero!\n"));
376 status = NDIS_STATUS_FAILURE;
377 goto err;
378 }
380 for (i = 0; vif_devs[i]; i++)
381 {
382 if (i > 0)
383 {
384 KdPrint((__DRIVER_NAME "Can only handle 1 vif so far, ignoring vif %s\n", vif_devs[i]));
385 continue;
386 }
387 RtlStringCbPrintfA(xi->Path, ARRAY_SIZE(xi->Path), "device/vif/%s", vif_devs[i]);
389 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath),
390 "device/vif/%s/state", vif_devs[i]);
391 KdPrint(("%s\n", TmpPath));
393 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/backend", xi->Path);
394 xi->XenBusInterface.Read(xi->XenBusInterface.InterfaceHeader.Context,
395 XBT_NIL, TmpPath, &Value);
396 if (!Value)
397 {
398 KdPrint((__DRIVER_NAME " backend Read Failed\n"));
399 }
400 else
401 {
402 RtlStringCbCopyA(xi->BackendPath, ARRAY_SIZE(xi->BackendPath), Value);
403 KdPrint((__DRIVER_NAME "backend path = %s\n", xi->BackendPath));
404 }
405 ExFreePool(Value);
407 /* Add watch on backend state */
408 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), xi->BackendPath);
409 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/state");
410 xi->XenBusInterface.AddWatch(xi->XenBusInterface.InterfaceHeader.Context,
411 XBT_NIL, TmpPath, XenNet_BackEndStateHandler, xi);
413 /* get mac address */
414 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/mac", xi->Path);
415 xi->XenBusInterface.Read(xi->XenBusInterface.InterfaceHeader.Context,
416 XBT_NIL, TmpPath, &Value);
417 if (!Value)
418 {
419 KdPrint((__DRIVER_NAME " mac Read Failed\n"));
420 }
421 else
422 {
423 char *s, *e;
424 int i;
426 s = Value;
428 for (i = 0; i < ETH_ALEN; i++) {
429 xi->perm_mac_addr[i] = (UINT8)simple_strtoul(s, &e, 16);
430 if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
431 KdPrint((__DRIVER_NAME "Error parsing MAC address\n"));
432 ExFreePool(Value);
433 ExFreePool(vif_devs);
434 status = NDIS_STATUS_FAILURE;
435 goto err;
436 }
437 s = e + 1;
438 }
439 }
440 ExFreePool(Value);
442 //XenVbd_HotPlugHandler(buffer, NULL);
443 //ExFreePoolWithTag(bdDevices[i], XENPCI_POOL_TAG);
444 }
445 ExFreePool(vif_devs);
447 return NDIS_STATUS_SUCCESS;
449 err:
450 NdisFreeMemory(xi, 0, 0);
451 return status;
452 }
454 NDIS_OID supported_oids[] =
455 {
456 OID_GEN_SUPPORTED_LIST,
457 OID_GEN_HARDWARE_STATUS,
458 OID_GEN_MEDIA_SUPPORTED,
459 OID_GEN_MEDIA_IN_USE,
460 OID_GEN_MAXIMUM_LOOKAHEAD,
461 OID_GEN_MAXIMUM_FRAME_SIZE,
462 OID_GEN_LINK_SPEED,
463 OID_GEN_TRANSMIT_BUFFER_SPACE,
464 OID_GEN_RECEIVE_BUFFER_SPACE,
465 OID_GEN_TRANSMIT_BLOCK_SIZE,
466 OID_GEN_RECEIVE_BLOCK_SIZE,
467 OID_GEN_VENDOR_ID,
468 OID_GEN_VENDOR_DESCRIPTION,
469 OID_GEN_CURRENT_PACKET_FILTER,
470 OID_GEN_CURRENT_LOOKAHEAD,
471 OID_GEN_DRIVER_VERSION,
472 OID_GEN_MAXIMUM_TOTAL_SIZE,
473 OID_GEN_MAC_OPTIONS,
474 OID_GEN_MEDIA_CONNECT_STATUS,
475 OID_GEN_MAXIMUM_SEND_PACKETS,
476 OID_802_3_PERMANENT_ADDRESS,
477 OID_802_3_CURRENT_ADDRESS,
478 OID_802_3_MULTICAST_LIST,
479 OID_802_3_MAXIMUM_LIST_SIZE,
480 };
482 NDIS_STATUS
483 XenNet_QueryInformation(
484 IN NDIS_HANDLE MiniportAdapterContext,
485 IN NDIS_OID Oid,
486 IN PVOID InformationBuffer,
487 IN ULONG InformationBufferLength,
488 OUT PULONG BytesWritten,
489 OUT PULONG BytesNeeded)
490 {
491 struct xennet_info *xi = MiniportAdapterContext;
492 UCHAR vendor_desc[] = XN_VENDOR_DESC;
493 ULONG temp_data;
494 PVOID data = &temp_data;
495 UINT len = sizeof(temp_data);
496 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
498 switch(Oid)
499 {
500 case OID_GEN_SUPPORTED_LIST:
501 data = supported_oids;
502 len = sizeof(supported_oids);
503 break;
504 case OID_GEN_HARDWARE_STATUS:
505 temp_data = NdisHardwareStatusReady;
506 break;
507 case OID_GEN_MEDIA_SUPPORTED:
508 temp_data = NdisMedium802_3;
509 break;
510 case OID_GEN_MEDIA_IN_USE:
511 temp_data = NdisMedium802_3;
512 break;
513 case OID_GEN_MAXIMUM_LOOKAHEAD:
514 temp_data = XN_DATA_SIZE;
515 break;
516 case OID_GEN_MAXIMUM_FRAME_SIZE:
517 temp_data = XN_MAX_PKT_SIZE;
518 break;
519 case OID_GEN_LINK_SPEED:
520 temp_data = 10000000; /* 1Gb */
521 break;
522 case OID_GEN_TRANSMIT_BUFFER_SPACE:
523 /* pkts times sizeof ring, maybe? */
524 temp_data = XN_MAX_PKT_SIZE * NET_TX_RING_SIZE;
525 break;
526 case OID_GEN_RECEIVE_BUFFER_SPACE:
527 /* pkts times sizeof ring, maybe? */
528 temp_data = XN_MAX_PKT_SIZE * NET_TX_RING_SIZE;
529 break;
530 case OID_GEN_TRANSMIT_BLOCK_SIZE:
531 temp_data = XN_MAX_PKT_SIZE;
532 break;
533 case OID_GEN_RECEIVE_BLOCK_SIZE:
534 temp_data = XN_MAX_PKT_SIZE;
535 break;
536 case OID_GEN_VENDOR_ID:
537 temp_data = XENSOURCE_MAC_HDR;
538 break;
539 case OID_GEN_VENDOR_DESCRIPTION:
540 data = vendor_desc;
541 len = sizeof(vendor_desc);
542 break;
543 case OID_GEN_CURRENT_PACKET_FILTER:
544 temp_data = xi->packet_filter;
545 break;
546 case OID_GEN_CURRENT_LOOKAHEAD:
547 temp_data = XN_MAX_PKT_SIZE;
548 break;
549 case OID_GEN_DRIVER_VERSION:
550 temp_data = (NDIS_MAJOR_VER << 8) | NDIS_MINOR_VER;
551 len = 2;
552 break;
553 case OID_GEN_MAXIMUM_TOTAL_SIZE:
554 temp_data = XN_MAX_PKT_SIZE;
555 break;
556 case OID_GEN_MAC_OPTIONS:
557 temp_data = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
558 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
559 NDIS_MAC_OPTION_NO_LOOPBACK;
560 break;
561 case OID_GEN_MEDIA_CONNECT_STATUS:
562 /* how can we not be connected?? */
563 temp_data = NdisMediaStateConnected;
564 break;
565 case OID_GEN_MAXIMUM_SEND_PACKETS:
566 temp_data = XN_MAX_SEND_PKTS;
567 break;
568 case OID_802_3_PERMANENT_ADDRESS:
569 data = xi->perm_mac_addr;
570 len = ETH_ALEN;
571 break;
572 case OID_802_3_CURRENT_ADDRESS:
573 data = xi->curr_mac_addr;
574 len = ETH_ALEN;
575 break;
576 case OID_802_3_MULTICAST_LIST:
577 data = NULL;
578 len = 0;
579 case OID_802_3_MAXIMUM_LIST_SIZE:
580 temp_data = 0; /* no mcast support */
581 break;
582 default:
583 KdPrint(("Unknown OID 0x%x\n", Oid));
584 status = NDIS_STATUS_NOT_SUPPORTED;
585 }
587 if (!NT_SUCCESS(status))
588 {
589 return status;
590 }
592 if (len > InformationBufferLength)
593 {
594 *BytesNeeded = len;
595 return NDIS_STATUS_BUFFER_TOO_SHORT;
596 }
598 *BytesWritten = len;
599 if (len)
600 {
601 NdisMoveMemory(InformationBuffer, data, len);
602 }
604 KdPrint(("Got OID 0x%x\n", Oid));
606 return status;
607 }
609 NDIS_STATUS
610 XenNet_SetInformation(
611 IN NDIS_HANDLE MiniportAdapterContext,
612 IN NDIS_OID Oid,
613 IN PVOID InformationBuffer,
614 IN ULONG InformationBufferLength,
615 OUT PULONG BytesRead,
616 OUT PULONG BytesNeeded
617 )
618 {
619 UNREFERENCED_PARAMETER(MiniportAdapterContext);
620 UNREFERENCED_PARAMETER(Oid);
621 UNREFERENCED_PARAMETER(InformationBuffer);
622 UNREFERENCED_PARAMETER(InformationBufferLength);
623 UNREFERENCED_PARAMETER(BytesRead);
624 UNREFERENCED_PARAMETER(BytesNeeded);
626 KdPrint((__FUNCTION__ " called with OID=0x%x\n", Oid));
627 return NDIS_STATUS_SUCCESS;
628 }
630 VOID
631 XenNet_ReturnPacket(
632 IN NDIS_HANDLE MiniportAdapterContext,
633 IN PNDIS_PACKET Packet
634 )
635 {
636 UNREFERENCED_PARAMETER(MiniportAdapterContext);
637 UNREFERENCED_PARAMETER(Packet);
639 KdPrint((__FUNCTION__ " called\n"));
640 }
642 VOID
643 XenNet_SendPackets(
644 IN NDIS_HANDLE MiniportAdapterContext,
645 IN PPNDIS_PACKET PacketArray,
646 IN UINT NumberOfPackets
647 )
648 {
649 /* for each packet:
650 req_prod_pvt is the next entry in the cmd ring to use
651 add pkt to array of saved packets
652 fill out tx request for the first part of skb
653 add to grant table
654 do flags for csum etc
655 gso (later)
656 inc req_prod_pvt
657 frags
658 possibly notify
659 network_tx)buf_gc
660 stop netif if no more room
661 */
662 struct xennet_info *xi = MiniportAdapterContext;
663 PNDIS_PACKET curr_packet;
664 UINT i;
665 UINT table_entry;
667 KdPrint((__FUNCTION__ " called\n"));
669 for (i = 0; i < NumberOfPackets; i++)
670 {
671 curr_packet = PacketArray[i];
672 ASSERT(curr_packet);
674 table_entry = xi->tx.req_prod_pvt;
675 }
677 }
679 VOID
680 XenNet_PnPEventNotify(
681 IN NDIS_HANDLE MiniportAdapterContext,
682 IN NDIS_DEVICE_PNP_EVENT PnPEvent,
683 IN PVOID InformationBuffer,
684 IN ULONG InformationBufferLength
685 )
686 {
687 UNREFERENCED_PARAMETER(MiniportAdapterContext);
688 UNREFERENCED_PARAMETER(PnPEvent);
689 UNREFERENCED_PARAMETER(InformationBuffer);
690 UNREFERENCED_PARAMETER(InformationBufferLength);
692 KdPrint((__FUNCTION__ " called\n"));
693 }
695 VOID
696 XenNet_Shutdown(
697 IN NDIS_HANDLE MiniportAdapterContext
698 )
699 {
700 UNREFERENCED_PARAMETER(MiniportAdapterContext);
702 KdPrint((__FUNCTION__ " called\n"));
703 }
705 NTSTATUS
706 DriverEntry(
707 PDRIVER_OBJECT DriverObject,
708 PUNICODE_STRING RegistryPath
709 )
710 {
711 NTSTATUS status;
712 WDF_DRIVER_CONFIG config;
713 NDIS_HANDLE ndis_wrapper_handle;
714 NDIS_MINIPORT_CHARACTERISTICS mini_chars;
716 RtlZeroMemory(&mini_chars, sizeof(mini_chars));
718 WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK);
719 config.DriverInitFlags |= WdfDriverInitNoDispatchOverride;
721 status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES,
722 &config, WDF_NO_HANDLE);
723 if (!NT_SUCCESS(status))
724 {
725 KdPrint(("WdfDriverCreate failed err = 0x%x\n", status));
726 return status;
727 }
729 NdisMInitializeWrapper(&ndis_wrapper_handle, DriverObject, RegistryPath, NULL);
730 if (!ndis_wrapper_handle)
731 {
732 KdPrint(("NdisMInitializeWrapper failed\n"));
733 return NDIS_STATUS_FAILURE;
734 }
736 /* NDIS 5.1 driver */
737 mini_chars.MajorNdisVersion = 5;
738 mini_chars.MinorNdisVersion = 1;
740 mini_chars.HaltHandler = XenNet_Halt;
741 mini_chars.InitializeHandler = XenNet_Init;
742 mini_chars.ISRHandler = NULL; // needed if we register interrupt?
743 mini_chars.QueryInformationHandler = XenNet_QueryInformation;
744 mini_chars.ResetHandler = NULL; //TODO: fill in
745 mini_chars.SetInformationHandler = XenNet_SetInformation;
746 /* added in v.4 -- use multiple pkts interface */
747 mini_chars.ReturnPacketHandler = XenNet_ReturnPacket;
748 mini_chars.SendPacketsHandler = XenNet_SendPackets;
749 /* added in v.5.1 */
750 mini_chars.PnPEventNotifyHandler = XenNet_PnPEventNotify;
751 mini_chars.AdapterShutdownHandler = XenNet_Shutdown;
753 /* TODO: we don't have hardware, but we have "resources", so do we need to implement fns to handle this? */
755 /* set up upper-edge interface */
756 status = NdisMRegisterMiniport(ndis_wrapper_handle, &mini_chars, sizeof(mini_chars));
757 if (!NT_SUCCESS(status))
758 {
759 KdPrint(("NdisMRegisterMiniport failed, status = 0x%x\n", status));
760 NdisTerminateWrapper(ndis_wrapper_handle, NULL);
761 return status;
762 }
764 return status;
765 }