win-pvdrivers

annotate xennet/xennet.c @ 821:9c0c4210b778

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