Staging: hv: remove UINT8 and INT8 typedefs
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / hv / Vmbus.c
CommitLineData
3e7ee490
HJ
1/*
2 *
3 * Copyright (c) 2009, Microsoft Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 *
18 * Authors:
19 * Haiyang Zhang <haiyangz@microsoft.com>
20 * Hank Janssen <hjanssen@microsoft.com>
21 *
22 */
23
5654e932 24#include <linux/kernel.h>
09d50ff8 25#include "include/logging.h"
3e7ee490
HJ
26#include "VersionInfo.h"
27#include "VmbusPrivate.h"
28
29//
30// Globals
31//
32static const char* gDriverName="vmbus";
33
34// Windows vmbus does not defined this. We defined this to be consistent with other devices
35//{c5295816-f63a-4d5f-8d1a-4daf999ca185}
36static const GUID gVmbusDeviceType={
37 .Data = {0x16, 0x58, 0x29, 0xc5, 0x3a, 0xf6, 0x5f, 0x4d, 0x8d, 0x1a, 0x4d, 0xaf, 0x99, 0x9c, 0xa1, 0x85}
38};
39
40//{ac3760fc-9adf-40aa-9427-a70ed6de95c5}
41static const GUID gVmbusDeviceId={
42 .Data = {0xfc, 0x60, 0x37, 0xac, 0xdf, 0x9a, 0xaa, 0x40, 0x94, 0x27, 0xa7, 0x0e, 0xd6, 0xde, 0x95, 0xc5}
43};
44
45static DRIVER_OBJECT* gDriver; // vmbus driver object
46static DEVICE_OBJECT* gDevice; // vmbus root device
47
48
49//
50// Internal routines
51//
52
53static void
54VmbusGetChannelInterface(
55 VMBUS_CHANNEL_INTERFACE *Interface
56 );
57
58static void
59VmbusGetChannelInfo(
60 DEVICE_OBJECT *DeviceObject,
61 DEVICE_INFO *DeviceInfo
62 );
63
64static void
65VmbusGetChannelOffers(
66 void
67 );
68
69static int
70VmbusOnDeviceAdd(
71 DEVICE_OBJECT *Device,
72 void *AdditionalInfo
73 );
74
75static int
76VmbusOnDeviceRemove(
77 DEVICE_OBJECT* dev
78 );
79
80static void
81VmbusOnCleanup(
82 DRIVER_OBJECT* drv
83 );
84
85static int
86VmbusOnISR(
87 DRIVER_OBJECT* drv
88 );
89
90static void
91VmbusOnMsgDPC(
92 DRIVER_OBJECT* drv
93 );
94
95static void
96VmbusOnEventDPC(
97 DRIVER_OBJECT* drv
98 );
99
100/*++;
101
102Name:
103 VmbusInitialize()
104
105Description:
106 Main entry point
107
108--*/
109int
110VmbusInitialize(
111 DRIVER_OBJECT* drv
112 )
113{
114 VMBUS_DRIVER_OBJECT* driver = (VMBUS_DRIVER_OBJECT*)drv;
115 int ret=0;
116
117 DPRINT_ENTER(VMBUS);
118
119 DPRINT_INFO(VMBUS, "+++++++ Build Date=%s %s +++++++", VersionDate, VersionTime);
120 DPRINT_INFO(VMBUS, "+++++++ Build Description=%s +++++++", VersionDesc);
121
122 DPRINT_INFO(VMBUS, "+++++++ Vmbus supported version = %d +++++++", VMBUS_REVISION_NUMBER);
123 DPRINT_INFO(VMBUS, "+++++++ Vmbus using SINT %d +++++++", VMBUS_MESSAGE_SINT);
124
125 DPRINT_DBG(VMBUS, "sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER)=%d, sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER)=%d",
126 sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER), sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER));
127
128 drv->name = gDriverName;
129 memcpy(&drv->deviceType, &gVmbusDeviceType, sizeof(GUID));
130
131 // Setup dispatch table
132 driver->Base.OnDeviceAdd = VmbusOnDeviceAdd;
133 driver->Base.OnDeviceRemove = VmbusOnDeviceRemove;
134 driver->Base.OnCleanup = VmbusOnCleanup;
135 driver->OnIsr = VmbusOnISR;
136 driver->OnMsgDpc = VmbusOnMsgDPC;
137 driver->OnEventDpc = VmbusOnEventDPC;
138 driver->GetChannelOffers = VmbusGetChannelOffers;
139 driver->GetChannelInterface = VmbusGetChannelInterface;
140 driver->GetChannelInfo = VmbusGetChannelInfo;
141
142 // Hypervisor initialization...setup hypercall page..etc
143 ret = HvInit();
144 if (ret != 0)
145 {
146 DPRINT_ERR(VMBUS, "Unable to initialize the hypervisor - 0x%x", ret);
147 }
148
149 gDriver = drv;
150
151 DPRINT_EXIT(VMBUS);
152
153 return ret;
154}
155
156
157/*++;
158
159Name:
160 VmbusGetChannelOffers()
161
162Description:
163 Retrieve the channel offers from the parent partition
164
165--*/
166
167static void
168VmbusGetChannelOffers(void)
169{
170 DPRINT_ENTER(VMBUS);
171 VmbusChannelRequestOffers();
172 DPRINT_EXIT(VMBUS);
173}
174
175
176/*++;
177
178Name:
179 VmbusGetChannelInterface()
180
181Description:
182 Get the channel interface
183
184--*/
185static void
186VmbusGetChannelInterface(
187 VMBUS_CHANNEL_INTERFACE *Interface
188 )
189{
190 GetChannelInterface(Interface);
191}
192
193
194/*++;
195
196Name:
197 VmbusGetChannelInterface()
198
199Description:
200 Get the device info for the specified device object
201
202--*/
203static void
204VmbusGetChannelInfo(
205 DEVICE_OBJECT *DeviceObject,
206 DEVICE_INFO *DeviceInfo
207 )
208{
209 GetChannelInfo(DeviceObject, DeviceInfo);
210}
211
212
213
214/*++
215
216Name:
217 VmbusCreateChildDevice()
218
219Description:
220 Creates the child device on the bus that represents the channel offer
221
222--*/
223
224DEVICE_OBJECT*
225VmbusChildDeviceCreate(
226 GUID DeviceType,
227 GUID DeviceInstance,
228 void *Context)
229{
230 VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
231
232 return vmbusDriver->OnChildDeviceCreate(
233 DeviceType,
234 DeviceInstance,
235 Context);
236}
237
238
239/*++
240
241Name:
242 VmbusChildDeviceAdd()
243
244Description:
245 Registers the child device with the vmbus
246
247--*/
248int
249VmbusChildDeviceAdd(
250 DEVICE_OBJECT* ChildDevice)
251{
252 VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
253
254 return vmbusDriver->OnChildDeviceAdd(gDevice, ChildDevice);
255}
256
257
258/*++
259
260Name:
261 VmbusChildDeviceRemove()
262
263Description:
264 Unregisters the child device from the vmbus
265
266--*/
267void
268VmbusChildDeviceRemove(
269 DEVICE_OBJECT* ChildDevice)
270{
271 VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
272
273 vmbusDriver->OnChildDeviceRemove(ChildDevice);
274}
275
276/*++
277
278Name:
279 VmbusChildDeviceDestroy()
280
281Description:
282 Release the child device from the vmbus
283
284--*/
285//void
286//VmbusChildDeviceDestroy(
287// DEVICE_OBJECT* ChildDevice
288// )
289//{
290// VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
291//
292// vmbusDriver->OnChildDeviceDestroy(ChildDevice);
293//}
294
295/*++
296
297Name:
298 VmbusOnDeviceAdd()
299
300Description:
301 Callback when the root bus device is added
302
303--*/
304static int
305VmbusOnDeviceAdd(
306 DEVICE_OBJECT *dev,
307 void *AdditionalInfo
308 )
309{
310 UINT32 *irqvector = (UINT32*) AdditionalInfo;
311 int ret=0;
312
313 DPRINT_ENTER(VMBUS);
314
315 gDevice = dev;
316
317 memcpy(&gDevice->deviceType, &gVmbusDeviceType, sizeof(GUID));
318 memcpy(&gDevice->deviceInstance, &gVmbusDeviceId, sizeof(GUID));
319
320 //strcpy(dev->name, "vmbus");
321 // SynIC setup...
322 ret = HvSynicInit(*irqvector);
323
324 // Connect to VMBus in the root partition
325 ret = VmbusConnect();
326
327 //VmbusSendEvent(device->localPortId+1);
328 DPRINT_EXIT(VMBUS);
329
330 return ret;
331}
332
333
334/*++
335
336Name:
337 VmbusOnDeviceRemove()
338
339Description:
340 Callback when the root bus device is removed
341
342--*/
343int VmbusOnDeviceRemove(
344 DEVICE_OBJECT* dev
345 )
346{
347 int ret=0;
348
349 DPRINT_ENTER(VMBUS);
350
351 VmbusChannelReleaseUnattachedChannels();
352
353 VmbusDisconnect();
354
355 HvSynicCleanup();
356
357 DPRINT_EXIT(VMBUS);
358
359 return ret;
360}
361
362
363/*++
364
365Name:
366 VmbusOnCleanup()
367
368Description:
369 Perform any cleanup when the driver is removed
370
371--*/
372void
373VmbusOnCleanup(
374 DRIVER_OBJECT* drv
375 )
376{
377 //VMBUS_DRIVER_OBJECT* driver = (VMBUS_DRIVER_OBJECT*)drv;
378
379 DPRINT_ENTER(VMBUS);
380
381 HvCleanup();
382
383 DPRINT_EXIT(VMBUS);
384}
385
386
387/*++
388
389Name:
390 VmbusOnMsgDPC()
391
392Description:
393 DPC routine to handle messages from the hypervisior
394
395--*/
396void
397VmbusOnMsgDPC(
398 DRIVER_OBJECT* drv
399 )
400{
401 void *page_addr = gHvContext.synICMessagePage[0];
402
403 HV_MESSAGE* msg = (HV_MESSAGE*)page_addr + VMBUS_MESSAGE_SINT;
404 HV_MESSAGE *copied;
405 while (1)
406 {
407 if (msg->Header.MessageType == HvMessageTypeNone) // no msg
408 {
409 break;
410 }
411 else
412 {
413 copied = MemAllocAtomic(sizeof(HV_MESSAGE));
414 if (copied == NULL)
415 {
416 continue;
417 }
418
419 memcpy(copied, msg, sizeof(HV_MESSAGE));
420 WorkQueueQueueWorkItem(gVmbusConnection.WorkQueue, VmbusOnChannelMessage, (void*)copied);
421 }
422
423 msg->Header.MessageType = HvMessageTypeNone;
424
425 // Make sure the write to MessageType (ie set to HvMessageTypeNone) happens
426 // before we read the MessagePending and EOMing. Otherwise, the EOMing will not deliver
427 // any more messages since there is no empty slot
428 MemoryFence();
429
430 if (msg->Header.MessageFlags.MessagePending)
431 {
432 // This will cause message queue rescan to possibly deliver another msg from the hypervisor
433 WriteMsr(HV_X64_MSR_EOM, 0);
434 }
435 }
436}
437
438/*++
439
440Name:
441 VmbusOnEventDPC()
442
443Description:
444 DPC routine to handle events from the hypervisior
445
446--*/
447void
448VmbusOnEventDPC(
449 DRIVER_OBJECT* drv
450 )
451{
452 // TODO: Process any events
453 VmbusOnEvents();
454}
455
456
457/*++
458
459Name:
460 VmbusOnISR()
461
462Description:
463 ISR routine
464
465--*/
466int
467VmbusOnISR(
468 DRIVER_OBJECT* drv
469 )
470{
471 //VMBUS_DRIVER_OBJECT* driver = (VMBUS_DRIVER_OBJECT*)drv;
472
473 int ret=0;
474 //struct page* page;
475 void *page_addr;
476 HV_MESSAGE* msg;
477 HV_SYNIC_EVENT_FLAGS* event;
478
479 //page = SynICMessagePage[0];
480 //page_addr = page_address(page);
481 page_addr = gHvContext.synICMessagePage[0];
482 msg = (HV_MESSAGE*)page_addr + VMBUS_MESSAGE_SINT;
483
484 DPRINT_ENTER(VMBUS);
485
486 // Check if there are actual msgs to be process
487 if (msg->Header.MessageType != HvMessageTypeNone)
488 {
489 DPRINT_DBG(VMBUS, "received msg type %d size %d", msg->Header.MessageType, msg->Header.PayloadSize);
490 ret |= 0x1;
491 }
492
493 // TODO: Check if there are events to be process
494 page_addr = gHvContext.synICEventPage[0];
495 event = (HV_SYNIC_EVENT_FLAGS*)page_addr + VMBUS_MESSAGE_SINT;
496
497 // Since we are a child, we only need to check bit 0
498 if (BitTestAndClear(&event->Flags32[0], 0))
499 {
500 DPRINT_DBG(VMBUS, "received event %d", event->Flags32[0]);
501 ret |= 0x2;
502 }
503
504 DPRINT_EXIT(VMBUS);
505 return ret;
506}
507
508// eof