replace nob with ms' build, move disk creation to build.bat, major comment cleanup, remove old and stupid tests, overhaul interrupt management with per-CPU vector allocation, affinity migration and safe teardown, add proper IOAPIC routing and PCI MSI/MSI-X/INTx support, migrate drivers to the new interrupt API, integrate ACPICA with a proper OS services layer, move ACPI firmware events, power button handling and S5 shutdown into acpi.sys, add parallel driver startup and atomic publication, replace PnP arrays with dynamic lists, redesign service startup again to be asynchronous, add delayed startup mode for services, allow omitting keys in services.ini, fix acpi ec deferred work handling, fix kernel threads having garbage exit code.
This commit is contained in:
1 parent
d36f19509c
commit
36eef8f58d
696 files changed
+147281
-7530
No files matched your search
@@ -0,0 +1 @@
|
||||
!include $(BASEDIR)\makefile.def
|
||||
@@ -4,9 +4,6 @@
|
||||
#include "rtl816x.h"
|
||||
|
||||
static DRIVER_OBJECT gRtl816xDriver;
|
||||
static RTL816X_DEVICE* gRtl816xDevices[RTL816X_MAX_DEVICES];
|
||||
static uint32_t gRtl816xDeviceCount;
|
||||
static SPINLOCK gRtl816xRegistryLock = SPINLOCK_INIT;
|
||||
|
||||
static const IO_DEVICE_ID gRtl816xIds[] = {
|
||||
{ IoBusPci, { "PCI\\VEN_10EC&DEV_8168", sizeof("PCI\\VEN_10EC&DEV_8168") - 1 } },
|
||||
@@ -18,53 +15,45 @@ static const IO_DRIVER_ID_TABLE gRtl816xIdTable = {
|
||||
sizeof(gRtl816xIds) / sizeof(gRtl816xIds[0]),
|
||||
};
|
||||
|
||||
// Implements the rtl Memory Barrier operation.
|
||||
static __forceinline void RtlMemoryBarrier(void) {
|
||||
_ReadWriteBarrier();
|
||||
_mm_mfence();
|
||||
_ReadWriteBarrier();
|
||||
}
|
||||
|
||||
// Implements the rtl Read8 operation.
|
||||
static uint8_t RtlRead8(RTL816X_DEVICE* r, uint32_t reg) {
|
||||
if (r->UseMmio)
|
||||
return *(volatile uint8_t*)(r->Mmio + reg);
|
||||
return __inbyte((unsigned short)(r->IoBase + reg));
|
||||
}
|
||||
|
||||
// Implements the rtl Read16 operation.
|
||||
static uint16_t RtlRead16(RTL816X_DEVICE* r, uint32_t reg) {
|
||||
if (r->UseMmio)
|
||||
return *(volatile uint16_t*)(r->Mmio + reg);
|
||||
return __inword((unsigned short)(r->IoBase + reg));
|
||||
}
|
||||
|
||||
// Implements the rtl Read32 operation.
|
||||
static uint32_t RtlRead32(RTL816X_DEVICE* r, uint32_t reg) {
|
||||
if (r->UseMmio)
|
||||
return *(volatile uint32_t*)(r->Mmio + reg);
|
||||
return __indword((unsigned short)(r->IoBase + reg));
|
||||
}
|
||||
|
||||
// Implements the rtl Write8 operation.
|
||||
static void RtlWrite8(RTL816X_DEVICE* r, uint32_t reg, uint8_t value) {
|
||||
if (r->UseMmio) *(volatile uint8_t*)(r->Mmio + reg) = value;
|
||||
else __outbyte((unsigned short)(r->IoBase + reg), value);
|
||||
}
|
||||
|
||||
// Implements the rtl Write16 operation.
|
||||
static void RtlWrite16(RTL816X_DEVICE* r, uint32_t reg, uint16_t value) {
|
||||
if (r->UseMmio) *(volatile uint16_t*)(r->Mmio + reg) = value;
|
||||
else __outword((unsigned short)(r->IoBase + reg), value);
|
||||
}
|
||||
|
||||
// Implements the rtl Write32 operation.
|
||||
static void RtlWrite32(RTL816X_DEVICE* r, uint32_t reg, uint32_t value) {
|
||||
if (r->UseMmio) *(volatile uint32_t*)(r->Mmio + reg) = value;
|
||||
else __outdword((unsigned short)(r->IoBase + reg), value);
|
||||
}
|
||||
|
||||
// Implements the rtl Reset operation.
|
||||
static KSTATUS RtlReset(RTL816X_DEVICE* r) {
|
||||
RtlWrite8(r, RTL_REG_CHIP_CMD, RTL_CMD_RESET);
|
||||
for (uint32_t i = 0; i < 1000; i++) {
|
||||
@@ -75,7 +64,6 @@ static KSTATUS RtlReset(RTL816X_DEVICE* r) {
|
||||
return NTLSTATUS_TIMEOUT;
|
||||
}
|
||||
|
||||
// Implements the rtl Read Mac operation.
|
||||
static void RtlReadMac(RTL816X_DEVICE* r) {
|
||||
for (uint32_t i = 0; i < 6; i++)
|
||||
r->NetDevice.HardwareAddress[i] = RtlRead8(r, RTL_REG_MAC0 + i);
|
||||
@@ -179,7 +167,6 @@ fail:
|
||||
return status;
|
||||
}
|
||||
|
||||
// Implements the rtl Init Descriptors operation.
|
||||
static void RtlInitDescriptors(RTL816X_DEVICE* r) {
|
||||
for (uint32_t i = 0; i < RTL_RX_COUNT; i++) {
|
||||
uint64_t address = r->RxBuffersDeviceAddress + (uint64_t)i * RTL_BUF_SIZE;
|
||||
@@ -202,7 +189,6 @@ static void RtlInitDescriptors(RTL816X_DEVICE* r) {
|
||||
RtlMemoryBarrier();
|
||||
}
|
||||
|
||||
// Implements the rtl Program Hardware operation.
|
||||
static void RtlProgramHardware(RTL816X_DEVICE* r) {
|
||||
RtlWrite8(r, RTL_REG_CFG9346, 0xC0);
|
||||
|
||||
@@ -232,7 +218,6 @@ static void RtlProgramHardware(RTL816X_DEVICE* r) {
|
||||
RtlWrite16(r, RTL_REG_INTR_MASK, RTL_INTR_ENABLES);
|
||||
}
|
||||
|
||||
// Implements the rtl Handle Rx operation.
|
||||
static void RtlHandleRx(RTL816X_DEVICE* r) {
|
||||
for (uint32_t budget = 0; budget < RTL_RX_COUNT; budget++) {
|
||||
RTL_DESC* d = &r->RxRing[r->RxIndex];
|
||||
@@ -270,7 +255,6 @@ static void RtlHandleRx(RTL816X_DEVICE* r) {
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the rtl Dpc Routine operation.
|
||||
static void RtlDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2) {
|
||||
(void)dpc;
|
||||
(void)systemArgument1;
|
||||
@@ -295,74 +279,19 @@ static void RtlDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void*
|
||||
DbgPrint("RTL816X: interrupt status error bits=0x%04x\n", status);
|
||||
}
|
||||
|
||||
// Implements the rtl Register Device operation.
|
||||
static KSTATUS RtlRegisterDevice(RTL816X_DEVICE* r) {
|
||||
if (!r) return NTLSTATUS_INVALID_PARAMETER;
|
||||
static void RtlIsr(void* context) {
|
||||
RTL816X_DEVICE* r = (RTL816X_DEVICE*)context;
|
||||
if (!r || !r->Started || r->Removed || r->SurpriseRemoved) return;
|
||||
uint16_t status = RtlRead16(r, RTL_REG_INTR_STAT);
|
||||
status &= RTL_INTR_ENABLES;
|
||||
if (!status || status == 0xFFFFu)
|
||||
return;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gRtl816xRegistryLock);
|
||||
for (uint32_t i = 0; i < gRtl816xDeviceCount; i++) {
|
||||
if (gRtl816xDevices[i] == r) {
|
||||
KeReleaseSpinlock(&gRtl816xRegistryLock, flags);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (gRtl816xDeviceCount >= RTL816X_MAX_DEVICES) {
|
||||
KeReleaseSpinlock(&gRtl816xRegistryLock, flags);
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
gRtl816xDevices[gRtl816xDeviceCount++] = r;
|
||||
KeReleaseSpinlock(&gRtl816xRegistryLock, flags);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
RtlWrite16(r, RTL_REG_INTR_STAT, status);
|
||||
r->PendingIsr |= status;
|
||||
KeInsertQueueDpc(&r->Dpc, (void*)0, (void*)0);
|
||||
}
|
||||
|
||||
// Implements the rtl Unregister Device operation.
|
||||
static void RtlUnregisterDevice(RTL816X_DEVICE* r) {
|
||||
if (!r) return;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gRtl816xRegistryLock);
|
||||
for (uint32_t i = 0; i < gRtl816xDeviceCount; i++) {
|
||||
if (gRtl816xDevices[i] == r) {
|
||||
gRtl816xDevices[i] = gRtl816xDevices[gRtl816xDeviceCount - 1u];
|
||||
gRtl816xDevices[gRtl816xDeviceCount - 1u] = (RTL816X_DEVICE*)0;
|
||||
gRtl816xDeviceCount--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
KeReleaseSpinlock(&gRtl816xRegistryLock, flags);
|
||||
}
|
||||
|
||||
// Implements the rtl Isr operation.
|
||||
static void RtlIsr(void) {
|
||||
RTL816X_DEVICE* snapshot[RTL816X_MAX_DEVICES];
|
||||
uint32_t count = 0;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gRtl816xRegistryLock);
|
||||
count = gRtl816xDeviceCount;
|
||||
if (count > RTL816X_MAX_DEVICES)
|
||||
count = RTL816X_MAX_DEVICES;
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
snapshot[i] = gRtl816xDevices[i];
|
||||
KeReleaseSpinlock(&gRtl816xRegistryLock, flags);
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
RTL816X_DEVICE* r = snapshot[i];
|
||||
if (!r || !r->Started || r->Removed || r->SurpriseRemoved)
|
||||
continue;
|
||||
|
||||
uint16_t status = RtlRead16(r, RTL_REG_INTR_STAT);
|
||||
status &= RTL_INTR_ENABLES;
|
||||
if (!status || status == 0xFFFFu)
|
||||
continue;
|
||||
|
||||
RtlWrite16(r, RTL_REG_INTR_STAT, status);
|
||||
r->PendingIsr |= status;
|
||||
KeInsertQueueDpc(&r->Dpc, (void*)0, (void*)0);
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the rtl Send Frame operation.
|
||||
static KSTATUS RtlSendFrame(NET_DEVICE* device, const void* frame, size_t length) {
|
||||
if (!device || !frame)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -402,7 +331,6 @@ static KSTATUS RtlSendFrame(NET_DEVICE* device, const void* frame, size_t length
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the rtl Select Register Bar operation.
|
||||
static KSTATUS RtlSelectRegisterBar(RTL816X_DEVICE* r) {
|
||||
if (!r || !r->Pdo)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -468,42 +396,15 @@ static KSTATUS RtlSelectRegisterBar(RTL816X_DEVICE* r) {
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Configures a dedicated MSI vector and falls back to a routed INTx line.
|
||||
// Connects a PCI message interrupt or a routed INTx source.
|
||||
static KSTATUS RtlConfigureInterrupt(RTL816X_DEVICE* r) {
|
||||
if (!r || !r->Pdo)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
r->Irq = 0xFFu;
|
||||
r->UsingMsi = false;
|
||||
|
||||
KSTATUS msiStatus = PciEnableMsiAuto(r->Pdo, &r->Irq);
|
||||
if (KSUCCESS(msiStatus)) {
|
||||
r->UsingMsi = true;
|
||||
DbgPrint("RTL816X: using MSI IRQ slot %u\n", r->Irq);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DbgPrint("RTL816X: MSI setup failed status=0x%x; attempting explicit INTx fallback\n",
|
||||
msiStatus);
|
||||
|
||||
KSTATUS intxStatus = PciGetInterrupt(r->Pdo, &r->Irq);
|
||||
if (!KSUCCESS(intxStatus))
|
||||
return intxStatus;
|
||||
if (r->Irq == 0xFFu || r->Irq >= 24u)
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
intxStatus = PciEnableDevice(r->Pdo,
|
||||
PCI_ENABLE_BUSMASTER |
|
||||
PCI_ENABLE_INTX |
|
||||
(r->UseMmio ? PCI_ENABLE_MEMORY : PCI_ENABLE_IO));
|
||||
if (!KSUCCESS(intxStatus))
|
||||
return intxStatus;
|
||||
|
||||
DbgPrint("RTL816X: using legacy INTx IRQ %u\n", r->Irq);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
r->InterruptRequest.Routine = RtlIsr;
|
||||
r->InterruptRequest.Context = r;
|
||||
r->InterruptRequest.Affinity = 0;
|
||||
r->InterruptRequest.Interrupt = (KE_INTERRUPT*)0;
|
||||
return PciConnectInterrupts(r->Pdo, &r->InterruptRequest, 1u, &r->UsingMsi);
|
||||
}
|
||||
|
||||
// Implements the rtl Start Device operation.
|
||||
static KSTATUS RtlStartDevice(RTL816X_DEVICE* r) {
|
||||
if (!r || r->Magic != RTL816X_DEVICE_MAGIC || !r->Pdo || !r->Fdo)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -547,18 +448,7 @@ static KSTATUS RtlStartDevice(RTL816X_DEVICE* r) {
|
||||
return st;
|
||||
}
|
||||
|
||||
st = RtlConfigureInterrupt(r);
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("RTL816X: no usable MSI or INTx interrupt status=0x%x\n", st);
|
||||
return st;
|
||||
}
|
||||
|
||||
RtlReadMac(r);
|
||||
DbgPrint("RTL816X: MAC %02x:%02x:%02x:%02x:%02x:%02x irq=%u mode=%s\n",
|
||||
r->NetDevice.HardwareAddress[0], r->NetDevice.HardwareAddress[1],
|
||||
r->NetDevice.HardwareAddress[2], r->NetDevice.HardwareAddress[3],
|
||||
r->NetDevice.HardwareAddress[4], r->NetDevice.HardwareAddress[5],
|
||||
r->Irq, r->UsingMsi ? "MSI" : "INTx");
|
||||
|
||||
st = RtlAllocateDma(r);
|
||||
if (!KSUCCESS(st))
|
||||
@@ -571,13 +461,21 @@ static KSTATUS RtlStartDevice(RTL816X_DEVICE* r) {
|
||||
r->NetDevice.DriverContext = r;
|
||||
r->NetDevice.SendFrame = RtlSendFrame;
|
||||
|
||||
st = RtlRegisterDevice(r);
|
||||
st = RtlConfigureInterrupt(r);
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("RTL816X: no usable MSI or INTx interrupt status=0x%x\n", st);
|
||||
RtlReleaseDma(r);
|
||||
return st;
|
||||
}
|
||||
|
||||
KeIrqRegister(r->Irq, RtlIsr);
|
||||
KE_INTERRUPT_INFO route;
|
||||
if (KSUCCESS(KeInterruptQuery(r->InterruptRequest.Interrupt, &route)))
|
||||
DbgPrint("RTL816X: MAC %02x:%02x:%02x:%02x:%02x:%02x cpu=%u vector=0x%02x mode=%s\n",
|
||||
r->NetDevice.HardwareAddress[0], r->NetDevice.HardwareAddress[1],
|
||||
r->NetDevice.HardwareAddress[2], r->NetDevice.HardwareAddress[3],
|
||||
r->NetDevice.HardwareAddress[4], r->NetDevice.HardwareAddress[5],
|
||||
route.CpuIndex, route.Vector, r->UsingMsi ? "MSI/MSI-X" : "INTx");
|
||||
|
||||
r->Started = true;
|
||||
RtlProgramHardware(r);
|
||||
r->Fdo->PnpState = DevicePnpStarted;
|
||||
@@ -585,13 +483,14 @@ static KSTATUS RtlStartDevice(RTL816X_DEVICE* r) {
|
||||
st = NetRegisterDevice(&r->NetDevice);
|
||||
if (!KSUCCESS(st)) {
|
||||
RtlStopDma(r);
|
||||
RtlUnregisterDevice(r);
|
||||
if (r->InterruptRequest.Interrupt)
|
||||
PciDisconnectInterrupts(r->Pdo, &r->InterruptRequest, 1u);
|
||||
RtlReleaseDma(r);
|
||||
return st;
|
||||
}
|
||||
|
||||
DbgPrint("RTL816X: initialized; RX/TX enabled on %s IRQ %u\n",
|
||||
r->UsingMsi ? "MSI" : "INTx", r->Irq);
|
||||
DbgPrint("RTL816X: initialized; RX/TX enabled via %s\n",
|
||||
r->UsingMsi ? "MSI/MSI-X" : "INTx");
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -626,7 +525,8 @@ KSTATUS Rtl816xDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
||||
r->Removed = true;
|
||||
device->PnpState = DevicePnpDeleted;
|
||||
RtlStopDma(r);
|
||||
RtlUnregisterDevice(r);
|
||||
if (r->InterruptRequest.Interrupt)
|
||||
PciDisconnectInterrupts(r->Pdo, &r->InterruptRequest, 1u);
|
||||
RtlReleaseDma(r);
|
||||
IoDetachDevice(device);
|
||||
IoDeleteDevice(device);
|
||||
@@ -637,7 +537,6 @@ KSTATUS Rtl816xDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the add Device operation.
|
||||
KSTATUS Rtl816xAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
||||
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -653,7 +552,7 @@ KSTATUS Rtl816xAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObj
|
||||
r->Magic = RTL816X_DEVICE_MAGIC;
|
||||
r->Fdo = fdo;
|
||||
r->Pdo = physicalDeviceObject;
|
||||
r->Irq = 0xFFu;
|
||||
r->PciInfo.InterruptLine = 0xFFu;
|
||||
r->TxLock = (SPINLOCK)SPINLOCK_INIT;
|
||||
|
||||
r->LowerDevice = IoAttachDeviceToDeviceStack(fdo, physicalDeviceObject);
|
||||
@@ -671,8 +570,6 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
||||
|
||||
DbgPrint("RTL816X: driver loading...\n");
|
||||
|
||||
gRtl816xDeviceCount = 0;
|
||||
|
||||
memset(&gRtl816xDriver, 0, sizeof(gRtl816xDriver));
|
||||
IoInitializeDriverObject(&gRtl816xDriver, SYS_SV_LITERAL("rtl816x"));
|
||||
gRtl816xDriver.IdTable = &gRtl816xIdTable;
|
||||
|
||||
@@ -116,7 +116,7 @@ typedef struct RTL816X_DEVICE {
|
||||
PCI_DEVICE_INFO PciInfo;
|
||||
PCI_BAR RegisterBar;
|
||||
uint64_t RegisterBytes;
|
||||
uint8_t Irq;
|
||||
PCI_INTERRUPT_REQUEST InterruptRequest;
|
||||
bool UsingMsi;
|
||||
|
||||
bool Started;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
TARGETNAME=rtl816x
|
||||
TARGETPATH=obj
|
||||
TARGETTYPE=DRIVER
|
||||
FLAVOR=DRIVER
|
||||
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\pci.lib"
|
||||
EXTRA_LFLAGS=/NOENTRY
|
||||
SOURCES=@/code/drivers/net/rtl816x/rtl816x.c
|
||||
Reference in new issue
Block a user