Kernel/pci - Catch non-assigned BARs with an error
[tpg/acess2.git] / KernelLand / Kernel / drv / pci.c
index 2c01b96..3a4ec86 100644 (file)
@@ -1,6 +1,9 @@
 /*\r
- * AcessOS/AcessBasic v0.1\r
- * PCI Bus Driver\r
+ * Acess2 Kernel\r
+ * - By John Hodge (thePowersGang)\r
+ * \r
+ * drv/pci.c\r
+ * - PCI Enumeration and Arbitration\r
  */\r
 #define DEBUG  0\r
 #include <acess.h>\r
@@ -9,8 +12,11 @@
 #include <fs_devfs.h>\r
 #include <drv_pci.h>\r
 #include <drv_pci_int.h>\r
+#include <virtual_pci.h>\r
 \r
+#define USE_PORT_BITMAP        0\r
 #define        LIST_DEVICES    1\r
+#define PCI_MAX_BUSSES 8\r
 \r
 // === STRUCTURES ===\r
 typedef struct sPCIDevice\r
@@ -32,15 +38,16 @@ typedef struct sPCIDevice
  int   PCI_Install(char **Arguments);\r
  int   PCI_ScanBus(int ID, int bFill);\r
  \r
-char   *PCI_int_ReadDirRoot(tVFS_Node *node, int pos);\r
-tVFS_Node      *PCI_int_FindDirRoot(tVFS_Node *node, const char *filename);\r
+ int   PCI_int_ReadDirRoot(tVFS_Node *node, int pos, char Dest[FILENAME_MAX]);\r
+tVFS_Node      *PCI_int_FindDirRoot(tVFS_Node *node, const char *filename, Uint Flags);\r
 Uint32 PCI_int_GetBusAddr(Uint16 Bus, Uint16 Slot, Uint16 Fcn, Uint8 Offset);\r
-size_t PCI_int_ReadDevice(tVFS_Node *node, off_t Offset, size_t Length, void *buffer);\r
+size_t PCI_int_ReadDevice(tVFS_Node *node, off_t Offset, size_t Length, void *buffer, Uint Flags);\r
  int   PCI_int_EnumDevice(Uint16 bus, Uint16 dev, Uint16 fcn, tPCIDevice *info);\r
 \r
 // === GLOBALS ===\r
 MODULE_DEFINE(0, 0x0100, PCI, PCI_Install, NULL, NULL);\r
  int   giPCI_BusCount = 1;\r
+Uint8  gaPCI_BusNumbers[PCI_MAX_BUSSES];\r
  int   giPCI_InodeHandle = -1;\r
  int   giPCI_DeviceCount = 0;\r
 tPCIDevice     *gPCI_Devices = NULL;\r
@@ -63,7 +70,9 @@ tDevFS_Driver gPCI_DriverStruct = {
        .Type = &gPCI_RootNodeType\r
        }\r
 };\r
+#if USE_PORT_BITMAP\r
 Uint32 *gaPCI_PortBitmap = NULL;\r
+#endif\r
 Uint32 gaPCI_BusBitmap[256/32];\r
  \r
 // === CODE ===\r
