]> Pileus Git - ~andy/linux/blob - drivers/staging/hv/Vmbus.c
Staging: hv: remove UINT32 and INT32 typedefs
[~andy/linux] / drivers / staging / hv / Vmbus.c
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
24 #include <linux/kernel.h>
25 #include "include/logging.h"
26 #include "VersionInfo.h"
27 #include "VmbusPrivate.h"
28
29 //
30 // Globals
31 //
32 static 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}
36 static 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}
41 static const GUID gVmbusDeviceId={
42         .Data = {0xfc, 0x60, 0x37, 0xac, 0xdf, 0x9a, 0xaa, 0x40, 0x94, 0x27, 0xa7, 0x0e, 0xd6, 0xde, 0x95, 0xc5}
43 };
44
45 static DRIVER_OBJECT* gDriver; // vmbus driver object
46 static DEVICE_OBJECT* gDevice; // vmbus root device
47
48
49 //
50 // Internal routines
51 //
52
53 static void
54 VmbusGetChannelInterface(
55         VMBUS_CHANNEL_INTERFACE *Interface
56         );
57
58 static void
59 VmbusGetChannelInfo(
60         DEVICE_OBJECT   *DeviceObject,
61         DEVICE_INFO             *DeviceInfo
62         );
63
64 static void
65 VmbusGetChannelOffers(
66         void
67         );
68
69 static int
70 VmbusOnDeviceAdd(
71         DEVICE_OBJECT   *Device,
72         void                    *AdditionalInfo
73         );
74
75 static int
76 VmbusOnDeviceRemove(
77         DEVICE_OBJECT* dev
78         );
79
80 static void
81 VmbusOnCleanup(
82         DRIVER_OBJECT* drv
83         );
84
85 static int
86 VmbusOnISR(
87         DRIVER_OBJECT* drv
88         );
89
90 static void
91 VmbusOnMsgDPC(
92         DRIVER_OBJECT* drv
93         );
94
95 static void
96 VmbusOnEventDPC(
97         DRIVER_OBJECT* drv
98         );
99
100 /*++;
101
102 Name:
103         VmbusInitialize()
104
105 Description:
106         Main entry point
107
108 --*/
109 int
110 VmbusInitialize(
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
159 Name:
160         VmbusGetChannelOffers()
161
162 Description:
163         Retrieve the channel offers from the parent partition
164
165 --*/
166
167 static void
168 VmbusGetChannelOffers(void)
169 {
170         DPRINT_ENTER(VMBUS);
171         VmbusChannelRequestOffers();
172         DPRINT_EXIT(VMBUS);
173 }
174
175
176 /*++;
177
178 Name:
179         VmbusGetChannelInterface()
180
181 Description:
182         Get the channel interface
183
184 --*/
185 static void
186 VmbusGetChannelInterface(
187         VMBUS_CHANNEL_INTERFACE *Interface
188         )
189 {
190         GetChannelInterface(Interface);
191 }
192
193
194 /*++;
195
196 Name:
197         VmbusGetChannelInterface()
198
199 Description:
200         Get the device info for the specified device object
201
202 --*/
203 static void
204 VmbusGetChannelInfo(
205         DEVICE_OBJECT   *DeviceObject,
206         DEVICE_INFO             *DeviceInfo
207         )
208 {
209         GetChannelInfo(DeviceObject, DeviceInfo);
210 }
211
212
213
214 /*++
215
216 Name:
217         VmbusCreateChildDevice()
218
219 Description:
220         Creates the child device on the bus that represents the channel offer
221
222 --*/
223
224 DEVICE_OBJECT*
225 VmbusChildDeviceCreate(
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
241 Name:
242         VmbusChildDeviceAdd()
243
244 Description:
245         Registers the child device with the vmbus
246
247 --*/
248 int
249 VmbusChildDeviceAdd(
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
260 Name:
261         VmbusChildDeviceRemove()
262
263 Description:
264         Unregisters the child device from the vmbus
265
266 --*/
267 void
268 VmbusChildDeviceRemove(
269    DEVICE_OBJECT* ChildDevice)
270 {
271         VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
272
273         vmbusDriver->OnChildDeviceRemove(ChildDevice);
274 }
275
276 /*++
277
278 Name:
279         VmbusChildDeviceDestroy()
280
281 Description:
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
297 Name:
298         VmbusOnDeviceAdd()
299
300 Description:
301         Callback when the root bus device is added
302
303 --*/
304 static int
305 VmbusOnDeviceAdd(
306         DEVICE_OBJECT   *dev,
307         void                    *AdditionalInfo
308         )
309 {
310         u32 *irqvector = (u32*) 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
336 Name:
337         VmbusOnDeviceRemove()
338
339 Description:
340         Callback when the root bus device is removed
341
342 --*/
343 int 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
365 Name:
366         VmbusOnCleanup()
367
368 Description:
369         Perform any cleanup when the driver is removed
370
371 --*/
372 void
373 VmbusOnCleanup(
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
389 Name:
390         VmbusOnMsgDPC()
391
392 Description:
393         DPC routine to handle messages from the hypervisior
394
395 --*/
396 void
397 VmbusOnMsgDPC(
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
440 Name:
441         VmbusOnEventDPC()
442
443 Description:
444         DPC routine to handle events from the hypervisior
445
446 --*/
447 void
448 VmbusOnEventDPC(
449         DRIVER_OBJECT* drv
450         )
451 {
452         // TODO: Process any events
453         VmbusOnEvents();
454 }
455
456
457 /*++
458
459 Name:
460         VmbusOnISR()
461
462 Description:
463         ISR routine
464
465 --*/
466 int
467 VmbusOnISR(
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