X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Fdrv%2Fpci.c;h=df5c11444cb51c3448090732bb5199a77eeedd0a;hb=df1d534cfe822903fc38e1cc13c4b18941c91908;hp=b256d369086ca6fdf89261d386b7e51ab3e78cb8;hpb=77ed20ce9d7e25654215980d0f89e63b8dd366f0;p=tpg%2Facess2.git diff --git a/Kernel/drv/pci.c b/Kernel/drv/pci.c index b256d369..df5c1144 100644 --- a/Kernel/drv/pci.c +++ b/Kernel/drv/pci.c @@ -3,26 +3,36 @@ * PCI Bus Driver */ #define DEBUG 0 -#include +#include +#include #include #include #include #define LIST_DEVICES 1 +// === IMPORTS === +extern Uint32 PCI_CfgReadDWord(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset); +extern void PCI_CfgWriteDWord(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset, Uint32 data); +extern Uint16 PCI_CfgReadWord(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset); +extern Uint8 PCI_CfgReadByte(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset); + // === STRUCTURES === -typedef struct s_pciDevice { +typedef struct sPCIDevice +{ Uint16 bus, slot, fcn; Uint16 vendor, device; union { - struct {Uint8 class, subclass;}; + struct { + Uint8 class, subclass; + }; Uint16 oc; }; Uint16 revision; Uint32 ConfigCache[256/4]; char Name[8]; tVFS_Node Node; -} t_pciDevice; +} tPCIDevice; // === CONSTANTS === #define SPACE_STEP 5 @@ -30,33 +40,34 @@ typedef struct s_pciDevice { // === PROTOTYPES === int PCI_Install(char **Arguments); + int PCI_ScanBus(int ID, int bFill); + char *PCI_ReadDirRoot(tVFS_Node *node, int pos); -tVFS_Node *PCI_FindDirRoot(tVFS_Node *node, char *filename); +tVFS_Node *PCI_FindDirRoot(tVFS_Node *node, const char *filename); Uint64 PCI_ReadDevice(tVFS_Node *node, Uint64 pos, Uint64 length, void *buffer); - + +#if 0 int PCI_CountDevices(Uint16 vendor, Uint16 device, Uint16 fcn); int PCI_GetDevice(Uint16 vendor, Uint16 device, Uint16 fcn, int idx); int PCI_GetDeviceByClass(Uint16 class, Uint16 mask, int prev); Uint8 PCI_GetIRQ(int id); Uint32 PCI_GetBAR0(int id); Uint32 PCI_GetBAR1(int id); +Uint32 PCI_GetBAR2(int id); Uint32 PCI_GetBAR3(int id); Uint32 PCI_GetBAR4(int id); Uint32 PCI_GetBAR5(int id); Uint16 PCI_AssignPort(int id, int bar, int count); +#endif - int PCI_EnumDevice(Uint16 bus, Uint16 dev, Uint16 fcn, t_pciDevice *info); -Uint32 PCI_CfgReadDWord(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset); -void PCI_CfgWriteDWord(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset, Uint32 data); -Uint16 PCI_CfgReadWord(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset); -Uint8 PCI_CfgReadByte(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset); + int PCI_EnumDevice(Uint16 bus, Uint16 dev, Uint16 fcn, tPCIDevice *info); // === GLOBALS === -//MODULE_DEFINE(0, 0x0100, PCI, PCI_Install, NULL); +MODULE_DEFINE(0, 0x0100, PCI, PCI_Install, NULL, NULL); int giPCI_BusCount = 1; int giPCI_InodeHandle = -1; int giPCI_DeviceCount = 0; -t_pciDevice *gPCI_Devices = NULL; +tPCIDevice *gPCI_Devices = NULL; tDevFS_Driver gPCI_DriverStruct = { NULL, "pci", { @@ -68,91 +79,120 @@ tDevFS_Driver gPCI_DriverStruct = { .FindDir = PCI_FindDirRoot } }; - Uint32 *gaPCI_PortBitmap = NULL; +Uint32 *gaPCI_PortBitmap = NULL; +Uint32 gaPCI_BusBitmap[256/32]; // === CODE === /** - * \fn int PCI_Install() * \brief Scan the PCI Bus for devices + * \param Arguments Boot-time parameters */ int PCI_Install(char **Arguments) { - int bus, dev, fcn, i; - int space = 0; - t_pciDevice devInfo; - void *tmpPtr = NULL; + int i; + void *tmpPtr; // Build Portmap gaPCI_PortBitmap = malloc( 1 << 13 ); + if( !gaPCI_PortBitmap ) { + Log_Error("PCI", "Unable to allocate %i bytes for bitmap", 1 << 13); + return MODULE_ERR_MALLOC; + } memset( gaPCI_PortBitmap, 0, 1 << 13 ); for( i = 0; i < MAX_RESERVED_PORT / 32; i ++ ) gaPCI_PortBitmap[i] = -1; for( i = 0; i < MAX_RESERVED_PORT % 32; i ++ ) gaPCI_PortBitmap[MAX_RESERVED_PORT / 32] = 1 << i; - //LogF("Done.\n"); - // Scan Busses - for( bus = 0; bus < giPCI_BusCount; bus++ ) + // Scan Bus (Bus 0, Don't fill gPCI_Devices) + i = PCI_ScanBus(0, 0); + if(i != MODULE_ERR_OK) return i; + + if(giPCI_DeviceCount == 0) { + Log_Notice("PCI", "No devices were found"); + return MODULE_ERR_NOTNEEDED; + } + + // Allocate device buffer + tmpPtr = malloc(giPCI_DeviceCount * sizeof(tPCIDevice)); + if(tmpPtr == NULL) { + Log_Warning("PCI", "Malloc ERROR"); + return MODULE_ERR_MALLOC; + } + gPCI_Devices = tmpPtr; + + Log_Log("PCI", "%i devices, filling structure", giPCI_DeviceCount); + + // Reset counts + giPCI_DeviceCount = 0; + giPCI_BusCount = 0; + memset(gaPCI_BusBitmap, 0, sizeof(gaPCI_BusBitmap)); + // Rescan, filling the PCI device array + PCI_ScanBus(0, 1); + + // Complete Driver Structure + gPCI_DriverStruct.RootNode.Size = giPCI_DeviceCount; + + // And add to DevFS + DevFS_AddDevice(&gPCI_DriverStruct); + + return MODULE_ERR_OK; +} + +/** + * \brief Scans a specific PCI Bus + * \param BusID PCI Bus ID to scan + * \param bFill Fill the \a gPCI_Devices array? + */ +int PCI_ScanBus(int BusID, int bFill) +{ + int dev, fcn; + tPCIDevice devInfo; + + if( gaPCI_BusBitmap[BusID/32] & (1 << (BusID%32)) ) + return MODULE_ERR_OK; + + gaPCI_BusBitmap[BusID/32] |= (1 << (BusID%32)); + + for( dev = 0; dev < 32; dev++ ) // 32 Devices per bus { - for( dev = 0; dev < 10; dev++ ) // 10 Devices per bus + for( fcn = 0; fcn < 8; fcn++ ) // Max 8 functions per device { - for( fcn = 0; fcn < 8; fcn++ ) // 8 functions per device + // Check if the device/function exists + if(!PCI_EnumDevice(BusID, dev, fcn, &devInfo)) + continue; + + if(devInfo.oc == PCI_OC_PCIBRIDGE) + { + #if LIST_DEVICES + Log_Log("PCI", "Bridge @ %i,%i:%i (0x%x:0x%x)", + BusID, dev, fcn, devInfo.vendor, devInfo.device); + #endif + //TODO: Handle PCI-PCI Bridges + //PCI_ScanBus(devInfo.???, bFill); + giPCI_BusCount ++; + } + else { - // Check if the device/function exists - if(!PCI_EnumDevice(bus, dev, fcn, &devInfo)) - { - continue; - } - - if(giPCI_DeviceCount == space) - { - space += SPACE_STEP; - tmpPtr = realloc(gPCI_Devices, space*sizeof(t_pciDevice)); - if(tmpPtr == NULL) - break; - gPCI_Devices = tmpPtr; - } - if(devInfo.oc == PCI_OC_PCIBRIDGE) - { - #if LIST_DEVICES - Log("[PCI ] Bridge @ %i,%i:%i (0x%x:0x%x)", - bus, dev, fcn, devInfo.vendor, devInfo.device); - #endif - giPCI_BusCount++; - } - devInfo.Node.Inode = giPCI_DeviceCount; - memcpy(&gPCI_Devices[giPCI_DeviceCount], &devInfo, sizeof(t_pciDevice)); - giPCI_DeviceCount ++; #if LIST_DEVICES - Log("[PCI ] Device %i,%i:%i => 0x%x:0x%x", - bus, dev, fcn, devInfo.vendor, devInfo.device); + Log_Log("PCI", "Device %i,%i:%i %04x => 0x%04x:0x%04x", + BusID, dev, fcn, devInfo.oc, devInfo.vendor, devInfo.device); #endif - - // WTF is this for? - if(fcn == 0) { - if( !(devInfo.ConfigCache[3] & 0x800000) ) - break; - } } - if(tmpPtr != gPCI_Devices) + + if( bFill ) { + devInfo.Node.Inode = giPCI_DeviceCount; + memcpy(&gPCI_Devices[giPCI_DeviceCount], &devInfo, sizeof(tPCIDevice)); + } + giPCI_DeviceCount ++; + + // If bit 23 of (soemthing) is set, there are sub-functions + if(fcn == 0 && !(devInfo.ConfigCache[3] & 0x00800000) ) break; } - if(tmpPtr != gPCI_Devices) - break; } - tmpPtr = realloc(gPCI_Devices, giPCI_DeviceCount*sizeof(t_pciDevice)); - if(tmpPtr == NULL) - return 0; - gPCI_Devices = tmpPtr; - //LogF("Done.\n"); - - // Complete Driver Structure - gPCI_DriverStruct.RootNode.Size = giPCI_DeviceCount; - // And add to DevFS - DevFS_AddDevice(&gPCI_DriverStruct); - - return 1; + return MODULE_ERR_OK; } /** @@ -171,9 +211,9 @@ char *PCI_ReadDirRoot(tVFS_Node *Node, int Pos) return strdup( gPCI_Devices[Pos].Name ); } /** - * \fn tVFS_Node *PCI_FindDirRoot(tVFS_Node *node, char *filename) + * \fn tVFS_Node *PCI_FindDirRoot(tVFS_Node *node, const char *filename) */ -tVFS_Node *PCI_FindDirRoot(tVFS_Node *node, char *filename) +tVFS_Node *PCI_FindDirRoot(tVFS_Node *node, const char *filename) { int bus,slot,fcn; int i; @@ -284,8 +324,8 @@ int PCI_GetDeviceByClass(Uint16 class, Uint16 mask, int prev) for( ; i < giPCI_DeviceCount; i++ ) { - if((gPCI_Devices[i].oc & mask) != class) continue; - return i; + if((gPCI_Devices[i].oc & mask) == class) + return i; } return -1; } @@ -366,7 +406,7 @@ Uint16 PCI_AssignPort(int id, int bar, int count) Uint16 portVals; int gran=0; int i, j; - t_pciDevice *dev; + tPCIDevice *dev; //LogF("PCI_AssignPort: (id=%i,bar=%i,count=%i)\n", id, bar, count); @@ -387,8 +427,14 @@ Uint16 PCI_AssignPort(int id, int bar, int count) portVals &= ~1; // Get Granuality + #if ARCHDIR_IS_x86 || ARCHDIR_IS_x86_64 __asm__ __volatile__ ("bsf %%eax, %%ecx" : "=c" (gran) : "a" (portVals) ); gran = 1 << gran; + #else + { + for(gran = 1; gran && !(portVals & gran); gran <<= 1); + } + #endif //LogF(" PCI_AssignPort: gran = 0x%x\n", gran); // Find free space @@ -423,13 +469,13 @@ Uint16 PCI_AssignPort(int id, int bar, int count) } /** - * \fn int PCI_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, t_pciDevice *info) + * \fn int PCI_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, tPCIDevice *info) + * \brief Get device information for a slot/function */ -int PCI_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, t_pciDevice *info) +int PCI_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, tPCIDevice *info) { Uint16 vendor; int i; - Uint32 addr; vendor = PCI_CfgReadWord(bus, slot, fcn, 0x0|0); if(vendor == 0xFFFF) // Invalid Device @@ -444,16 +490,9 @@ int PCI_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, t_pciDevice *info) info->oc = PCI_CfgReadWord(bus, slot, fcn, 0x8|2); // Load Config Bytes - addr = 0x80000000 | ((Uint)bus<<16) | ((Uint)slot<<11) | ((Uint)fcn<<8); for(i=0;i<256/4;i++) { - #if 1 - outd(0xCF8, addr); - info->ConfigCache[i] = ind(0xCFC); - addr += 4; - #else info->ConfigCache[i] = PCI_CfgReadDWord(bus, slot, fcn, i*4); - #endif } //#if LIST_DEVICES @@ -484,74 +523,6 @@ int PCI_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, t_pciDevice *info) return 1; } -Uint32 PCI_CfgReadDWord(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset) -{ - Uint32 address; - Uint32 data; - - bus &= 0xFF; // 8 Bits - dev &= 0x1F; // 5 Bits - func &= 0x7; // 3 Bits - offset &= 0xFF; // 8 Bits - - address = 0x80000000 | ((Uint)bus<<16) | ((Uint)dev<<11) | ((Uint)func<<8) | (offset&0xFC); - outd(0xCF8, address); - - data = ind(0xCFC); - return (Uint32)data; -} -void PCI_CfgWriteDWord(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset, Uint32 data) -{ - Uint32 address; - - bus &= 0xFF; // 8 Bits - dev &= 0x1F; // 5 Bits - func &= 0x7; // 3 Bits - offset &= 0xFF; // 8 Bits - - address = 0x80000000 | ((Uint)bus<<16) | ((Uint)dev<<11) | ((Uint)func<<8) | (offset&0xFC); - outd(0xCF8, address); - outd(0xCFC, data); -} -Uint16 PCI_CfgReadWord(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset) -{ - Uint32 data; - - bus &= 0xFF; // 8 Bits - dev &= 0x1F; // 5 Bits - func &= 0x7; // 3 Bits - offset &= 0xFF; // 8 Bits - - //LogF("PCI_CfgReadWord: (bus=0x%x,dev=0x%x,func=%x,offset=0x%x)\n", bus, dev, func, offset); - - outd(0xCF8, - 0x80000000 | ((Uint)bus<<16) | ((Uint)dev<<11) | ((Uint)func<<8) | (offset&0xFC) ); - - data = ind(0xCFC); - data >>= (offset&2)*8; //Allow Access to Upper Word - //LogF("PCI_CfgReadWord: RETURN 0x%x\n", data&0xFFFF); - return (Uint16)data; -} - -Uint8 PCI_CfgReadByte(Uint16 bus, Uint16 dev, Uint16 func, Uint16 offset) -{ - Uint32 address; - Uint32 data; - - bus &= 0xFF; // 8 Bits - dev &= 0x1F; // 4 Bits - func &= 0x7; // 3 Bits - offset &= 0xFF; // 8 Bits - - address = 0x80000000 | ((Uint)bus<<16) | ((Uint)dev<<11) | ((Uint)func<<8) | (offset&0xFC); - outd(0xCF8, address); - - data = ind(0xCFC); - data >>= (offset&3)*8; //Allow Access to Upper Word - return (Uint8)data; -} - - // === EXPORTS === //* EXPORT(PCI_CountDevices);