From acd60c52c949c3abadbeacca9e01fe12920796cf Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 13 Jul 2013 00:16:18 +0800 Subject: [PATCH] Kernel/PCI - Added function to access the Command field, better BAR functions - New BAR access function allows consistent sanity checking --- KernelLand/Kernel/drv/pci.c | 62 +++++++++++++++++++++++++++++ KernelLand/Kernel/include/drv_pci.h | 25 ++++++++++++ 2 files changed, 87 insertions(+) diff --git a/KernelLand/Kernel/drv/pci.c b/KernelLand/Kernel/drv/pci.c index d3a1ebcf..e926f94f 100644 --- a/KernelLand/Kernel/drv/pci.c +++ b/KernelLand/Kernel/drv/pci.c @@ -463,6 +463,17 @@ void PCI_ConfigWrite(tPCIDev ID, int Offset, int Size, Uint32 Value) PCI_CfgWriteDWord(addr, dword); } +Uint16 PCI_SetCommand(tPCIDev id, Uint16 SBits, Uint16 CBits) +{ + tPCIDevice *dev = &gPCI_Devices[id]; + dev->ConfigCache[1] &= ~CBits; + dev->ConfigCache[1] |= SBits; + Uint32 addr = PCI_int_GetBusAddr(dev->bus, dev->slot, dev->fcn, 1*4); + PCI_CfgWriteDWord(addr, dev->ConfigCache[1]); + dev->ConfigCache[1] = PCI_CfgReadDWord(addr); + return dev->ConfigCache[1]; +} + /** * \brief Get the IRQ assigned to a device */ @@ -486,6 +497,57 @@ Uint32 PCI_GetBAR(tPCIDev id, int BARNum) return gPCI_Devices[id].ConfigCache[4+BARNum]; } +/** + */ +Uint64 PCI_GetValidBAR(tPCIDev ID, int BARNum, tPCI_BARType Type) +{ + if( ID < 0 || ID >= giPCI_DeviceCount ) + return 0; + if( BARNum < 0 || BARNum >= 6 ) + return 0; + tPCIDevice *dev = &gPCI_Devices[ID]; + Uint32 bar_val = dev->ConfigCache[4+BARNum]; + Uint64 ret = -1; + switch( Type ) + { + case PCI_BARTYPE_IO: + if( !(bar_val & 1) ) + return 0; + ret = bar_val & ~3; + break; + + case PCI_BARTYPE_MEMNP: + if( bar_val & 8 ) return 0; + if(0) + case PCI_BARTYPE_MEMP: + if( !(bar_val & 8) ) return 0; + case PCI_BARTYPE_MEM: + if( bar_val & 1 ) return 0; + if( (bar_val & 6) == 4 ) { + ASSERTCR(BARNum, <, 5, 0); + ret = (bar_val & ~0xF) | ((Uint64)dev->ConfigCache[4+BARNum+1] << 32); + } + else { + ret = bar_val & ~0xF; + } + break; + case PCI_BARTYPE_MEM32: + if( bar_val & 1 ) return 0; + if( (bar_val & 6) != 0 ) return 0; + ret = bar_val & ~0xF; + break; + case PCI_BARTYPE_MEM64: + if( bar_val & 1 ) return 0; + if( (bar_val & 6) != 4 ) return 0; + ASSERTCR(BARNum, <, 5, 0); + ret = (bar_val & ~0xF) | ((Uint64)dev->ConfigCache[4+BARNum+1] << 32); + break; + } + ASSERT(ret != -1); + ASSERT(ret); + return ret; +} + /** * \brief Get device information for a slot/function */ diff --git a/KernelLand/Kernel/include/drv_pci.h b/KernelLand/Kernel/include/drv_pci.h index 33c4a3ec..1032814f 100644 --- a/KernelLand/Kernel/include/drv_pci.h +++ b/KernelLand/Kernel/include/drv_pci.h @@ -33,6 +33,29 @@ enum ePCIOverClasses PCI_OC_SCSI = 0x010000 }; +typedef enum ePCI_BARTypes tPCI_BARType; + +enum ePCI_BARTypes +{ + PCI_BARTYPE_IO, + PCI_BARTYPE_MEM, // Any memory type + PCI_BARTYPE_MEMP, // Prefetchable memory + PCI_BARTYPE_MEMNP, // Non-prefetchable memory + PCI_BARTYPE_MEM32, // 32-bit memory + PCI_BARTYPE_MEM64 // 64-bit memory +}; + +#define PCI_CMD_IOENABLE (1 << 0) +#define PCI_CMD_MEMENABLE (1 << 1) +#define PCI_CMD_BUSMASTER (1 << 2) // Device can behave as a bus master +#define PCI_CMD_SPECIALCYCLES (1 << 3) // Can monitor 'Special Cycle' operations +#define PCI_CMD_WRAINVAL (1 << 4) // Memory 'Write and Invalidate' can be generated +#define PCI_CMD_VGAPALSNOOP (1 << 5) // VGA Palette Snoop enabled +#define PCI_CMD_PARITYERRRESP (1 << 6) // Pairity Error Response (suppress PERR# generation) +#define PCI_CMD_SERRENABLE (1 << 8) // Enable SERR# Driver +#define PCI_CMD_FASTBACKBACK (1 << 9) // Fast Back-Back Enable +#define PCI_CMD_INTDISABLE (1 <<10) // Disable generation of INTx# signals + typedef int tPCIDev; /** @@ -54,8 +77,10 @@ extern int PCI_GetDeviceSubsys(tPCIDev id, Uint16 *SubsystemVendor, Uint16 *Subs extern Uint32 PCI_ConfigRead(tPCIDev id, int Offset, int Size); extern void PCI_ConfigWrite(tPCIDev id, int Offset, int Size, Uint32 Value); +extern Uint16 PCI_SetCommand(tPCIDev id, Uint16 SBits, Uint16 CBits); extern Uint8 PCI_GetIRQ(tPCIDev id); extern Uint32 PCI_GetBAR(tPCIDev id, int BAR); +extern Uint64 PCI_GetValidBAR(tPCIDev id, int BAR, tPCI_BARType BARType); //extern Uint16 PCI_AssignPort(tPCIDev id, int bar, int count); #endif -- 2.20.1