win-pvdrivers

view xennet/xennet.c @ 360:cb12e8b450a8

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