win-pvdrivers

view xennet/xennet.c @ 353:a7c4b65e754a

Bugfixes for save/restore
author James Harper <james.harper@bendigoit.com.au>
date Wed Jul 02 09:54:40 2008 +1000 (2008-07-02)
parents 6cfd70daada3
children cb12e8b450a8 5a762fd1fba9
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 LARGE_INTEGER ProfTime_TxBufferGC;
26 LARGE_INTEGER ProfTime_RxBufferAlloc;
27 LARGE_INTEGER ProfTime_ReturnPacket;
28 LARGE_INTEGER ProfTime_RxBufferCheck;
29 LARGE_INTEGER ProfTime_Linearize;
30 LARGE_INTEGER ProfTime_SendPackets;
31 LARGE_INTEGER ProfTime_SendQueuedPackets;
32 LARGE_INTEGER ProfTime_RxBufferCheckTopHalf;
33 LARGE_INTEGER ProfTime_RxBufferCheckBotHalf;
35 int ProfCount_TxBufferGC;
36 int ProfCount_RxBufferAlloc;
37 int ProfCount_ReturnPacket;
38 int ProfCount_RxBufferCheck;
39 int ProfCount_Linearize;
40 int ProfCount_SendPackets;
41 int ProfCount_PacketsPerSendPackets;
42 int ProfCount_SendQueuedPackets;
44 int ProfCount_TxPacketsTotal;
45 int ProfCount_TxPacketsCsumOffload;
46 int ProfCount_TxPacketsLargeOffload;
47 int ProfCount_RxPacketsTotal;
48 int ProfCount_RxPacketsCsumOffload;
49 int ProfCount_CallsToIndicateReceive;
51 /* This function copied from linux's lib/vsprintf.c, see it for attribution */
52 static unsigned long
53 simple_strtoul(const char *cp,char **endp,unsigned int base)
54 {
55 unsigned long result = 0,value;
57 if (!base) {
58 base = 10;
59 if (*cp == '0') {
60 base = 8;
61 cp++;
62 if ((toupper(*cp) == 'X') && isxdigit(cp[1])) {
63 cp++;
64 base = 16;
65 }
66 }
67 } else if (base == 16) {
68 if (cp[0] == '0' && toupper(cp[1]) == 'X')
69 cp += 2;
70 }
71 while (isxdigit(*cp) &&
72 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {
73 result = result*base + value;
74 cp++;
75 }
76 if (endp)
77 *endp = (char *)cp;
78 return result;
79 }
81 // Called at DISPATCH_LEVEL
83 static VOID
84 XenNet_InterruptIsr(
85 PBOOLEAN InterruptRecognized,
86 PBOOLEAN QueueMiniportHandleInterrupt,
87 NDIS_HANDLE MiniportAdapterContext)
88 {
89 struct xennet_info *xi = MiniportAdapterContext;
91 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
93 *QueueMiniportHandleInterrupt = (BOOLEAN)!!xi->connected;
94 *InterruptRecognized = FALSE; /* we can't be sure here... */
96 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
97 }
99 static VOID
100 XenNet_InterruptDpc(NDIS_HANDLE MiniportAdapterContext)
101 {
102 struct xennet_info *xi = MiniportAdapterContext;
104 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
105 if (xi->connected)
106 {
107 XenNet_TxBufferGC(xi);
108 XenNet_RxBufferCheck(xi);
109 }
110 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
111 }
113 static NDIS_STATUS
114 XenNet_ConnectBackend(struct xennet_info *xi)
115 {
116 PUCHAR ptr;
117 UCHAR type;
118 PCHAR setting, value;
119 UINT i;
121 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
123 ptr = xi->config_page;
124 while((type = GET_XEN_INIT_RSP(&ptr, &setting, &value)) != XEN_INIT_TYPE_END)
125 {
126 switch(type)
127 {
128 case XEN_INIT_TYPE_RING: /* frontend ring */
129 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
130 if (strcmp(setting, "tx-ring-ref") == 0)
131 {
132 FRONT_RING_INIT(&xi->tx, (netif_tx_sring_t *)value, PAGE_SIZE);
133 } else if (strcmp(setting, "rx-ring-ref") == 0)
134 {
135 FRONT_RING_INIT(&xi->rx, (netif_rx_sring_t *)value, PAGE_SIZE);
136 }
137 break;
138 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
139 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
140 if (strcmp(setting, "event-channel") == 0)
141 {
142 xi->event_channel = PtrToUlong(value);
143 }
144 break;
145 case XEN_INIT_TYPE_READ_STRING_BACK:
146 case XEN_INIT_TYPE_READ_STRING_FRONT:
147 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
148 if (strcmp(setting, "mac") == 0)
149 {
150 char *s, *e;
151 s = value;
152 for (i = 0; i < ETH_ALEN; i++) {
153 xi->perm_mac_addr[i] = (UINT8)simple_strtoul(s, &e, 16);
154 if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
155 KdPrint((__DRIVER_NAME "Error parsing MAC address\n"));
156 }
157 s = e + 1;
158 }
159 memcpy(xi->curr_mac_addr, xi->perm_mac_addr, ETH_ALEN);
160 }
161 break;
162 case XEN_INIT_TYPE_VECTORS:
163 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
164 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
165 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
166 {
167 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
168 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
169 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
170 return NDIS_ERROR_CODE_ADAPTER_NOT_FOUND;
171 }
172 else
173 memcpy(&xi->vectors, value, sizeof(XENPCI_VECTORS));
174 break;
175 case XEN_INIT_TYPE_STATE_PTR:
176 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
177 xi->device_state = (PXENPCI_DEVICE_STATE)value;
178 break;
179 default:
180 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
181 break;
182 }
183 }
184 return NDIS_STATUS_SUCCESS;
185 }
187 static VOID
188 XenNet_Resume(PDEVICE_OBJECT device_object, PVOID context)
189 {
190 struct xennet_info *xi = context;
192 UNREFERENCED_PARAMETER(device_object);
194 XenNet_RxResumeStart(xi);
195 XenNet_TxResumeStart(xi);
196 XenNet_ConnectBackend(xi);
197 xi->device_state->resume_state = RESUME_STATE_RUNNING;
198 XenNet_RxResumeEnd(xi);
199 XenNet_TxResumeEnd(xi);
200 NdisMSetPeriodicTimer(&xi->resume_timer, 100);
201 }
203 static VOID
204 XenResumeCheck_Timer(
205 PVOID SystemSpecific1,
206 PVOID FunctionContext,
207 PVOID SystemSpecific2,
208 PVOID SystemSpecific3
209 )
210 {
211 struct xennet_info *xi = FunctionContext;
212 PIO_WORKITEM work_item;
213 BOOLEAN timer_cancelled;
215 UNREFERENCED_PARAMETER(SystemSpecific1);
216 UNREFERENCED_PARAMETER(SystemSpecific2);
217 UNREFERENCED_PARAMETER(SystemSpecific3);
219 if (xi->device_state->resume_state == RESUME_STATE_FRONTEND_RESUME)
220 {
221 NdisMCancelTimer(&xi->resume_timer, &timer_cancelled);
222 work_item = IoAllocateWorkItem(xi->fdo);
223 IoQueueWorkItem(work_item, XenNet_Resume, DelayedWorkQueue, xi);
224 }
225 }
227 // Called at <= DISPATCH_LEVEL
228 static NDIS_STATUS
229 XenNet_Init(
230 OUT PNDIS_STATUS OpenErrorStatus,
231 OUT PUINT SelectedMediumIndex,
232 IN PNDIS_MEDIUM MediumArray,
233 IN UINT MediumArraySize,
234 IN NDIS_HANDLE MiniportAdapterHandle,
235 IN NDIS_HANDLE WrapperConfigurationContext
236 )
237 {
238 NDIS_STATUS status;
239 BOOLEAN medium_found = FALSE;
240 struct xennet_info *xi = NULL;
241 ULONG nrl_length;
242 PNDIS_RESOURCE_LIST nrl;
243 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
244 KIRQL irq_level = 0;
245 ULONG irq_vector = 0;
246 NDIS_HANDLE config_handle;
247 NDIS_STRING config_param_name;
248 PNDIS_CONFIGURATION_PARAMETER config_param;
249 ULONG i;
250 PUCHAR ptr;
251 UCHAR type;
252 PCHAR setting, value;
253 ULONG length;
254 CHAR buf[128];
256 UNREFERENCED_PARAMETER(OpenErrorStatus);
258 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
259 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
261 /* deal with medium stuff */
262 for (i = 0; i < MediumArraySize; i++)
263 {
264 if (MediumArray[i] == NdisMedium802_3)
265 {
266 medium_found = TRUE;
267 break;
268 }
269 }
270 if (!medium_found)
271 {
272 KdPrint(("NIC_MEDIA_TYPE not in MediumArray\n"));
273 return NDIS_STATUS_UNSUPPORTED_MEDIA;
274 }
275 *SelectedMediumIndex = i;
277 /* Alloc memory for adapter private info */
278 status = NdisAllocateMemoryWithTag(&xi, sizeof(*xi), XENNET_POOL_TAG);
279 if (!NT_SUCCESS(status))
280 {
281 KdPrint(("NdisAllocateMemoryWithTag failed with 0x%x\n", status));
282 status = NDIS_STATUS_RESOURCES;
283 goto err;
284 }
285 RtlZeroMemory(xi, sizeof(*xi));
286 xi->adapter_handle = MiniportAdapterHandle;
287 xi->rx_target = RX_DFL_MIN_TARGET;
288 xi->rx_min_target = RX_DFL_MIN_TARGET;
289 xi->rx_max_target = RX_MAX_TARGET;
290 NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE) xi,
291 0, NDIS_ATTRIBUTE_DESERIALIZE, // | NDIS_ATTRIBUTE_BUS_MASTER),
292 NdisInterfaceInternal);
294 nrl_length = 0;
295 NdisMQueryAdapterResources(&status, WrapperConfigurationContext,
296 NULL, (PUINT)&nrl_length);
297 KdPrint((__DRIVER_NAME " nrl_length = %d\n", nrl_length));
298 status = NdisAllocateMemoryWithTag(&nrl, nrl_length, XENNET_POOL_TAG);
299 if (status != NDIS_STATUS_SUCCESS)
300 {
301 KdPrint((__DRIVER_NAME " Could not get allocate memory for Adapter Resources 0x%x\n", status));
302 return NDIS_ERROR_CODE_ADAPTER_NOT_FOUND;
303 }
304 NdisMQueryAdapterResources(&status, WrapperConfigurationContext,
305 nrl, (PUINT)&nrl_length);
306 if (status != NDIS_STATUS_SUCCESS)
307 {
308 KdPrint((__DRIVER_NAME " Could not get Adapter Resources 0x%x\n", status));
309 return NDIS_ERROR_CODE_ADAPTER_NOT_FOUND;
310 }
311 xi->event_channel = 0;
312 xi->config_csum = 1;
313 xi->config_sg = 1;
314 xi->config_gso = 61440;
315 xi->config_page = NULL;
317 for (i = 0; i < nrl->Count; i++)
318 {
319 prd = &nrl->PartialDescriptors[i];
321 switch(prd->Type)
322 {
323 case CmResourceTypeInterrupt:
324 irq_vector = prd->u.Interrupt.Vector;
325 irq_level = (KIRQL)prd->u.Interrupt.Level;
326 KdPrint((__DRIVER_NAME " irq_vector = %03x, irq_level = %03x\n", irq_vector, irq_level));
327 break;
329 case CmResourceTypeMemory:
330 status = NdisMMapIoSpace(&xi->config_page, MiniportAdapterHandle, prd->u.Memory.Start, prd->u.Memory.Length);
331 if (!NT_SUCCESS(status))
332 {
333 KdPrint(("NdisMMapIoSpace failed with 0x%x\n", status));
334 NdisFreeMemory(nrl, nrl_length, 0);
335 return NDIS_STATUS_RESOURCES;
336 }
337 break;
338 }
339 }
340 NdisFreeMemory(nrl, nrl_length, 0);
341 if (!xi->config_page)
342 {
343 KdPrint(("No config page given\n"));
344 return NDIS_STATUS_RESOURCES;
345 }
347 KeInitializeSpinLock(&xi->rx_lock);
349 InitializeListHead(&xi->tx_waiting_pkt_list);
351 NdisAllocatePacketPool(&status, &xi->packet_pool, XN_RX_QUEUE_LEN * 8,
352 PROTOCOL_RESERVED_SIZE_IN_PACKET);
353 if (status != NDIS_STATUS_SUCCESS)
354 {
355 KdPrint(("NdisAllocatePacketPool failed with 0x%x\n", status));
356 status = NDIS_STATUS_RESOURCES;
357 goto err;
358 }
359 NdisSetPacketPoolProtocolId(xi->packet_pool, NDIS_PROTOCOL_ID_TCP_IP);
361 NdisAllocateBufferPool(&status, &xi->buffer_pool, XN_RX_QUEUE_LEN);
362 if (status != NDIS_STATUS_SUCCESS)
363 {
364 KdPrint(("NdisAllocateBufferPool failed with 0x%x\n", status));
365 status = NDIS_STATUS_RESOURCES;
366 goto err;
367 }
369 NdisMGetDeviceProperty(MiniportAdapterHandle, &xi->pdo, &xi->fdo,
370 &xi->lower_do, NULL, NULL);
371 xi->packet_filter = NDIS_PACKET_TYPE_PROMISCUOUS;
373 status = IoGetDeviceProperty(xi->pdo, DevicePropertyDeviceDescription,
374 NAME_SIZE, xi->dev_desc, &length);
375 if (!NT_SUCCESS(status))
376 {
377 KdPrint(("IoGetDeviceProperty failed with 0x%x\n", status));
378 status = NDIS_STATUS_FAILURE;
379 goto err;
380 }
382 ptr = xi->config_page;
383 while((type = GET_XEN_INIT_RSP(&ptr, &setting, &value)) != XEN_INIT_TYPE_END)
384 {
385 switch(type)
386 {
387 case XEN_INIT_TYPE_VECTORS:
388 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
389 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
390 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
391 {
392 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
393 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
394 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
395 return NDIS_ERROR_CODE_ADAPTER_NOT_FOUND;
396 }
397 else
398 memcpy(&xi->vectors, value, sizeof(XENPCI_VECTORS));
399 break;
400 case XEN_INIT_TYPE_STATE_PTR:
401 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
402 xi->device_state = (PXENPCI_DEVICE_STATE)value;
403 break;
404 default:
405 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
406 break;
407 }
408 }
410 // now build config page
412 NdisOpenConfiguration(&status, &config_handle, WrapperConfigurationContext);
413 if (!NT_SUCCESS(status))
414 {
415 KdPrint(("Could not open config in registry (%08x)\n", status));
416 goto err;
417 }
419 NdisInitUnicodeString(&config_param_name, L"ScatterGather");
420 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
421 if (!NT_SUCCESS(status))
422 {
423 KdPrint(("Could not read ScatterGather value (%08x)\n", status));
424 xi->config_sg = 1;
425 }
426 else
427 {
428 KdPrint(("ScatterGather = %d\n", config_param->ParameterData.IntegerData));
429 xi->config_sg = config_param->ParameterData.IntegerData;
430 }
432 NdisInitUnicodeString(&config_param_name, L"LargeSendOffload");
433 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
434 if (!NT_SUCCESS(status))
435 {
436 KdPrint(("Could not read LargeSendOffload value (%08x)\n", status));
437 xi->config_gso = 0;
438 }
439 else
440 {
441 KdPrint(("LargeSendOffload = %d\n", config_param->ParameterData.IntegerData));
442 xi->config_gso = config_param->ParameterData.IntegerData;
443 if (xi->config_gso > 61440)
444 {
445 xi->config_gso = 61440;
446 KdPrint(("(clipped to %d)\n", xi->config_gso));
447 }
448 }
450 NdisInitUnicodeString(&config_param_name, L"ChecksumOffload");
451 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
452 if (!NT_SUCCESS(status))
453 {
454 KdPrint(("Could not read ChecksumOffload value (%08x)\n", status));
455 xi->config_csum = 1;
456 }
457 else
458 {
459 KdPrint(("ChecksumOffload = %d\n", config_param->ParameterData.IntegerData));
460 xi->config_csum = !!config_param->ParameterData.IntegerData;
461 }
463 NdisInitUnicodeString(&config_param_name, L"MTU");
464 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
465 if (!NT_SUCCESS(status))
466 {
467 KdPrint(("Could not read MTU value (%08x)\n", status));
468 xi->config_mtu = 1500;
469 }
470 else
471 {
472 KdPrint(("MTU = %d\n", config_param->ParameterData.IntegerData));
473 xi->config_mtu = config_param->ParameterData.IntegerData;
474 }
476 xi->config_max_pkt_size = max(xi->config_mtu + XN_HDR_SIZE, xi->config_gso + XN_HDR_SIZE);
478 NdisCloseConfiguration(config_handle);
480 ptr = xi->config_page;
481 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL);
482 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "tx-ring-ref", NULL);
483 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "rx-ring-ref", NULL);
484 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL);
485 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mac", NULL);
486 RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !xi->config_csum);
487 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-no-csum-offload", buf);
488 RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", xi->config_sg);
489 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-sg", buf);
490 RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !!xi->config_gso);
491 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-gso-tcpv4", buf);
492 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "request-rx-copy", "1");
493 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-rx-notify", "1");
494 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL);
496 status = xi->vectors.XenPci_XenConfigDevice(xi->vectors.context);
497 // check return value
499 status = XenNet_ConnectBackend(xi);
501 KeInitializeEvent(&xi->shutdown_event, SynchronizationEvent, FALSE);
503 XenNet_TxInit(xi);
504 XenNet_RxInit(xi);
506 xi->connected = TRUE;
508 KeMemoryBarrier(); // packets could be received anytime after we set Frontent to Connected
510 status = NdisMRegisterInterrupt(&xi->interrupt, MiniportAdapterHandle, irq_vector, irq_level,
511 TRUE, TRUE, NdisInterruptLatched);
512 /* send fake arp? */
513 if (!NT_SUCCESS(status))
514 {
515 KdPrint(("NdisMRegisterInterrupt failed with 0x%x\n", status));
516 //status = NDIS_STATUS_FAILURE;
517 //goto err;
518 }
520 NdisMInitializeTimer(&xi->resume_timer, xi->adapter_handle, XenResumeCheck_Timer, xi);
521 NdisMSetPeriodicTimer(&xi->resume_timer, 100);
523 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
525 return NDIS_STATUS_SUCCESS;
527 err:
528 NdisFreeMemory(xi, 0, 0);
529 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ " (error path)\n"));
530 return status;
531 }
533 VOID
534 XenNet_PnPEventNotify(
535 IN NDIS_HANDLE MiniportAdapterContext,
536 IN NDIS_DEVICE_PNP_EVENT PnPEvent,
537 IN PVOID InformationBuffer,
538 IN ULONG InformationBufferLength
539 )
540 {
541 UNREFERENCED_PARAMETER(MiniportAdapterContext);
542 UNREFERENCED_PARAMETER(PnPEvent);
543 UNREFERENCED_PARAMETER(InformationBuffer);
544 UNREFERENCED_PARAMETER(InformationBufferLength);
546 KdPrint((__FUNCTION__ " called\n"));
547 }
549 /* Called when machine is shutting down, so just quiesce the HW and be done fast. */
550 VOID
551 XenNet_Shutdown(
552 IN NDIS_HANDLE MiniportAdapterContext
553 )
554 {
555 struct xennet_info *xi = MiniportAdapterContext;
557 KdPrint((__FUNCTION__ " called\n"));
559 NdisMDeregisterInterrupt(&xi->interrupt);
560 }
562 /* Opposite of XenNet_Init */
563 VOID
564 XenNet_Halt(
565 IN NDIS_HANDLE MiniportAdapterContext
566 )
567 {
568 struct xennet_info *xi = MiniportAdapterContext;
569 // CHAR TmpPath[MAX_XENBUS_STR_LEN];
570 // PVOID if_cxt = xi->XenInterface.InterfaceHeader.Context;
571 // LARGE_INTEGER timeout;
573 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
574 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
576 // Disables the interrupt
577 XenNet_Shutdown(xi);
579 xi->vectors.XenPci_XenShutdownDevice(xi->vectors.context);
581 xi->connected = FALSE;
582 KeMemoryBarrier(); /* make sure everyone sees that we are now shut down */
584 // TODO: remove event channel xenbus entry (how?)
586 XenNet_TxShutdown(xi);
587 XenNet_RxShutdown(xi);
589 NdisFreeBufferPool(xi->buffer_pool);
590 NdisFreePacketPool(xi->packet_pool);
592 NdisFreeMemory(xi, 0, 0); // <= DISPATCH_LEVEL
594 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
595 }
597 NTSTATUS
598 DriverEntry(
599 PDRIVER_OBJECT DriverObject,
600 PUNICODE_STRING RegistryPath
601 )
602 {
603 NTSTATUS status;
604 NDIS_HANDLE ndis_wrapper_handle;
605 NDIS_MINIPORT_CHARACTERISTICS mini_chars;
607 ProfTime_TxBufferGC.QuadPart = 0;
608 ProfTime_RxBufferAlloc.QuadPart = 0;
609 ProfTime_ReturnPacket.QuadPart = 0;
610 ProfTime_RxBufferCheck.QuadPart = 0;
611 ProfTime_RxBufferCheckTopHalf.QuadPart = 0;
612 ProfTime_RxBufferCheckBotHalf.QuadPart = 0;
613 ProfTime_Linearize.QuadPart = 0;
614 ProfTime_SendPackets.QuadPart = 0;
615 ProfTime_SendQueuedPackets.QuadPart = 0;
617 ProfCount_TxBufferGC = 0;
618 ProfCount_RxBufferAlloc = 0;
619 ProfCount_ReturnPacket = 0;
620 ProfCount_RxBufferCheck = 0;
621 ProfCount_Linearize = 0;
622 ProfCount_SendPackets = 0;
623 ProfCount_PacketsPerSendPackets = 0;
624 ProfCount_SendQueuedPackets = 0;
626 ProfCount_TxPacketsTotal = 0;
627 ProfCount_TxPacketsCsumOffload = 0;
628 ProfCount_TxPacketsLargeOffload = 0;
629 ProfCount_RxPacketsTotal = 0;
630 ProfCount_RxPacketsCsumOffload = 0;
631 ProfCount_CallsToIndicateReceive = 0;
633 RtlZeroMemory(&mini_chars, sizeof(mini_chars));
635 NdisMInitializeWrapper(&ndis_wrapper_handle, DriverObject, RegistryPath, NULL);
636 if (!ndis_wrapper_handle)
637 {
638 KdPrint(("NdisMInitializeWrapper failed\n"));
639 return NDIS_STATUS_FAILURE;
640 }
642 /* NDIS 5.1 driver */
643 mini_chars.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
644 mini_chars.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
646 mini_chars.HaltHandler = XenNet_Halt;
647 mini_chars.InitializeHandler = XenNet_Init;
648 mini_chars.ISRHandler = XenNet_InterruptIsr;
649 mini_chars.HandleInterruptHandler = XenNet_InterruptDpc;
650 mini_chars.QueryInformationHandler = XenNet_QueryInformation;
651 mini_chars.ResetHandler = NULL; //TODO: fill in
652 mini_chars.SetInformationHandler = XenNet_SetInformation;
653 /* added in v.4 -- use multiple pkts interface */
654 mini_chars.ReturnPacketHandler = XenNet_ReturnPacket;
655 mini_chars.SendPacketsHandler = XenNet_SendPackets;
657 #if defined (NDIS51_MINIPORT)
658 /* added in v.5.1 */
659 mini_chars.PnPEventNotifyHandler = XenNet_PnPEventNotify;
660 mini_chars.AdapterShutdownHandler = XenNet_Shutdown;
661 #else
662 // something else here
663 #endif
665 /* set up upper-edge interface */
666 status = NdisMRegisterMiniport(ndis_wrapper_handle, &mini_chars, sizeof(mini_chars));
667 if (!NT_SUCCESS(status))
668 {
669 KdPrint(("NdisMRegisterMiniport failed, status = 0x%x\n", status));
670 NdisTerminateWrapper(ndis_wrapper_handle, NULL);
671 return status;
672 }
674 return status;
675 }