From: John Hodge Date: Thu, 13 Sep 2012 05:29:21 +0000 (+0800) Subject: Kernel - Added a (slightly hacky) virtual PCI interface X-Git-Tag: rel0.15~706^2~13 X-Git-Url: https://git.ucc.asn.au/?p=tpg%2Facess2.git;a=commitdiff_plain;h=32c93b6a866e881d37704e9c2f8bd89bb121746e Kernel - Added a (slightly hacky) virtual PCI interface - Used to present the Tegra2's USB controllers to the EHCI driver --- diff --git a/KernelLand/Kernel/Makefile b/KernelLand/Kernel/Makefile index 454dd098..a82bbc99 100644 --- a/KernelLand/Kernel/Makefile +++ b/KernelLand/Kernel/Makefile @@ -57,7 +57,7 @@ OBJ += heap.o logging.o debug.o lib.o libc.o adt.o time.o OBJ += drvutil_video.o drvutil_disk.o OBJ += messages.o modules.o syscalls.o system.o OBJ += threads.o mutex.o semaphore.o workqueue.o events.o rwlock.o -OBJ += drv/zero-one.o drv/proc.o drv/fifo.o drv/iocache.o drv/pci.o +OBJ += drv/zero-one.o drv/proc.o drv/fifo.o drv/iocache.o drv/pci.o drv/vpci.o OBJ += drv/vterm.o drv/vterm_font.o drv/vterm_vt100.o drv/vterm_output.o drv/vterm_input.o drv/vterm_termbuf.o OBJ += binary.o bin/elf.o bin/pe.o OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/dir.o vfs/io.o vfs/mount.o diff --git a/KernelLand/Kernel/arch/armv7/Makefile b/KernelLand/Kernel/arch/armv7/Makefile index fad1b55d..5429fe66 100644 --- a/KernelLand/Kernel/arch/armv7/Makefile +++ b/KernelLand/Kernel/arch/armv7/Makefile @@ -12,6 +12,7 @@ LDFLAGS += `$(CC) --print-libgcc-file-name` A_OBJ = start.ao main.o lib.o lib.ao time.o pci.o debug.o A_OBJ += mm_phys.o mm_virt.o proc.o proc.ao +A_OBJ += vpci_$(PLATFORM).o #main.c: Makefile.BuildNum.$(ARCH) diff --git a/KernelLand/Kernel/arch/armv7/link.ld b/KernelLand/Kernel/arch/armv7/link.ld index e45101bf..fbd35820 100644 --- a/KernelLand/Kernel/arch/armv7/link.ld +++ b/KernelLand/Kernel/arch/armv7/link.ld @@ -29,13 +29,27 @@ SECTIONS . += gUsertextPhysStart + _kernel_base - _usertext_vbase; /DISCARD/ : { *(.ARM.extab.init .ARM.exidx.init) } - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } + .ARM.extab : AT( ADDR(.ARM.extab) - _kernel_base) + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } PROVIDE_HIDDEN ( __exidx_start = . ); - .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + .ARM.exidx : AT( ADDR(.ARM.exidx) - _kernel_base) + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } PROVIDE_HIDDEN ( __exidx_end = . ); - .eh_frame_hdr : { *(.eh_frame_hdr) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + .eh_frame_hdr : AT( ADDR(.eh_frame_hdr) - _kernel_base) { + *(.eh_frame_hdr) + } + .eh_frame : AT( ADDR(.eh_frame) - _kernel_base) ONLY_IF_RO + { + KEEP (*(.eh_frame)) + } + .gcc_except_table : AT( ADDR(.gcc_except_table) - _kernel_base) ONLY_IF_RO + { + *(.gcc_except_table .gcc_except_table.*) + } /* 0x4000 (4 pages) alignment needed for root table */ . = ALIGN(0x4000); diff --git a/KernelLand/Kernel/arch/armv7/vpci_tegra2.c b/KernelLand/Kernel/arch/armv7/vpci_tegra2.c new file mode 100644 index 00000000..d44e9d58 --- /dev/null +++ b/KernelLand/Kernel/arch/armv7/vpci_tegra2.c @@ -0,0 +1,34 @@ +/* + * Acess2 Kernel ARMv7 Port + * - By John Hodge (thePowersGang) + * + * vpci_tegra2.c + * - Tegra2 VPCI Definitions + */ +#include + +// === PROTOTYPES === + +// === GLOBALS === +tVPCI_Device gaVPCI_Devices[] = { + { + .Vendor=0x0ACE,.Device=0x1100, + .Class = 0x0C032000, // Serial, USB, ECHI + .BARs = {0xC5000000,0,0,0,0,0}, + .IRQ = 0*32+20, + }, + { + .Vendor=0x0ACE,.Device=0x1100, + .Class = 0x0C032000, // Serial, USB, ECHI + .BARs = {0xC5004000,0,0,0,0,0}, + .IRQ = 0*32+21, + }, + { + .Vendor=0x0ACE,.Device=0x1100, + .Class = 0x0C032000, // Serial, USB, ECHI + .BARs = {0xC5008000,0,0,0,0,0}, + .IRQ = 4*32+1, + } +}; +int giVPCI_DeviceCount = sizeof(gaVPCI_Devices)/sizeof(gaVPCI_Devices[0]); + diff --git a/KernelLand/Kernel/arch/x86/Makefile b/KernelLand/Kernel/arch/x86/Makefile index c3223d01..7372839d 100644 --- a/KernelLand/Kernel/arch/x86/Makefile +++ b/KernelLand/Kernel/arch/x86/Makefile @@ -23,4 +23,4 @@ CPPFLAGS += -DUSE_MP=$(USE_MP) A_OBJ = start.ao main.o mboot.o lib.o desctab.ao errors.o irq.o A_OBJ += mm_phys.o mm_virt.o A_OBJ += proc.o proc.ao time.o vm8086.o -A_OBJ += kpanic.o pci.o +A_OBJ += kpanic.o pci.o vpci.o diff --git a/KernelLand/Kernel/arch/x86/main.c b/KernelLand/Kernel/arch/x86/main.c index af9007da..a2932c1c 100644 --- a/KernelLand/Kernel/arch/x86/main.c +++ b/KernelLand/Kernel/arch/x86/main.c @@ -54,7 +54,7 @@ int kmain(Uint MbMagic, void *MbInfoPtr) gsBootCmdLine = (char*)(mbInfo->CommandLine + KERNEL_BASE); // Adjust Multiboot structure address - mbInfo = (void*)( (Uint)MbInfoPtr + KERNEL_BASE ); + mbInfo = (void*)( (tVAddr)MbInfoPtr + KERNEL_BASE ); nPMemMapEnts = Multiboot_LoadMemoryMap(mbInfo, KERNEL_BASE, pmemmap, MAX_PMEMMAP_ENTS, KERNEL_LOAD, (tVAddr)&gKernelEnd - KERNEL_BASE); diff --git a/KernelLand/Kernel/arch/x86/mboot.c b/KernelLand/Kernel/arch/x86/mboot.c index 5fe4068d..897c9bbb 100644 --- a/KernelLand/Kernel/arch/x86/mboot.c +++ b/KernelLand/Kernel/arch/x86/mboot.c @@ -5,7 +5,7 @@ * mboot.c * - Multiboot Support */ -#define DEBUG 0 +#define DEBUG 1 #include #include @@ -19,26 +19,52 @@ int Multiboot_LoadMemoryMap(tMBoot_Info *MBInfo, tVAddr MapOffset, tPMemMapEnt * ENTER("pMBInfo pMapOffset pMap iMapSize PKStart PKEnd", MBInfo, MapOffset, Map, MapSize, KStart, KEnd); - // Build up memory map - nPMemMapEnts = 0; - while( ent < last && nPMemMapEnts < MapSize ) + // Check that the memory map is present + if( MBInfo->Flags & (1 << 6) ) { - tPMemMapEnt *nent = &Map[nPMemMapEnts]; - nent->Start = ent->Base; - nent->Length = ent->Length; - switch(ent->Type) + // Build up memory map + nPMemMapEnts = 0; + while( ent < last && nPMemMapEnts < MapSize ) { - case 1: - nent->Type = PMEMTYPE_FREE; - break; - default: - nent->Type = PMEMTYPE_RESERVED; - break; + tPMemMapEnt *nent = &Map[nPMemMapEnts]; + if( !MM_GetPhysAddr(ent) ) + Log_KernelPanic("MBoot", "MBoot Map entry %i addres bad (%p)", + nPMemMapEnts, ent); + + nent->Start = ent->Base; + nent->Length = ent->Length; + switch(ent->Type) + { + case 1: + nent->Type = PMEMTYPE_FREE; + break; + default: + nent->Type = PMEMTYPE_RESERVED; + break; + } + nent->NUMADomain = 0; + + nPMemMapEnts ++; + ent = (void*)( (tVAddr)ent + ent->Size + 4 ); } - nent->NUMADomain = 0; - - nPMemMapEnts ++; - ent = (void*)( (tVAddr)ent + ent->Size + 4 ); + } + else if( MBInfo->Flags & (1 << 0) ) + { + Log_Warning("MBoot", "No memory map passed, using mem_lower and mem_upper"); + nPMemMapEnts = 2; + Map[0].Start = 0; + Map[0].Length = MBInfo->LowMem * 1024; + Map[0].Type = PMEMTYPE_FREE; + Map[0].NUMADomain = 0; + + Map[1].Start = 0x100000; + Map[1].Length = MBInfo->HighMem * 1024; + Map[1].Type = PMEMTYPE_FREE; + Map[1].NUMADomain = 0; + } + else + { + Log_KernelPanic("MBoot", "Multiboot didn't pass memory information"); } // Ensure it's valid @@ -51,19 +77,28 @@ int Multiboot_LoadMemoryMap(tMBoot_Info *MBInfo, tVAddr MapOffset, tPMemMapEnt * KStart, KEnd - KStart ); - // Replace modules with PMEMTYPE_USED - nPMemMapEnts = PMemMap_MarkRangeUsed(Map, nPMemMapEnts, MapSize, - MBInfo->Modules, MBInfo->ModuleCount*sizeof(tMBoot_Module) - ); - tMBoot_Module *mods = (void*)( (tVAddr)MBInfo->Modules + MapOffset); - for( int i = 0; i < MBInfo->ModuleCount; i ++ ) + PMemMap_DumpBlocks(Map, nPMemMapEnts); + + // Check if boot modules were passed + if( MBInfo->Flags & (1 << 3) ) { - nPMemMapEnts = PMemMap_MarkRangeUsed( - Map, nPMemMapEnts, MapSize, - mods->Start, mods->End - mods->Start + // Replace modules with PMEMTYPE_USED + nPMemMapEnts = PMemMap_MarkRangeUsed(Map, nPMemMapEnts, MapSize, + MBInfo->Modules, MBInfo->ModuleCount*sizeof(tMBoot_Module) ); + LOG("MBInfo->Modules = %x", MBInfo->Modules); + tMBoot_Module *mods = (void*)( (tVAddr)MBInfo->Modules + MapOffset); + for( int i = 0; i < MBInfo->ModuleCount; i ++ ) + { + LOG("&mods[%i] = %p", i, &mods[i]); + LOG("mods[i] = {0x%x -> 0x%x}", mods[i].Start, mods[i].End); + nPMemMapEnts = PMemMap_MarkRangeUsed( + Map, nPMemMapEnts, MapSize, + mods[i].Start, mods[i].End - mods[i].Start + ); + } } - + // Debug - Output map PMemMap_DumpBlocks(Map, nPMemMapEnts); @@ -73,6 +108,12 @@ int Multiboot_LoadMemoryMap(tMBoot_Info *MBInfo, tVAddr MapOffset, tPMemMapEnt * tBootModule *Multiboot_LoadModules(tMBoot_Info *MBInfo, tVAddr MapOffset, int *ModuleCount) { + if( !(MBInfo->Flags & (1 << 3)) ) { + *ModuleCount = 0; + Log_Log("Arch", "No multiboot module information passed"); + return NULL; + } + tMBoot_Module *mods = (void*)( MBInfo->Modules + MapOffset ); *ModuleCount = MBInfo->ModuleCount; tBootModule *ret = malloc( MBInfo->ModuleCount * sizeof(*ret) ); diff --git a/KernelLand/Kernel/arch/x86/vpci.c b/KernelLand/Kernel/arch/x86/vpci.c new file mode 100644 index 00000000..0319e6ee --- /dev/null +++ b/KernelLand/Kernel/arch/x86/vpci.c @@ -0,0 +1,13 @@ +/* + * Acess2 Kernel x86 Port + * - By John Hodge (thePowersGang) + * + * vpci.c + * - Virtual PCI Bus + */ +#include + +// === GLOBALS === + int giVPCI_DeviceCount = 0; +tVPCI_Device gaVPCI_Devices[0]; + diff --git a/KernelLand/Kernel/drv/pci.c b/KernelLand/Kernel/drv/pci.c index 702c9ccc..2e1ce151 100644 --- a/KernelLand/Kernel/drv/pci.c +++ b/KernelLand/Kernel/drv/pci.c @@ -1,6 +1,9 @@ /* - * AcessOS/AcessBasic v0.1 - * PCI Bus Driver + * Acess2 Kernel + * - By John Hodge (thePowersGang) + * + * drv/pci.c + * - PCI Enumeration and Arbitration */ #define DEBUG 0 #include @@ -9,9 +12,11 @@ #include #include #include +#include #define USE_PORT_BITMAP 0 #define LIST_DEVICES 1 +#define PCI_MAX_BUSSES 8 // === STRUCTURES === typedef struct sPCIDevice @@ -42,6 +47,7 @@ size_t PCI_int_ReadDevice(tVFS_Node *node, off_t Offset, size_t Length, void *bu // === GLOBALS === MODULE_DEFINE(0, 0x0100, PCI, PCI_Install, NULL, NULL); int giPCI_BusCount = 1; +Uint8 gaPCI_BusNumbers[PCI_MAX_BUSSES]; int giPCI_InodeHandle = -1; int giPCI_DeviceCount = 0; tPCIDevice *gPCI_Devices = NULL; @@ -95,12 +101,18 @@ int PCI_Install(char **Arguments) #endif // Scan Bus (Bus 0, Don't fill gPCI_Devices) + giPCI_DeviceCount = 0; + giPCI_BusCount = 1; + gaPCI_BusNumbers[0] = 0; for( bus = 0; bus < giPCI_BusCount; bus ++ ) { - ret = PCI_ScanBus(bus, 0); + ret = PCI_ScanBus(gaPCI_BusNumbers[bus], 0); if(ret != MODULE_ERR_OK) return ret; } - + // TODO: PCIe + // - Add VPCI Devices + giPCI_DeviceCount += giVPCI_DeviceCount; + if(giPCI_DeviceCount == 0) { Log_Notice("PCI", "No devices were found"); return MODULE_ERR_NOTNEEDED; @@ -123,7 +135,33 @@ int PCI_Install(char **Arguments) // Rescan, filling the PCI device array for( bus = 0; bus < giPCI_BusCount; bus ++ ) { - PCI_ScanBus(bus, 1); + PCI_ScanBus(gaPCI_BusNumbers[bus], 1); + } + // Insert VPCI Devices + for( int i = 0; i < giVPCI_DeviceCount; i ++ ) + { + tPCIDevice *devinfo = &gPCI_Devices[giPCI_DeviceCount]; + + devinfo->bus = -1; + devinfo->slot = i; + devinfo->fcn = 0; + devinfo->vendor = gaVPCI_Devices[i].Vendor; + devinfo->device = gaVPCI_Devices[i].Device; + devinfo->revision = gaVPCI_Devices[i].Class & 0xFF; + devinfo->class = gaVPCI_Devices[i].Class >> 8; + snprintf(devinfo->Name, sizeof(devinfo->Name), "%02x.%02x:%x", 0xFF, i, 0); + + for(int j = 0; j < 256/4; j ++ ) + devinfo->ConfigCache[i] = VPCI_Read(&gaVPCI_Devices[i], j*4, 4); + + memset(&devinfo->Node, 0, sizeof(devinfo->Node)); + devinfo->Node.Inode = giPCI_DeviceCount; + devinfo->Node.Size = 256; + devinfo->Node.NumACLs = 1; + devinfo->Node.ACLs = &gVFS_ACL_EveryoneRO; + devinfo->Node.Type = &gPCI_DevNodeType; + + giPCI_DeviceCount ++; } // Complete Driver Structure @@ -158,26 +196,12 @@ int PCI_ScanBus(int BusID, int bFill) if(!PCI_int_EnumDevice(BusID, dev, fcn, &devInfo)) continue; - if(devInfo.class == PCI_OC_PCIBRIDGE) - { - #if LIST_DEVICES - if( !bFill ) - 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 - { - #if LIST_DEVICES - if( !bFill ) - Log_Log("PCI", "Device %i,%i:%i %06x => 0x%04x:0x%04x Rev %i", - BusID, dev, fcn, devInfo.class, - devInfo.vendor, devInfo.device, devInfo.revision); - #endif - } + #if LIST_DEVICES + if( !bFill ) + Log_Log("PCI", "Device %i,%i:%i %06x => 0x%04x:0x%04x Rev %i", + BusID, dev, fcn, devInfo.class, + devInfo.vendor, devInfo.device, devInfo.revision); + #endif if( bFill ) { devInfo.Node.Inode = giPCI_DeviceCount; @@ -185,7 +209,28 @@ int PCI_ScanBus(int BusID, int bFill) } giPCI_DeviceCount ++; - // If bit 23 of (soemthing) is set, there are sub-functions + switch(devInfo.ConfigCache[3] & 0x007F0000) + { + case 0x00: // Normal device + break; + case 0x01: // PCI-PCI Bridge + { + // TODO: Add to list of busses? + Uint8 sec = (devInfo.ConfigCache[6] & 0x0000FF00) >> 8; + #if LIST_DEVICES + if( !bFill ) { + Uint8 pri = (devInfo.ConfigCache[6] & 0x000000FF) >> 0; + Log_Log("PCI", "- PCI-PCI Bridge %02x=>%02x", pri, sec); + } + #endif + gaPCI_BusNumbers[giPCI_BusCount++] = sec; + } + break; + case 0x02: // PCI-CardBus Bridge + break; + } + + // If bit 8 of the Header Type register is set, there are sub-functions if(fcn == 0 && !(devInfo.ConfigCache[3] & 0x00800000) ) break; } @@ -212,35 +257,16 @@ int PCI_int_ReadDirRoot(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]) */ tVFS_Node *PCI_int_FindDirRoot(tVFS_Node *node, const char *filename) { - int bus,slot,fcn; int i; - // Validate Filename (Pointer and length) - if(!filename || strlen(filename) != 7) - return NULL; - // Check for spacers - if(filename[2] != '.' || filename[5] != ':') - return NULL; - - // Get Information - if(filename[0] < '0' || filename[0] > '9') return NULL; - bus = (filename[0] - '0')*10; - if(filename[1] < '0' || filename[1] > '9') return NULL; - bus += filename[1] - '0'; - if(filename[3] < '0' || filename[3] > '9') return NULL; - slot = (filename[3] - '0')*10; - if(filename[4] < '0' || filename[4] > '9') return NULL; - slot += filename[4] - '0'; - if(filename[6] < '0' || filename[6] > '9') return NULL; - fcn = filename[6] - '0'; // Find Match for(i=0;i 0 ) // Sorted list + break; + if( cmp == 0 ) + return &gPCI_Devices[i].Node; } // Error Return @@ -372,6 +398,11 @@ Uint32 PCI_ConfigRead(tPCIDev ID, int Offset, int Size) if( Offset & (Size - 1) ) return 0; dev = &gPCI_Devices[ID]; + // Detect VPCI devices + if( dev->bus == -1 ) { + return VPCI_Read(&gaVPCI_Devices[dev->slot], Offset, Size); + } + addr = PCI_int_GetBusAddr(dev->bus, dev->slot, dev->fcn, Offset); dword = PCI_CfgReadDWord(addr); @@ -391,10 +422,18 @@ void PCI_ConfigWrite(tPCIDev ID, int Offset, int Size, Uint32 Value) tPCIDevice *dev; Uint32 dword, addr; int shift; + if( ID < 0 || ID >= giPCI_DeviceCount ) return ; if( Offset < 0 || Offset > 256 ) return ; - + dev = &gPCI_Devices[ID]; + + // Detect VPCI devices + if( dev->bus == -1 ) { + VPCI_Write(&gaVPCI_Devices[dev->slot], Offset, Size, Value); + return ; + } + addr = PCI_int_GetBusAddr(dev->bus, dev->slot, dev->fcn, Offset); if(Size != 4) @@ -456,16 +495,18 @@ int PCI_int_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, tPCIDevice *info) vendor_dev = PCI_CfgReadDWord( addr ); if((vendor_dev & 0xFFFF) == 0xFFFF) // Invalid Device return 0; + + info->bus = bus; + info->slot = slot; + info->fcn = fcn; + // Read configuration info->ConfigCache[0] = vendor_dev; for( i = 1, addr += 4; i < 256/4; i ++, addr += 4 ) { info->ConfigCache[i] = PCI_CfgReadDWord(addr); } - info->bus = bus; - info->slot = slot; - info->fcn = fcn; info->vendor = vendor_dev & 0xFFFF; info->device = vendor_dev >> 16; tmp = info->ConfigCache[2]; @@ -479,14 +520,7 @@ int PCI_int_EnumDevice(Uint16 bus, Uint16 slot, Uint16 fcn, tPCIDevice *info) // #endif // Make node name - info->Name[0] = '0' + bus/10; - info->Name[1] = '0' + bus%10; - info->Name[2] = '.'; - info->Name[3] = '0' + slot/10; - info->Name[4] = '0' + slot%10; - info->Name[5] = ':'; - info->Name[6] = '0' + fcn; - info->Name[7] = '\0'; + snprintf(info->Name, 8, "%02x.%02x:%x", bus, slot, fcn); // Create VFS Node memset( &info->Node, 0, sizeof(tVFS_Node) ); diff --git a/KernelLand/Kernel/drv/vpci.c b/KernelLand/Kernel/drv/vpci.c new file mode 100644 index 00000000..4fccdb85 --- /dev/null +++ b/KernelLand/Kernel/drv/vpci.c @@ -0,0 +1,84 @@ +/* + * Acess2 Kernel + * - By John Hodge (thePowersGang) + * + * drv/vpci.c + * - Virtual PCI Bus + */ +#include + +// === CODE === +Uint32 VPCI_Read(tVPCI_Device *Dev, Uint8 Offset, Uint8 Size) +{ + Uint32 tmp_dword = 0; + + if( Size > 4 || Size == 3 || Size == 0 ) + return 0; + if( Offset & (Size - 1) ) + return 0; + + switch( Offset >> 2 ) + { + case 0: // Vendor[0:15], Device[16:31] + tmp_dword = (Dev->Vendor) | (Dev->Device << 16); + break; + case 2: // Class Code + tmp_dword = Dev->Class; + break; + // 1: Command[0:15], Status[16:31] + // 3: Cache Line Size, Latency Timer, Header Type, BIST + // 4-9: BARs + // 10: Unused (Cardbus CIS Pointer) + // 11: Subsystem Vendor ID, Subsystem ID + // 12: Expansion ROM Address + // 13: Capabilities[0:8], Reserved[9:31] + // 14: Reserved + // 15: Interrupt Line, Interrupt Pin, Min Grant, Max Latency + default: + tmp_dword = Dev->Read(Dev->Ptr, Offset >> 2); + break; + } + + tmp_dword >>= 8*(Offset & 3); + switch(Size) + { + case 4: break; + case 2: tmp_dword &= 0xFFFF; break; + case 1: tmp_dword &= 0xFF; + } + + return tmp_dword; +} + +void VPCI_Write(tVPCI_Device *Dev, Uint8 Offset, Uint8 Size, Uint32 Data) +{ + Uint32 tmp_dword; + if( Size > 4 || Size == 3 || Size == 0 ) + return ; + if( Offset & (Size - 1) ) + return ; + + switch(Offset >> 2) + { + case 0: // Vendor / Device IDs + case 2: // Class Code + // READ ONLY + return ; + } + + tmp_dword = Dev->Read(Dev->Ptr, Offset>>2); + switch(Size) + { + case 4: tmp_dword = 0; break; + case 2: + tmp_dword &= ~(0xFFFF << ((Offset&2)*16)); + Data |= 0xFFFF; + break; + case 1: + tmp_dword &= ~(0xFF << ((Offset&3)*8)); + Data |= 0xFF; + break; + } + tmp_dword |= Data << ((Offset&3)*8); + Dev->Write(Dev->Ptr, Offset>>2, tmp_dword); +} diff --git a/KernelLand/Kernel/include/virtual_pci.h b/KernelLand/Kernel/include/virtual_pci.h new file mode 100644 index 00000000..c6408cd4 --- /dev/null +++ b/KernelLand/Kernel/include/virtual_pci.h @@ -0,0 +1,41 @@ +/* + * Acess2 Kernel + * - By John Hodge (thePowersGang) + * + * virtual_pci.h + * - Virtual PCI bus definitions + */ +#ifndef _VIRTUAL_PCI_H_ +#define _VIRTUAL_PCI_H_ +#include + +typedef struct sVPCI_Device tVPCI_Device; + +struct sVPCI_Device +{ + void *Ptr; + + // Vendor/Device is defined at runtime as 0x0ACE:0x[ARCH][ARCH][IDX][IDX] + Uint16 Vendor; + Uint16 Device; + // Class code (Class, Subclass, Programming Interface, Revision) + Uint32 Class; + + Uint32 BARs[6]; + Uint8 IRQ; + + /** + * \param Ptr Value in sVPCI_Device.Ptr + * \param Data Data to write to the specified address + */ + void (*Write)(void *Ptr, Uint8 DWord, Uint32 Data); + Uint32 (*Read)(void *Ptr, Uint8 DWord); +}; + +extern int giVPCI_DeviceCount; +extern tVPCI_Device gaVPCI_Devices[]; + +extern Uint32 VPCI_Read(tVPCI_Device *Dev, Uint8 Offset, Uint8 Size); +extern void VPCI_Write(tVPCI_Device *Dev, Uint8 Offset, Uint8 Size, Uint32 Data); +#endif +