@@ -73,9 +82,10 @@ Uint32       gaPCI_BusBitmap[256/32];
  */\r
 int PCI_Install(char **Arguments)\r
 {\r
-        int    i, ret, bus;\r
+        int    ret, bus;\r
        void    *tmpPtr;\r
        \r
+       #if USE_PORT_BITMAP\r
        // Build Portmap\r
        gaPCI_PortBitmap = malloc( 1 << 13 );\r
        if( !gaPCI_PortBitmap ) {\r
@@ -83,18 +93,26 @@ int PCI_Install(char **Arguments)
                return MODULE_ERR_MALLOC;\r
        }\r
        memset( gaPCI_PortBitmap, 0, 1 << 13 );\r
+        int    i;\r
        for( i = 0; i < MAX_RESERVED_PORT / 32; i ++ )\r
                gaPCI_PortBitmap[i] = -1;\r
        for( i = 0; i < MAX_RESERVED_PORT % 32; i ++ )\r
                gaPCI_PortBitmap[MAX_RESERVED_PORT / 32] = 1 << i;\r
-       \r
+       #endif  \r
+\r
        // Scan Bus (Bus 0, Don't fill gPCI_Devices)\r
+       giPCI_DeviceCount = 0;\r
+       giPCI_BusCount = 1;\r
+       gaPCI_BusNumbers[0] = 0;\r
        for( bus = 0; bus < giPCI_BusCount; bus ++ )\r
        {\r
-               ret = PCI_ScanBus(bus, 0);\r
-               if(ret != MODULE_ERR_OK)        return i;\r
+               ret = PCI_ScanBus(gaPCI_BusNumbers[bus], 0);\r
+               if(ret != MODULE_ERR_OK)        return ret;\r
        }\r
-               \r
+       // TODO: PCIe\r
+       // - Add VPCI Devices\r
+       giPCI_DeviceCount += giVPCI_DeviceCount;\r
+       \r
        if(giPCI_DeviceCount == 0) {\r
                Log_Notice("PCI", "No devices were found");\r
                return MODULE_ERR_NOTNEEDED;\r
@@ -117,7 +135,39 @@ int PCI_Install(char **Arguments)
        // Rescan, filling the PCI device array\r
        for( bus = 0; bus < giPCI_BusCount; bus ++ )\r
        {\r
-               PCI_ScanBus(bus, 1);\r
+               PCI_ScanBus(gaPCI_BusNumbers[bus], 1);\r
+       }\r
+       // Insert VPCI Devices\r
+       for( int i = 0; i < giVPCI_DeviceCount; i ++ )\r
+       {\r
+               tPCIDevice      *devinfo = &gPCI_Devices[giPCI_DeviceCount];\r
+               \r
+               devinfo->bus = -1;\r
+               devinfo->slot = i;\r
+               devinfo->fcn = 0;\r
+               devinfo->vendor = gaVPCI_Devices[i].Vendor;\r
+               devinfo->device = gaVPCI_Devices[i].Device;\r
+               devinfo->revision = gaVPCI_Devices[i].Class & 0xFF;\r
+               devinfo->class = gaVPCI_Devices[i].Class >> 8;\r
+               snprintf(devinfo->Name, sizeof(devinfo->Name), "%02x.%02x:%x", 0xFF, i, 0);\r
+               \r
+               #if LIST_DEVICES\r
+               Log_Log("PCI", "Device %i,%i:%i %06x => 0x%04x:0x%04x Rev %i",\r
+                       0xFF, i, 0, devinfo->class,\r
+                       devinfo->vendor, devinfo->device, devinfo->revision);\r
+               #endif\r
+\r
+               for(int j = 0; j < 256/4; j ++ )\r
+                       devinfo->ConfigCache[j] = VPCI_Read(&gaVPCI_Devices[i], j*4, 4);\r
+\r
+               memset(&devinfo->Node, 0, sizeof(devinfo->Node));\r
+               devinfo->Node.Inode = giPCI_DeviceCount;\r
+               devinfo->Node.Size = 256;\r
+               devinfo->Node.NumACLs = 1;\r
+               devinfo->Node.ACLs = &gVFS_ACL_EveryoneRO;\r
+               devinfo->Node.Type = &gPCI_DevNodeType;\r
+\r
+               giPCI_DeviceCount ++;\r
        }\r
        \r
        // Complete Driver Structure\r
@@ -152,25 +202,12 @@ int PCI_ScanBus(int BusID, int bFill)
                        if(!PCI_int_EnumDevice(BusID, dev, fcn, &devInfo))\r
                                continue;\r
                        \r
-                       if(devInfo.class == PCI_OC_PCIBRIDGE)\r
-                       {\r
-                               #if LIST_DEVICES\r
-                               if( !bFill )\r
-                                       Log_Log("PCI", "Bridge @ %i,%i:%i (0x%x:0x%x)",\r
-                                               BusID, dev, fcn, devInfo.vendor, devInfo.device);\r
-                               #endif\r
-                               //TODO: Handle PCI-PCI Bridges\r
-                               //PCI_ScanBus(devInfo.???, bFill);\r
-                               giPCI_BusCount ++;\r
-                       }\r
-                       else\r
-                       {\r
-                               #if LIST_DEVICES\r
-                               if( !bFill )\r
-                                       Log_Log("PCI", "Device %i,%i:%i %06x => 0x%04x:0x%04x",\r
-                                               BusID, dev, fcn, devInfo.class, devInfo.vendor, devInfo.device);\r
-                               #endif\r
-                       }\r
+                       #if LIST_DEVICES\r
+                       if( !bFill )\r
+                               Log_Log("PCI", "Device %i,%i:%i %06x => 0x%04x:0x%04x Rev %i",\r
+                                       BusID, dev, fcn, devInfo.class,\r
+                                       devInfo.vendor, devInfo.device, devInfo.revision);\r
+                       #endif\r
                        \r
                        if( bFill ) {\r
                                devInfo.Node.Inode = giPCI_DeviceCount;\r
@@ -178,7 +215,28 @@ int PCI_ScanBus(int BusID, int bFill)
                        }\r
                        giPCI_DeviceCount ++;\r
                        \r
-                       // If bit 23 of (soemthing) is set, there are sub-functions\r
+                       switch( (devInfo.ConfigCache[3] >> 16) & 0x7F )\r
+                       {\r
+                       case 0x00:      // Normal device\r
+                               break;\r
+                       case 0x01:      // PCI-PCI Bridge\r
+                               {\r
+                               // TODO: Add to list of busses?\r
+                               Uint8   sec = (devInfo.ConfigCache[6] & 0x0000FF00) >> 8;\r
+                               #if LIST_DEVICES\r
+                               if( !bFill ) {\r
+                                       Uint8   pri = (devInfo.ConfigCache[6] & 0x000000FF) >> 0;\r
+                                       Log_Log("PCI", "- PCI-PCI Bridge %02x=>%02x", pri, sec);\r
+                               }\r
+                               #endif\r
+                               gaPCI_BusNumbers[giPCI_BusCount++] = sec;\r
+                               }\r
+                               break;\r
+                       case 0x02:      // PCI-CardBus Bridge\r
+                               break;\r
+                       }\r
+\r
+                       // If bit 8 of the Header Type register is set, there are sub-functions\r
                        if(fcn == 0 && !(devInfo.ConfigCache[3] & 0x00800000) )\r
                                break;\r
                }\r
@@ -190,50 +248,29 @@ int PCI_ScanBus(int BusID, int bFill)
 /**\r
  * \brief Read from Root of PCI Driver\r
 */\r
-char *PCI_int_ReadDirRoot(tVFS_Node *Node, int Pos)\r
+int PCI_int_ReadDirRoot(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])\r
 {\r
        ENTER("pNode iPos", Node, Pos);\r
        if(Pos < 0 || Pos >= giPCI_DeviceCount) {\r
-               LEAVE('n');\r
-               return NULL;\r
+               LEAVE_RET('i', -EINVAL);\r
        }\r
        \r
-       LEAVE('s', gPCI_Devices[Pos].Name);\r
-       return strdup( gPCI_Devices[Pos].Name );\r
+       LOG("Name = %s", gPCI_Devices[Pos].Name);\r
+       strncpy(Dest, gPCI_Devices[Pos].Name, FILENAME_MAX);\r
+       LEAVE_RET('i', 0);\r
 }\r
 /**\r
  */\r
