add display subsystem and vmwaresvga driver, support absolute mouse and qemu tablet, map pci mmio to private virtual aperture, better smp panic handling, remove legacy io publish/match, add sys query display info and display command to native shell
This commit is contained in:
1 parent
e41bf6e2c0
commit
6260de0085
38 files changed
+4011
-467
No files matched your search
@@ -20,6 +20,40 @@ static const HAL_API* gHal;
|
||||
static DRIVER_OBJECT gPciDriver;
|
||||
static uint32_t gPciDeviceCount;
|
||||
|
||||
/*
|
||||
* PCI MMIO BARs use a private virtual aperture instead of the physical
|
||||
* direct map. This avoids cacheability aliasing with large direct-map pages
|
||||
* and keeps BAR mappings page-granular.
|
||||
*/
|
||||
#define PCI_MMIO_VA_BASE 0xFFFF900000000000ULL
|
||||
#define PCI_MMIO_VA_LIMIT 0xFFFF980000000000ULL
|
||||
|
||||
static uintptr_t gPciMmioNext = PCI_MMIO_VA_BASE;
|
||||
|
||||
static uint64_t PciAlignUp64(uint64_t value, uint64_t alignment) {
|
||||
return (value + alignment - 1u) & ~(alignment - 1u);
|
||||
}
|
||||
|
||||
static uint64_t PciDefaultMmioFlags(void) {
|
||||
return PAGE_PRESENT | PAGE_WRITE | PAGE_WRITETHROUGH | PAGE_NOCACHE | PAGE_NX;
|
||||
}
|
||||
|
||||
static KSTATUS PciAllocateMmioVa(uint64_t length, uintptr_t* outVa) {
|
||||
if (!outVa || !length)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
uint64_t alignedLength = PciAlignUp64(length, PAGE_SIZE);
|
||||
uintptr_t va = (uintptr_t)PciAlignUp64((uint64_t)gPciMmioNext, PAGE_SIZE);
|
||||
if (va < PCI_MMIO_VA_BASE || va >= PCI_MMIO_VA_LIMIT)
|
||||
return STATUS_NO_MEMORY;
|
||||
if (alignedLength > (uint64_t)(PCI_MMIO_VA_LIMIT - va))
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
gPciMmioNext = va + (uintptr_t)alignedLength;
|
||||
*outVa = va;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static bool PciIsPdo(DEVICE_OBJECT* pdo, PCI_PDO_EXTENSION** outExt) {
|
||||
if (!pdo || pdo->Type != DeviceObjectPhysical || pdo->u.Pdo.BusType != IoBusPci)
|
||||
return false;
|
||||
@@ -455,27 +489,35 @@ __declspec(dllexport) KSTATUS PciGetBar(DEVICE_OBJECT* pdo, uint8_t index, PCI_B
|
||||
__declspec(dllexport) KSTATUS PciMapBar(DEVICE_OBJECT* pdo, uint8_t index, uint64_t pageFlags, void** outVirtual, uint64_t* outLength) {
|
||||
PCI_BAR bar;
|
||||
if (!outVirtual) return STATUS_INVALID_PARAMETER;
|
||||
*outVirtual = NULL;
|
||||
KSTATUS st = PciGetBar(pdo, index, &bar);
|
||||
if (!KSUCCESS(st)) return st;
|
||||
if (bar.Type != PciBarMemory32 && bar.Type != PciBarMemory64)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
if (!bar.Length)
|
||||
return STATUS_DEVICE_ERROR;
|
||||
if (bar.Base + bar.Length < bar.Base)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
uint64_t flags = pageFlags ? pageFlags : (PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE);
|
||||
uint64_t pageBase = bar.Base & ~(uint64_t)(PAGE_SIZE - 1u);
|
||||
uint64_t pageEnd = (bar.Base + bar.Length + PAGE_SIZE - 1u) & ~(uint64_t)(PAGE_SIZE - 1u);
|
||||
uint64_t flags = pageFlags ? pageFlags : PciDefaultMmioFlags();
|
||||
flags |= PAGE_PRESENT;
|
||||
|
||||
for (uint64_t phys = pageBase; phys < pageEnd; phys += PAGE_SIZE) {
|
||||
uintptr_t virt = (uintptr_t)gHal->PhysToVirt(phys);
|
||||
st = MmMapPage(virt, phys, flags, MmMapFailIfPresent);
|
||||
if (st == STATUS_ALREADY_EXISTS)
|
||||
st = MmSetPageProtect(virt, PAGE_SIZE, flags);
|
||||
uint64_t physBase = bar.Base & ~(uint64_t)(PAGE_SIZE - 1u);
|
||||
uint64_t physOffset = bar.Base - physBase;
|
||||
uint64_t mapLength = PciAlignUp64(physOffset + bar.Length, PAGE_SIZE);
|
||||
|
||||
uintptr_t virtBase = 0;
|
||||
st = PciAllocateMmioVa(mapLength, &virtBase);
|
||||
if (!KSUCCESS(st))
|
||||
return st;
|
||||
|
||||
for (uint64_t off = 0; off < mapLength; off += PAGE_SIZE) {
|
||||
st = MmMapPage(virtBase + (uintptr_t)off, physBase + off, flags, MmMapFailIfPresent);
|
||||
if (!KSUCCESS(st))
|
||||
return st;
|
||||
}
|
||||
|
||||
*outVirtual = (void*)((uintptr_t)gHal->PhysToVirt(pageBase) + (uintptr_t)(bar.Base - pageBase));
|
||||
*outVirtual = (void*)(virtBase + (uintptr_t)physOffset);
|
||||
if (outLength) *outLength = bar.Length;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ static __inline void UsbTrace(const char* fmt, ...) { (void)fmt; }
|
||||
|
||||
|
||||
#define XHCI_CC_SUCCESS 1u
|
||||
#define XHCI_CC_SHORT_PACKET 13u
|
||||
|
||||
#define XHCI_TRB_ISP (1u << 2)
|
||||
#define XHCI_TRB_IOC (1u << 5)
|
||||
@@ -458,6 +459,7 @@ struct USB_URB {
|
||||
PHYSICAL_ADDRESS BufferPhys;
|
||||
uint32_t Length;
|
||||
uint32_t ActualLength;
|
||||
uint32_t HcdCompletionCode;
|
||||
KSTATUS Status;
|
||||
IRP* Irp;
|
||||
USB_URB_COMPLETION Complete;
|
||||
@@ -562,6 +564,11 @@ typedef struct USB_HID_EXTENSION {
|
||||
bool Removed;
|
||||
bool Keyboard;
|
||||
bool Mouse;
|
||||
bool AbsoluteMouse;
|
||||
uint16_t AbsoluteMaxX;
|
||||
uint16_t AbsoluteMaxY;
|
||||
uint16_t LastAbsoluteX;
|
||||
uint16_t LastAbsoluteY;
|
||||
uint8_t InterfaceNumber;
|
||||
uint8_t Protocol;
|
||||
uint8_t EndpointAddress;
|
||||
@@ -954,9 +961,6 @@ KSTATUS XhciStartHidInterrupts(XHCI_CONTROLLER* xhci);
|
||||
KSTATUS XhciSetHidBootProtocol(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev);
|
||||
KSTATUS XhciAllocateHidMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev);
|
||||
KSTATUS XhciConfigureHidEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev);
|
||||
const IO_PUBLISHED_USB_ENDPOINT* UsbFindEndpoint(const IO_PUBLISHED_DEVICE* pub, uint8_t endpointType, bool wantIn);
|
||||
bool UsbHidMatch(const IO_PUBLISHED_DEVICE* pub, void* context);
|
||||
KSTATUS UsbHidBind(IO_PUBLISHED_DEVICE* pub, void* context);
|
||||
KSTATUS UsbHidAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject);
|
||||
KSTATUS UsbHidDispatchPnp(DEVICE_OBJECT* device, IRP* irp);
|
||||
void XhciInitialiseTransferRing(XHCI_TRB* ring, PHYSICAL_ADDRESS ringPhys, uint32_t trbCount, uint8_t cycle);
|
||||
@@ -982,8 +986,6 @@ KSTATUS XhciAllocateMassStorageMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev);
|
||||
KSTATUS XhciConfigureMassStorageEndpoints(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev);
|
||||
uint8_t UsbFindFreeDiskIndex(void);
|
||||
KSTATUS UsbStorageRegisterDisk(USB_STORAGE_EXTENSION* storage);
|
||||
bool UsbStorageMatch(const IO_PUBLISHED_DEVICE* pub, void* context);
|
||||
KSTATUS UsbStorageBind(IO_PUBLISHED_DEVICE* pub, void* context);
|
||||
KSTATUS XhciSetConfiguration(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, uint8_t configurationValue);
|
||||
void XhciLogConfigurationTree(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, const USB_CONFIGURATION_DESCRIPTOR* config, uint16_t totalLength);
|
||||
KSTATUS XhciDiscoverAndSetConfiguration(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, const USB_DEVICE_DESCRIPTOR* devDesc);
|
||||
|
||||
@@ -135,7 +135,7 @@ static void XhciHandleLegacyHidTransferEvent(XHCI_CONTROLLER* xhci, uint64_t trb
|
||||
return;
|
||||
|
||||
dev->HidArmed = false;
|
||||
if (completionCode != XHCI_CC_SUCCESS) {
|
||||
if (completionCode != XHCI_CC_SUCCESS && completionCode != XHCI_CC_SHORT_PACKET) {
|
||||
DbgPrint("usb: HID transfer failed slot=%u ep=%u cc=%u residue=%u\n",
|
||||
slotId, endpointId, completionCode, residue);
|
||||
return;
|
||||
@@ -298,73 +298,6 @@ KSTATUS XhciConfigureHidEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) {
|
||||
}
|
||||
|
||||
|
||||
const IO_PUBLISHED_USB_ENDPOINT* UsbFindEndpoint(const IO_PUBLISHED_DEVICE* pub,
|
||||
uint8_t endpointType,
|
||||
bool wantIn) {
|
||||
if (!pub || pub->BusType != IoBusUsb) return (const IO_PUBLISHED_USB_ENDPOINT*)0;
|
||||
|
||||
for (uint8_t i = 0; i < pub->u.Usb.EndpointCount; i++) {
|
||||
const IO_PUBLISHED_USB_ENDPOINT* ep = &pub->u.Usb.Endpoints[i];
|
||||
uint8_t type = ep->Attributes & USB_ENDPOINT_ATTR_TYPE_MASK;
|
||||
bool in = (ep->Address & USB_ENDPOINT_DIR_IN) != 0;
|
||||
if (type == endpointType && in == wantIn)
|
||||
return ep;
|
||||
}
|
||||
|
||||
return (const IO_PUBLISHED_USB_ENDPOINT*)0;
|
||||
}
|
||||
|
||||
|
||||
bool UsbHidMatch(const IO_PUBLISHED_DEVICE* pub, void* context) {
|
||||
(void)context;
|
||||
if (!pub || pub->BusType != IoBusUsb)
|
||||
return false;
|
||||
if (pub->u.Usb.InterfaceClass != USB_CLASS_HID)
|
||||
return false;
|
||||
if (pub->u.Usb.InterfaceSubclass != USB_HID_SUBCLASS_BOOT)
|
||||
return false;
|
||||
if (pub->u.Usb.InterfaceProtocol != USB_HID_PROTOCOL_KEYBOARD &&
|
||||
pub->u.Usb.InterfaceProtocol != USB_HID_PROTOCOL_MOUSE)
|
||||
return false;
|
||||
|
||||
return UsbFindEndpoint(pub, USB_ENDPOINT_TYPE_INTERRUPT, true) != (const IO_PUBLISHED_USB_ENDPOINT*)0;
|
||||
}
|
||||
|
||||
|
||||
KSTATUS UsbHidBind(IO_PUBLISHED_DEVICE* pub, void* context) {
|
||||
(void)context;
|
||||
if (!pub || !pub->BusContext || !pub->DeviceContext)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
XHCI_CONTROLLER* xhci = (XHCI_CONTROLLER*)pub->BusContext;
|
||||
XHCI_DEVICE* dev = (XHCI_DEVICE*)pub->DeviceContext;
|
||||
|
||||
if (dev->HidActive || dev->HidCandidate)
|
||||
return STATUS_ALREADY_EXISTS;
|
||||
|
||||
const IO_PUBLISHED_USB_ENDPOINT* ep = UsbFindEndpoint(pub, USB_ENDPOINT_TYPE_INTERRUPT, true);
|
||||
if (!ep)
|
||||
return STATUS_NOT_FOUND;
|
||||
|
||||
dev->HidCandidate = true;
|
||||
dev->HidKeyboard = (pub->u.Usb.InterfaceProtocol == USB_HID_PROTOCOL_KEYBOARD);
|
||||
dev->HidMouse = (pub->u.Usb.InterfaceProtocol == USB_HID_PROTOCOL_MOUSE);
|
||||
dev->HidInterface = pub->u.Usb.InterfaceNumber;
|
||||
dev->HidProtocol = pub->u.Usb.InterfaceProtocol;
|
||||
dev->HidEndpointAddress = ep->Address;
|
||||
dev->HidEndpointId = XhciEndpointIdFromAddress(ep->Address);
|
||||
dev->HidInterval = ep->Interval;
|
||||
dev->HidMaxPacket = ep->MaxPacketSize;
|
||||
|
||||
KSTATUS st = XhciConfigureHidEndpoint(xhci, dev);
|
||||
if (!KSUCCESS(st)) {
|
||||
dev->HidCandidate = false;
|
||||
dev->HidKeyboard = false;
|
||||
dev->HidMouse = false;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// PDO/FDO boot HID function driver path.
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -374,6 +307,7 @@ DRIVER_OBJECT gUsbHidDriver;
|
||||
static const IO_DEVICE_ID gUsbHidIds[] = {
|
||||
{ IoBusUsb, { "USB\\CLASS_03&SUBCLASS_01&PROT_01", sizeof("USB\\CLASS_03&SUBCLASS_01&PROT_01") - 1 } },
|
||||
{ IoBusUsb, { "USB\\CLASS_03&SUBCLASS_01&PROT_02", sizeof("USB\\CLASS_03&SUBCLASS_01&PROT_02") - 1 } },
|
||||
{ IoBusUsb, { "USB\\CLASS_03&SUBCLASS_00&PROT_00", sizeof("USB\\CLASS_03&SUBCLASS_00&PROT_00") - 1 } },
|
||||
};
|
||||
|
||||
static const IO_DRIVER_ID_TABLE gUsbHidIdTable = {
|
||||
@@ -381,6 +315,26 @@ static const IO_DRIVER_ID_TABLE gUsbHidIdTable = {
|
||||
sizeof(gUsbHidIds) / sizeof(gUsbHidIds[0]),
|
||||
};
|
||||
|
||||
|
||||
static bool UsbHidIsQemuAbsoluteTabletPdo(const USB_PDO_EXTENSION* pdoExt, const USB_ENDPOINT_DESCRIPTOR* ep) {
|
||||
if (!pdoExt || !pdoExt->Device || !ep)
|
||||
return false;
|
||||
if (pdoExt->InterfaceDescriptor.bInterfaceClass != USB_CLASS_HID)
|
||||
return false;
|
||||
if (pdoExt->InterfaceDescriptor.bInterfaceSubClass != 0 ||
|
||||
pdoExt->InterfaceDescriptor.bInterfaceProtocol != 0)
|
||||
return false;
|
||||
if (pdoExt->Device->VendorId != 0x0627u || pdoExt->Device->ProductId != 0x0001u)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* QEMU's usb-kbd and usb-tablet commonly share VID:PID 0627:0001.
|
||||
* Do not classify by VID:PID alone: the boot keyboard is subclass/protocol
|
||||
* 01/01, while usb-tablet is the non-boot HID interface 00/00.
|
||||
*/
|
||||
return (ep->wMaxPacketSize & 0x07FFu) >= 6u;
|
||||
}
|
||||
|
||||
static const USB_ENDPOINT_DESCRIPTOR* UsbHidFindInterruptInPdo(const USB_PDO_EXTENSION* ext) {
|
||||
if (!ext) return (const USB_ENDPOINT_DESCRIPTOR*)0;
|
||||
|
||||
@@ -443,6 +397,24 @@ static void UsbHidProcessBootMouseReport(USB_HID_EXTENSION* ext, const uint8_t*
|
||||
ext->LastButtons = buttons;
|
||||
}
|
||||
|
||||
static void UsbHidProcessQemuTabletReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) {
|
||||
if (!ext || len < 5) return;
|
||||
|
||||
uint8_t buttons = report[0] & 0x07u;
|
||||
uint16_t x = (uint16_t)report[1] | ((uint16_t)report[2] << 8);
|
||||
uint16_t y = (uint16_t)report[3] | ((uint16_t)report[4] << 8);
|
||||
int wheel = (len >= 6) ? (int)(int8_t)report[5] : 0;
|
||||
|
||||
if (x != ext->LastAbsoluteX || y != ext->LastAbsoluteY ||
|
||||
wheel || buttons != ext->LastButtons) {
|
||||
KeInputSubmitMouseAbsoluteScaled(x, y, ext->AbsoluteMaxX, ext->AbsoluteMaxY, wheel, buttons);
|
||||
}
|
||||
|
||||
ext->LastAbsoluteX = x;
|
||||
ext->LastAbsoluteY = y;
|
||||
ext->LastButtons = buttons;
|
||||
}
|
||||
|
||||
static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext);
|
||||
|
||||
static void UsbHidInterruptComplete(USB_URB* urb, void* context) {
|
||||
@@ -460,14 +432,19 @@ static void UsbHidInterruptComplete(USB_URB* urb, void* context) {
|
||||
|
||||
if (ext->Keyboard)
|
||||
UsbHidProcessBootKeyboardReport(ext, ext->ReportBuffer, length);
|
||||
else if (ext->AbsoluteMouse)
|
||||
UsbHidProcessQemuTabletReport(ext, ext->ReportBuffer, length);
|
||||
else if (ext->Mouse)
|
||||
UsbHidProcessBootMouseReport(ext, ext->ReportBuffer, length);
|
||||
} else if (urb->Status != STATUS_CANCELLED) {
|
||||
DbgPrint("usb: HID interrupt URB failed slot=%u if=%u ep=%02x st=0x%x\n",
|
||||
DbgPrint("usb: HID interrupt URB failed slot=%u if=%u ep=%02x st=0x%x cc=%u actual=%u/%u\n",
|
||||
ext->Device ? ext->Device->SlotId : 0,
|
||||
ext->InterfaceNumber,
|
||||
ext->EndpointAddress,
|
||||
urb->Status);
|
||||
urb->Status,
|
||||
urb->HcdCompletionCode,
|
||||
urb->ActualLength,
|
||||
urb->Length);
|
||||
}
|
||||
|
||||
if (!ext->SurpriseRemoved && !ext->Removed)
|
||||
@@ -563,8 +540,14 @@ static KSTATUS UsbHidStartDevice(DEVICE_OBJECT* device, USB_HID_EXTENSION* ext)
|
||||
if (!ep)
|
||||
return STATUS_NOT_FOUND;
|
||||
|
||||
ext->Keyboard = (pdoExt->InterfaceDescriptor.bInterfaceProtocol == USB_HID_PROTOCOL_KEYBOARD);
|
||||
ext->Mouse = (pdoExt->InterfaceDescriptor.bInterfaceProtocol == USB_HID_PROTOCOL_MOUSE);
|
||||
ext->Keyboard = (pdoExt->InterfaceDescriptor.bInterfaceSubClass == USB_HID_SUBCLASS_BOOT &&
|
||||
pdoExt->InterfaceDescriptor.bInterfaceProtocol == USB_HID_PROTOCOL_KEYBOARD);
|
||||
ext->AbsoluteMouse = UsbHidIsQemuAbsoluteTabletPdo(pdoExt, ep);
|
||||
ext->Mouse = ext->AbsoluteMouse ||
|
||||
(pdoExt->InterfaceDescriptor.bInterfaceSubClass == USB_HID_SUBCLASS_BOOT &&
|
||||
pdoExt->InterfaceDescriptor.bInterfaceProtocol == USB_HID_PROTOCOL_MOUSE);
|
||||
ext->AbsoluteMaxX = 0x7FFFu;
|
||||
ext->AbsoluteMaxY = 0x7FFFu;
|
||||
ext->InterfaceNumber = pdoExt->InterfaceDescriptor.bInterfaceNumber;
|
||||
ext->Protocol = pdoExt->InterfaceDescriptor.bInterfaceProtocol;
|
||||
ext->EndpointAddress = ep->bEndpointAddress;
|
||||
@@ -572,9 +555,10 @@ static KSTATUS UsbHidStartDevice(DEVICE_OBJECT* device, USB_HID_EXTENSION* ext)
|
||||
ext->Interval = ep->bInterval;
|
||||
|
||||
uint16_t reportLength = ext->MaxPacketSize & 0x07FFu;
|
||||
if (reportLength == 0) reportLength = ext->Keyboard ? 8u : 4u;
|
||||
if (reportLength == 0) reportLength = ext->Keyboard ? 8u : (ext->AbsoluteMouse ? 6u : 4u);
|
||||
if (ext->Keyboard && reportLength < 8) reportLength = 8;
|
||||
if (ext->Mouse && reportLength < 3) reportLength = 3;
|
||||
if (ext->AbsoluteMouse && reportLength < 6) reportLength = 6;
|
||||
if (ext->Mouse && !ext->AbsoluteMouse && reportLength < 3) reportLength = 3;
|
||||
if (reportLength > XHCI_MAX_HID_REPORT) reportLength = XHCI_MAX_HID_REPORT;
|
||||
ext->ReportLength = reportLength;
|
||||
|
||||
@@ -591,15 +575,17 @@ static KSTATUS UsbHidStartDevice(DEVICE_OBJECT* device, USB_HID_EXTENSION* ext)
|
||||
if (!KSUCCESS(st))
|
||||
return st;
|
||||
|
||||
st = UsbHidSendBootProtocol(ext);
|
||||
if (!KSUCCESS(st))
|
||||
return st;
|
||||
if (!ext->AbsoluteMouse) {
|
||||
st = UsbHidSendBootProtocol(ext);
|
||||
if (!KSUCCESS(st))
|
||||
return st;
|
||||
}
|
||||
|
||||
memset(ext->LastKeys, 0, sizeof(ext->LastKeys));
|
||||
ext->LastModifiers = 0;
|
||||
ext->LastButtons = 0;
|
||||
|
||||
KeInputRegisterDevice(ext->Keyboard ? "usb-hid-keyboard" : "usb-hid-mouse", 0, &ext->InputDeviceId);
|
||||
KeInputRegisterDevice(ext->Keyboard ? "usb-hid-keyboard" : (ext->AbsoluteMouse ? "usb-hid-tablet" : "usb-hid-mouse"), 0, &ext->InputDeviceId);
|
||||
|
||||
ext->Started = true;
|
||||
device->PnpState = DevicePnpStarted;
|
||||
@@ -616,8 +602,8 @@ static KSTATUS UsbHidStartDevice(DEVICE_OBJECT* device, USB_HID_EXTENSION* ext)
|
||||
if (xhci)
|
||||
xhci->HidDeviceCount++;
|
||||
|
||||
DbgPrint("usb: HID boot %s bound slot=%u if=%u ep=%02x maxpkt=%u interval=%u input=%u urb\n",
|
||||
ext->Keyboard ? "keyboard" : "mouse",
|
||||
DbgPrint("usb: HID %s bound slot=%u if=%u ep=%02x maxpkt=%u interval=%u input=%u urb\n",
|
||||
ext->Keyboard ? "boot-keyboard" : (ext->AbsoluteMouse ? "qemu-tablet" : "boot-mouse"),
|
||||
ext->Device->SlotId,
|
||||
ext->InterfaceNumber,
|
||||
ext->EndpointAddress,
|
||||
@@ -720,24 +706,31 @@ KSTATUS UsbHidAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObje
|
||||
USB_PDO_EXTENSION* pdoExt = (USB_PDO_EXTENSION*)physicalDeviceObject->DeviceExtension;
|
||||
if (!pdoExt || pdoExt->Kind != UsbPdoInterface || !pdoExt->Device)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (pdoExt->InterfaceDescriptor.bInterfaceClass != USB_CLASS_HID ||
|
||||
pdoExt->InterfaceDescriptor.bInterfaceSubClass != USB_HID_SUBCLASS_BOOT)
|
||||
if (pdoExt->InterfaceDescriptor.bInterfaceClass != USB_CLASS_HID)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (pdoExt->InterfaceDescriptor.bInterfaceProtocol != USB_HID_PROTOCOL_KEYBOARD &&
|
||||
pdoExt->InterfaceDescriptor.bInterfaceProtocol != USB_HID_PROTOCOL_MOUSE)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (!UsbHidFindInterruptInPdo(pdoExt))
|
||||
|
||||
const USB_ENDPOINT_DESCRIPTOR* ep = UsbHidFindInterruptInPdo(pdoExt);
|
||||
if (!ep)
|
||||
return STATUS_NOT_FOUND;
|
||||
|
||||
bool bootKeyboard = pdoExt->InterfaceDescriptor.bInterfaceSubClass == USB_HID_SUBCLASS_BOOT &&
|
||||
pdoExt->InterfaceDescriptor.bInterfaceProtocol == USB_HID_PROTOCOL_KEYBOARD;
|
||||
bool bootMouse = pdoExt->InterfaceDescriptor.bInterfaceSubClass == USB_HID_SUBCLASS_BOOT &&
|
||||
pdoExt->InterfaceDescriptor.bInterfaceProtocol == USB_HID_PROTOCOL_MOUSE;
|
||||
bool qemuTablet = UsbHidIsQemuAbsoluteTabletPdo(pdoExt, ep);
|
||||
if (!bootKeyboard && !bootMouse && !qemuTablet)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
DEVICE_OBJECT* fdo = (DEVICE_OBJECT*)0;
|
||||
KSTATUS st = IoCreateDevice(driver, sizeof(USB_HID_EXTENSION), &fdo);
|
||||
if (!KSUCCESS(st))
|
||||
return st;
|
||||
|
||||
(void)IoSetDeviceName(fdo,
|
||||
pdoExt->InterfaceDescriptor.bInterfaceProtocol == USB_HID_PROTOCOL_KEYBOARD
|
||||
bootKeyboard
|
||||
? SYS_SV_LITERAL("usb-hid-keyboard")
|
||||
: SYS_SV_LITERAL("usb-hid-mouse"));
|
||||
: (qemuTablet ? SYS_SV_LITERAL("usb-hid-tablet")
|
||||
: SYS_SV_LITERAL("usb-hid-mouse")));
|
||||
|
||||
USB_HID_EXTENSION* ext = (USB_HID_EXTENSION*)fdo->DeviceExtension;
|
||||
ext->Self = fdo;
|
||||
@@ -758,10 +751,11 @@ KSTATUS UsbHidAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObje
|
||||
return STATUS_FAILURE;
|
||||
}
|
||||
|
||||
DbgPrint("usb: HID FDO attached slot=%u if=%u proto=%u\n",
|
||||
DbgPrint("usb: HID FDO attached slot=%u if=%u proto=%u kind=%s\n",
|
||||
ext->Device->SlotId,
|
||||
pdoExt->InterfaceDescriptor.bInterfaceNumber,
|
||||
pdoExt->InterfaceDescriptor.bInterfaceProtocol);
|
||||
pdoExt->InterfaceDescriptor.bInterfaceProtocol,
|
||||
qemuTablet ? "qemu-tablet" : (bootKeyboard ? "keyboard" : "mouse"));
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -764,26 +764,6 @@ KSTATUS UsbStorageDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
bool UsbStorageMatch(const IO_PUBLISHED_DEVICE* pub, void* context) {
|
||||
(void)context;
|
||||
if (!pub || pub->BusType != IoBusUsb)
|
||||
return false;
|
||||
if (pub->u.Usb.InterfaceClass != USB_CLASS_MASS_STORAGE)
|
||||
return false;
|
||||
if (pub->u.Usb.InterfaceSubclass != USB_MASS_SUBCLASS_SCSI)
|
||||
return false;
|
||||
if (pub->u.Usb.InterfaceProtocol != USB_MASS_PROTOCOL_BOT)
|
||||
return false;
|
||||
|
||||
return UsbFindEndpoint(pub, USB_ENDPOINT_TYPE_BULK, true) &&
|
||||
UsbFindEndpoint(pub, USB_ENDPOINT_TYPE_BULK, false);
|
||||
}
|
||||
|
||||
KSTATUS UsbStorageBind(IO_PUBLISHED_DEVICE* pub, void* context) {
|
||||
(void)pub;
|
||||
(void)context;
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
KSTATUS UsbStorageAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
||||
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
||||
|
||||
@@ -1667,6 +1667,7 @@ static KSTATUS XhciHcdSubmitInterruptUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev
|
||||
urb->Cancelled = false;
|
||||
urb->Status = STATUS_PENDING;
|
||||
urb->ActualLength = 0;
|
||||
urb->HcdCompletionCode = 0;
|
||||
|
||||
XhciBarrier();
|
||||
XhciWrite32(xhci->Doorbells, (uint32_t)dev->SlotId * 4u, ctx->EndpointId);
|
||||
@@ -1699,7 +1700,8 @@ void XhciHandleAsyncTransferEvent(XHCI_CONTROLLER* xhci, uint64_t trbPhys,
|
||||
KSTATUS st = STATUS_SUCCESS;
|
||||
if (urb->Cancelled) {
|
||||
st = STATUS_CANCELLED;
|
||||
} else if (completionCode != XHCI_CC_SUCCESS) {
|
||||
} else if (completionCode != XHCI_CC_SUCCESS &&
|
||||
completionCode != XHCI_CC_SHORT_PACKET) {
|
||||
st = STATUS_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
@@ -1711,6 +1713,7 @@ void XhciHandleAsyncTransferEvent(XHCI_CONTROLLER* xhci, uint64_t trbPhys,
|
||||
urb->Pending = false;
|
||||
urb->Status = st;
|
||||
urb->ActualLength = actual;
|
||||
urb->HcdCompletionCode = completionCode;
|
||||
|
||||
IRP* completeIrp = urb->Irp;
|
||||
urb->Irp = (IRP*)0;
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,215 @@
|
||||
#pragma once
|
||||
// vmwaresvga.h - VMware SVGA-II display provider internals.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <intrin.h>
|
||||
|
||||
#include <ntlite/status.h>
|
||||
#include <ntlite/ddi/hal_api.h>
|
||||
#include <ntlite/ddi/io_driver.h>
|
||||
#include <ntlite/ddi/pci.h>
|
||||
#include <ntlite/ddi/display.h>
|
||||
#include <kernel/ke_display.h>
|
||||
#include <kernel/ke_debug.h>
|
||||
#include <kernel/mm_virt.h>
|
||||
#include <kernel/display_cursor.h>
|
||||
|
||||
#define VMWSVGA_VENDOR_VMWARE 0x15ADu
|
||||
#define VMWSVGA_DEVICE_SVGA2 0x0405u
|
||||
#define VMWSVGA_DEVICE_MAGIC 0x564D5356u /* VMSV */
|
||||
|
||||
#define SVGA_ID_INVALID 0xFFFFFFFFu
|
||||
#define SVGA_ID_0 0x90000000u
|
||||
#define SVGA_ID_1 0x90000001u
|
||||
#define SVGA_ID_2 0x90000002u
|
||||
|
||||
#define SVGA_INDEX_PORT 0u
|
||||
#define SVGA_VALUE_PORT 1u
|
||||
|
||||
#define SVGA_REG_ID 0u
|
||||
#define SVGA_REG_ENABLE 1u
|
||||
#define SVGA_REG_WIDTH 2u
|
||||
#define SVGA_REG_HEIGHT 3u
|
||||
#define SVGA_REG_MAX_WIDTH 4u
|
||||
#define SVGA_REG_MAX_HEIGHT 5u
|
||||
#define SVGA_REG_DEPTH 6u
|
||||
#define SVGA_REG_BITS_PER_PIXEL 7u
|
||||
#define SVGA_REG_BYTES_PER_LINE 12u
|
||||
#define SVGA_REG_FB_START 13u
|
||||
#define SVGA_REG_FB_OFFSET 14u
|
||||
#define SVGA_REG_VRAM_SIZE 15u
|
||||
#define SVGA_REG_FB_SIZE 16u
|
||||
#define SVGA_REG_CAPABILITIES 17u
|
||||
#define SVGA_REG_MEM_START 18u
|
||||
#define SVGA_REG_MEM_SIZE 19u
|
||||
#define SVGA_REG_CONFIG_DONE 20u
|
||||
#define SVGA_REG_SYNC 21u
|
||||
#define SVGA_REG_BUSY 22u
|
||||
#define SVGA_REG_GUEST_ID 23u
|
||||
#define SVGA_REG_CURSOR_ID 24u
|
||||
#define SVGA_REG_CURSOR_X 25u
|
||||
#define SVGA_REG_CURSOR_Y 26u
|
||||
#define SVGA_REG_CURSOR_ON 27u
|
||||
#define SVGA_REG_HOST_BITS_PER_PIXEL 28u
|
||||
#define SVGA_REG_MEM_REGS 30u
|
||||
#define SVGA_REG_NUM_GUEST_DISPLAYS 34u
|
||||
#define SVGA_REG_DISPLAY_ID 35u
|
||||
#define SVGA_REG_DISPLAY_IS_PRIMARY 36u
|
||||
#define SVGA_REG_DISPLAY_POSITION_X 37u
|
||||
#define SVGA_REG_DISPLAY_POSITION_Y 38u
|
||||
#define SVGA_REG_DISPLAY_WIDTH 39u
|
||||
#define SVGA_REG_DISPLAY_HEIGHT 40u
|
||||
#define SVGA_REG_PITCHLOCK 32u
|
||||
|
||||
#define SVGA_CMD_INVALID_CMD 0u
|
||||
#define SVGA_CMD_UPDATE 1u
|
||||
#define SVGA_CMD_RECT_FILL 2u
|
||||
#define SVGA_CMD_RECT_COPY 3u
|
||||
#define SVGA_CMD_DEFINE_CURSOR 19u
|
||||
#define SVGA_CMD_DISPLAY_CURSOR 20u
|
||||
#define SVGA_CMD_DEFINE_ALPHA_CURSOR 22u
|
||||
#define SVGA_CMD_DEFINE_SCREEN 34u
|
||||
#define SVGA_CMD_DESTROY_SCREEN 35u
|
||||
#define SVGA_CMD_DEFINE_GMRFB 36u
|
||||
#define SVGA_CMD_BLIT_GMRFB_TO_SCREEN 37u
|
||||
|
||||
#define SVGA_FIFO_MIN 0u
|
||||
#define SVGA_FIFO_MAX 1u
|
||||
#define SVGA_FIFO_NEXT_CMD 2u
|
||||
#define SVGA_FIFO_STOP 3u
|
||||
#define SVGA_FIFO_CAPABILITIES 4u
|
||||
#define SVGA_FIFO_FLAGS 5u
|
||||
#define SVGA_FIFO_FENCE 6u
|
||||
#define SVGA_FIFO_3D_HWVERSION 7u
|
||||
#define SVGA_FIFO_PITCHLOCK 8u
|
||||
#define SVGA_FIFO_CURSOR_ON 9u
|
||||
#define SVGA_FIFO_CURSOR_X 10u
|
||||
#define SVGA_FIFO_CURSOR_Y 11u
|
||||
#define SVGA_FIFO_CURSOR_COUNT 12u
|
||||
#define SVGA_FIFO_CURSOR_LAST_UPDATED 13u
|
||||
#define SVGA_FIFO_RESERVED 14u
|
||||
#define SVGA_FIFO_CURSOR_SCREEN_ID 15u
|
||||
#define SVGA_FIFO_3D_CAPS 32u
|
||||
#define SVGA_FIFO_3D_CAPS_LAST (SVGA_FIFO_3D_CAPS + 255u)
|
||||
#define SVGA_FIFO_GUEST_3D_HWVERSION (SVGA_FIFO_3D_CAPS_LAST + 1u)
|
||||
#define SVGA_FIFO_FENCE_GOAL (SVGA_FIFO_3D_CAPS_LAST + 2u)
|
||||
#define SVGA_FIFO_BUSY (SVGA_FIFO_3D_CAPS_LAST + 3u)
|
||||
#define SVGA_FIFO_NUM_LEGACY_REGS 4u
|
||||
#define SVGA_FIFO_NUM_REGS_FALLBACK (SVGA_FIFO_BUSY + 3u)
|
||||
|
||||
#define SVGA_CAP_CURSOR 0x00000020u
|
||||
#define SVGA_CAP_CURSOR_BYPASS 0x00000040u
|
||||
#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080u
|
||||
#define SVGA_CAP_ALPHA_CURSOR 0x00000200u
|
||||
#define SVGA_CAP_EXTENDED_FIFO 0x00008000u
|
||||
#define SVGA_CAP_MULTIMON 0x00010000u
|
||||
#define SVGA_CAP_PITCHLOCK 0x00020000u
|
||||
#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000u
|
||||
#define SVGA_CAP_GMR 0x00100000u
|
||||
#define SVGA_CAP_GMR2 0x00400000u
|
||||
#define SVGA_CAP_SCREEN_OBJECT_2 0x00800000u
|
||||
|
||||
#define SVGA_CURSOR_ON_HIDE 0u
|
||||
#define SVGA_CURSOR_ON_SHOW 1u
|
||||
|
||||
#define SVGA_FIFO_CAP_CURSOR_BYPASS_3 0x00000010u
|
||||
#define SVGA_FIFO_CAP_SCREEN_OBJECT 0x00000080u
|
||||
#define SVGA_FIFO_CAP_SCREEN_OBJECT_2 0x00000200u
|
||||
|
||||
#define SVGA_GMR_FRAMEBUFFER 0xFFFFFFFEu
|
||||
#define SVGA_SCREEN_MUST_BE_SET 0x00000001u
|
||||
#define SVGA_SCREEN_IS_PRIMARY 0x00000002u
|
||||
#define SVGA_SCREEN_OBJECT_ID_PRIMARY 0u
|
||||
#define SVGA_GMRFB_FORMAT_32BPP_24DEPTH ((32u) | (24u << 8))
|
||||
|
||||
/*
|
||||
* The production path is legacy GFB + UPDATE. Screen objects are kept behind
|
||||
* an opt-in switch until the SO/GMRFB path is independently validated on real
|
||||
* VMware hosts.
|
||||
*/
|
||||
#ifndef VMWSVGA_ENABLE_SCREEN_OBJECTS
|
||||
#define VMWSVGA_ENABLE_SCREEN_OBJECTS 0
|
||||
#endif
|
||||
|
||||
#define VMWSVGA_MAX_WAIT_ITERS 1000000u
|
||||
#define VMWSVGA_CURSOR_W DISPLAY_DEFAULT_CURSOR_W
|
||||
#define VMWSVGA_CURSOR_H DISPLAY_DEFAULT_CURSOR_H
|
||||
|
||||
#define VMWSVGA_CAPS_MINIMAL (DISPLAY_CAP_FRAMEBUFFER | DISPLAY_CAP_SOFTWARE_CURSOR | DISPLAY_CAP_PRESENT_SYNC)
|
||||
#define VMWSVGA_CAPS_HW_CURSOR (DISPLAY_CAP_FRAMEBUFFER | DISPLAY_CAP_HARDWARE_CURSOR | DISPLAY_CAP_PRESENT_SYNC)
|
||||
|
||||
typedef struct VMWSVGA_DEVICE {
|
||||
uint32_t Magic;
|
||||
|
||||
DEVICE_OBJECT* Fdo;
|
||||
DEVICE_OBJECT* Pdo;
|
||||
DEVICE_OBJECT* LowerDevice;
|
||||
|
||||
PCI_DEVICE_INFO PciInfo;
|
||||
PCI_BAR IoBar;
|
||||
PCI_BAR FramebufferBar;
|
||||
PCI_BAR FifoBar;
|
||||
|
||||
uint16_t IoBase;
|
||||
volatile uint8_t* FramebufferMapping;
|
||||
volatile uint8_t* Framebuffer;
|
||||
volatile uint32_t* Fifo;
|
||||
uint64_t FramebufferBytes;
|
||||
uint32_t FramebufferOffset;
|
||||
uint64_t FifoBytes;
|
||||
uint32_t FifoDeviceBytes;
|
||||
|
||||
uint32_t DeviceId;
|
||||
uint32_t Capabilities;
|
||||
uint32_t Width;
|
||||
uint32_t Height;
|
||||
uint32_t Stride;
|
||||
uint32_t BytesPerLine;
|
||||
uint32_t BitsPerPixel;
|
||||
|
||||
uint32_t* Backbuffer;
|
||||
size_t BackbufferBytes;
|
||||
|
||||
uint32_t FifoRegCount;
|
||||
uint32_t FifoCaps;
|
||||
|
||||
bool UseScreenObject;
|
||||
uint32_t ScreenId;
|
||||
uint32_t ScreenSourceOffset;
|
||||
uint32_t ScreenSourceBytes;
|
||||
uint32_t ScreenBackingOffset;
|
||||
uint32_t ScreenBackingBytes;
|
||||
|
||||
bool FifoReady;
|
||||
bool HardwareCursor;
|
||||
bool AlphaCursor;
|
||||
bool CursorBypass3;
|
||||
bool CursorImageDefined;
|
||||
bool CursorVisible;
|
||||
uint32_t* CursorImageArgb;
|
||||
size_t CursorImageBytes;
|
||||
int CursorImageWidth;
|
||||
int CursorImageHeight;
|
||||
int CursorHotX;
|
||||
int CursorHotY;
|
||||
bool Started;
|
||||
bool Removed;
|
||||
bool SurpriseRemoved;
|
||||
|
||||
int CursorX;
|
||||
int CursorY;
|
||||
int CursorDrawX;
|
||||
int CursorDrawY;
|
||||
bool CursorDrawn;
|
||||
|
||||
DISPLAY_STATS Stats;
|
||||
DISPLAY_DEVICE DisplayDevice;
|
||||
} VMWSVGA_DEVICE;
|
||||
|
||||
extern const HAL_API* gVmwSvgaHal;
|
||||
|
||||
KSTATUS VmwSvgaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject);
|
||||
KSTATUS VmwSvgaDispatchPnp(DEVICE_OBJECT* device, IRP* irp);
|
||||
@@ -8,5 +8,6 @@ fat32.sys
|
||||
|
||||
[runtime]
|
||||
lwip.sys
|
||||
vmwaresvga.sys
|
||||
rtl8139.sys
|
||||
rtl816x.sys
|
||||
Reference in new issue
Block a user