win-pvdrivers

view xenpci/evtchn.c @ 73:f74723639713

Corrected merge of dpc patches.
Releasing 0.5.0.0
author James Harper <james.harper@bendigoit.com.au>
date Thu Dec 20 13:07:44 2007 +1100 (2007-12-20)
parents 7ae8e22810a3
children 63da9239cfe2
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #include "xenpci.h"
21 #include "hypercall.h"
23 static VOID
24 EvtChn_DpcBounce(WDFDPC Dpc)
25 {
26 ev_action_t *Action;
28 Action = GetEvtChnDeviceData(Dpc)->Action;
29 Action->ServiceRoutine(NULL, Action->ServiceContext);
30 }
32 BOOLEAN
33 EvtChn_Interrupt(WDFINTERRUPT Interrupt, ULONG MessageID)
34 {
35 int cpu = 0;
36 vcpu_info_t *vcpu_info;
37 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(WdfInterruptGetDevice(Interrupt));
38 shared_info_t *shared_info_area = xpdd->shared_info_area;
39 unsigned long evt_words, evt_word;
40 unsigned long evt_bit;
41 unsigned long port;
42 ev_action_t *ev_action;
44 UNREFERENCED_PARAMETER(MessageID);
46 vcpu_info = &shared_info_area->vcpu_info[cpu];
48 vcpu_info->evtchn_upcall_pending = 0;
50 evt_words = _InterlockedExchange((volatile LONG *)&vcpu_info->evtchn_pending_sel, 0);
52 while (_BitScanForward(&evt_word, evt_words))
53 {
54 evt_words &= ~(1 << evt_word);
55 while (_BitScanForward(&evt_bit, shared_info_area->evtchn_pending[evt_word] & ~shared_info_area->evtchn_mask[evt_word]))
56 {
57 port = (evt_word << 5) + evt_bit;
58 ev_action = &xpdd->ev_actions[port];
59 if (ev_action->ServiceRoutine == NULL)
60 {
61 KdPrint((__DRIVER_NAME " Unhandled Event!!!\n"));
62 }
63 else
64 {
65 if (ev_action->DpcFlag)
66 {
67 WdfDpcEnqueue(ev_action->Dpc);
68 }
69 else
70 {
71 ev_action->ServiceRoutine(NULL, ev_action->ServiceContext);
72 }
73 }
74 _interlockedbittestandreset((volatile LONG *)&shared_info_area->evtchn_pending[0], port);
75 }
76 }
78 return FALSE; // This needs to be FALSE so it can fall through to the scsiport ISR.
79 }
81 NTSTATUS
82 EvtChn_Bind(PVOID Context, evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
83 {
84 WDFDEVICE Device = Context;
85 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
87 KdPrint((__DRIVER_NAME " --> EvtChn_Bind (ServiceRoutine = %08X, ServiceContext = %08x)\n", ServiceRoutine, ServiceContext));
89 if(xpdd->ev_actions[Port].ServiceRoutine != NULL)
90 {
91 xpdd->ev_actions[Port].ServiceRoutine = NULL;
92 KeMemoryBarrier(); // make sure we don't call the old Service Routine with the new data...
93 KdPrint((__DRIVER_NAME " Handler for port %d already registered, replacing\n", Port));
94 }
96 xpdd->ev_actions[Port].DpcFlag = FALSE;
97 xpdd->ev_actions[Port].ServiceContext = ServiceContext;
98 KeMemoryBarrier();
99 xpdd->ev_actions[Port].ServiceRoutine = ServiceRoutine;
101 EvtChn_Unmask(Device, Port);
103 KdPrint((__DRIVER_NAME " <-- EvtChn_Bind\n"));
105 return STATUS_SUCCESS;
106 }
108 EvtChn_BindDpc(PVOID Context, evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
109 {
110 WDFDEVICE Device = Context;
111 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
112 WDF_DPC_CONFIG DpcConfig;
113 WDF_OBJECT_ATTRIBUTES DpcObjectAttributes;
115 KdPrint((__DRIVER_NAME " --> EvtChn_BindDpc\n"));
117 if(xpdd->ev_actions[Port].ServiceRoutine != NULL)
118 {
119 KdPrint((__DRIVER_NAME " Handler for port %d already registered, replacing\n", Port));
120 xpdd->ev_actions[Port].ServiceRoutine = NULL;
121 KeMemoryBarrier(); // make sure we don't call the old Service Routine with the new data...
122 }
124 xpdd->ev_actions[Port].ServiceContext = ServiceContext;
125 xpdd->ev_actions[Port].DpcFlag = TRUE;
127 WDF_DPC_CONFIG_INIT(&DpcConfig, EvtChn_DpcBounce);
128 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&DpcObjectAttributes, EVTCHN_DEVICE_DATA);
129 DpcObjectAttributes.ParentObject = Device;
130 WdfDpcCreate(&DpcConfig, &DpcObjectAttributes, &xpdd->ev_actions[Port].Dpc);
131 GetEvtChnDeviceData(xpdd->ev_actions[Port].Dpc)->Action = &xpdd->ev_actions[Port];
133 KeMemoryBarrier(); // make sure that the new service routine is only called once the context is set up
134 xpdd->ev_actions[Port].ServiceRoutine = ServiceRoutine;
136 EvtChn_Unmask(Device, Port);
138 KdPrint((__DRIVER_NAME " <-- EvtChn_BindDpc\n"));
140 return STATUS_SUCCESS;
141 }
143 NTSTATUS
144 EvtChn_Unbind(PVOID Context, evtchn_port_t Port)
145 {
146 WDFDEVICE Device = Context;
147 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
149 EvtChn_Mask(Context, Port);
150 xpdd->ev_actions[Port].ServiceContext = NULL;
151 xpdd->ev_actions[Port].ServiceRoutine = NULL;
153 //KdPrint((__DRIVER_NAME " <-- EvtChn_UnBind\n"));
155 return STATUS_SUCCESS;
156 }
158 NTSTATUS
159 EvtChn_Mask(PVOID Context, evtchn_port_t Port)
160 {
161 WDFDEVICE Device = Context;
162 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
163 //KdPrint((__DRIVER_NAME " --> EvtChn_Mask\n"));
165 _interlockedbittestandset(
166 (volatile LONG *)&xpdd->shared_info_area->evtchn_mask[0], Port);
168 //KdPrint((__DRIVER_NAME " <-- EvtChn_Mask\n"));
170 return STATUS_SUCCESS;
171 }
173 NTSTATUS
174 EvtChn_Unmask(PVOID Context, evtchn_port_t Port)
175 {
176 WDFDEVICE Device = Context;
177 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
178 //KdPrint((__DRIVER_NAME " --> EvtChn_Unmask\n"));
180 _interlockedbittestandreset(
181 (volatile LONG *)&xpdd->shared_info_area->evtchn_mask[0], Port);
182 // should we kick off pending interrupts here too???
184 //KdPrint((__DRIVER_NAME " <-- EvtChn_Unmask\n"));
186 return STATUS_SUCCESS;
187 }
189 NTSTATUS
190 EvtChn_Notify(PVOID Context, evtchn_port_t Port)
191 {
192 struct evtchn_send send;
194 //KdPrint((__DRIVER_NAME " --> EvtChn_Notify\n"));
196 send.port = Port;
198 (void)HYPERVISOR_event_channel_op(Context, EVTCHNOP_send, &send);
200 //KdPrint((__DRIVER_NAME " <-- EvtChn_Notify\n"));
202 return STATUS_SUCCESS;
203 }
205 evtchn_port_t
206 EvtChn_AllocUnbound(PVOID Context, domid_t Domain)
207 {
208 evtchn_alloc_unbound_t op;
210 //KdPrint((__DRIVER_NAME " --> AllocUnbound\n"));
212 op.dom = DOMID_SELF;
213 op.remote_dom = Domain;
214 HYPERVISOR_event_channel_op(Context, EVTCHNOP_alloc_unbound, &op);
216 //KdPrint((__DRIVER_NAME " <-- AllocUnbound\n"));
218 return op.port;
219 }
221 evtchn_port_t
222 EvtChn_GetXenStorePort(WDFDEVICE Device)
223 {
224 evtchn_port_t Port;
226 //KdPrint((__DRIVER_NAME " --> EvtChn_GetStorePort\n"));
228 Port = (evtchn_port_t)hvm_get_parameter(Device, HVM_PARAM_STORE_EVTCHN);
230 //KdPrint((__DRIVER_NAME " <-- EvtChn_GetStorePort\n"));
232 return Port;
233 }
235 PVOID
236 EvtChn_GetXenStoreRingAddr(WDFDEVICE Device)
237 {
238 PHYSICAL_ADDRESS pa_xen_store_interface;
239 PVOID xen_store_interface;
241 ULONG xen_store_mfn;
243 //KdPrint((__DRIVER_NAME " --> EvtChn_GetRingAddr\n"));
245 xen_store_mfn = (ULONG)hvm_get_parameter(Device, HVM_PARAM_STORE_PFN);
247 pa_xen_store_interface.QuadPart = xen_store_mfn << PAGE_SHIFT;
248 xen_store_interface = MmMapIoSpace(pa_xen_store_interface, PAGE_SIZE, MmNonCached);
250 //KdPrint((__DRIVER_NAME " xen_store_mfn = %08x\n", xen_store_mfn));
251 //KdPrint((__DRIVER_NAME " xen_store_evtchn = %08x\n", xen_store_evtchn));
252 //KdPrint((__DRIVER_NAME " xen_store_interface = %08x\n", xen_store_interface));
254 //KeInitializeEvent(&xenbus_waitevent, NotificationEvent, FALSE);
256 //KdPrint((__DRIVER_NAME " <-- EvtChn_GetRingAddr\n"));
258 return xen_store_interface;
259 }
261 NTSTATUS
262 EvtChn_Init(WDFDEVICE Device)
263 {
264 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
265 int i;
267 for (i = 0; i < NR_EVENTS; i++)
268 {
269 EvtChn_Mask(Device, i);
270 xpdd->ev_actions[i].ServiceRoutine = NULL;
271 xpdd->ev_actions[i].ServiceContext = NULL;
272 xpdd->ev_actions[i].Count = 0;
273 }
275 for (i = 0; i < 8; i++)
276 {
277 xpdd->shared_info_area->evtchn_pending[i] = 0;
278 }
279 xpdd->shared_info_area->vcpu_info[0].evtchn_upcall_pending = 0;
280 xpdd->shared_info_area->vcpu_info[0].evtchn_pending_sel = 0;
282 return STATUS_SUCCESS;
283 }