//----------------------------------------------------------------------------// // GNU GPL OS/K // // // // Desc: PCI driver // // // // // // Copyright © 2018-2020 The OS/K Team // // // // This file is part of OS/K. // // // // OS/K is free software: you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation, either version 3 of the License, or // // any later version. // // // // OS/K is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY//without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU General Public License for more details. // // // // You should have received a copy of the GNU General Public License // // along with OS/K. If not, see . // //----------------------------------------------------------------------------// #include #include #include void* pciConfigBaseAddress = NULL; static inline void* pciGetConfigAddr(uchar bus, uchar device, uchar function, ushort offset) { if(device > 32) { DebugLog("pciGetConfigAddr(): bad device ID\n"); return 0; } if(function > 8) { DebugLog("pciGetConfigAddr(): bad function ID\n"); return 0; } if(offset > 4096) { DebugLog("pciGetConfigAddr(): bad register offset\n"); return 0; } return (void*)(bus*32*8*4096 + device*8*4096 + function*4096 + offset + (ulong)pciConfigBaseAddress); } static inline uchar pciReadConfigByte(uchar bus, uchar device, uchar function, ushort offset) { return *((uchar*)(pciGetConfigAddr(bus, device, function, offset))); } static inline ushort pciReadConfigWord(uchar bus, uchar device, uchar function, ushort offset) { return *((ushort*)(pciGetConfigAddr(bus, device, function, offset))); } static inline uint pciReadConfigDWord(uchar bus, uchar device, uchar function, ushort offset) { return *((uint*)(pciGetConfigAddr(bus, device, function, offset))); } //----------------------------------------------------------------------------// uchar IoPciReadConfigByte(PciDev_t *device, ushort offset) { return *((uchar *)((ulong)device->configAddr + offset)); } ushort IoPciReadConfigWord(PciDev_t *device, ushort offset) { return *((ushort *)((ulong)device->configAddr + offset)); } uint IoPciReadConfigDWord(PciDev_t *device, ushort offset) { return *((uint *)((ulong)device->configAddr + offset)); } void IoPciWriteConfigByte(PciDev_t *device, ushort offset, uchar data) { memmove((void *)((ulong)device->configAddr + offset), &data, 1); } void IoPciWriteConfigWord(PciDev_t *device, ushort offset, ushort data) { memmove((void *)((ulong)device->configAddr + offset), &data, 2); } void IoPciWriteConfigDWord(PciDev_t *device, ushort offset, uint data) { memmove((void *)((ulong)device->configAddr + offset), &data, 4); } void IoPciEnumerate() { if(pciConfigBaseAddress == NULL) { KeStartPanic("Unable to access PCI configuration : MCFG table not reachable\n"); return; } for(ushort bus = 0; bus < 256; bus++) { for(uchar device = 0; device < 32; device++) { for(uchar function = 0; function < 8; function++) { ushort vendor = pciReadConfigWord((uchar)bus, device, function, PCI_REG_VENDOR); if(vendor == 0xffff) continue; DebugLog("PCI device found ! vendor: %x, device: %x\n", vendor, pciReadConfigWord((uchar)bus, device, function, PCI_REG_DEVICE) ); } } } } PciDev_t *IoPciGetDevice(ushort vendorID, ushort deviceID) { if(pciConfigBaseAddress == NULL) { KeStartPanic("Unable to access PCI configuration : MCFG table not reachable\n"); return NULL; } for(ushort bus = 0; bus < 256; bus++) { for(uchar device = 0; device < 32; device++) { for(uchar function = 0; function < 8; function++) { if(vendorID == pciReadConfigWord((uchar)bus, device, function, PCI_REG_VENDOR) && deviceID == pciReadConfigWord((uchar)bus, device, function, PCI_REG_DEVICE)) { PciDev_t *pciDevicePtr = (PciDev_t *)malloc(sizeof(PciDev_t)); pciDevicePtr->vendorID = vendorID; pciDevicePtr->deviceID = deviceID; pciDevicePtr->configAddr = pciGetConfigAddr((uchar)bus, device, function, 0); return pciDevicePtr; } } } } return NULL; } void IoInitPCI() { struct MCFG_t *MCFG_table = (struct MCFG_t*)IoGetAcpiTable(SDT_MCFG); if(MCFG_table == NULL) { KeStartPanic("Unable to access PCI configuration : MCFG table not reachable\n"); } pciConfigBaseAddress = MCFG_table->pciConfigBaseAddress; DebugLog("PCI Config Base address = 0x%p\n", pciConfigBaseAddress); IoPciEnumerate(); // Give R/W access to the configuration space for(int i=0; i < 65536; i++) // 65536 = 256 * 32 * 8 { MmMapPage((void *)((ulong)pciConfigBaseAddress + i * KPAGESIZE), (void *)((ulong)pciConfigBaseAddress + i * KPAGESIZE), PRESENT | READWRITE); } }