-tVFS_Node *PCI_int_FindDirRoot(tVFS_Node *node, const char *filename)\r
+tVFS_Node *PCI_int_FindDirRoot(tVFS_Node *node, const char *filename, Uint Flags)\r
 {\r
-        int    bus,slot,fcn;\r
-        int    i;\r
-       // Validate Filename (Pointer and length)\r
-       if(!filename || strlen(filename) != 7)\r
-               return NULL;\r
-       // Check for spacers\r
-       if(filename[2] != '.' || filename[5] != ':')\r
-               return NULL;\r
-       \r
-       // Get Information\r
-       if(filename[0] < '0' || filename[0] > '9')      return NULL;\r
-       bus = (filename[0] - '0')*10;\r
-       if(filename[1] < '0' || filename[1] > '9')      return NULL;\r
-       bus += filename[1] - '0';\r
-       if(filename[3] < '0' || filename[3] > '9')      return NULL;\r
-       slot = (filename[3] - '0')*10;\r
-       if(filename[4] < '0' || filename[4] > '9')      return NULL;\r
-       slot += filename[4] - '0';\r
-       if(filename[6] < '0' || filename[6] > '9')      return NULL;\r
-       fcn = filename[6] - '0';\r
-       \r
        // Find Match\r
-       for(i=0;i<giPCI_DeviceCount;i++)\r
+       for( int i = 0; i < giPCI_DeviceCount; i ++ )\r
        {\r
-               if(gPCI_Devices[i].bus != bus)          continue;\r
-               if(gPCI_Devices[i].slot != slot)        continue;\r
-               if(gPCI_Devices[i].fcn != fcn)  continue;\r
-               \r
-               return &gPCI_Devices[i].Node;\r
+               int cmp = strcmp(gPCI_Devices[i].Name, filename);\r
+               if( cmp > 0 )   // Sorted list\r
+                       break;\r
+               if( cmp == 0 )\r
+                       return &gPCI_Devices[i].Node;\r
        }\r
        \r
        // Error Return\r
@@ -243,7 +280,7 @@ tVFS_Node *PCI_int_FindDirRoot(tVFS_Node *node, const char *filename)
 /**\r
  * \brief Read the PCI configuration space of a device\r
  */\r
-size_t PCI_int_ReadDevice(tVFS_Node *node, off_t pos, size_t length, void *buffer)\r
+size_t PCI_int_ReadDevice(tVFS_Node *node, off_t pos, size_t length, void *buffer, Uint Flags)\r
 {      \r
        if( pos + length > 256 )        return 0;\r
        \r
@@ -365,6 +402,11 @@ Uint32 PCI_ConfigRead(tPCIDev ID, int Offset, int Size)
        if( Offset & (Size - 1) )       return 0;\r
 \r
        dev = &gPCI_Devices[ID];\r
+       // Detect VPCI devices\r
+       if( dev->bus == -1 ) {\r
+               return VPCI_Read(&gaVPCI_Devices[dev->slot], Offset, Size);\r
+       }\r
+\r
        addr = PCI_int_GetBusAddr(dev->bus, dev->slot, dev->fcn, Offset);\r
 \r
        dword = PCI_CfgReadDWord(addr);\r
@@ -384,10 +426,18 @@ void PCI_ConfigWrite(tPCIDev ID, int Offset, int Size, Uint32 Value)
        tPCIDevice      *dev;\r
        Uint32  dword, addr;\r
         int    shift;\r
+\r
        if( ID < 0 || ID >= giPCI_DeviceCount ) return ;\r
        if( Offset < 0 || Offset > 256 )        return ;\r
-       \r
+\r
        dev = &gPCI_Devices[ID];\r
+\r
+       // Detect VPCI devices\r
+       if( dev->bus == -1 ) {\r
+               VPCI_Write(&gaVPCI_Devices[dev->slot], Offset, Size, Value);\r
+               return ;\r
+       }\r
+\r
        addr = PCI_int_GetBusAddr(dev->bus, dev->slot, dev->fcn, Offset);\r
 \r
        if(Size != 4)\r
@@ -413,6 +463,17 @@ void PCI_ConfigWrite(tPCIDev ID, int Offset, int Size, Uint32 Value)
        PCI_CfgWriteDWord(addr, dword);\r
 }\r
 \r
+Uint16 PCI_SetCommand(tPCIDev id, Uint16 SBits, Uint16 CBits)\r
+{\r
+       tPCIDevice      *dev = &gPCI_Devices[id];\r
+       dev->ConfigCache[1] &= ~CBits;\r
+       dev->ConfigCache[1] |= SBits;\r
+       Uint32 addr = PCI_int_GetBusAddr(dev->bus, dev->slot, dev->fcn, 1*4);\r
+       PCI_CfgWriteDWord(addr, dev->ConfigCache[1]);\r
+       dev->ConfigCache[1] = PCI_CfgReadDWord(addr);\r
+       return dev->ConfigCache[1];\r
+}\r
+\r
 /**\r
  * \brief Get the IRQ assigned to a device\r
  */\r
@@ -436,6 +497,61 @@ Uint32 PCI_GetBAR(tPCIDev id, int BARNum)
        return gPCI_Devices[id].ConfigCache[4+BARNum];\r
 }\r
 \r
