win-pvdrivers

view xennet/xennet.c @ 23:e4f0a0a21488

xennet: flesh out initialization more

move code from xennet_init to backendstatehandler
properly report connected state to ndis
copy perm mac addr to curr mac addr
author Andy Grover <andy@groveronline.com>
date Fri Nov 30 11:45:00 2007 -0800 (2007-11-30)
parents 2e1ad5552529
children bc0ea67acebb
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 int connected;
47 UINT8 perm_mac_addr[ETH_ALEN];
48 UINT8 curr_mac_addr[ETH_ALEN];
50 char Path[128];
51 char BackendPath[128];
52 XEN_IFACE_EVTCHN EvtChnInterface;
53 XEN_IFACE_XENBUS XenBusInterface;
54 XEN_IFACE_XEN XenInterface;
55 XEN_IFACE_GNTTBL GntTblInterface;
57 struct netif_tx_front_ring tx;
58 struct netif_rx_front_ring rx;
60 PMDL tx_mdl;
61 PMDL rx_mdl;
62 struct netif_tx_sring *tx_pgs;
63 struct netif_rx_sring *rx_pgs;
65 UINT irq;
66 evtchn_port_t event_channel;
68 grant_ref_t tx_ring_ref;
69 grant_ref_t rx_ring_ref;
70 };
72 /* need to do typedef so the DECLARE below works */
73 typedef struct _wdf_device_info
74 {
75 struct xennet_info *xennet_info;
76 } wdf_device_info;
78 WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(wdf_device_info, GetWdfDeviceInfo)
80 /* This function copied from linux's lib/vsprintf.c, see it for attribution */
81 static unsigned long
82 simple_strtoul(const char *cp,char **endp,unsigned int base)
83 {
84 unsigned long result = 0,value;
86 if (!base) {
87 base = 10;
88 if (*cp == '0') {
89 base = 8;
90 cp++;
91 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
92 cp++;
93 base = 16;
94 }
95 }
96 } else if (base == 16) {
97 if (cp[0] == '0' && toupper(cp[1]) == 'X')
98 cp += 2;
99 }
100 while (isxdigit(*cp) &&
101 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
102 result = result*base + value;
103 cp++;
104 }
105 if (endp)
106 *endp = (char *)cp;
107 return result;
108 }
110 static PMDL
111 AllocatePages(int Pages)
112 {
113 PHYSICAL_ADDRESS Min;
114 PHYSICAL_ADDRESS Max;
115 PHYSICAL_ADDRESS Align;
116 PMDL Mdl;
118 KdPrint((__DRIVER_NAME " --> Allocate Pages\n"));
120 Min.QuadPart = 0;
121 Max.QuadPart = 0xFFFFFFFF;
122 Align.QuadPart = PAGE_SIZE;
124 Mdl = MmAllocatePagesForMdl(Min, Max, Align, Pages * PAGE_SIZE);
126 KdPrint((__DRIVER_NAME " <-- Allocate Pages (mdl = %08x)\n", Mdl));
128 return Mdl;
129 }
131 static PMDL
132 AllocatePage()
133 {
134 return AllocatePages(1);
135 }
137 static BOOLEAN
138 XenNet_Interrupt(
139 PKINTERRUPT Interrupt,
140 PVOID ServiceContext
141 )
142 {
143 // struct xennet_info *xennet_info = ServiceContext;
144 // KIRQL KIrql;
146 UNREFERENCED_PARAMETER(Interrupt);
147 UNREFERENCED_PARAMETER(ServiceContext);
149 // KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
150 // KdPrint((__DRIVER_NAME " --> Setting Dpc Event\n"));
151 // KeSetEvent(&ChildDeviceData->DpcThreadEvent, 1, FALSE);
152 // KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
153 // KdPrint((__DRIVER_NAME " --> Dpc Event Set\n"));
155 /* do something */
157 return TRUE;
158 }
160 static VOID
161 XenNet_BackEndStateHandler(char *Path, PVOID Data)
162 {
163 struct xennet_info *xi = Data;
164 char *Value;
165 int be_state;
166 char TmpPath[128];
167 xenbus_transaction_t xbt = 0;
168 int retry = 0;
169 char *err;
171 xi->XenBusInterface.Read(xi->XenBusInterface.InterfaceHeader.Context,
172 XBT_NIL, Path, &Value);
173 be_state = atoi(Value);
174 ExFreePool(Value);
176 switch (be_state)
177 {
178 case XenbusStateUnknown:
179 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
180 break;
182 case XenbusStateInitialising:
183 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
184 break;
186 case XenbusStateInitWait:
187 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
189 xi->event_channel = xi->EvtChnInterface.AllocUnbound(
190 xi->EvtChnInterface.InterfaceHeader.Context, 0);
191 xi->EvtChnInterface.Bind(xi->EvtChnInterface.InterfaceHeader.Context,
192 xi->event_channel, XenNet_Interrupt, xi);
194 /* TODO: must free pages in MDL as well as MDL using MmFreePagesFromMdl and ExFreePool */
195 // or, allocate mem and then get mdl, then free mdl
196 xi->tx_mdl = AllocatePage();
197 xi->tx_pgs = MmMapLockedPagesSpecifyCache(xi->tx_mdl, KernelMode, MmNonCached,
198 NULL, FALSE, NormalPagePriority);
199 SHARED_RING_INIT(xi->tx_pgs);
200 FRONT_RING_INIT(&xi->tx, xi->tx_pgs, PAGE_SIZE);
201 xi->tx_ring_ref = xi->GntTblInterface.GrantAccess(
202 xi->GntTblInterface.InterfaceHeader.Context, 0,
203 *MmGetMdlPfnArray(xi->tx_mdl), FALSE);
205 xi->rx_mdl = AllocatePage();
206 xi->rx_pgs = MmMapLockedPagesSpecifyCache(xi->rx_mdl, KernelMode, MmNonCached,
207 NULL, FALSE, NormalPagePriority);
208 SHARED_RING_INIT(xi->rx_pgs);
209 FRONT_RING_INIT(&xi->rx, xi->rx_pgs, PAGE_SIZE);
210 xi->rx_ring_ref = xi->GntTblInterface.GrantAccess(
211 xi->GntTblInterface.InterfaceHeader.Context, 0,
212 *MmGetMdlPfnArray(xi->rx_mdl), FALSE);
214 xi->XenBusInterface.StartTransaction(xi->XenBusInterface.InterfaceHeader.Context,
215 &xbt);
217 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/tx-ring-ref", xi->Path);
218 err = xi->XenBusInterface.Printf(xi->XenBusInterface.InterfaceHeader.Context,
219 XBT_NIL, TmpPath, "%d", xi->tx_ring_ref);
220 if (err)
221 goto trouble;
223 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/rx-ring-ref", xi->Path);
224 err = xi->XenBusInterface.Printf(xi->XenBusInterface.InterfaceHeader.Context,
225 XBT_NIL, TmpPath, "%d", xi->rx_ring_ref);
226 if (err)
227 goto trouble;
229 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/event-channel", xi->Path);
230 err = xi->XenBusInterface.Printf(xi->XenBusInterface.InterfaceHeader.Context,
231 XBT_NIL, TmpPath, "%d", xi->event_channel);
232 if (err)
233 goto trouble;
235 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/request-rx-copy", xi->Path);
236 err = xi->XenBusInterface.Printf(xi->XenBusInterface.InterfaceHeader.Context,
237 XBT_NIL, TmpPath, "%d", 1);
238 if (err)
239 goto trouble;
241 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/feature-rx-notify",
242 xi->Path);
243 err = xi->XenBusInterface.Printf(xi->XenBusInterface.InterfaceHeader.Context,
244 XBT_NIL, TmpPath, "%d", 1);
245 if (err)
246 goto trouble;
248 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath),
249 "%s/feature-no-csum-offload", xi->Path);
250 err = xi->XenBusInterface.Printf(xi->XenBusInterface.InterfaceHeader.Context,
251 XBT_NIL, TmpPath, "%d", 1);
252 if (err)
253 goto trouble;
255 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath),
256 "%s/feature-sg", xi->Path);
257 err = xi->XenBusInterface.Printf(xi->XenBusInterface.InterfaceHeader.Context,
258 XBT_NIL, TmpPath, "%d", 0);
259 if (err)
260 goto trouble;
262 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath),
263 "%s/feature-gso-tcpv4", xi->Path);
264 err = xi->XenBusInterface.Printf(xi->XenBusInterface.InterfaceHeader.Context,
265 XBT_NIL, TmpPath, "%d", 0);
266 if (err)
267 goto trouble;
269 /* commit transaction */
270 xi->XenBusInterface.EndTransaction(xi->XenBusInterface.InterfaceHeader.Context,
271 xbt, 0, &retry);
273 /* TODO: prepare tx and rx rings */
275 KdPrint((__DRIVER_NAME " Set Frontend state to Initialised\n"));
276 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->Path);
277 xi->XenBusInterface.Printf(xi->XenBusInterface.InterfaceHeader.Context,
278 XBT_NIL, TmpPath, "%d", XenbusStateInitialised);
280 /* send fake arp? */
282 xi->connected = TRUE;
284 break;
286 case XenbusStateInitialised:
287 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
288 // create the device
289 break;
291 case XenbusStateConnected:
292 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
294 /* do more stuff here */
296 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
297 break;
299 case XenbusStateClosing:
300 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
301 break;
303 case XenbusStateClosed:
304 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
305 break;
307 default:
308 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", be_state));
309 break;
310 }
312 trouble:
313 KdPrint((__DRIVER_NAME __FUNCTION__ ": Should never happen!\n"));
314 xi->XenBusInterface.EndTransaction(xi->XenBusInterface.InterfaceHeader.Context,
315 xbt, 1, &retry);
317 }
320 VOID
321 XenNet_Halt(
322 IN NDIS_HANDLE MiniportAdapterContext
323 )
324 {
325 UNREFERENCED_PARAMETER(MiniportAdapterContext);
326 }
328 static NDIS_STATUS
329 XenNet_Init(
330 OUT PNDIS_STATUS OpenErrorStatus,
331 OUT PUINT SelectedMediumIndex,
332 IN PNDIS_MEDIUM MediumArray,
333 IN UINT MediumArraySize,
334 IN NDIS_HANDLE MiniportAdapterHandle,
335 IN NDIS_HANDLE WrapperConfigurationContext
336 )
337 {
338 NDIS_STATUS status;
339 UINT i;
340 BOOLEAN medium_found = FALSE;
341 struct xennet_info *xi = NULL;
342 ULONG length;
343 WDF_OBJECT_ATTRIBUTES wdf_attrs;
344 char *msg;
345 char *Value;
346 char **vif_devs;
347 char TmpPath[128];
349 UNREFERENCED_PARAMETER(OpenErrorStatus);
350 UNREFERENCED_PARAMETER(WrapperConfigurationContext);
352 /* deal with medium stuff */
353 for (i = 0; i < MediumArraySize; i++)
354 {
355 if (MediumArray[i] == NdisMedium802_3)
356 {
357 medium_found = TRUE;
358 break;
359 }
360 }
361 if (!medium_found)
362 {
363 KdPrint(("NIC_MEDIA_TYPE not in MediumArray\n"));
364 return NDIS_STATUS_UNSUPPORTED_MEDIA;
365 }
366 *SelectedMediumIndex = i;
368 /* Alloc memory for adapter private info */
369 status = NdisAllocateMemoryWithTag(&xi, sizeof(*xi), XENNET_POOL_TAG);
370 if (!NT_SUCCESS(status))
371 {
372 KdPrint(("NdisAllocateMemoryWithTag failed with 0x%x\n", status));
373 status = NDIS_STATUS_RESOURCES;
374 goto err;
375 }
376 RtlZeroMemory(xi, sizeof(*xi));
378 /* init xennet_info */
379 xi->adapter_handle = MiniportAdapterHandle;
380 NdisMGetDeviceProperty(MiniportAdapterHandle, &xi->pdo, &xi->fdo,
381 &xi->lower_do, NULL, NULL);
383 status = IoGetDeviceProperty(xi->pdo, DevicePropertyDeviceDescription,
384 NAME_SIZE, xi->name, &length);
385 if (!NT_SUCCESS(status))
386 {
387 KdPrint(("IoGetDeviceProperty failed with 0x%x\n", status));
388 status = NDIS_STATUS_FAILURE;
389 goto err;
390 }
392 NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE) xi,
393 0, NDIS_ATTRIBUTE_DESERIALIZE, NdisInterfaceInternal);
395 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&wdf_attrs, wdf_device_info);
397 status = WdfDeviceMiniportCreate(WdfGetDriver(), &wdf_attrs, xi->fdo,
398 xi->lower_do, xi->pdo, &xi->wdf_device);
399 if (!NT_SUCCESS(status))
400 {
401 KdPrint(("WdfDeviceMiniportCreate failed with 0x%x\n", status));
402 status = NDIS_STATUS_FAILURE;
403 goto err;
404 }
406 GetWdfDeviceInfo(xi->wdf_device)->xennet_info = xi;
408 /* get lower (Xen) interfaces */
410 status = WdfFdoQueryForInterface(xi->wdf_device, &GUID_XEN_IFACE_EVTCHN,
411 (PINTERFACE) &xi->EvtChnInterface, sizeof(XEN_IFACE_EVTCHN), 1, NULL);
412 if(!NT_SUCCESS(status))
413 {
414 KdPrint(("WdfFdoQueryForInterface (EvtChn) failed with status 0x%08x\n", status));
415 status = NDIS_STATUS_FAILURE;
416 goto err;
417 }
419 status = WdfFdoQueryForInterface(xi->wdf_device, &GUID_XEN_IFACE_XENBUS,
420 (PINTERFACE) &xi->XenBusInterface, sizeof(XEN_IFACE_XENBUS), 1, NULL);
421 if(!NT_SUCCESS(status))
422 {
423 KdPrint(("WdfFdoQueryForInterface (XenBus) failed with status 0x%08x\n", status));
424 status = NDIS_STATUS_FAILURE;
425 goto err;
426 }
428 #if 0
429 status = WdfFdoQueryForInterface(xi->wdf_device, &GUID_XEN_IFACE_XEN,
430 (PINTERFACE) &xi->XenInterface, sizeof(XEN_IFACE_XEN), 1, NULL);
431 if(!NT_SUCCESS(status))
432 {
433 KdPrint(("WdfFdoQueryForInterface (Xen) failed with status 0x%08x\n", status));
434 status = NDIS_STATUS_FAILURE;
435 goto err;
436 }
437 #endif
439 status = WdfFdoQueryForInterface(xi->wdf_device, &GUID_XEN_IFACE_GNTTBL,
440 (PINTERFACE) &xi->GntTblInterface, sizeof(XEN_IFACE_GNTTBL), 1, NULL);
441 if(!NT_SUCCESS(status))
442 {
443 KdPrint(("WdfFdoQueryForInterface (GntTbl) failed with status 0x%08x\n", status));
444 status = NDIS_STATUS_FAILURE;
445 goto err;
446 }
448 msg = xi->XenBusInterface.List(xi->EvtChnInterface.InterfaceHeader.Context,
449 XBT_NIL, "device/vif", &vif_devs);
450 if (msg)
451 {
452 KdPrint((__DRIVER_NAME ": " __FUNCTION__ ": List retval is nonzero!\n"));
453 status = NDIS_STATUS_FAILURE;
454 goto err;
455 }
457 for (i = 0; vif_devs[i]; i++)
458 {
459 if (i > 0)
460 {
461 KdPrint((__DRIVER_NAME "Can only handle 1 vif so far, ignoring vif %s\n", vif_devs[i]));
462 continue;
463 }
464 RtlStringCbPrintfA(xi->Path, ARRAY_SIZE(xi->Path), "device/vif/%s", vif_devs[i]);
466 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath),
467 "device/vif/%s/state", vif_devs[i]);
468 KdPrint(("%s\n", TmpPath));
470 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/backend", xi->Path);
471 xi->XenBusInterface.Read(xi->XenBusInterface.InterfaceHeader.Context,
472 XBT_NIL, TmpPath, &Value);
473 if (!Value)
474 {
475 KdPrint((__DRIVER_NAME " backend Read Failed\n"));
476 }
477 else
478 {
479 RtlStringCbCopyA(xi->BackendPath, ARRAY_SIZE(xi->BackendPath), Value);
480 KdPrint((__DRIVER_NAME "backend path = %s\n", xi->BackendPath));
481 }
482 ExFreePool(Value);
484 /* Add watch on backend state */
485 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/state", xi->BackendPath);
486 xi->XenBusInterface.AddWatch(xi->XenBusInterface.InterfaceHeader.Context,
487 XBT_NIL, TmpPath, XenNet_BackEndStateHandler, xi);
489 /* get mac address */
490 RtlStringCbPrintfA(TmpPath, ARRAY_SIZE(TmpPath), "%s/mac", xi->Path);
491 xi->XenBusInterface.Read(xi->XenBusInterface.InterfaceHeader.Context,
492 XBT_NIL, TmpPath, &Value);
493 if (!Value)
494 {
495 KdPrint((__DRIVER_NAME " mac Read Failed\n"));
496 }
497 else
498 {
499 char *s, *e;
500 int i;
502 s = Value;
504 for (i = 0; i < ETH_ALEN; i++) {
505 xi->perm_mac_addr[i] = (UINT8)simple_strtoul(s, &e, 16);
506 if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
507 KdPrint((__DRIVER_NAME "Error parsing MAC address\n"));
508 ExFreePool(Value);
509 ExFreePool(vif_devs);
510 status = NDIS_STATUS_FAILURE;
511 goto err;
512 }
513 s = e + 1;
514 }
515 memcpy(xi->curr_mac_addr, xi->perm_mac_addr, ETH_ALEN);
516 }
517 ExFreePool(Value);
519 //XenVbd_HotPlugHandler(buffer, NULL);
520 //ExFreePoolWithTag(bdDevices[i], XENPCI_POOL_TAG);
521 }
522 ExFreePool(vif_devs);
524 return NDIS_STATUS_SUCCESS;
526 err:
527 NdisFreeMemory(xi, 0, 0);
528 return status;
529 }
531 NDIS_OID supported_oids[] =
532 {
533 OID_GEN_SUPPORTED_LIST,
534 OID_GEN_HARDWARE_STATUS,
535 OID_GEN_MEDIA_SUPPORTED,
536 OID_GEN_MEDIA_IN_USE,
537 OID_GEN_MAXIMUM_LOOKAHEAD,
538 OID_GEN_MAXIMUM_FRAME_SIZE,
539 OID_GEN_LINK_SPEED,
540 OID_GEN_TRANSMIT_BUFFER_SPACE,
541 OID_GEN_RECEIVE_BUFFER_SPACE,
542 OID_GEN_TRANSMIT_BLOCK_SIZE,
543 OID_GEN_RECEIVE_BLOCK_SIZE,
544 OID_GEN_VENDOR_ID,
545 OID_GEN_VENDOR_DESCRIPTION,
546 OID_GEN_CURRENT_PACKET_FILTER,
547 OID_GEN_CURRENT_LOOKAHEAD,
548 OID_GEN_DRIVER_VERSION,
549 OID_GEN_MAXIMUM_TOTAL_SIZE,
550 OID_GEN_MAC_OPTIONS,
551 OID_GEN_MEDIA_CONNECT_STATUS,
552 OID_GEN_MAXIMUM_SEND_PACKETS,
553 OID_802_3_PERMANENT_ADDRESS,
554 OID_802_3_CURRENT_ADDRESS,
555 OID_802_3_MULTICAST_LIST,
556 OID_802_3_MAXIMUM_LIST_SIZE,
557 };
559 NDIS_STATUS
560 XenNet_QueryInformation(
561 IN NDIS_HANDLE MiniportAdapterContext,
562 IN NDIS_OID Oid,
563 IN PVOID InformationBuffer,
564 IN ULONG InformationBufferLength,
565 OUT PULONG BytesWritten,
566 OUT PULONG BytesNeeded)
567 {
568 struct xennet_info *xi = MiniportAdapterContext;
569 UCHAR vendor_desc[] = XN_VENDOR_DESC;
570 ULONG temp_data;
571 PVOID data = &temp_data;
572 UINT len = sizeof(temp_data);
573 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
575 switch(Oid)
576 {
577 case OID_GEN_SUPPORTED_LIST:
578 data = supported_oids;
579 len = sizeof(supported_oids);
580 break;
581 case OID_GEN_HARDWARE_STATUS:
582 temp_data = NdisHardwareStatusReady;
583 break;
584 case OID_GEN_MEDIA_SUPPORTED:
585 temp_data = NdisMedium802_3;
586 break;
587 case OID_GEN_MEDIA_IN_USE:
588 temp_data = NdisMedium802_3;
589 break;
590 case OID_GEN_MAXIMUM_LOOKAHEAD:
591 temp_data = XN_DATA_SIZE;
592 break;
593 case OID_GEN_MAXIMUM_FRAME_SIZE:
594 temp_data = XN_MAX_PKT_SIZE;
595 break;
596 case OID_GEN_LINK_SPEED:
597 temp_data = 10000000; /* 1Gb */
598 break;
599 case OID_GEN_TRANSMIT_BUFFER_SPACE:
600 /* pkts times sizeof ring, maybe? */
601 temp_data = XN_MAX_PKT_SIZE * NET_TX_RING_SIZE;
602 break;
603 case OID_GEN_RECEIVE_BUFFER_SPACE:
604 /* pkts times sizeof ring, maybe? */
605 temp_data = XN_MAX_PKT_SIZE * NET_TX_RING_SIZE;
606 break;
607 case OID_GEN_TRANSMIT_BLOCK_SIZE:
608 temp_data = XN_MAX_PKT_SIZE;
609 break;
610 case OID_GEN_RECEIVE_BLOCK_SIZE:
611 temp_data = XN_MAX_PKT_SIZE;
612 break;
613 case OID_GEN_VENDOR_ID:
614 temp_data = XENSOURCE_MAC_HDR;
615 break;
616 case OID_GEN_VENDOR_DESCRIPTION:
617 data = vendor_desc;
618 len = sizeof(vendor_desc);
619 break;
620 case OID_GEN_CURRENT_PACKET_FILTER:
621 temp_data = xi->packet_filter;
622 break;
623 case OID_GEN_CURRENT_LOOKAHEAD:
624 temp_data = XN_MAX_PKT_SIZE;
625 break;
626 case OID_GEN_DRIVER_VERSION:
627 temp_data = (NDIS_MAJOR_VER << 8) | NDIS_MINOR_VER;
628 len = 2;
629 break;
630 case OID_GEN_MAXIMUM_TOTAL_SIZE:
631 temp_data = XN_MAX_PKT_SIZE;
632 break;
633 case OID_GEN_MAC_OPTIONS:
634 temp_data = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
635 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
636 NDIS_MAC_OPTION_NO_LOOPBACK;
637 break;
638 case OID_GEN_MEDIA_CONNECT_STATUS:
639 if (xi->connected)
640 temp_data = NdisMediaStateConnected;
641 else
642 temp_data = NdisMediaStateDisconnected;
643 break;
644 case OID_GEN_MAXIMUM_SEND_PACKETS:
645 temp_data = XN_MAX_SEND_PKTS;
646 break;
647 case OID_802_3_PERMANENT_ADDRESS:
648 data = xi->perm_mac_addr;
649 len = ETH_ALEN;
650 break;
651 case OID_802_3_CURRENT_ADDRESS:
652 data = xi->curr_mac_addr;
653 len = ETH_ALEN;
654 break;
655 case OID_802_3_MULTICAST_LIST:
656 data = NULL;
657 len = 0;
658 case OID_802_3_MAXIMUM_LIST_SIZE:
659 temp_data = 0; /* no mcast support */
660 break;
661 default:
662 KdPrint(("Unknown OID 0x%x\n", Oid));
663 status = NDIS_STATUS_NOT_SUPPORTED;
664 }
666 if (!NT_SUCCESS(status))
667 {
668 return status;
669 }
671 if (len > InformationBufferLength)
672 {
673 *BytesNeeded = len;
674 return NDIS_STATUS_BUFFER_TOO_SHORT;
675 }
677 *BytesWritten = len;
678 if (len)
679 {
680 NdisMoveMemory(InformationBuffer, data, len);
681 }
683 KdPrint(("Got OID 0x%x\n", Oid));
685 return status;
686 }
688 NDIS_STATUS
689 XenNet_SetInformation(
690 IN NDIS_HANDLE MiniportAdapterContext,
691 IN NDIS_OID Oid,
692 IN PVOID InformationBuffer,
693 IN ULONG InformationBufferLength,
694 OUT PULONG BytesRead,
695 OUT PULONG BytesNeeded
696 )
697 {
698 UNREFERENCED_PARAMETER(MiniportAdapterContext);
699 UNREFERENCED_PARAMETER(Oid);
700 UNREFERENCED_PARAMETER(InformationBuffer);
701 UNREFERENCED_PARAMETER(InformationBufferLength);
702 UNREFERENCED_PARAMETER(BytesRead);
703 UNREFERENCED_PARAMETER(BytesNeeded);
705 KdPrint((__FUNCTION__ " called with OID=0x%x\n", Oid));
706 return NDIS_STATUS_SUCCESS;
707 }
709 VOID
710 XenNet_ReturnPacket(
711 IN NDIS_HANDLE MiniportAdapterContext,
712 IN PNDIS_PACKET Packet
713 )
714 {
715 UNREFERENCED_PARAMETER(MiniportAdapterContext);
716 UNREFERENCED_PARAMETER(Packet);
718 KdPrint((__FUNCTION__ " called\n"));
719 }
721 VOID
722 XenNet_SendPackets(
723 IN NDIS_HANDLE MiniportAdapterContext,
724 IN PPNDIS_PACKET PacketArray,
725 IN UINT NumberOfPackets
726 )
727 {
728 /* for each packet:
729 req_prod_pvt is the next entry in the cmd ring to use
730 add pkt to array of saved packets
731 fill out tx request for the first part of skb
732 add to grant table
733 do flags for csum etc
734 gso (later)
735 inc req_prod_pvt
736 frags
737 possibly notify
738 network_tx)buf_gc
739 stop netif if no more room
740 */
741 struct xennet_info *xi = MiniportAdapterContext;
742 PNDIS_PACKET curr_packet;
743 UINT i;
744 UINT table_entry;
746 KdPrint((__FUNCTION__ " called\n"));
748 for (i = 0; i < NumberOfPackets; i++)
749 {
750 curr_packet = PacketArray[i];
751 ASSERT(curr_packet);
753 table_entry = xi->tx.req_prod_pvt;
754 }
756 }
758 VOID
759 XenNet_PnPEventNotify(
760 IN NDIS_HANDLE MiniportAdapterContext,
761 IN NDIS_DEVICE_PNP_EVENT PnPEvent,
762 IN PVOID InformationBuffer,
763 IN ULONG InformationBufferLength
764 )
765 {
766 UNREFERENCED_PARAMETER(MiniportAdapterContext);
767 UNREFERENCED_PARAMETER(PnPEvent);
768 UNREFERENCED_PARAMETER(InformationBuffer);
769 UNREFERENCED_PARAMETER(InformationBufferLength);
771 KdPrint((__FUNCTION__ " called\n"));
772 }
774 VOID
775 XenNet_Shutdown(
776 IN NDIS_HANDLE MiniportAdapterContext
777 )
778 {
779 UNREFERENCED_PARAMETER(MiniportAdapterContext);
781 KdPrint((__FUNCTION__ " called\n"));
782 }
784 NTSTATUS
785 DriverEntry(
786 PDRIVER_OBJECT DriverObject,
787 PUNICODE_STRING RegistryPath
788 )
789 {
790 NTSTATUS status;
791 WDF_DRIVER_CONFIG config;
792 NDIS_HANDLE ndis_wrapper_handle;
793 NDIS_MINIPORT_CHARACTERISTICS mini_chars;
795 RtlZeroMemory(&mini_chars, sizeof(mini_chars));
797 WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK);
798 config.DriverInitFlags |= WdfDriverInitNoDispatchOverride;
800 status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES,
801 &config, WDF_NO_HANDLE);
802 if (!NT_SUCCESS(status))
803 {
804 KdPrint(("WdfDriverCreate failed err = 0x%x\n", status));
805 return status;
806 }
808 NdisMInitializeWrapper(&ndis_wrapper_handle, DriverObject, RegistryPath, NULL);
809 if (!ndis_wrapper_handle)
810 {
811 KdPrint(("NdisMInitializeWrapper failed\n"));
812 return NDIS_STATUS_FAILURE;
813 }
815 /* NDIS 5.1 driver */
816 mini_chars.MajorNdisVersion = 5;
817 mini_chars.MinorNdisVersion = 1;
819 mini_chars.HaltHandler = XenNet_Halt;
820 mini_chars.InitializeHandler = XenNet_Init;
821 mini_chars.ISRHandler = NULL; // needed if we register interrupt?
822 mini_chars.QueryInformationHandler = XenNet_QueryInformation;
823 mini_chars.ResetHandler = NULL; //TODO: fill in
824 mini_chars.SetInformationHandler = XenNet_SetInformation;
825 /* added in v.4 -- use multiple pkts interface */
826 mini_chars.ReturnPacketHandler = XenNet_ReturnPacket;
827 mini_chars.SendPacketsHandler = XenNet_SendPackets;
828 /* added in v.5.1 */
829 mini_chars.PnPEventNotifyHandler = XenNet_PnPEventNotify;
830 mini_chars.AdapterShutdownHandler = XenNet_Shutdown;
832 /* TODO: we don't have hardware, but we have "resources", so do we need to implement fns to handle this? */
834 /* set up upper-edge interface */
835 status = NdisMRegisterMiniport(ndis_wrapper_handle, &mini_chars, sizeof(mini_chars));
836 if (!NT_SUCCESS(status))
837 {
838 KdPrint(("NdisMRegisterMiniport failed, status = 0x%x\n", status));
839 NdisTerminateWrapper(ndis_wrapper_handle, NULL);
840 return status;
841 }
843 return status;
844 }