add system time, clean up pci into pci.sys, clean up syscall names, fix USERAPC1 typo
This commit is contained in:
1 parent
c1a291c4c9
commit
e41bf6e2c0
64 files changed
+4514
-2220
No files matched your search
@@ -2,8 +2,19 @@
|
||||
#include "rtl8139.h"
|
||||
|
||||
const HAL_API* gHal;
|
||||
RTL8139_DEVICE gDevice;
|
||||
bool gDevicePresent = false;
|
||||
static DRIVER_OBJECT gRtl8139Driver;
|
||||
static RTL8139_DEVICE* gRtl8139Devices[RTL8139_MAX_DEVICES];
|
||||
static uint32_t gRtl8139DeviceCount;
|
||||
static SPINLOCK gRtl8139RegistryLock = SPINLOCK_INIT;
|
||||
|
||||
static const IO_DEVICE_ID gRtl8139Ids[] = {
|
||||
{ IoBusPci, { "PCI\\VEN_10EC&DEV_8139", sizeof("PCI\\VEN_10EC&DEV_8139") - 1 } },
|
||||
};
|
||||
|
||||
static const IO_DRIVER_ID_TABLE gRtl8139IdTable = {
|
||||
gRtl8139Ids,
|
||||
sizeof(gRtl8139Ids) / sizeof(gRtl8139Ids[0]),
|
||||
};
|
||||
|
||||
static __forceinline void Rtl8139MemoryBarrier(void) {
|
||||
_ReadWriteBarrier();
|
||||
@@ -201,19 +212,68 @@ static void Rtl8139DpcRoutine(KDPC* dpc, void* context, void* systemArgument1, v
|
||||
DbgPrint("RTL8139: interrupt error bits=0x%04x\n", status);
|
||||
}
|
||||
|
||||
static KSTATUS Rtl8139RegisterDevice(RTL8139_DEVICE* r) {
|
||||
if (!r) return STATUS_INVALID_PARAMETER;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gRtl8139RegistryLock);
|
||||
for (uint32_t i = 0; i < gRtl8139DeviceCount; i++) {
|
||||
if (gRtl8139Devices[i] == r) {
|
||||
KeReleaseSpinlock(&gRtl8139RegistryLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (gRtl8139DeviceCount >= RTL8139_MAX_DEVICES) {
|
||||
KeReleaseSpinlock(&gRtl8139RegistryLock, flags);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
gRtl8139Devices[gRtl8139DeviceCount++] = r;
|
||||
KeReleaseSpinlock(&gRtl8139RegistryLock, flags);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void Rtl8139UnregisterDevice(RTL8139_DEVICE* r) {
|
||||
if (!r) return;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gRtl8139RegistryLock);
|
||||
for (uint32_t i = 0; i < gRtl8139DeviceCount; i++) {
|
||||
if (gRtl8139Devices[i] == r) {
|
||||
gRtl8139Devices[i] = gRtl8139Devices[gRtl8139DeviceCount - 1u];
|
||||
gRtl8139Devices[gRtl8139DeviceCount - 1u] = (RTL8139_DEVICE*)0;
|
||||
gRtl8139DeviceCount--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
KeReleaseSpinlock(&gRtl8139RegistryLock, flags);
|
||||
}
|
||||
|
||||
static void Rtl8139Isr(void) {
|
||||
if (!gDevicePresent)
|
||||
return;
|
||||
RTL8139_DEVICE* snapshot[RTL8139_MAX_DEVICES];
|
||||
uint32_t count = 0;
|
||||
|
||||
RTL8139_DEVICE* r = &gDevice;
|
||||
uint16_t status = Rtl8139Read16(r, RTL8139_REG_ISR);
|
||||
status &= RTL8139_INTR_ENABLES;
|
||||
if (!status || status == 0xFFFFu)
|
||||
return;
|
||||
uintptr_t flags = KeAcquireSpinlock(&gRtl8139RegistryLock);
|
||||
count = gRtl8139DeviceCount;
|
||||
if (count > RTL8139_MAX_DEVICES)
|
||||
count = RTL8139_MAX_DEVICES;
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
snapshot[i] = gRtl8139Devices[i];
|
||||
KeReleaseSpinlock(&gRtl8139RegistryLock, flags);
|
||||
|
||||
Rtl8139Write16(r, RTL8139_REG_ISR, status);
|
||||
r->PendingIsr |= status;
|
||||
KeInsertQueueDpc(&r->Dpc, (void*)0, (void*)0);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
RTL8139_DEVICE* r = snapshot[i];
|
||||
if (!r || !r->Started || r->Removed || r->SurpriseRemoved)
|
||||
continue;
|
||||
|
||||
uint16_t status = Rtl8139Read16(r, RTL8139_REG_ISR);
|
||||
status &= RTL8139_INTR_ENABLES;
|
||||
if (!status || status == 0xFFFFu)
|
||||
continue;
|
||||
|
||||
Rtl8139Write16(r, RTL8139_REG_ISR, status);
|
||||
r->PendingIsr |= status;
|
||||
KeInsertQueueDpc(&r->Dpc, (void*)0, (void*)0);
|
||||
}
|
||||
}
|
||||
|
||||
static KSTATUS Rtl8139SendFrame(NET_DEVICE* device, const void* frame, size_t length) {
|
||||
@@ -252,76 +312,242 @@ static KSTATUS Rtl8139SendFrame(NET_DEVICE* device, const void* frame, size_t le
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static KSTATUS Rtl8139Initialize(const HAL_API* hal) {
|
||||
gHal = hal;
|
||||
memset(&gDevice, 0, sizeof(gDevice));
|
||||
gDevice.TxLock = (SPINLOCK)SPINLOCK_INIT;
|
||||
static KSTATUS Rtl8139SelectRegisterBar(RTL8139_DEVICE* r) {
|
||||
if (!r || !r->Pdo)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
if (!gHal->Pci.FindDevice(RTL8139_VENDOR_REALTEK, RTL8139_DEVICE_ID,
|
||||
&gDevice.Bus, &gDevice.Dev, &gDevice.Fn)) {
|
||||
DbgPrint("RTL8139: no PCI device 10ec:8139 found; skipping\n");
|
||||
PCI_BAR best;
|
||||
PCI_BAR fallback;
|
||||
memset(&best, 0, sizeof(best));
|
||||
memset(&fallback, 0, sizeof(fallback));
|
||||
best.Type = PciBarUnused;
|
||||
fallback.Type = PciBarUnused;
|
||||
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
PCI_BAR bar;
|
||||
KSTATUS st = PciGetBar(r->Pdo, i, &bar);
|
||||
if (!KSUCCESS(st))
|
||||
continue;
|
||||
|
||||
if (bar.Type == PciBarMemory32 || bar.Type == PciBarMemory64) {
|
||||
best = bar;
|
||||
break;
|
||||
}
|
||||
if (bar.Type == PciBarIo && fallback.Type == PciBarUnused)
|
||||
fallback = bar;
|
||||
}
|
||||
|
||||
if (best.Type == PciBarUnused)
|
||||
best = fallback;
|
||||
|
||||
if (best.Type == PciBarMemory32 || best.Type == PciBarMemory64) {
|
||||
KSTATUS st = PciMapBar(r->Pdo,
|
||||
best.Index,
|
||||
PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE,
|
||||
(void**)&r->Mmio,
|
||||
&r->RegisterBytes);
|
||||
if (!KSUCCESS(st))
|
||||
return st;
|
||||
|
||||
r->RegisterBar = best;
|
||||
r->UseMmio = true;
|
||||
DbgPrint("RTL8139: BAR%u MMIO base=0x%016llX len=0x%llx virt=0x%016llX\n",
|
||||
best.Index,
|
||||
(unsigned long long)best.Base,
|
||||
(unsigned long long)r->RegisterBytes,
|
||||
r->Mmio);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DbgPrint("RTL8139: found Realtek PCI device 10ec:8139 at %u:%u.%u\n",
|
||||
gDevice.Bus, gDevice.Dev, gDevice.Fn);
|
||||
if (best.Type == PciBarIo) {
|
||||
if (best.Base > 0xFFFFu)
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
|
||||
KSTATUS st = Rtl8139SelectRegisterBar(&gDevice);
|
||||
r->RegisterBar = best;
|
||||
r->RegisterBytes = best.Length;
|
||||
r->IoBase = (uint16_t)best.Base;
|
||||
r->UseMmio = false;
|
||||
DbgPrint("RTL8139: BAR%u I/O base=0x%04x len=0x%llx\n",
|
||||
best.Index,
|
||||
r->IoBase,
|
||||
(unsigned long long)r->RegisterBytes);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
static KSTATUS Rtl8139StartDevice(RTL8139_DEVICE* r) {
|
||||
if (!r || r->Magic != RTL8139_DEVICE_MAGIC || !r->Pdo || !r->Fdo)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (r->Started)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
KSTATUS st = PciGetDeviceInfo(r->Pdo, &r->PciInfo);
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("RTL8139: PciGetDeviceInfo failed: 0x%x\n", st);
|
||||
return st;
|
||||
}
|
||||
|
||||
DbgPrint("RTL8139: controller at PCI %02x:%02x.%x vendor=%04x device=%04x\n",
|
||||
r->PciInfo.Address.Bus,
|
||||
r->PciInfo.Address.Device,
|
||||
r->PciInfo.Address.Function,
|
||||
r->PciInfo.VendorId,
|
||||
r->PciInfo.DeviceId);
|
||||
|
||||
st = Rtl8139SelectRegisterBar(r);
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("RTL8139: no usable register BAR (0x%x)\n", st);
|
||||
return st;
|
||||
}
|
||||
|
||||
Rtl8139EnablePci(&gDevice);
|
||||
|
||||
gDevice.Irq = hal->Pci.GetIrqLine(gDevice.Bus, gDevice.Dev, gDevice.Fn);
|
||||
if (gDevice.Irq == 0xFFu) {
|
||||
DbgPrint("RTL8139: no legacy PCI IRQ line wired\n");
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
st = PciEnableDevice(r->Pdo,
|
||||
PCI_ENABLE_BUSMASTER |
|
||||
PCI_ENABLE_INTX |
|
||||
(r->UseMmio ? PCI_ENABLE_MEMORY : PCI_ENABLE_IO));
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("RTL8139: PciEnableDevice failed: 0x%x\n", st);
|
||||
return st;
|
||||
}
|
||||
|
||||
// Wake, reset, then read the station address.
|
||||
Rtl8139Write8(&gDevice, RTL8139_REG_CONFIG1, 0x00);
|
||||
st = Rtl8139Reset(&gDevice);
|
||||
st = PciGetInterrupt(r->Pdo, &r->Irq);
|
||||
if (!KSUCCESS(st) || r->Irq == 0xFFu) {
|
||||
DbgPrint("RTL8139: no legacy PCI IRQ line wired\n");
|
||||
return KSUCCESS(st) ? STATUS_NOT_SUPPORTED : st;
|
||||
}
|
||||
|
||||
Rtl8139Write8(r, RTL8139_REG_CONFIG1, 0x00);
|
||||
st = Rtl8139Reset(r);
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("RTL8139: reset timed out\n");
|
||||
return st;
|
||||
}
|
||||
|
||||
Rtl8139ReadMac(&gDevice);
|
||||
Rtl8139ReadMac(r);
|
||||
DbgPrint("RTL8139: MAC %02x:%02x:%02x:%02x:%02x:%02x irq=%u\n",
|
||||
gDevice.NetDevice.HardwareAddress[0], gDevice.NetDevice.HardwareAddress[1],
|
||||
gDevice.NetDevice.HardwareAddress[2], gDevice.NetDevice.HardwareAddress[3],
|
||||
gDevice.NetDevice.HardwareAddress[4], gDevice.NetDevice.HardwareAddress[5],
|
||||
gDevice.Irq);
|
||||
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);
|
||||
|
||||
st = Rtl8139AllocateDma(&gDevice);
|
||||
st = Rtl8139AllocateDma(r);
|
||||
if (!KSUCCESS(st))
|
||||
return st;
|
||||
|
||||
KeInitializeDpc(&gDevice.Dpc, Rtl8139DpcRoutine, &gDevice);
|
||||
KeInitializeDpc(&r->Dpc, Rtl8139DpcRoutine, r);
|
||||
|
||||
gDevice.NetDevice.Mtu = NET_MTU_ETHERNET;
|
||||
gDevice.NetDevice.DriverContext = &gDevice;
|
||||
gDevice.NetDevice.SendFrame = Rtl8139SendFrame;
|
||||
r->NetDevice.Mtu = NET_MTU_ETHERNET;
|
||||
r->NetDevice.DriverContext = r;
|
||||
r->NetDevice.SendFrame = Rtl8139SendFrame;
|
||||
|
||||
Rtl8139ProgramHardware(&gDevice);
|
||||
|
||||
gDevicePresent = true;
|
||||
KeIrqRegister(gDevice.Irq, Rtl8139Isr);
|
||||
|
||||
st = NetRegisterDevice(&gDevice.NetDevice);
|
||||
st = Rtl8139RegisterDevice(r);
|
||||
if (!KSUCCESS(st))
|
||||
return st;
|
||||
|
||||
DbgPrint("RTL8139: initialized; RX/TX enabled on IRQ %u\n", gDevice.Irq);
|
||||
KeIrqRegister(r->Irq, Rtl8139Isr);
|
||||
r->Started = true;
|
||||
Rtl8139ProgramHardware(r);
|
||||
r->Fdo->PnpState = DevicePnpStarted;
|
||||
|
||||
st = NetRegisterDevice(&r->NetDevice);
|
||||
if (!KSUCCESS(st)) {
|
||||
Rtl8139Write16(r, RTL8139_REG_IMR, 0);
|
||||
r->Started = false;
|
||||
Rtl8139UnregisterDevice(r);
|
||||
return st;
|
||||
}
|
||||
|
||||
DbgPrint("RTL8139: initialized; RX/TX enabled on IRQ %u\n", r->Irq);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KSTATUS Rtl8139DispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
||||
if (!device || !irp || !device->DeviceExtension)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
RTL8139_DEVICE* r = (RTL8139_DEVICE*)device->DeviceExtension;
|
||||
if (r->Magic != RTL8139_DEVICE_MAGIC)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
IO_STACK_LOCATION* ios = IoGetCurrentIrpStackLocation(irp);
|
||||
if (!ios || ios->MajorFunction != IRP_MJ_PNP)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
switch ((IO_PNP_MINOR_FUNCTION)ios->MinorFunction) {
|
||||
case IRP_MN_START_DEVICE:
|
||||
return Rtl8139StartDevice(r);
|
||||
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
case IRP_MN_SURPRISE_REMOVAL:
|
||||
r->SurpriseRemoved = true;
|
||||
device->PnpState = DevicePnpSurpriseRemoved;
|
||||
if (r->Started)
|
||||
Rtl8139Write16(r, RTL8139_REG_IMR, 0);
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
r->Removed = true;
|
||||
device->PnpState = DevicePnpDeleted;
|
||||
if (r->Started)
|
||||
Rtl8139Write16(r, RTL8139_REG_IMR, 0);
|
||||
Rtl8139UnregisterDevice(r);
|
||||
IoDetachDevice(device);
|
||||
IoDeleteDevice(device);
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
default:
|
||||
return IoForwardIrpToLower(device, irp);
|
||||
}
|
||||
}
|
||||
|
||||
KSTATUS Rtl8139AddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
||||
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
DEVICE_OBJECT* fdo = (DEVICE_OBJECT*)0;
|
||||
KSTATUS st = IoCreateDevice(driver, sizeof(RTL8139_DEVICE), &fdo);
|
||||
if (!KSUCCESS(st))
|
||||
return st;
|
||||
(void)IoSetDeviceName(fdo, SYS_SV_LITERAL("rtl8139"));
|
||||
|
||||
RTL8139_DEVICE* r = (RTL8139_DEVICE*)fdo->DeviceExtension;
|
||||
memset(r, 0, sizeof(*r));
|
||||
r->Magic = RTL8139_DEVICE_MAGIC;
|
||||
r->Fdo = fdo;
|
||||
r->Pdo = physicalDeviceObject;
|
||||
r->Irq = 0xFFu;
|
||||
r->TxLock = (SPINLOCK)SPINLOCK_INIT;
|
||||
|
||||
r->LowerDevice = IoAttachDeviceToDeviceStack(fdo, physicalDeviceObject);
|
||||
if (!r->LowerDevice) {
|
||||
IoDeleteDevice(fdo);
|
||||
return STATUS_FAILURE;
|
||||
}
|
||||
|
||||
DbgPrint("RTL8139: FDO attached to %v\n", physicalDeviceObject->Name);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KSTATUS DriverEntry(const HAL_API* hal) {
|
||||
if (!hal)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
DbgPrint("RTL8139: driver loading...\n");
|
||||
KSTATUS st = Rtl8139Initialize(hal);
|
||||
gHal = hal;
|
||||
gRtl8139DeviceCount = 0;
|
||||
|
||||
memset(&gRtl8139Driver, 0, sizeof(gRtl8139Driver));
|
||||
IoInitializeDriverObject(&gRtl8139Driver, SYS_SV_LITERAL("rtl8139"));
|
||||
gRtl8139Driver.IdTable = &gRtl8139IdTable;
|
||||
gRtl8139Driver.DriverAddDevice = Rtl8139AddDevice;
|
||||
gRtl8139Driver.MajorFunction[IRP_MJ_PNP] = Rtl8139DispatchPnp;
|
||||
|
||||
KSTATUS st = IoRegisterDriverObject(&gRtl8139Driver);
|
||||
if (!KSUCCESS(st))
|
||||
DbgPrint("RTL8139: init failed: 0x%x\n", st);
|
||||
DbgPrint("RTL8139: IoRegisterDriverObject failed: 0x%x\n", st);
|
||||
return st;
|
||||
}
|
||||
Reference in new issue
Block a user