+/**\r
+ */\r
+Uint64 PCI_GetValidBAR(tPCIDev ID, int BARNum, tPCI_BARType Type)\r
+{\r
+       if( ID < 0 || ID >= giPCI_DeviceCount )\r
+               return 0;\r
+       if( BARNum < 0 || BARNum >= 6 )\r
+               return 0;\r
+       tPCIDevice      *dev = &gPCI_Devices[ID];\r
+       Uint32  bar_val = dev->ConfigCache[4+BARNum];\r
+       Uint64  ret = -1;\r
+       switch( Type )\r
+       {\r
+       case PCI_BARTYPE_IO:\r
+               if( !(bar_val & 1) )\r
+                       return 0;\r
+               ret = bar_val & ~3;\r
+               break;\r
+\r
+       case PCI_BARTYPE_MEMNP:\r
+               if( bar_val & 8 )       return 0;\r
+               if(0)   \r
+       case PCI_BARTYPE_MEMP:\r
+               if( !(bar_val & 8) )    return 0;\r
+       case PCI_BARTYPE_MEM:\r
+               if( bar_val & 1 )       return 0;\r
+               if( (bar_val & 6) == 4 ) {\r
+                       ASSERTCR(BARNum, <, 5, 0);\r
+                       ret = (bar_val & ~0xF) | ((Uint64)dev->ConfigCache[4+BARNum+1] << 32);\r
+               }\r
+               else {\r
+                       ret = bar_val & ~0xF;\r
+               }\r
+               break;\r
+       case PCI_BARTYPE_MEM32:\r
+               if( bar_val & 1 )       return 0;\r
+               if( (bar_val & 6) != 0 )        return 0;\r
+               ret = bar_val & ~0xF;\r
+               break;\r
+       case PCI_BARTYPE_MEM64:\r
+               if( bar_val & 1 )       return 0;\r
+               if( (bar_val & 6) != 4 )        return 0;\r
+               ASSERTCR(BARNum, <, 5, 0);\r
+               ret = (bar_val & ~0xF) | ((Uint64)dev->ConfigCache[4+BARNum+1] << 32);\r
+               break;\r
+       }\r
+       ASSERT(ret != -1);\r
+       if( ret == 0 ) {\r
+               Log_Error("PCI", "PCI%i BAR%i correct type, but unallocated (0x%x)",\r
+                       ID, BARNum, bar_val);\r
+               return 0;\r
+       }\r
+       return ret;\r
+}\r
+\r
 /**\r
  * \brief Get device information for a slot/function\r
  */\r
