2 XenBus Bus driver implemtation.
4 This file implement the necessary to discover and enumerate Xen PV devices
7 Copyright (C) 2010 Spectra Logic Corporation
8 Copyright (C) 2008 Doug Rabson
9 Copyright (C) 2005 Rusty Russell, IBM Corporation
10 Copyright (C) 2005 Mike Wray, Hewlett-Packard
11 Copyright (C) 2005 XenSource Ltd
12 Copyright (C) 2014, Citrix Ltd.
14 This file may be distributed separately from the Linux kernel, or
15 incorporated into other software packages, subject to the following license:
17 Permission is hereby granted, free of charge, to any person obtaining a copy
18 of this source file (the "Software"), to deal in the Software without
19 restriction, including without limitation the rights to use, copy, modify,
20 merge, publish, distribute, sublicense, and/or sell copies of the Software,
21 and to permit persons to whom the Software is furnished to do so, subject to
22 the following conditions:
24 The above copyright notice and this permission notice shall be included in
25 all copies or substantial portions of the Software.
27 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
36 #include <Library/PrintLib.h>
39 #include "GrantTable.h"
41 #include "EventChannel.h"
43 #include <IndustryStandard/Xen/io/xenbus.h>
45 STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData
;
47 STATIC XENBUS_DEVICE_PATH gXenBusDevicePathTemplate
= {
48 .Vendor
.Header
.Type
= HARDWARE_DEVICE_PATH
,
49 .Vendor
.Header
.SubType
= HW_VENDOR_DP
,
50 .Vendor
.Header
.Length
[0] = (UINT8
) sizeof (XENBUS_DEVICE_PATH
),
51 .Vendor
.Header
.Length
[1] = (UINT8
) (sizeof (XENBUS_DEVICE_PATH
) >> 8),
52 .Vendor
.Guid
= XENBUS_PROTOCOL_GUID
,
59 Search our internal record of configured devices (not the XenStore) to
60 determine if the XenBus device indicated by Node is known to the system.
62 @param Dev The XENBUS_DEVICE instance to search for device children.
63 @param Node The XenStore node path for the device to find.
65 @return The XENBUS_PRIVATE_DATA of the found device if any, or NULL.
69 XenBusDeviceInitialized (
70 IN XENBUS_DEVICE
*Dev
,
75 XENBUS_PRIVATE_DATA
*Child
;
76 XENBUS_PRIVATE_DATA
*Result
;
78 if (IsListEmpty (&Dev
->ChildList
)) {
83 for (Entry
= GetFirstNode (&Dev
->ChildList
);
84 !IsNodeAtEnd (&Dev
->ChildList
, Entry
);
85 Entry
= GetNextNode (&Dev
->ChildList
, Entry
)) {
86 Child
= XENBUS_PRIVATE_DATA_FROM_LINK (Entry
);
87 if (!AsciiStrCmp (Child
->XenBusIo
.Node
, Node
)) {
98 XenBusReadDriverState (
104 XENSTORE_STATUS Status
;
106 Status
= XenStoreRead (XST_NIL
, Path
, "state", NULL
, (VOID
**)&Ptr
);
107 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
108 State
= XenbusStateClosed
;
110 State
= AsciiStrDecimalToUintn (Ptr
);
121 // Callers should ensure that they are only one calling XenBusAddDevice.
130 CHAR8 DevicePath
[XENSTORE_ABS_PATH_MAX
];
131 XENSTORE_STATUS StatusXenStore
;
132 XENBUS_PRIVATE_DATA
*Private
;
134 XENBUS_DEVICE_PATH
*TempXenBusPath
;
137 AsciiSPrint (DevicePath
, sizeof (DevicePath
),
138 "device/%a/%a", Type
, Id
);
140 if (XenStorePathExists (XST_NIL
, DevicePath
, "")) {
141 XENBUS_PRIVATE_DATA
*Child
;
142 enum xenbus_state State
;
145 Child
= XenBusDeviceInitialized (Dev
, DevicePath
);
148 * We are already tracking this node
150 Status
= EFI_SUCCESS
;
154 State
= XenBusReadDriverState (DevicePath
);
155 if (State
!= XenbusStateInitialising
) {
157 * Device is not new, so ignore it. This can
158 * happen if a device is going away after
159 * switching to Closed.
161 DEBUG ((EFI_D_INFO
, "XenBus: Device %a ignored. "
162 "State %d\n", DevicePath
, State
));
163 Status
= EFI_SUCCESS
;
167 StatusXenStore
= XenStoreRead (XST_NIL
, DevicePath
, "backend",
168 NULL
, (VOID
**) &BackendPath
);
169 if (StatusXenStore
!= XENSTORE_STATUS_SUCCESS
) {
170 DEBUG ((EFI_D_ERROR
, "xenbus: %a no backend path.\n", DevicePath
));
171 Status
= EFI_NOT_FOUND
;
175 Private
= AllocateCopyPool (sizeof (*Private
), &gXenBusPrivateData
);
176 Private
->XenBusIo
.Type
= AsciiStrDup (Type
);
177 Private
->XenBusIo
.Node
= AsciiStrDup (DevicePath
);
178 Private
->XenBusIo
.Backend
= BackendPath
;
179 Private
->XenBusIo
.DeviceId
= AsciiStrDecimalToUintn (Id
);
182 TempXenBusPath
= AllocateCopyPool (sizeof (XENBUS_DEVICE_PATH
),
183 &gXenBusDevicePathTemplate
);
184 if (!AsciiStrCmp (Private
->XenBusIo
.Type
, "vbd")) {
185 TempXenBusPath
->Type
= XENBUS_DEVICE_PATH_TYPE_VBD
;
187 TempXenBusPath
->DeviceId
= Private
->XenBusIo
.DeviceId
;
188 Private
->DevicePath
= (XENBUS_DEVICE_PATH
*)AppendDevicePathNode (
190 &TempXenBusPath
->Vendor
.Header
);
191 FreePool (TempXenBusPath
);
193 InsertTailList (&Dev
->ChildList
, &Private
->Link
);
195 Status
= gBS
->InstallMultipleProtocolInterfaces (
197 &gEfiDevicePathProtocolGuid
, Private
->DevicePath
,
198 &gXenBusProtocolGuid
, &Private
->XenBusIo
,
200 if (EFI_ERROR (Status
)) {
201 goto ErrorInstallProtocol
;
204 Status
= gBS
->OpenProtocol (Dev
->ControllerHandle
,
205 &gEfiPciIoProtocolGuid
,
206 &ChildPciIo
, Dev
->This
->DriverBindingHandle
,
208 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
209 if (EFI_ERROR (Status
)) {
210 DEBUG ((EFI_D_ERROR
, "open by child controller fail (%r)\n",
212 goto ErrorOpenProtocolByChild
;
215 DEBUG ((EFI_D_ERROR
, "XenBus: does not exist: %a\n", DevicePath
));
216 Status
= EFI_NOT_FOUND
;
221 ErrorOpenProtocolByChild
:
222 gBS
->UninstallMultipleProtocolInterfaces (
224 &gEfiDevicePathProtocolGuid
, Private
->DevicePath
,
225 &gXenBusProtocolGuid
, &Private
->XenBusIo
,
227 ErrorInstallProtocol
:
228 RemoveEntryList (&Private
->Link
);
229 FreePool (Private
->DevicePath
);
230 FreePool ((VOID
*) Private
->XenBusIo
.Backend
);
231 FreePool ((VOID
*) Private
->XenBusIo
.Node
);
232 FreePool ((VOID
*) Private
->XenBusIo
.Type
);
239 Enumerate all devices of the given type on this bus.
241 @param Dev A XENBUS_DEVICE instance.
242 @param Type String indicating the device sub-tree (e.g. "vfb", "vif")
245 Devices that are found are been initialize via XenBusAddDevice ().
246 XenBusAddDevice () ignores duplicate detects and ignores duplicate devices,
247 so it can be called unconditionally for any device found in the XenStore.
251 XenBusEnumerateDeviceType (
256 CONST CHAR8
**Directory
;
259 XENSTORE_STATUS Status
;
261 Status
= XenStoreListDirectory (XST_NIL
,
264 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
267 for (Index
= 0; Index
< Count
; Index
++) {
268 XenBusAddDevice (Dev
, Type
, Directory
[Index
]);
271 FreePool (Directory
);
276 Enumerate the devices on a XenBus bus and install a XenBus Protocol instance.
278 Caller should ensure that it is the only one to call this function. This
279 function cannot be called concurrently.
281 @param Dev A XENBUS_DEVICE instance.
283 @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
284 indicating the type of failure.
294 XENSTORE_STATUS Status
;
296 Status
= XenStoreListDirectory (XST_NIL
,
299 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
303 for (Index
= 0; Index
< Count
; Index
++) {
304 XenBusEnumerateDeviceType (Dev
, Types
[Index
]);
309 return XENSTORE_STATUS_SUCCESS
;
316 IN XENBUS_PROTOCOL
*This
,
317 IN XENSTORE_TRANSACTION Transaction
,
318 IN
enum xenbus_state NewState
321 enum xenbus_state CurrentState
;
322 XENSTORE_STATUS Status
;
325 DEBUG ((EFI_D_INFO
, "XenBus: Set state to %d\n", NewState
));
327 Status
= XenStoreRead (Transaction
, This
->Node
, "state", NULL
, (VOID
**)&Temp
);
328 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
331 CurrentState
= AsciiStrDecimalToUintn (Temp
);
333 if (CurrentState
== NewState
) {
338 Status
= XenStoreSPrint (Transaction
, This
->Node
, "state", "%d", NewState
);
339 } while (Status
== XENSTORE_STATUS_EAGAIN
);
340 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
341 DEBUG ((EFI_D_ERROR
, "XenBus: failed to write new state\n"));
344 DEBUG ((EFI_D_INFO
, "XenBus: Set state to %d, done\n", NewState
));
350 STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData
= {
351 .Signature
= XENBUS_PRIVATE_DATA_SIGNATURE
,
353 .XenBusIo
.XsRead
= XenBusXenStoreRead
,
354 .XenBusIo
.XsBackendRead
= XenBusXenStoreBackendRead
,
355 .XenBusIo
.XsPrintf
= XenBusXenStoreSPrint
,
356 .XenBusIo
.XsRemove
= XenBusXenStoreRemove
,
357 .XenBusIo
.XsTransactionStart
= XenBusXenStoreTransactionStart
,
358 .XenBusIo
.XsTransactionEnd
= XenBusXenStoreTransactionEnd
,
359 .XenBusIo
.SetState
= XenBusSetState
,
360 .XenBusIo
.GrantAccess
= XenBusGrantAccess
,
361 .XenBusIo
.GrantEndAccess
= XenBusGrantEndAccess
,
362 .XenBusIo
.EventChannelAllocate
= XenBusEventChannelAllocate
,
363 .XenBusIo
.EventChannelNotify
= XenBusEventChannelNotify
,
364 .XenBusIo
.EventChannelClose
= XenBusEventChannelClose
,
365 .XenBusIo
.RegisterWatch
= XenBusRegisterWatch
,
366 .XenBusIo
.RegisterWatchBackend
= XenBusRegisterWatchBackend
,
367 .XenBusIo
.UnregisterWatch
= XenBusUnregisterWatch
,
368 .XenBusIo
.WaitForWatch
= XenBusWaitForWatch
,
370 .XenBusIo
.Type
= NULL
,
371 .XenBusIo
.Node
= NULL
,
372 .XenBusIo
.Backend
= NULL
,