1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
/** @file
*
* Copyright (c) 2020, Andrei Warkentin <andrey.warkentin@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
**/
#include "ConfigDxe.h"
#include <IndustryStandard/Pci.h>
#include <Protocol/PciIo.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#pragma pack(1)
typedef struct {
UINT8 ProgInterface;
UINT8 SubClassCode;
UINT8 BaseCode;
} USB_CLASSC;
#pragma pack()
STATIC VOID *mPciIoNotificationRegistration = NULL;
STATIC
VOID
EFIAPI
PciIoNotificationEvent (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
USB_CLASSC UsbClassCReg;
UINTN SegmentNumber;
UINTN BusNumber;
UINTN DeviceNumber;
UINTN FunctionNumber;
RASPBERRY_PI_FIRMWARE_PROTOCOL *FwProtocol = Context;
Status = gBS->LocateProtocol (&gEfiPciIoProtocolGuid,
mPciIoNotificationRegistration, (VOID **)&PciIo);
if (EFI_ERROR (Status)) {
return;
}
Status = PciIo->Pci.Read (PciIo,
EfiPciIoWidthUint8,
PCI_CLASSCODE_OFFSET,
sizeof (USB_CLASSC) / sizeof (UINT8),
&UsbClassCReg
);
if (EFI_ERROR (Status)) {
return;
}
//
// Test whether the controller belongs to Xhci type
//
if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
(UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
(UsbClassCReg.ProgInterface != PCI_IF_XHCI)) {
return;
}
Status = PciIo->GetLocation (PciIo, &SegmentNumber, &BusNumber,
&DeviceNumber, &FunctionNumber);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "%a: failed to get SBDF for xHCI controller: %r\n",
__func__, Status));
return;
}
DEBUG ((DEBUG_INFO, "xHCI found at %u:%u:%u:%u\n",
SegmentNumber, BusNumber, DeviceNumber, FunctionNumber));
ASSERT (SegmentNumber == 0);
Status = FwProtocol->NotifyXhciReset(BusNumber, DeviceNumber, FunctionNumber);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "%a: couldn't signal xHCI firmware load: %r\n",
__func__, Status));
}
}
VOID
RegisterXhciQuirkHandler (
IN RASPBERRY_PI_FIRMWARE_PROTOCOL *FwProtocol
)
{
EfiCreateProtocolNotifyEvent (&gEfiPciIoProtocolGuid,
TPL_NOTIFY,
PciIoNotificationEvent,
FwProtocol,
&mPciIoNotificationRegistration
);
}
|