/*\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
#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
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
+ 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);\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
// === 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
#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
+ 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
// 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
+ for(int j = 0; j < 256/4; j ++ )\r
+ devinfo->ConfigCache[i] = 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
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 Rev %i",\r
- BusID, dev, fcn, devInfo.class,\r
- devInfo.vendor, devInfo.device, devInfo.revision);\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
}\r
giPCI_DeviceCount ++;\r
\r
- // If bit 23 of (soemthing) is set, there are sub-functions\r
+ switch(devInfo.ConfigCache[3] & 0x007F0000)\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
/**\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
{\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
{\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
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
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
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
// #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