win-pvdrivers

annotate xenpci/evtchn.c @ 910:1ee7940af105

Fix compilation under older DDK
author James Harper <james.harper@bendigoit.com.au>
date Fri Apr 29 23:56:03 2011 +1000 (2011-04-29)
parents e315b8490131
children 1ad5f1d3a664
rev   line source
james@0 1 /*
james@0 2 PV Drivers for Windows Xen HVM Domains
james@0 3 Copyright (C) 2007 James Harper
james@0 4
james@0 5 This program is free software; you can redistribute it and/or
james@0 6 modify it under the terms of the GNU General Public License
james@0 7 as published by the Free Software Foundation; either version 2
james@0 8 of the License, or (at your option) any later version.
james@0 9
james@0 10 This program is distributed in the hope that it will be useful,
james@0 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
james@0 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
james@0 13 GNU General Public License for more details.
james@0 14
james@0 15 You should have received a copy of the GNU General Public License
james@0 16 along with this program; if not, write to the Free Software
james@0 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
james@0 18 */
james@0 19
james@0 20 #include "xenpci.h"
james@0 21
james@716 22 /* Not really necessary but keeps PREfast happy */
james@910 23 #if (VER_PRODUCTBUILD >= 7600)
james@716 24 static KDEFERRED_ROUTINE EvtChn_DpcBounce;
james@818 25 #endif
james@716 26
james@716 27 #if defined(_X86_)
james@432 28 #define xchg(p1, p2) InterlockedExchange(p1, p2)
james@432 29 #define synch_clear_bit(p1, p2) InterlockedBitTestAndReset(p2, p1)
james@432 30 #define synch_set_bit(p1, p2) InterlockedBitTestAndSet(p2, p1)
james@147 31 #define bit_scan_forward(p1, p2) _BitScanForward(p1, p2)
james@147 32 #else
james@432 33 #define xchg(p1, p2) InterlockedExchange64(p1, p2)
james@579 34 #define synch_clear_bit(p1, p2) InterlockedBitTestAndReset64(p2, p1)
james@579 35 #define synch_set_bit(p1, p2) InterlockedBitTestAndSet64(p2, p1)
james@147 36 #define bit_scan_forward(p1, p2) _BitScanForward64(p1, p2)
james@147 37 #endif
james@147 38
james@432 39 #define BITS_PER_LONG (sizeof(xen_ulong_t) * 8)
james@432 40 #define BITS_PER_LONG_SHIFT (5 + (sizeof(xen_ulong_t) >> 3))
james@432 41
james@880 42 static VOID
james@258 43 EvtChn_DpcBounce(PRKDPC Dpc, PVOID Context, PVOID SystemArgument1, PVOID SystemArgument2)
james@73 44 {
james@258 45 ev_action_t *action = Context;
james@73 46
james@258 47 UNREFERENCED_PARAMETER(Dpc);
james@258 48 UNREFERENCED_PARAMETER(SystemArgument1);
james@258 49 UNREFERENCED_PARAMETER(SystemArgument2);
james@258 50
james@651 51 //FUNCTION_ENTER();
james@341 52
james@536 53 if (action->type != EVT_ACTION_TYPE_EMPTY)
james@364 54 {
james@515 55 action->ServiceRoutine(action->ServiceContext);
james@364 56 }
james@651 57 //FUNCTION_EXIT();
james@73 58 }
james@73 59
james@416 60 /* Called at DIRQL */
james@416 61 BOOLEAN
james@561 62 EvtChn_AckEvent(PVOID context, evtchn_port_t port, BOOLEAN *last_interrupt)
james@416 63 {
james@416 64 PXENPCI_DEVICE_DATA xpdd = context;
james@575 65 ULONG pcpu = KeGetCurrentProcessorNumber() & 0xff;
james@416 66 ULONG evt_word;
james@416 67 ULONG evt_bit;
james@416 68 xen_ulong_t val;
james@561 69 int i;
james@432 70
james@432 71 evt_bit = port & (BITS_PER_LONG - 1);
james@432 72 evt_word = port >> BITS_PER_LONG_SHIFT;
james@416 73
james@575 74 val = synch_clear_bit(evt_bit, (volatile xen_long_t *)&xpdd->evtchn_pending_pvt[pcpu][evt_word]);
james@575 75 *last_interrupt = TRUE;
james@561 76 for (i = 0; i < sizeof(xen_ulong_t) * 8; i++)
james@561 77 {
james@575 78 if (xpdd->evtchn_pending_pvt[pcpu][i])
james@561 79 {
james@575 80 *last_interrupt = FALSE;
james@561 81 break;
james@561 82 }
james@561 83 }
james@416 84
james@416 85 return (BOOLEAN)!!val;
james@416 86 }
james@416 87
james@575 88 volatile ULONG in_inq = 0;
james@575 89
james@536 90 BOOLEAN
james@536 91 EvtChn_EvtInterruptIsr(WDFINTERRUPT interrupt, ULONG message_id)
james@0 92 {
james@417 93 /*
james@417 94 For HVM domains, Xen always triggers the event on CPU0. Because the
james@417 95 interrupt is delivered via the virtual PCI device it might get delivered
james@417 96 to CPU != 0, but we should always use vcpu_info[0]
james@417 97 */
james@575 98 int vcpu = 0;
james@575 99 ULONG pcpu = KeGetCurrentProcessorNumber() & 0xff;
james@0 100 vcpu_info_t *vcpu_info;
james@536 101 PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfInterruptGetDevice(interrupt));
andy@68 102 shared_info_t *shared_info_area = xpdd->shared_info_area;
james@147 103 xen_ulong_t evt_words;
james@147 104 unsigned long evt_word;
james@73 105 unsigned long evt_bit;
james@147 106 unsigned int port;
james@73 107 ev_action_t *ev_action;
james@364 108 BOOLEAN handled = FALSE;
james@416 109 BOOLEAN deferred = FALSE;
james@422 110 int i;
andy@68 111
james@536 112 UNREFERENCED_PARAMETER(message_id);
james@536 113
james@536 114 if (xpdd->interrupts_masked)
james@406 115 {
james@536 116 KdPrint((__DRIVER_NAME " unhandled interrupt\n"));
james@406 117 }
james@450 118
james@538 119 if (xpdd->hibernated)
james@538 120 {
james@538 121 KdPrint((__DRIVER_NAME " interrupt while hibernated\n"));
james@538 122 }
james@538 123
james@575 124 for (i = 0; i < ARRAY_SIZE(xpdd->evtchn_pending_pvt[pcpu]); i++)
james@432 125 {
james@575 126 if (xpdd->evtchn_pending_pvt[pcpu][i])
james@432 127 {
james@575 128 KdPrint((__DRIVER_NAME " Unacknowledged event word = %d, val = %p\n", i, xpdd->evtchn_pending_pvt[pcpu][i]));
james@575 129 xpdd->evtchn_pending_pvt[pcpu][i] = 0;
james@432 130 }
james@432 131 }
james@432 132
james@575 133 vcpu_info = &shared_info_area->vcpu_info[vcpu];
andy@68 134
andy@68 135 vcpu_info->evtchn_upcall_pending = 0;
andy@68 136
james@450 137 if (xpdd->interrupts_masked)
james@450 138 {
james@450 139 return TRUE;
james@450 140 }
james@450 141
james@157 142 evt_words = (xen_ulong_t)xchg((volatile xen_long_t *)&vcpu_info->evtchn_pending_sel, 0);
james@432 143
james@147 144 while (bit_scan_forward(&evt_word, evt_words))
james@0 145 {
james@0 146 evt_words &= ~(1 << evt_word);
james@147 147 while (bit_scan_forward(&evt_bit, shared_info_area->evtchn_pending[evt_word] & ~shared_info_area->evtchn_mask[evt_word]))
james@0 148 {
james@432 149 synch_clear_bit(evt_bit, (volatile xen_long_t *)&shared_info_area->evtchn_pending[evt_word]);
james@364 150 handled = TRUE;
james@432 151 port = (evt_word << BITS_PER_LONG_SHIFT) + evt_bit;
andy@16 152 ev_action = &xpdd->ev_actions[port];
james@411 153 ev_action->count++;
james@267 154 switch (ev_action->type)
james@0 155 {
james@267 156 case EVT_ACTION_TYPE_NORMAL:
james@841 157 //KdPrint((__DRIVER_NAME " EVT_ACTION_TYPE_NORMAL port = %d\n", port));
james@515 158 ev_action->ServiceRoutine(ev_action->ServiceContext);
james@267 159 break;
james@411 160 case EVT_ACTION_TYPE_IRQ:
james@841 161 //KdPrint((__DRIVER_NAME " EVT_ACTION_TYPE_IRQ port = %d\n", port));
james@575 162 synch_set_bit(evt_bit, (volatile xen_long_t *)&xpdd->evtchn_pending_pvt[pcpu][evt_word]);
james@416 163 deferred = TRUE;
james@411 164 break;
james@267 165 case EVT_ACTION_TYPE_DPC:
james@841 166 //KdPrint((__DRIVER_NAME " EVT_ACTION_TYPE_DPC port = %d\n", port));
james@267 167 KeInsertQueueDpc(&ev_action->Dpc, NULL, NULL);
james@267 168 break;
james@422 169 case EVT_ACTION_TYPE_SUSPEND:
james@536 170 KdPrint((__DRIVER_NAME " EVT_ACTION_TYPE_SUSPEND\n"));
james@575 171 for (i = 0; i < ARRAY_SIZE(xpdd->evtchn_pending_pvt[pcpu]); i++)
james@422 172 {
james@841 173 if (!(xpdd->ev_actions[i].flags & EVT_ACTION_FLAGS_NO_SUSPEND))
james@422 174 {
james@841 175 switch(xpdd->ev_actions[i].type)
james@834 176 {
james@841 177 case EVT_ACTION_TYPE_IRQ:
james@841 178 {
james@841 179 int suspend_bit = i & (BITS_PER_LONG - 1);
james@841 180 int suspend_word = i >> BITS_PER_LONG_SHIFT;
james@841 181 synch_set_bit(suspend_bit, (volatile xen_long_t *)&xpdd->evtchn_pending_pvt[pcpu][suspend_word]);
james@841 182 }
james@841 183 break;
james@841 184 case EVT_ACTION_TYPE_NORMAL:
james@841 185 if (xpdd->ev_actions[i].ServiceRoutine)
james@841 186 {
james@841 187 xpdd->ev_actions[i].ServiceRoutine(xpdd->ev_actions[i].ServiceContext);
james@841 188 }
james@841 189 break;
james@841 190 case EVT_ACTION_TYPE_DPC:
james@841 191 KeInsertQueueDpc(&xpdd->ev_actions[i].Dpc, NULL, NULL);
james@841 192 break;
james@834 193 }
james@515 194 }
james@422 195 }
james@536 196 KeInsertQueueDpc(&ev_action->Dpc, NULL, NULL);
james@422 197 deferred = TRUE;
james@422 198 break;
james@267 199 default:
james@834 200 KdPrint((__DRIVER_NAME " Unhandled Event!!! port=%d\n", port));
james@267 201 break;
james@0 202 }
james@0 203 }
james@0 204 }
james@73 205
james@536 206 return handled && !deferred;
james@536 207 }
james@515 208
james@536 209 NTSTATUS
james@536 210 EvtChn_EvtInterruptEnable(WDFINTERRUPT interrupt, WDFDEVICE device)
james@536 211 {
james@536 212 NTSTATUS status = STATUS_SUCCESS;
james@536 213
james@536 214 UNREFERENCED_PARAMETER(interrupt);
james@536 215 UNREFERENCED_PARAMETER(device);
james@536 216
james@536 217 FUNCTION_ENTER();
james@536 218 FUNCTION_EXIT();
james@536 219
james@536 220 return status;
james@536 221 }
james@536 222
james@536 223 NTSTATUS
james@536 224 EvtChn_EvtInterruptDisable(WDFINTERRUPT interrupt, WDFDEVICE device)
james@536 225 {
james@536 226 NTSTATUS status = STATUS_SUCCESS;
james@536 227
james@536 228 UNREFERENCED_PARAMETER(interrupt);
james@536 229 UNREFERENCED_PARAMETER(device);
james@536 230
james@536 231 FUNCTION_ENTER();
james@536 232 FUNCTION_EXIT();
james@536 233
james@536 234 return status;
james@0 235 }
james@0 236
andy@13 237 NTSTATUS
james@841 238 EvtChn_Bind(PVOID Context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext, ULONG flags)
james@0 239 {
james@258 240 PXENPCI_DEVICE_DATA xpdd = Context;
james@788 241 ev_action_t *action = &xpdd->ev_actions[Port];
james@0 242
andy@398 243 FUNCTION_ENTER();
james@267 244
james@788 245 if (InterlockedCompareExchange((volatile LONG *)&action->type, EVT_ACTION_TYPE_NEW, EVT_ACTION_TYPE_EMPTY) != EVT_ACTION_TYPE_EMPTY)
james@0 246 {
james@788 247 KdPrint((__DRIVER_NAME " Handler for port %d already registered\n", Port));
james@788 248 return STATUS_UNSUCCESSFUL;
james@0 249 }
james@0 250
james@267 251 xpdd->ev_actions[Port].ServiceRoutine = ServiceRoutine;
andy@16 252 xpdd->ev_actions[Port].ServiceContext = ServiceContext;
james@341 253 xpdd->ev_actions[Port].xpdd = xpdd;
james@841 254 xpdd->ev_actions[Port].flags = flags;
james@0 255 KeMemoryBarrier();
james@267 256 xpdd->ev_actions[Port].type = EVT_ACTION_TYPE_NORMAL;
james@0 257
james@258 258 EvtChn_Unmask(Context, Port);
james@0 259
andy@398 260 FUNCTION_EXIT();
james@0 261
james@0 262 return STATUS_SUCCESS;
james@0 263 }
james@0 264
andy@120 265 NTSTATUS
james@841 266 EvtChn_BindDpc(PVOID Context, evtchn_port_t Port, PXEN_EVTCHN_SERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext, ULONG flags)
james@73 267 {
james@258 268 PXENPCI_DEVICE_DATA xpdd = Context;
james@788 269 ev_action_t *action = &xpdd->ev_actions[Port];
james@73 270
andy@398 271 FUNCTION_ENTER();
james@788 272
james@788 273 if (InterlockedCompareExchange((volatile LONG *)&action->type, EVT_ACTION_TYPE_NEW, EVT_ACTION_TYPE_EMPTY) != EVT_ACTION_TYPE_EMPTY)
james@73 274 {
james@788 275 KdPrint((__DRIVER_NAME " Handler for port %d already registered\n", Port));
james@788 276 return STATUS_UNSUCCESSFUL;
james@73 277 }
james@73 278
james@267 279 xpdd->ev_actions[Port].ServiceRoutine = ServiceRoutine;
james@73 280 xpdd->ev_actions[Port].ServiceContext = ServiceContext;
james@341 281 xpdd->ev_actions[Port].xpdd = xpdd;
james@841 282 xpdd->ev_actions[Port].flags = flags;
james@73 283 KeMemoryBarrier(); // make sure that the new service routine is only called once the context is set up
james@788 284 InterlockedExchange((volatile LONG *)&action->type, EVT_ACTION_TYPE_DPC);
james@73 285
james@258 286 EvtChn_Unmask(Context, Port);
james@73 287
andy@398 288 FUNCTION_EXIT();
james@73 289
james@267 290 return STATUS_SUCCESS;
james@267 291 }
james@73 292
james@267 293 NTSTATUS
james@841 294 EvtChn_BindIrq(PVOID Context, evtchn_port_t Port, ULONG vector, PCHAR description, ULONG flags)
james@267 295 {
james@267 296 PXENPCI_DEVICE_DATA xpdd = Context;
james@788 297 ev_action_t *action = &xpdd->ev_actions[Port];
james@267 298
andy@398 299 FUNCTION_ENTER();
james@788 300
james@788 301 if (InterlockedCompareExchange((volatile LONG *)&action->type, EVT_ACTION_TYPE_NEW, EVT_ACTION_TYPE_EMPTY) != EVT_ACTION_TYPE_EMPTY)
james@267 302 {
james@788 303 KdPrint((__DRIVER_NAME " Handler for port %d already registered\n", Port));
james@788 304 return STATUS_UNSUCCESSFUL;
james@267 305 }
james@267 306
james@267 307 xpdd->ev_actions[Port].vector = vector;
james@341 308 xpdd->ev_actions[Port].xpdd = xpdd;
james@267 309 KeMemoryBarrier();
james@267 310 xpdd->ev_actions[Port].type = EVT_ACTION_TYPE_IRQ;
james@716 311 RtlStringCbCopyA(xpdd->ev_actions[Port].description, 128, description);
james@841 312 xpdd->ev_actions[Port].flags = flags;
james@841 313
james@267 314 EvtChn_Unmask(Context, Port);
james@267 315
andy@398 316 FUNCTION_EXIT();
james@73 317
james@73 318 return STATUS_SUCCESS;
james@73 319 }
james@73 320
james@0 321 NTSTATUS
andy@13 322 EvtChn_Unbind(PVOID Context, evtchn_port_t Port)
james@0 323 {
james@258 324 PXENPCI_DEVICE_DATA xpdd = Context;
james@788 325 ev_action_t *action = &xpdd->ev_actions[Port];
james@432 326 int old_type;
james@258 327
andy@13 328 EvtChn_Mask(Context, Port);
james@788 329 old_type = InterlockedExchange((volatile LONG *)&action->type, EVT_ACTION_TYPE_EMPTY);
james@788 330
james@788 331 if (old_type == EVT_ACTION_TYPE_DPC || old_type == EVT_ACTION_TYPE_SUSPEND)
james@585 332 {
james@258 333 KeRemoveQueueDpc(&xpdd->ev_actions[Port].Dpc);
james@818 334 #if (NTDDI_VERSION >= NTDDI_WINXP)
james@585 335 KeFlushQueuedDpcs();
james@818 336 #endif
james@585 337 }
james@115 338
james@788 339 KeMemoryBarrier(); // make sure we don't call the old Service Routine with the new data...
james@788 340 xpdd->ev_actions[Port].ServiceRoutine = NULL;
james@788 341 xpdd->ev_actions[Port].ServiceContext = NULL;
james@788 342
james@0 343 return STATUS_SUCCESS;
james@0 344 }
james@0 345
james@0 346 NTSTATUS
james@408 347 EvtChn_Mask(PVOID Context, evtchn_port_t port)
james@0 348 {
andy@338 349 PXENPCI_DEVICE_DATA xpdd = Context;
andy@338 350
james@432 351 synch_set_bit(port & (BITS_PER_LONG - 1),
james@432 352 (volatile xen_long_t *)&xpdd->shared_info_area->evtchn_mask[port >> BITS_PER_LONG_SHIFT]);
james@0 353 return STATUS_SUCCESS;
james@0 354 }
james@0 355
james@0 356 NTSTATUS
james@408 357 EvtChn_Unmask(PVOID context, evtchn_port_t port)
james@0 358 {
james@408 359 PXENPCI_DEVICE_DATA xpdd = context;
andy@338 360
james@432 361 synch_clear_bit(port & (BITS_PER_LONG - 1),
james@432 362 (volatile xen_long_t *)&xpdd->shared_info_area->evtchn_mask[port >> BITS_PER_LONG_SHIFT]);
james@0 363 return STATUS_SUCCESS;
james@0 364 }
james@0 365
james@0 366 NTSTATUS
andy@338 367 EvtChn_Notify(PVOID Context, evtchn_port_t Port)
james@0 368 {
andy@338 369 PXENPCI_DEVICE_DATA xpdd = Context;
james@0 370 struct evtchn_send send;
james@0 371
james@0 372 send.port = Port;
james@258 373 (void)HYPERVISOR_event_channel_op(xpdd, EVTCHNOP_send, &send);
james@0 374 return STATUS_SUCCESS;
james@0 375 }
james@0 376
andy@13 377 evtchn_port_t
james@464 378 EvtChn_AllocIpi(PVOID context, ULONG vcpu)
james@422 379 {
james@422 380 PXENPCI_DEVICE_DATA xpdd = context;
james@422 381 evtchn_bind_ipi_t op;
james@422 382
james@422 383 FUNCTION_ENTER();
james@422 384 op.vcpu = vcpu;
james@422 385 op.port = 0;
james@422 386 HYPERVISOR_event_channel_op(xpdd, EVTCHNOP_bind_ipi, &op);
james@422 387 FUNCTION_EXIT();
james@422 388 return op.port;
james@422 389 }
james@422 390
james@422 391 evtchn_port_t
andy@13 392 EvtChn_AllocUnbound(PVOID Context, domid_t Domain)
andy@13 393 {
james@258 394 PXENPCI_DEVICE_DATA xpdd = Context;
andy@13 395 evtchn_alloc_unbound_t op;
andy@13 396 op.dom = DOMID_SELF;
andy@13 397 op.remote_dom = Domain;
james@258 398 HYPERVISOR_event_channel_op(xpdd, EVTCHNOP_alloc_unbound, &op);
andy@13 399 return op.port;
andy@13 400 }
james@0 401
james@408 402 VOID
james@408 403 EvtChn_Close(PVOID Context, evtchn_port_t port )
james@408 404 {
james@408 405 PXENPCI_DEVICE_DATA xpdd = Context;
james@408 406 evtchn_close_t op;
james@408 407 op.port = port;
james@408 408 HYPERVISOR_event_channel_op(xpdd, EVTCHNOP_close, &op);
james@408 409 return;
james@408 410 }
james@408 411
james@536 412 VOID
james@536 413 EvtChn_PdoEventChannelDpc(PVOID context)
james@536 414 {
james@536 415 PXENPCI_DEVICE_DATA xpdd = context;
james@536 416
james@536 417 FUNCTION_ENTER();
james@536 418 KeSetEvent(&xpdd->pdo_suspend_event, IO_NO_INCREMENT, FALSE);
james@536 419 FUNCTION_EXIT();
james@536 420 }
james@536 421
james@389 422 NTSTATUS
james@389 423 EvtChn_Init(PXENPCI_DEVICE_DATA xpdd)
james@0 424 {
james@536 425 ULONGLONG result;
james@788 426 ev_action_t *action;
james@258 427 int i;
james@0 428
andy@398 429 FUNCTION_ENTER();
james@0 430
james@0 431 for (i = 0; i < NR_EVENTS; i++)
james@0 432 {
james@258 433 EvtChn_Mask(xpdd, i);
james@788 434 action = &xpdd->ev_actions[i];
james@788 435 action->type = EVT_ACTION_TYPE_EMPTY;
james@788 436 action->count = 0;
james@788 437 KeInitializeDpc(&action->Dpc, EvtChn_DpcBounce, action);
james@0 438 }
james@0 439
andy@13 440 for (i = 0; i < 8; i++)
andy@13 441 {
andy@16 442 xpdd->shared_info_area->evtchn_pending[i] = 0;
james@0 443 }
james@92 444
james@92 445 for (i = 0; i < MAX_VIRT_CPUS; i++)
james@92 446 {
james@92 447 xpdd->shared_info_area->vcpu_info[i].evtchn_upcall_pending = 0;
james@92 448 xpdd->shared_info_area->vcpu_info[i].evtchn_pending_sel = 0;
james@408 449 xpdd->shared_info_area->vcpu_info[i].evtchn_upcall_mask = 1; /* apparantly this doesn't do anything */
james@92 450 }
james@0 451
james@406 452 KeMemoryBarrier();
james@406 453
james@536 454 result = hvm_set_parameter(xpdd, HVM_PARAM_CALLBACK_IRQ, xpdd->irq_number);
james@536 455 KdPrint((__DRIVER_NAME " hvm_set_parameter(HVM_PARAM_CALLBACK_IRQ, %d) = %d\n", xpdd->irq_number, (ULONG)result));
james@258 456
james@258 457 for (i = 0; i < MAX_VIRT_CPUS; i++)
james@407 458 xpdd->shared_info_area->vcpu_info[i].evtchn_upcall_mask = 0;
james@407 459 xpdd->interrupts_masked = FALSE;
james@407 460 KeMemoryBarrier();
james@406 461
james@536 462 KeInitializeEvent(&xpdd->pdo_suspend_event, SynchronizationEvent, FALSE);
james@480 463 xpdd->pdo_event_channel = EvtChn_AllocIpi(xpdd, 0);
james@841 464 EvtChn_BindDpc(xpdd, xpdd->pdo_event_channel, EvtChn_PdoEventChannelDpc, xpdd, EVT_ACTION_FLAGS_DEFAULT);
james@536 465 xpdd->ev_actions[xpdd->pdo_event_channel].type = EVT_ACTION_TYPE_SUSPEND; /* override dpc type */
james@258 466
james@480 467 KdPrint((__DRIVER_NAME " pdo_event_channel = %d\n", xpdd->pdo_event_channel));
james@422 468
andy@398 469 FUNCTION_EXIT();
james@389 470
james@389 471 return STATUS_SUCCESS;
james@342 472 }
james@258 473
james@342 474 NTSTATUS
james@536 475 EvtChn_Suspend(PXENPCI_DEVICE_DATA xpdd)
james@258 476 {
james@359 477 int i;
james@406 478 // LARGE_INTEGER wait_time;
james@359 479
james@407 480 xpdd->interrupts_masked = TRUE;
james@406 481 for (i = 0; i < MAX_VIRT_CPUS; i++)
james@406 482 xpdd->shared_info_area->vcpu_info[i].evtchn_upcall_mask = 1;
james@406 483 KeMemoryBarrier();
james@407 484 hvm_set_parameter(xpdd, HVM_PARAM_CALLBACK_IRQ, 0);
james@258 485
james@359 486 for (i = 0; i < NR_EVENTS; i++)
james@359 487 {
james@432 488 if (xpdd->ev_actions[i].type == EVT_ACTION_TYPE_DPC)
james@359 489 {
james@359 490 KeRemoveQueueDpc(&xpdd->ev_actions[i].Dpc);
james@359 491 }
james@359 492 }
james@818 493 #if (NTDDI_VERSION >= NTDDI_WINXP)
james@432 494 KeFlushQueuedDpcs();
james@818 495 #endif
james@0 496 return STATUS_SUCCESS;
james@0 497 }
james@536 498
james@536 499 NTSTATUS
james@536 500 EvtChn_Resume(PXENPCI_DEVICE_DATA xpdd)
james@536 501 {
james@536 502 return EvtChn_Init(xpdd);
james@536 503 }