// rtl816x_pci.c - PCI BAR/MMIO front-end for rtl816x. #include "rtl816x.h" bool RtlFindDevice(uint8_t* outBus, uint8_t* outDev, uint8_t* outFn, uint16_t* outDeviceId) { if (gHal->Pci.FindDevice(RTL_VENDOR_REALTEK, RTL_DEVICE_8168, outBus, outDev, outFn)) { *outDeviceId = RTL_DEVICE_8168; return true; } if (gHal->Pci.FindDevice(RTL_VENDOR_REALTEK, RTL_DEVICE_8169, outBus, outDev, outFn)) { *outDeviceId = RTL_DEVICE_8169; return true; } return false; } bool RtlReadBar(uint8_t bus, uint8_t dev, uint8_t fn, uint8_t index, RTL_BAR* out) { uint8_t reg = (uint8_t)(PCI_REG_BAR0 + index * 4u); uint32_t lo = gHal->Pci.Read32(bus, dev, fn, reg); out->Kind = RtlBarNone; out->Base = 0; out->Index = index; if (lo == 0 || lo == 0xFFFFFFFFu) return false; if (lo & 1u) { uint32_t base = lo & ~0x3u; if (!base) return false; out->Kind = RtlBarIo; out->Base = base; return true; } uint64_t base = (uint64_t)(lo & ~0xFu); uint32_t type = (lo >> 1) & 0x3u; if (type == 0x2u && index < 5) { uint32_t hi = gHal->Pci.Read32(bus, dev, fn, (uint8_t)(reg + 4u)); base |= ((uint64_t)hi << 32); } if (!base) return false; out->Kind = RtlBarMmio; out->Base = base; return true; } KSTATUS RtlMapMmio(uint64_t physBase, volatile uint8_t** outMmio) { uint64_t pageBase = physBase & PAGE_MASK; uint64_t pageOff = physBase - pageBase; for (uint32_t i = 0; i < RTL_MMIO_PAGES; i++) { PHYSICAL_ADDRESS phys = pageBase + (uint64_t)i * PAGE_SIZE; uintptr_t virt = (uintptr_t)gHal->PhysToVirt(phys); KSTATUS st = MmMapPage(virt, phys, PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE); if (st == STATUS_ALREADY_EXISTS) st = MmSetPageProtect(virt, PAGE_SIZE, PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE); if (!KSUCCESS(st)) return st; } *outMmio = (volatile uint8_t*)((uintptr_t)gHal->PhysToVirt(pageBase) + pageOff); return STATUS_SUCCESS; } KSTATUS RtlSelectRegisterBar(RTL816X_DEVICE* r) { RTL_BAR best = { RtlBarNone, 0, 0 }; RTL_BAR fallback = { RtlBarNone, 0, 0 }; for (uint8_t i = 0; i < 6; i++) { RTL_BAR bar; if (!RtlReadBar(r->Bus, r->Dev, r->Fn, i, &bar)) continue; if (bar.Kind == RtlBarMmio) { best = bar; break; } if (bar.Kind == RtlBarIo && fallback.Kind == RtlBarNone) fallback = bar; // Skip the high dword of 64-bit memory BARs. if (bar.Kind == RtlBarMmio) { uint32_t lo = gHal->Pci.Read32(r->Bus, r->Dev, r->Fn, (uint8_t)(PCI_REG_BAR0 + i * 4u)); if (((lo >> 1) & 0x3u) == 0x2u) i++; } } if (best.Kind == RtlBarNone) best = fallback; if (best.Kind == RtlBarMmio) { KSTATUS st = RtlMapMmio(best.Base, &r->Mmio); if (!KSUCCESS(st)) return st; r->UseMmio = true; DbgPrint("RTL816X: BAR%u MMIO base=0x%016llX virt=0x%016llX\n", best.Index, (unsigned long long)best.Base, r->Mmio); return STATUS_SUCCESS; } if (best.Kind == RtlBarIo) { if (best.Base > 0xFFFFu) return STATUS_NOT_SUPPORTED; r->IoBase = (uint16_t)best.Base; r->UseMmio = false; DbgPrint("RTL816X: BAR%u I/O base=0x%04x\n", best.Index, r->IoBase); return STATUS_SUCCESS; } return STATUS_NOT_FOUND; } void RtlEnablePci(RTL816X_DEVICE* r) { uint32_t cmd = gHal->Pci.Read32(r->Bus, r->Dev, r->Fn, PCI_REG_COMMAND); cmd |= PCI_COMMAND_MASTER; if (r->UseMmio) cmd |= PCI_COMMAND_MEMORY; else cmd |= PCI_COMMAND_IO; cmd &= ~PCI_COMMAND_INTX_DISABLE; gHal->Pci.Write32(r->Bus, r->Dev, r->Fn, PCI_REG_COMMAND, cmd); }