@@ -449,16 +565,18 @@ int PCI_int_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, tPCIDevice *info)
        vendor_dev = PCI_CfgReadDWord( addr );\r
        if((vendor_dev & 0xFFFF) == 0xFFFF)     // Invalid Device\r
                return 0;\r
+       \r
+       info->bus = bus;\r
+       info->slot = slot;\r
+       info->fcn = fcn;\r
 \r
+       // Read configuration\r
        info->ConfigCache[0] = vendor_dev;\r
        for( i = 1, addr += 4; i < 256/4; i ++, addr += 4 )\r
        {\r
                info->ConfigCache[i] = PCI_CfgReadDWord(addr);\r
        }       \r
 \r
-       info->bus = bus;\r
-       info->slot = slot;\r
-       info->fcn = fcn;\r
        info->vendor = vendor_dev & 0xFFFF;\r
        info->device = vendor_dev >> 16;\r
        tmp = info->ConfigCache[2];\r
@@ -472,14 +590,7 @@ int PCI_int_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, tPCIDevice *info)
 //     #endif\r
        \r
        // Make node name\r
-       info->Name[0] = '0' + bus/10;\r
-       info->Name[1] = '0' + bus%10;\r
-       info->Name[2] = '.';\r
-       info->Name[3] = '0' + slot/10;\r
-       info->Name[4] = '0' + slot%10;\r
-       info->Name[5] = ':';\r
-       info->Name[6] = '0' + fcn;\r
-       info->Name[7] = '\0';\r
+       snprintf(info->Name, 8, "%02x.%02x:%x", bus, slot, fcn);\r
        \r
        // Create VFS Node\r
        memset( &info->Node, 0, sizeof(tVFS_Node) );\r
@@ -488,7 +599,7 @@ int PCI_int_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, tPCIDevice *info)
        info->Node.NumACLs = 1;\r
        info->Node.ACLs = &gVFS_ACL_EveryoneRO;\r
        \r
-       info->Node.Type = &gPCI_RootNodeType;\r
+       info->Node.Type = &gPCI_DevNodeType;\r
        \r
        return 1;\r
 }\r

UCC git Repository :: git.ucc.asn.au