win-pvdrivers

annotate xennet/xennet5.c @ 979:8f483a2b2991

Fix up PREfast warnings
author James Harper <james.harper@bendigoit.com.au>
date Sun Apr 15 19:47:10 2012 +1000 (2012-04-15)
parents 99023e044544
children
rev   line source
james@914 1 /*
james@914 2 PV Net Driver for Windows Xen HVM Domains
james@914 3 Copyright (C) 2007 James Harper
james@914 4 Copyright (C) 2007 Andrew Grover <andy.grover@oracle.com>
james@914 5
james@914 6 This program is free software; you can redistribute it and/or
james@914 7 modify it under the terms of the GNU General Public License
james@914 8 as published by the Free Software Foundation; either version 2
james@914 9 of the License, or (at your option) any later version.
james@914 10
james@914 11 This program is distributed in the hope that it will be useful,
james@914 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
james@914 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
james@914 14 GNU General Public License for more details.
james@914 15
james@914 16 You should have received a copy of the GNU General Public License
james@914 17 along with this program; if not, write to the Free Software
james@914 18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
james@914 19 */
james@914 20
james@914 21 #include <stdlib.h>
james@914 22 #include <io/xenbus.h>
james@914 23 #include "xennet5.h"
james@914 24
james@914 25 /* Not really necessary but keeps PREfast happy */
james@914 26 DRIVER_INITIALIZE DriverEntry;
james@914 27 static IO_WORKITEM_ROUTINE XenNet_ResumeWorkItem;
james@914 28 #if (VER_PRODUCTBUILD >= 7600)
james@914 29 static KDEFERRED_ROUTINE XenNet_SuspendResume;
james@979 30 static KDEFERRED_ROUTINE XenNet_RxTxDpc;
james@914 31 #endif
james@914 32
james@914 33 #pragma NDIS_INIT_FUNCTION(DriverEntry)
james@914 34
james@914 35 /* ----- BEGIN Other people's code --------- */
james@914 36 /* from linux/include/linux/ctype.h, used under GPLv2 */
james@914 37 #define _U 0x01 /* upper */
james@914 38 #define _L 0x02 /* lower */
james@914 39 #define _D 0x04 /* digit */
james@914 40 #define _C 0x08 /* cntrl */
james@914 41 #define _P 0x10 /* punct */
james@914 42 #define _S 0x20 /* white space (space/lf/tab) */
james@914 43 #define _X 0x40 /* hex digit */
james@914 44 #define _SP 0x80 /* hard space (0x20) */
james@914 45
james@914 46 /* from linux/include/lib/ctype.c, used under GPLv2 */
james@914 47 unsigned char _ctype[] = {
james@914 48 _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
james@914 49 _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
james@914 50 _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
james@914 51 _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
james@914 52 _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
james@914 53 _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
james@914 54 _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
james@914 55 _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
james@914 56 _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
james@914 57 _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
james@914 58 _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
james@914 59 _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
james@914 60 _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
james@914 61 _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
james@914 62 _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
james@914 63 _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
james@914 64 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
james@914 65 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
james@914 66 _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
james@914 67 _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
james@914 68 _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
james@914 69 _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
james@914 70 _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
james@914 71 _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
james@914 72
james@914 73 /* from linux/include/linux/ctype.h, used under GPLv2 */
james@914 74 #define __ismask(x) (_ctype[(int)(unsigned char)(x)])
james@914 75
james@914 76 #define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
james@914 77 #define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
james@914 78 #define iscntrl(c) ((__ismask(c)&(_C)) != 0)
james@914 79 #define isdigit(c) ((__ismask(c)&(_D)) != 0)
james@914 80 #define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
james@914 81 #define islower(c) ((__ismask(c)&(_L)) != 0)
james@914 82 #define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
james@914 83 #define ispunct(c) ((__ismask(c)&(_P)) != 0)
james@914 84 #define isspace(c) ((__ismask(c)&(_S)) != 0)
james@914 85 #define isupper(c) ((__ismask(c)&(_U)) != 0)
james@914 86 #define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
james@914 87
james@914 88 #define TOLOWER(x) ((x) | 0x20)
james@914 89
james@914 90 /* from linux/lib/vsprintf.c, used under GPLv2 */
james@914 91 /* Copyright (C) 1991, 1992 Linus Torvalds
james@914 92 * Wirzenius wrote this portably, Torvalds fucked it up :-)
james@914 93 */
james@914 94 /**
james@914 95 * simple_strtoul - convert a string to an unsigned long
james@914 96 * @cp: The start of the string
james@914 97 * @endp: A pointer to the end of the parsed string will be placed here
james@914 98 * @base: The number base to use
james@914 99 */
james@914 100 unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
james@914 101 {
james@914 102 unsigned long result = 0,value;
james@914 103
james@914 104 if (!base) {
james@914 105 base = 10;
james@914 106 if (*cp == '0') {
james@914 107 base = 8;
james@914 108 cp++;
james@914 109 if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) {
james@914 110 cp++;
james@914 111 base = 16;
james@914 112 }
james@914 113 }
james@914 114 } else if (base == 16) {
james@914 115 if (cp[0] == '0' && TOLOWER(cp[1]) == 'x')
james@914 116 cp += 2;
james@914 117 }
james@914 118 while (isxdigit(*cp) &&
james@914 119 (value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) {
james@914 120 result = result*base + value;
james@914 121 cp++;
james@914 122 }
james@914 123 if (endp)
james@914 124 *endp = (char *)cp;
james@914 125 return result;
james@914 126 }
james@914 127 /* end vsprintf.c code */
james@914 128 /* ----- END Other people's code --------- */
james@914 129
james@914 130 static NDIS_STATUS
james@914 131 XenNet_ConnectBackend(struct xennet_info *xi)
james@914 132 {
james@914 133 PUCHAR ptr;
james@914 134 UCHAR type;
james@914 135 PCHAR setting, value, value2;
james@914 136 UINT i;
james@914 137 ULONG backend_sg = 0;
james@914 138 ULONG backend_gso = 0;
james@914 139
james@914 140 FUNCTION_ENTER();
james@914 141
james@914 142 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
james@914 143
james@914 144 ptr = xi->config_page;
james@914 145 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
james@914 146 {
james@914 147 switch(type)
james@914 148 {
james@914 149 case XEN_INIT_TYPE_RING: /* frontend ring */
james@914 150 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
james@914 151 if (strcmp(setting, "tx-ring-ref") == 0)
james@914 152 {
james@914 153 FRONT_RING_INIT(&xi->tx, (netif_tx_sring_t *)value, PAGE_SIZE);
james@914 154 } else if (strcmp(setting, "rx-ring-ref") == 0)
james@914 155 {
james@914 156 FRONT_RING_INIT(&xi->rx, (netif_rx_sring_t *)value, PAGE_SIZE);
james@914 157 }
james@914 158 break;
james@914 159 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
james@914 160 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
james@914 161 if (strcmp(setting, "event-channel") == 0)
james@914 162 {
james@914 163 xi->event_channel = PtrToUlong(value);
james@914 164 }
james@914 165 break;
james@914 166 case XEN_INIT_TYPE_READ_STRING_FRONT:
james@914 167 break;
james@914 168 case XEN_INIT_TYPE_READ_STRING_BACK:
james@914 169 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
james@914 170 if (strcmp(setting, "mac") == 0)
james@914 171 {
james@914 172 char *s, *e;
james@914 173 s = value;
james@914 174 for (i = 0; i < ETH_ALEN; i++) {
james@914 175 xi->perm_mac_addr[i] = (uint8_t)simple_strtoul(s, &e, 16);
james@914 176 if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
james@914 177 KdPrint((__DRIVER_NAME "Error parsing MAC address\n"));
james@914 178 }
james@914 179 s = e + 1;
james@914 180 }
james@914 181 if ((xi->curr_mac_addr[0] & 0x03) != 0x02)
james@914 182 {
james@914 183 /* only copy if curr_mac_addr is not a LUA */
james@914 184 memcpy(xi->curr_mac_addr, xi->perm_mac_addr, ETH_ALEN);
james@914 185 }
james@914 186 }
james@914 187 else if (strcmp(setting, "feature-sg") == 0)
james@914 188 {
james@914 189 if (atoi(value))
james@914 190 {
james@914 191 backend_sg = 1;
james@914 192 }
james@914 193 }
james@914 194 else if (strcmp(setting, "feature-gso-tcpv4") == 0)
james@914 195 {
james@914 196 if (atoi(value))
james@914 197 {
james@914 198 backend_gso = 1;
james@914 199 }
james@914 200 }
james@914 201 break;
james@914 202 case XEN_INIT_TYPE_VECTORS:
james@914 203 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
james@914 204 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
james@914 205 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
james@914 206 {
james@914 207 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
james@914 208 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
james@914 209 FUNCTION_EXIT();
james@914 210 return NDIS_STATUS_ADAPTER_NOT_FOUND;
james@914 211 }
james@914 212 else
james@914 213 memcpy(&xi->vectors, value, sizeof(XENPCI_VECTORS));
james@914 214 break;
james@914 215 case XEN_INIT_TYPE_STATE_PTR:
james@914 216 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
james@914 217 xi->device_state = (PXENPCI_DEVICE_STATE)value;
james@914 218 break;
james@914 219 default:
james@914 220 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
james@914 221 break;
james@914 222 }
james@914 223 }
james@914 224 if (xi->config_sg && !backend_sg)
james@914 225 {
james@914 226 KdPrint((__DRIVER_NAME " SG not supported by backend - disabling\n"));
james@914 227 xi->config_sg = 0;
james@914 228 }
james@914 229 if (xi->config_gso && !backend_gso)
james@914 230 {
james@914 231 KdPrint((__DRIVER_NAME " GSO not supported by backend - disabling\n"));
james@914 232 xi->config_gso = 0;
james@914 233 }
james@914 234 FUNCTION_EXIT();
james@914 235
james@914 236 return NDIS_STATUS_SUCCESS;
james@914 237 }
james@914 238
james@914 239 static VOID
james@914 240 XenNet_ResumeWorkItem(PDEVICE_OBJECT device_object, PVOID context)
james@914 241 {
james@914 242 struct xennet_info *xi = context;
james@914 243 KIRQL old_irql;
james@914 244
james@914 245 UNREFERENCED_PARAMETER(device_object);
james@914 246
james@914 247 FUNCTION_ENTER();
james@914 248
james@914 249 ASSERT(xi->resume_work_item);
james@914 250
james@914 251 IoFreeWorkItem(xi->resume_work_item);
james@914 252
james@914 253 XenNet_TxResumeStart(xi);
james@914 254 XenNet_RxResumeStart(xi);
james@914 255 XenNet_ConnectBackend(xi);
james@914 256 XenNet_RxResumeEnd(xi);
james@914 257 XenNet_TxResumeEnd(xi);
james@914 258
james@914 259 KeAcquireSpinLock(&xi->resume_lock, &old_irql);
james@914 260 xi->resume_work_item = NULL;
james@914 261 KdPrint((__DRIVER_NAME " *Setting suspend_resume_state_fdo = %d\n", xi->device_state->suspend_resume_state_pdo));
james@914 262 xi->device_state->suspend_resume_state_fdo = xi->device_state->suspend_resume_state_pdo;
james@914 263 KdPrint((__DRIVER_NAME " *Notifying event channel %d\n", xi->device_state->pdo_event_channel));
james@914 264 xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel);
james@914 265 KeReleaseSpinLock(&xi->resume_lock, old_irql);
james@914 266
james@914 267 FUNCTION_EXIT();
james@914 268
james@914 269 }
james@914 270
james@914 271 static VOID
james@914 272 XenNet_SuspendResume(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2)
james@914 273 {
james@914 274 struct xennet_info *xi = context;
james@914 275 KIRQL old_irql;
james@914 276 PIO_WORKITEM resume_work_item;
james@914 277
james@914 278 UNREFERENCED_PARAMETER(dpc);
james@914 279 UNREFERENCED_PARAMETER(arg1);
james@914 280 UNREFERENCED_PARAMETER(arg2);
james@914 281
james@914 282 FUNCTION_ENTER();
james@914 283
james@914 284 switch (xi->device_state->suspend_resume_state_pdo)
james@914 285 {
james@914 286 case SR_STATE_SUSPENDING:
james@914 287 KdPrint((__DRIVER_NAME " New state SUSPENDING\n"));
james@914 288 KeAcquireSpinLock(&xi->rx_lock, &old_irql);
james@914 289 if (xi->rx_id_free == NET_RX_RING_SIZE)
james@914 290 {
james@914 291 xi->device_state->suspend_resume_state_fdo = SR_STATE_SUSPENDING;
james@914 292 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xi->device_state->pdo_event_channel));
james@914 293 xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel);
james@914 294 }
james@914 295 KeReleaseSpinLock(&xi->rx_lock, old_irql);
james@914 296 break;
james@914 297 case SR_STATE_RESUMING:
james@914 298 KdPrint((__DRIVER_NAME " New state SR_STATE_RESUMING\n"));
james@914 299 /* do it like this so we don't race and double-free the work item */
james@914 300 resume_work_item = IoAllocateWorkItem(xi->fdo);
james@914 301 KeAcquireSpinLock(&xi->resume_lock, &old_irql);
james@914 302 if (xi->resume_work_item || xi->device_state->suspend_resume_state_fdo == SR_STATE_RESUMING)
james@914 303 {
james@914 304 KeReleaseSpinLock(&xi->resume_lock, old_irql);
james@914 305 IoFreeWorkItem(resume_work_item);
james@914 306 return;
james@914 307 }
james@914 308 xi->resume_work_item = resume_work_item;
james@914 309 KeReleaseSpinLock(&xi->resume_lock, old_irql);
james@914 310 IoQueueWorkItem(xi->resume_work_item, XenNet_ResumeWorkItem, DelayedWorkQueue, xi);
james@914 311 break;
james@914 312 default:
james@914 313 KdPrint((__DRIVER_NAME " New state %d\n", xi->device_state->suspend_resume_state_fdo));
james@914 314 xi->device_state->suspend_resume_state_fdo = xi->device_state->suspend_resume_state_pdo;
james@914 315 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xi->device_state->pdo_event_channel));
james@914 316 xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel);
james@914 317 break;
james@914 318 }
james@914 319 KeMemoryBarrier();
james@914 320
james@914 321 FUNCTION_EXIT();
james@914 322 }
james@914 323
james@914 324 static VOID
james@914 325 XenNet_RxTxDpc(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2)
james@914 326 {
james@914 327 struct xennet_info *xi = context;
james@914 328 BOOLEAN dont_set_event;
james@914 329
james@914 330 UNREFERENCED_PARAMETER(dpc);
james@914 331 UNREFERENCED_PARAMETER(arg1);
james@914 332 UNREFERENCED_PARAMETER(arg2);
james@914 333
james@914 334 /* if Rx goes over its per-dpc quota then make sure TxBufferGC doesn't set an event as we are already guaranteed to be called again */
james@914 335 dont_set_event = XenNet_RxBufferCheck(xi);
james@914 336 XenNet_TxBufferGC(xi, dont_set_event);
james@914 337 }
james@914 338
james@914 339 static BOOLEAN
james@914 340 XenNet_HandleEvent(PVOID context)
james@914 341 {
james@914 342 struct xennet_info *xi = context;
james@914 343 ULONG suspend_resume_state_pdo;
james@914 344
james@914 345 //FUNCTION_ENTER();
james@914 346 suspend_resume_state_pdo = xi->device_state->suspend_resume_state_pdo;
james@914 347 KeMemoryBarrier();
james@914 348 // KdPrint((__DRIVER_NAME " connected = %d, inactive = %d, suspend_resume_state_pdo = %d\n",
james@914 349 // xi->connected, xi->inactive, suspend_resume_state_pdo));
james@914 350 if (!xi->shutting_down && suspend_resume_state_pdo != xi->device_state->suspend_resume_state_fdo)
james@914 351 {
james@914 352 KeInsertQueueDpc(&xi->suspend_dpc, NULL, NULL);
james@914 353 }
james@914 354 if (xi->connected && !xi->inactive && suspend_resume_state_pdo != SR_STATE_RESUMING)
james@914 355 {
james@914 356 KeInsertQueueDpc(&xi->rxtx_dpc, NULL, NULL);
james@914 357 }
james@914 358 //FUNCTION_EXIT();
james@914 359 return TRUE;
james@914 360 }
james@914 361
james@914 362 VOID
james@914 363 XenNet_SetPower(PDEVICE_OBJECT device_object, PVOID context)
james@914 364 {
james@914 365 NTSTATUS status = STATUS_SUCCESS;
james@914 366 KIRQL old_irql;
james@914 367 struct xennet_info *xi = context;
james@914 368
james@914 369 FUNCTION_ENTER();
james@914 370 UNREFERENCED_PARAMETER(device_object);
james@914 371
james@914 372 switch (xi->new_power_state)
james@914 373 {
james@914 374 case NdisDeviceStateD0:
james@914 375 KdPrint((" NdisDeviceStateD0\n"));
james@914 376 status = XenNet_D0Entry(xi);
james@914 377 break;
james@914 378 case NdisDeviceStateD1:
james@914 379 KdPrint((" NdisDeviceStateD1\n"));
james@914 380 if (xi->power_state == NdisDeviceStateD0)
james@914 381 status = XenNet_D0Exit(xi);
james@914 382 break;
james@914 383 case NdisDeviceStateD2:
james@914 384 KdPrint((" NdisDeviceStateD2\n"));
james@914 385 if (xi->power_state == NdisDeviceStateD0)
james@914 386 status = XenNet_D0Exit(xi);
james@914 387 break;
james@914 388 case NdisDeviceStateD3:
james@914 389 KdPrint((" NdisDeviceStateD3\n"));
james@914 390 if (xi->power_state == NdisDeviceStateD0)
james@914 391 status = XenNet_D0Exit(xi);
james@914 392 break;
james@914 393 default:
james@914 394 KdPrint((" NdisDeviceState??\n"));
james@914 395 status = NDIS_STATUS_NOT_SUPPORTED;
james@914 396 break;
james@914 397 }
james@914 398 xi->power_state = xi->new_power_state;
james@914 399
james@914 400 old_irql = KeRaiseIrqlToDpcLevel();
james@914 401 NdisMSetInformationComplete(xi->adapter_handle, status);
james@914 402 KeLowerIrql(old_irql);
james@914 403
james@914 404 FUNCTION_EXIT();
james@914 405 }
james@914 406
james@914 407 NDIS_STATUS
james@914 408 XenNet_D0Entry(struct xennet_info *xi)
james@914 409 {
james@914 410 NDIS_STATUS status;
james@914 411 PUCHAR ptr;
james@914 412 CHAR buf[128];
james@914 413
james@914 414 FUNCTION_ENTER();
james@914 415
james@914 416 xi->shutting_down = FALSE;
james@914 417
james@914 418 ptr = xi->config_page;
james@914 419 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "tx-ring-ref", NULL, NULL);
james@914 420 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "rx-ring-ref", NULL, NULL);
james@914 421 #pragma warning(suppress:4054)
james@914 422 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL, "event-channel", (PVOID)XenNet_HandleEvent, xi);
james@914 423 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mac", NULL, NULL);
james@914 424 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "feature-sg", NULL, NULL);
james@914 425 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "feature-gso-tcpv4", NULL, NULL);
james@914 426 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "request-rx-copy", "1", NULL);
james@914 427 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-rx-notify", "1", NULL);
james@914 428 RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !xi->config_csum);
james@914 429 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-no-csum-offload", buf, NULL);
james@914 430 RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", (int)xi->config_sg);
james@914 431 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-sg", buf, NULL);
james@914 432 RtlStringCbPrintfA(buf, ARRAY_SIZE(buf), "%d", !!xi->config_gso);
james@914 433 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_WRITE_STRING, "feature-gso-tcpv4", buf, NULL);
james@914 434 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT, NULL, NULL, NULL);
james@914 435 __ADD_XEN_INIT_UCHAR(&ptr, 0); /* no pre-connect required */
james@914 436 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT, NULL, NULL, NULL);
james@914 437 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
james@914 438 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
james@914 439 __ADD_XEN_INIT_UCHAR(&ptr, 20);
james@914 440 __ADD_XEN_INIT_UCHAR(&ptr, 0);
james@914 441 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN, NULL, NULL, NULL);
james@914 442 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
james@914 443 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
james@914 444 __ADD_XEN_INIT_UCHAR(&ptr, 50);
james@914 445 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
james@914 446 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
james@914 447 __ADD_XEN_INIT_UCHAR(&ptr, 50);
james@914 448 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialising);
james@914 449 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitWait);
james@914 450 __ADD_XEN_INIT_UCHAR(&ptr, 50);
james@914 451 __ADD_XEN_INIT_UCHAR(&ptr, 0);
james@914 452 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
james@914 453
james@914 454 status = xi->vectors.XenPci_XenConfigDevice(xi->vectors.context);
james@914 455 if (!NT_SUCCESS(status))
james@914 456 {
james@914 457 KdPrint(("Failed to complete device configuration (%08x)\n", status));
james@914 458 return status;
james@914 459 }
james@914 460
james@914 461 status = XenNet_ConnectBackend(xi);
james@914 462
james@914 463 if (!NT_SUCCESS(status))
james@914 464 {
james@914 465 KdPrint(("Failed to complete device configuration (%08x)\n", status));
james@914 466 return status;
james@914 467 }
james@914 468
james@914 469 if (!xi->config_sg)
james@914 470 {
james@914 471 /* without SG, GSO can be a maximum of PAGE_SIZE */
james@914 472 xi->config_gso = min(xi->config_gso, PAGE_SIZE);
james@914 473 }
james@914 474
james@914 475 XenNet_TxInit(xi);
james@914 476 XenNet_RxInit(xi);
james@914 477
james@914 478 xi->connected = TRUE;
james@914 479
james@914 480 KeMemoryBarrier(); // packets could be received anytime after we set Frontent to Connected
james@914 481
james@914 482 FUNCTION_EXIT();
james@914 483
james@914 484 return status;
james@914 485 }
james@914 486
james@914 487 // Called at <= DISPATCH_LEVEL
james@914 488 static NDIS_STATUS
james@914 489 XenNet_Init(
james@914 490 OUT PNDIS_STATUS OpenErrorStatus,
james@914 491 OUT PUINT SelectedMediumIndex,
james@914 492 IN PNDIS_MEDIUM MediumArray,
james@914 493 IN UINT MediumArraySize,
james@914 494 IN NDIS_HANDLE MiniportAdapterHandle,
james@914 495 IN NDIS_HANDLE WrapperConfigurationContext
james@914 496 )
james@914 497 {
james@914 498 NDIS_STATUS status;
james@914 499 BOOLEAN medium_found = FALSE;
james@914 500 struct xennet_info *xi = NULL;
james@914 501 UINT nrl_length;
james@914 502 PNDIS_RESOURCE_LIST nrl;
james@914 503 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
james@914 504 KIRQL irq_level = 0;
james@914 505 ULONG irq_vector = 0;
james@914 506 ULONG irq_mode = 0;
james@914 507 NDIS_HANDLE config_handle;
james@914 508 NDIS_STRING config_param_name;
james@914 509 PNDIS_CONFIGURATION_PARAMETER config_param;
james@914 510 ULONG i;
james@914 511 PUCHAR ptr;
james@914 512 UCHAR type;
james@914 513 PCHAR setting, value;
james@914 514 ULONG length;
james@914 515 //CHAR buf[128];
james@914 516 PVOID network_address;
james@914 517 UINT network_address_length;
james@914 518 BOOLEAN qemu_hide_filter = FALSE;
james@914 519 ULONG qemu_hide_flags_value = 0;
james@914 520
james@914 521 UNREFERENCED_PARAMETER(OpenErrorStatus);
james@914 522
james@914 523 FUNCTION_ENTER();
james@914 524
james@914 525 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@914 526
james@914 527 /* deal with medium stuff */
james@914 528 for (i = 0; i < MediumArraySize; i++)
james@914 529 {
james@914 530 if (MediumArray[i] == NdisMedium802_3)
james@914 531 {
james@914 532 medium_found = TRUE;
james@914 533 break;
james@914 534 }
james@914 535 }
james@914 536 if (!medium_found)
james@914 537 {
james@914 538 KdPrint(("NIC_MEDIA_TYPE not in MediumArray\n"));
james@914 539 return NDIS_STATUS_UNSUPPORTED_MEDIA;
james@914 540 }
james@914 541 *SelectedMediumIndex = i;
james@914 542
james@914 543 /* Alloc memory for adapter private info */
james@914 544 status = NdisAllocateMemoryWithTag((PVOID)&xi, sizeof(*xi), XENNET_POOL_TAG);
james@914 545 if (!NT_SUCCESS(status))
james@914 546 {
james@914 547 KdPrint(("NdisAllocateMemoryWithTag failed with 0x%x\n", status));
james@914 548 status = NDIS_STATUS_RESOURCES;
james@914 549 goto err;
james@914 550 }
james@914 551 RtlZeroMemory(xi, sizeof(*xi));
james@914 552 xi->adapter_handle = MiniportAdapterHandle;
james@914 553 xi->rx_target = RX_DFL_MIN_TARGET;
james@914 554 xi->rx_min_target = RX_DFL_MIN_TARGET;
james@914 555 xi->rx_max_target = RX_MAX_TARGET;
james@914 556 xi->inactive = TRUE;
james@914 557 NdisMSetAttributesEx(xi->adapter_handle, (NDIS_HANDLE) xi, 0, 0 /* the last zero is to give the next | something to | with */
james@914 558 #ifdef NDIS51_MINIPORT
james@914 559 |NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS
james@914 560 #endif
james@914 561 |NDIS_ATTRIBUTE_DESERIALIZE
james@935 562 |NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK,
james@933 563 NdisInterfaceInternal); /* PnpBus option doesn't exist... */
james@914 564 xi->multicast_list_size = 0;
james@914 565 xi->current_lookahead = MIN_LOOKAHEAD_LENGTH;
james@914 566
james@914 567 nrl_length = 0;
james@914 568 NdisMQueryAdapterResources(&status, WrapperConfigurationContext,
james@914 569 NULL, (PUINT)&nrl_length);
james@914 570 KdPrint((__DRIVER_NAME " nrl_length = %d\n", nrl_length));
james@914 571 status = NdisAllocateMemoryWithTag((PVOID)&nrl, nrl_length, XENNET_POOL_TAG);
james@914 572 if (status != NDIS_STATUS_SUCCESS)
james@914 573 {
james@914 574 KdPrint((__DRIVER_NAME " Could not get allocate memory for Adapter Resources 0x%x\n", status));
james@914 575 return NDIS_STATUS_RESOURCES;
james@914 576 }
james@914 577 NdisMQueryAdapterResources(&status, WrapperConfigurationContext,
james@914 578 nrl, (PUINT)&nrl_length);
james@914 579 if (status != NDIS_STATUS_SUCCESS)
james@914 580 {
james@914 581 KdPrint((__DRIVER_NAME " Could not get Adapter Resources 0x%x\n", status));
james@914 582 return NDIS_STATUS_RESOURCES;
james@914 583 }
james@914 584 xi->event_channel = 0;
james@914 585 xi->config_csum = 1;
james@914 586 xi->config_csum_rx_check = 1;
james@914 587 xi->config_sg = 1;
james@914 588 xi->config_gso = 61440;
james@914 589 xi->config_page = NULL;
james@914 590 xi->config_rx_interrupt_moderation = 0;
james@914 591
james@914 592 for (i = 0; i < nrl->Count; i++)
james@914 593 {
james@914 594 prd = &nrl->PartialDescriptors[i];
james@914 595
james@914 596 switch(prd->Type)
james@914 597 {
james@914 598 case CmResourceTypeInterrupt:
james@914 599 irq_vector = prd->u.Interrupt.Vector;
james@914 600 irq_level = (KIRQL)prd->u.Interrupt.Level;
james@914 601 irq_mode = (prd->Flags & CM_RESOURCE_INTERRUPT_LATCHED)?NdisInterruptLatched:NdisInterruptLevelSensitive;
james@914 602 KdPrint((__DRIVER_NAME " irq_vector = %03x, irq_level = %03x, irq_mode = %s\n", irq_vector, irq_level,
james@914 603 (irq_mode == NdisInterruptLatched)?"NdisInterruptLatched":"NdisInterruptLevelSensitive"));
james@914 604 break;
james@914 605 case CmResourceTypeMemory:
james@914 606 if (xi->config_page)
james@914 607 {
james@914 608 KdPrint(("More than one memory range\n"));
james@914 609 return NDIS_STATUS_RESOURCES;
james@914 610 }
james@914 611 else
james@914 612 {
james@914 613 status = NdisMMapIoSpace(&xi->config_page, MiniportAdapterHandle, prd->u.Memory.Start, prd->u.Memory.Length);
james@914 614 if (!NT_SUCCESS(status))
james@914 615 {
james@914 616 KdPrint(("NdisMMapIoSpace failed with 0x%x\n", status));
james@914 617 NdisFreeMemory(nrl, nrl_length, 0);
james@914 618 return NDIS_STATUS_RESOURCES;
james@914 619 }
james@914 620 }
james@914 621 break;
james@914 622 }
james@914 623 }
james@914 624 NdisFreeMemory(nrl, nrl_length, 0);
james@914 625 if (!xi->config_page)
james@914 626 {
james@914 627 KdPrint(("No config page given\n"));
james@914 628 return NDIS_STATUS_RESOURCES;
james@914 629 }
james@914 630
james@914 631 KeInitializeDpc(&xi->suspend_dpc, XenNet_SuspendResume, xi);
james@914 632 KeInitializeSpinLock(&xi->resume_lock);
james@914 633
james@914 634 KeInitializeDpc(&xi->rxtx_dpc, XenNet_RxTxDpc, xi);
james@914 635 KeSetTargetProcessorDpc(&xi->rxtx_dpc, 0);
james@914 636 KeSetImportanceDpc(&xi->rxtx_dpc, HighImportance);
james@914 637
james@914 638 NdisMGetDeviceProperty(MiniportAdapterHandle, &xi->pdo, &xi->fdo,
james@914 639 &xi->lower_do, NULL, NULL);
james@914 640 xi->packet_filter = 0;
james@914 641
james@914 642 status = IoGetDeviceProperty(xi->pdo, DevicePropertyDeviceDescription,
james@914 643 NAME_SIZE, xi->dev_desc, &length);
james@914 644 if (!NT_SUCCESS(status))
james@914 645 {
james@914 646 KdPrint(("IoGetDeviceProperty failed with 0x%x\n", status));
james@914 647 status = NDIS_STATUS_FAILURE;
james@914 648 goto err;
james@914 649 }
james@914 650
james@914 651 ptr = xi->config_page;
james@914 652 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value)) != XEN_INIT_TYPE_END)
james@914 653 {
james@914 654 switch(type)
james@914 655 {
james@914 656 case XEN_INIT_TYPE_VECTORS:
james@914 657 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
james@914 658 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
james@914 659 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
james@914 660 {
james@914 661 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
james@914 662 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
james@914 663 FUNCTION_EXIT();
james@914 664 return NDIS_STATUS_FAILURE;
james@914 665 }
james@914 666 else
james@914 667 memcpy(&xi->vectors, value, sizeof(XENPCI_VECTORS));
james@914 668 break;
james@914 669 case XEN_INIT_TYPE_STATE_PTR:
james@914 670 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
james@914 671 xi->device_state = (PXENPCI_DEVICE_STATE)value;
james@914 672 break;
james@914 673 case XEN_INIT_TYPE_QEMU_HIDE_FLAGS:
james@914 674 qemu_hide_flags_value = PtrToUlong(value);
james@914 675 break;
james@914 676 case XEN_INIT_TYPE_QEMU_HIDE_FILTER:
james@914 677 qemu_hide_filter = TRUE;
james@914 678 break;
james@914 679 default:
james@914 680 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
james@914 681 break;
james@914 682 }
james@914 683 }
james@914 684
james@914 685 if ((qemu_hide_flags_value & QEMU_UNPLUG_ALL_IDE_DISKS) || qemu_hide_filter)
james@914 686 xi->inactive = FALSE;
james@914 687
james@914 688 xi->power_state = NdisDeviceStateD0;
james@914 689 xi->power_workitem = IoAllocateWorkItem(xi->fdo);
james@914 690
james@914 691 // now build config page
james@914 692
james@914 693 NdisOpenConfiguration(&status, &config_handle, WrapperConfigurationContext);
james@914 694 if (!NT_SUCCESS(status))
james@914 695 {
james@914 696 KdPrint(("Could not open config in registry (%08x)\n", status));
james@914 697 status = NDIS_STATUS_RESOURCES;
james@914 698 goto err;
james@914 699 }
james@914 700
james@914 701 NdisInitUnicodeString(&config_param_name, L"ScatterGather");
james@914 702 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
james@914 703 if (!NT_SUCCESS(status))
james@914 704 {
james@914 705 KdPrint(("Could not read ScatterGather value (%08x)\n", status));
james@914 706 xi->config_sg = 1;
james@914 707 }
james@914 708 else
james@914 709 {
james@914 710 KdPrint(("ScatterGather = %d\n", config_param->ParameterData.IntegerData));
james@914 711 xi->config_sg = config_param->ParameterData.IntegerData;
james@914 712 }
james@914 713
james@914 714 NdisInitUnicodeString(&config_param_name, L"LargeSendOffload");
james@914 715 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
james@914 716 if (!NT_SUCCESS(status))
james@914 717 {
james@914 718 KdPrint(("Could not read LargeSendOffload value (%08x)\n", status));
james@914 719 xi->config_gso = 0;
james@914 720 }
james@914 721 else
james@914 722 {
james@914 723 KdPrint(("LargeSendOffload = %d\n", config_param->ParameterData.IntegerData));
james@914 724 xi->config_gso = config_param->ParameterData.IntegerData;
james@914 725 if (xi->config_gso > 61440)
james@914 726 {
james@914 727 xi->config_gso = 61440;
james@914 728 KdPrint(("(clipped to %d)\n", xi->config_gso));
james@914 729 }
james@914 730 }
james@914 731
james@914 732 NdisInitUnicodeString(&config_param_name, L"ChecksumOffload");
james@914 733 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
james@914 734 if (!NT_SUCCESS(status))
james@914 735 {
james@914 736 KdPrint(("Could not read ChecksumOffload value (%08x)\n", status));
james@914 737 xi->config_csum = 1;
james@914 738 }
james@914 739 else
james@914 740 {
james@914 741 KdPrint(("ChecksumOffload = %d\n", config_param->ParameterData.IntegerData));
james@914 742 xi->config_csum = !!config_param->ParameterData.IntegerData;
james@914 743 }
james@914 744
james@914 745 NdisInitUnicodeString(&config_param_name, L"ChecksumOffloadRxCheck");
james@914 746 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
james@914 747 if (!NT_SUCCESS(status))
james@914 748 {
james@914 749 KdPrint(("Could not read ChecksumOffloadRxCheck value (%08x)\n", status));
james@914 750 xi->config_csum_rx_check = 1;
james@914 751 }
james@914 752 else
james@914 753 {
james@914 754 KdPrint(("ChecksumOffloadRxCheck = %d\n", config_param->ParameterData.IntegerData));
james@914 755 xi->config_csum_rx_check = !!config_param->ParameterData.IntegerData;
james@914 756 }
james@914 757
james@914 758 NdisInitUnicodeString(&config_param_name, L"ChecksumOffloadDontFix");
james@914 759 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
james@914 760 if (!NT_SUCCESS(status))
james@914 761 {
james@914 762 KdPrint(("Could not read ChecksumOffloadDontFix value (%08x)\n", status));
james@914 763 xi->config_csum_rx_dont_fix = 0;
james@914 764 }
james@914 765 else
james@914 766 {
james@914 767 KdPrint(("ChecksumOffloadDontFix = %d\n", config_param->ParameterData.IntegerData));
james@914 768 xi->config_csum_rx_dont_fix = !!config_param->ParameterData.IntegerData;
james@914 769 }
james@914 770
james@914 771
james@914 772
james@914 773 NdisInitUnicodeString(&config_param_name, L"MTU");
james@914 774 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
james@914 775 if (!NT_SUCCESS(status))
james@914 776 {
james@914 777 KdPrint(("Could not read MTU value (%08x)\n", status));
james@914 778 xi->config_mtu = 1500;
james@914 779 }
james@914 780 else
james@914 781 {
james@914 782 KdPrint(("MTU = %d\n", config_param->ParameterData.IntegerData));
james@914 783 xi->config_mtu = config_param->ParameterData.IntegerData;
james@914 784 }
james@914 785
james@914 786 NdisInitUnicodeString(&config_param_name, L"RxInterruptModeration");
james@914 787 NdisReadConfiguration(&status, &config_param, config_handle, &config_param_name, NdisParameterInteger);
james@914 788 if (!NT_SUCCESS(status))
james@914 789 {
james@914 790 KdPrint(("Could not read RxInterruptModeration value (%08x)\n", status));
james@914 791 xi->config_rx_interrupt_moderation = 1500;
james@914 792 }
james@914 793 else
james@914 794 {
james@914 795 KdPrint(("RxInterruptModeration = %d\n", config_param->ParameterData.IntegerData));
james@914 796 xi->config_rx_interrupt_moderation = config_param->ParameterData.IntegerData;
james@914 797 }
james@914 798
james@914 799
james@914 800 NdisReadNetworkAddress(&status, &network_address, &network_address_length, config_handle);
james@914 801 if (!NT_SUCCESS(status) || network_address_length != ETH_ALEN || ((((PUCHAR)network_address)[0] & 0x03) != 0x02))
james@914 802 {
james@914 803 KdPrint(("Could not read NetworkAddress value (%08x) or value is invalid\n", status));
james@914 804 memset(xi->curr_mac_addr, 0, ETH_ALEN);
james@914 805 }
james@914 806 else
james@914 807 {
james@914 808 memcpy(xi->curr_mac_addr, network_address, ETH_ALEN);
james@914 809 KdPrint((" Set MAC address from registry to %02X:%02X:%02X:%02X:%02X:%02X\n",
james@914 810 xi->curr_mac_addr[0], xi->curr_mac_addr[1], xi->curr_mac_addr[2],
james@914 811 xi->curr_mac_addr[3], xi->curr_mac_addr[4], xi->curr_mac_addr[5]));
james@914 812 }
james@914 813
james@914 814 xi->config_max_pkt_size = max(xi->config_mtu + XN_HDR_SIZE, xi->config_gso + XN_HDR_SIZE);
james@914 815
james@914 816 NdisCloseConfiguration(config_handle);
james@914 817
james@914 818 status = XenNet_D0Entry(xi);
james@914 819 if (!NT_SUCCESS(status))
james@914 820 {
james@914 821 KdPrint(("Failed to go to D0 (%08x)\n", status));
james@914 822 goto err;
james@914 823 }
james@914 824 return NDIS_STATUS_SUCCESS;
james@914 825
james@914 826 err:
james@914 827 NdisFreeMemory(xi, 0, 0);
james@914 828 *OpenErrorStatus = status;
james@914 829 FUNCTION_EXIT_STATUS(status);
james@914 830 return status;
james@914 831 }
james@914 832
james@914 833 VOID
james@914 834 XenNet_PnPEventNotify(
james@914 835 IN NDIS_HANDLE MiniportAdapterContext,
james@914 836 IN NDIS_DEVICE_PNP_EVENT PnPEvent,
james@914 837 IN PVOID InformationBuffer,
james@914 838 IN ULONG InformationBufferLength
james@914 839 )
james@914 840 {
james@914 841 UNREFERENCED_PARAMETER(MiniportAdapterContext);
james@914 842 UNREFERENCED_PARAMETER(PnPEvent);
james@914 843 UNREFERENCED_PARAMETER(InformationBuffer);
james@914 844 UNREFERENCED_PARAMETER(InformationBufferLength);
james@914 845
james@914 846 FUNCTION_ENTER();
james@914 847 switch (PnPEvent)
james@914 848 {
james@914 849 case NdisDevicePnPEventSurpriseRemoved:
james@914 850 KdPrint((__DRIVER_NAME " NdisDevicePnPEventSurpriseRemoved\n"));
james@914 851 break;
james@914 852 case NdisDevicePnPEventPowerProfileChanged :
james@914 853 KdPrint((__DRIVER_NAME " NdisDevicePnPEventPowerProfileChanged\n"));
james@914 854 break;
james@914 855 default:
james@914 856 KdPrint((__DRIVER_NAME " %d\n", PnPEvent));
james@914 857 break;
james@914 858 }
james@914 859 FUNCTION_EXIT();
james@914 860 }
james@914 861
james@914 862 /* Called when machine is shutting down, so just quiesce the HW and be done fast. */
james@914 863 VOID
james@914 864 XenNet_Shutdown(
james@914 865 IN NDIS_HANDLE MiniportAdapterContext
james@914 866 )
james@914 867 {
james@914 868 UNREFERENCED_PARAMETER(MiniportAdapterContext);
james@914 869
james@914 870 /* remember we are called at >= DIRQL here */
james@914 871 FUNCTION_ENTER();
james@914 872 FUNCTION_EXIT();
james@914 873 }
james@914 874
james@914 875 /* Opposite of XenNet_Init */
james@914 876 VOID
james@914 877 XenNet_Halt(
james@914 878 IN NDIS_HANDLE MiniportAdapterContext
james@914 879 )
james@914 880 {
james@914 881 struct xennet_info *xi = MiniportAdapterContext;
james@914 882
james@914 883 FUNCTION_ENTER();
james@914 884 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@914 885
james@914 886 XenNet_D0Exit(xi);
james@914 887
james@914 888 NdisFreeMemory(xi, 0, 0);
james@914 889
james@914 890 FUNCTION_EXIT();
james@914 891 }
james@914 892
james@914 893 NDIS_STATUS
james@914 894 XenNet_D0Exit(struct xennet_info *xi)
james@914 895 {
james@914 896 FUNCTION_ENTER();
james@914 897 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@914 898
james@914 899 xi->shutting_down = TRUE;
james@914 900 KeMemoryBarrier(); /* make sure everyone sees that we are now shutting down */
james@914 901
james@914 902 XenNet_TxShutdown(xi);
james@914 903 XenNet_RxShutdown(xi);
james@914 904
james@914 905 xi->connected = FALSE;
james@914 906 KeMemoryBarrier(); /* make sure everyone sees that we are now disconnected */
james@914 907
james@914 908 xi->vectors.XenPci_XenShutdownDevice(xi->vectors.context);
james@914 909
james@914 910 FUNCTION_EXIT();
james@914 911
james@914 912 return STATUS_SUCCESS;
james@914 913 }
james@914 914
james@914 915 NDIS_STATUS
james@914 916 XenNet_Reset(
james@914 917 PBOOLEAN AddressingReset,
james@914 918 NDIS_HANDLE MiniportAdapterContext
james@914 919 )
james@914 920 {
james@914 921 UNREFERENCED_PARAMETER(MiniportAdapterContext);
james@914 922
james@914 923 *AddressingReset = FALSE;
james@914 924 return NDIS_STATUS_SUCCESS;
james@914 925 }
james@914 926
james@914 927 NTSTATUS
james@914 928 DriverEntry(
james@914 929 PDRIVER_OBJECT DriverObject,
james@914 930 PUNICODE_STRING RegistryPath
james@914 931 )
james@914 932 {
james@914 933 NTSTATUS status;
james@914 934 NDIS_HANDLE ndis_wrapper_handle = NULL;
james@914 935 NDIS_MINIPORT_CHARACTERISTICS mini_chars;
james@914 936
james@914 937 FUNCTION_ENTER();
james@914 938
james@914 939 KdPrint((__DRIVER_NAME " DriverObject = %p, RegistryPath = %p\n", DriverObject, RegistryPath));
james@914 940
james@914 941 NdisZeroMemory(&mini_chars, sizeof(mini_chars));
james@914 942
james@914 943 KdPrint((__DRIVER_NAME " NdisGetVersion = %x\n", NdisGetVersion()));
james@914 944
james@914 945 KdPrint((__DRIVER_NAME " ndis_wrapper_handle = %p\n", ndis_wrapper_handle));
james@914 946 NdisMInitializeWrapper(&ndis_wrapper_handle, DriverObject, RegistryPath, NULL);
james@914 947 KdPrint((__DRIVER_NAME " ndis_wrapper_handle = %p\n", ndis_wrapper_handle));
james@914 948 if (!ndis_wrapper_handle)
james@914 949 {
james@914 950 KdPrint((__DRIVER_NAME " NdisMInitializeWrapper failed\n"));
james@914 951 return NDIS_STATUS_FAILURE;
james@914 952 }
james@914 953 KdPrint((__DRIVER_NAME " NdisMInitializeWrapper succeeded\n"));
james@914 954
james@914 955 /* NDIS 5.1 driver */
james@914 956 mini_chars.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
james@914 957 mini_chars.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
james@914 958
james@914 959 KdPrint((__DRIVER_NAME " MajorNdisVersion = %d, MinorNdisVersion = %d\n", NDIS_MINIPORT_MAJOR_VERSION, NDIS_MINIPORT_MINOR_VERSION));
james@914 960
james@914 961 mini_chars.HaltHandler = XenNet_Halt;
james@914 962 mini_chars.InitializeHandler = XenNet_Init;
james@914 963 //mini_chars.ISRHandler = XenNet_InterruptIsr;
james@914 964 //mini_chars.HandleInterruptHandler = XenNet_InterruptDpc;
james@914 965 mini_chars.QueryInformationHandler = XenNet_QueryInformation;
james@914 966 mini_chars.ResetHandler = XenNet_Reset;
james@914 967 mini_chars.SetInformationHandler = XenNet_SetInformation;
james@914 968 /* added in v.4 -- use multiple pkts interface */
james@914 969 mini_chars.ReturnPacketHandler = XenNet_ReturnPacket;
james@914 970 mini_chars.SendPacketsHandler = XenNet_SendPackets;
james@914 971 /* don't support cancel - no point as packets are never queued for long */
james@914 972 //mini_chars.CancelSendPacketsHandler = XenNet_CancelSendPackets;
james@914 973
james@914 974 #ifdef NDIS51_MINIPORT
james@914 975 /* added in v.5.1 */
james@914 976 mini_chars.PnPEventNotifyHandler = XenNet_PnPEventNotify;
james@914 977 mini_chars.AdapterShutdownHandler = XenNet_Shutdown;
james@914 978 #else
james@914 979 // something else here
james@914 980 #endif
james@914 981
james@914 982 /* set up upper-edge interface */
james@914 983 KdPrint((__DRIVER_NAME " about to call NdisMRegisterMiniport\n"));
james@914 984 status = NdisMRegisterMiniport(ndis_wrapper_handle, &mini_chars, sizeof(mini_chars));
james@914 985 KdPrint((__DRIVER_NAME " called NdisMRegisterMiniport\n"));
james@914 986 if (!NT_SUCCESS(status))
james@914 987 {
james@914 988 KdPrint((__DRIVER_NAME " NdisMRegisterMiniport failed, status = 0x%x\n", status));
james@914 989 NdisTerminateWrapper(ndis_wrapper_handle, NULL);
james@914 990 return status;
james@914 991 }
james@914 992
james@914 993 FUNCTION_EXIT();
james@914 994
james@914 995 return status;
james@914 996 }