mirror of
				https://gitlab.com/sortix/sortix.git
				synced 2023-02-13 20:55:38 -05:00 
			
		
		
		
	Refactored the PCI code to become a library of utility functions.
This commit is contained in:
		
							parent
							
								
									5f6ca5e729
								
							
						
					
					
						commit
						19b5451f3b
					
				
					 4 changed files with 244 additions and 307 deletions
				
			
		
							
								
								
									
										75
									
								
								sortix/include/sortix/kernel/pci.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								sortix/include/sortix/kernel/pci.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,75 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
	Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
 | 
			
		||||
 | 
			
		||||
	This file is part of Sortix.
 | 
			
		||||
 | 
			
		||||
	Sortix is free software: you can redistribute it and/or modify it under the
 | 
			
		||||
	terms of the GNU General Public License as published by the Free Software
 | 
			
		||||
	Foundation, either version 3 of the License, or (at your option) any later
 | 
			
		||||
	version.
 | 
			
		||||
 | 
			
		||||
	Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
 | 
			
		||||
	WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
			
		||||
	FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 | 
			
		||||
	details.
 | 
			
		||||
 | 
			
		||||
	You should have received a copy of the GNU General Public License along with
 | 
			
		||||
	Sortix. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
	pci.h
 | 
			
		||||
	Functions for handling PCI devices.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef SORTIX_PCI_H
 | 
			
		||||
#define SORTIX_PCI_H
 | 
			
		||||
 | 
			
		||||
namespace Sortix {
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
	uint16_t deviceid;
 | 
			
		||||
	uint16_t vendorid;
 | 
			
		||||
} pciid_t;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
	uint8_t classid;
 | 
			
		||||
	uint8_t subclassid;
 | 
			
		||||
	uint8_t progif;
 | 
			
		||||
	uint8_t revid;
 | 
			
		||||
} pcitype_t;
 | 
			
		||||
 | 
			
		||||
// memset(&pcifind, 255, sizeof(pcifind)) and fill out rest.
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
	uint16_t deviceid;
 | 
			
		||||
	uint16_t vendorid;
 | 
			
		||||
	uint8_t classid;
 | 
			
		||||
	uint8_t subclassid;
 | 
			
		||||
	uint8_t progif;
 | 
			
		||||
	uint8_t revid;
 | 
			
		||||
} pcifind_t;
 | 
			
		||||
 | 
			
		||||
namespace PCI {
 | 
			
		||||
 | 
			
		||||
void Init();
 | 
			
		||||
uint32_t MakeDevAddr(uint8_t bus, uint8_t slot, uint8_t func);
 | 
			
		||||
void SplitDevAddr(uint32_t devaddr, uint8_t* vals /* bus, slot, func */);
 | 
			
		||||
uint8_t Read8(uint32_t devaddr, uint8_t off); // Host endian
 | 
			
		||||
uint16_t Read16(uint32_t devaddr, uint8_t off); // Host endian
 | 
			
		||||
uint32_t Read32(uint32_t devaddr, uint8_t off); // Host endian
 | 
			
		||||
uint32_t ReadRaw32(uint32_t devaddr, uint8_t off); // PCI endian
 | 
			
		||||
void Write32(uint32_t devaddr, uint8_t off, uint32_t val); // Host endian
 | 
			
		||||
void WriteRaw32(uint32_t devaddr, uint8_t off, uint32_t val); // PCI endian
 | 
			
		||||
pciid_t GetDeviceId(uint32_t devaddr);
 | 
			
		||||
pcitype_t GetDeviceType(uint32_t devaddr);
 | 
			
		||||
uint32_t SearchForDevice(pcifind_t pcifind);
 | 
			
		||||
addr_t ParseDevBar0(uint32_t devaddr);
 | 
			
		||||
 | 
			
		||||
} // namespace PCI
 | 
			
		||||
} // namespace Sortix
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -27,6 +27,7 @@
 | 
			
		|||
#include <sortix/kernel/kthread.h>
 | 
			
		||||
#include <sortix/kernel/refcount.h>
 | 
			
		||||
#include <sortix/kernel/textbuffer.h>
 | 
			
		||||
#include <sortix/kernel/pci.h>
 | 
			
		||||
#include <libmaxsi/memory.h>
 | 
			
		||||
#include <libmaxsi/string.h>
 | 
			
		||||
#include <libmaxsi/format.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +43,7 @@
 | 
			
		|||
#include "process.h"
 | 
			
		||||
#include "scheduler.h"
 | 
			
		||||
#include "syscall.h"
 | 
			
		||||
#include "pci.h"
 | 
			
		||||
#include "ata.h"
 | 
			
		||||
#include "com.h"
 | 
			
		||||
#include "uart.h"
 | 
			
		||||
#include "vgatextbuffer.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -218,6 +219,9 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo)
 | 
			
		|||
	// Search for PCI devices and load their drivers.
 | 
			
		||||
	PCI::Init();
 | 
			
		||||
 | 
			
		||||
	// Initialize ATA devices.
 | 
			
		||||
	ATA::Init();
 | 
			
		||||
 | 
			
		||||
	// Alright, now the system's drivers are loaded and initialized. It is
 | 
			
		||||
	// time to load the initial user-space programs and start execution of
 | 
			
		||||
	// the actual operating system.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										431
									
								
								sortix/pci.cpp
									
										
									
									
									
								
							
							
						
						
									
										431
									
								
								sortix/pci.cpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
 | 
			
		||||
	Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
 | 
			
		||||
 | 
			
		||||
	This file is part of Sortix.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -14,283 +14,180 @@
 | 
			
		|||
	FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 | 
			
		||||
	details.
 | 
			
		||||
 | 
			
		||||
	You should have received a copy of the GNU General Public License along
 | 
			
		||||
	with Sortix. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
	You should have received a copy of the GNU General Public License along with
 | 
			
		||||
	Sortix. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
	pci.h
 | 
			
		||||
	Handles basic PCI bus stuff.
 | 
			
		||||
	pci.cpp
 | 
			
		||||
	Functions for handling PCI devices.
 | 
			
		||||
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <sortix/kernel/platform.h>
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include <libmaxsi/error.h>
 | 
			
		||||
#include "pci.h"
 | 
			
		||||
#include <sortix/kernel/log.h>
 | 
			
		||||
#include "ata.h"
 | 
			
		||||
#include <sortix/kernel/endian.h>
 | 
			
		||||
#include <sortix/kernel/pci.h>
 | 
			
		||||
#include "cpu.h" // TODO: Put this in some <sortix/kernel/cpu.h>
 | 
			
		||||
 | 
			
		||||
using namespace Maxsi;
 | 
			
		||||
// TODO: Verify that the endian conversions in this file actually works. I have
 | 
			
		||||
// a sneaking suspicion that they won't work on non-little endian platforms.
 | 
			
		||||
 | 
			
		||||
namespace Sortix
 | 
			
		||||
namespace Sortix {
 | 
			
		||||
namespace PCI {
 | 
			
		||||
 | 
			
		||||
const uint16_t CONFIG_ADDRESS = 0xCF8;
 | 
			
		||||
const uint16_t CONFIG_DATA = 0xCFC;
 | 
			
		||||
 | 
			
		||||
uint32_t MakeDevAddr(uint8_t bus, uint8_t slot, uint8_t func)
 | 
			
		||||
{
 | 
			
		||||
	namespace PCI
 | 
			
		||||
	//ASSERT(bus < 1UL<<8UL); // bus is 8 bit anyways.
 | 
			
		||||
	ASSERT(slot < 1UL<<5UL);
 | 
			
		||||
	ASSERT(func < 1UL<<3UL);
 | 
			
		||||
	return func << 8U | slot << 11U | bus << 16U | 1 << 31U;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SplitDevAddr(uint32_t devaddr, uint8_t* vals /* bus, slot, func */)
 | 
			
		||||
{
 | 
			
		||||
	vals[0] = devaddr >> 16U & ((1UL<<8UL)-1);
 | 
			
		||||
	vals[1] = devaddr >> 11U & ((1UL<<3UL)-1);
 | 
			
		||||
	vals[2] = devaddr >>  8U & ((1UL<<5UL)-1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t ReadRaw32(uint32_t devaddr, uint8_t off)
 | 
			
		||||
{
 | 
			
		||||
	CPU::OutPortL(CONFIG_ADDRESS, devaddr + off);
 | 
			
		||||
	return CPU::InPortL(CONFIG_DATA);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WriteRaw32(uint32_t devaddr, uint8_t off, uint32_t val)
 | 
			
		||||
{
 | 
			
		||||
	CPU::OutPortL(CONFIG_ADDRESS, devaddr + off);
 | 
			
		||||
	CPU::OutPortL(CONFIG_DATA, val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t Read32(uint32_t devaddr, uint8_t off)
 | 
			
		||||
{
 | 
			
		||||
	return LittleToHost(ReadRaw32(devaddr, off));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Write32(uint32_t devaddr, uint8_t off, uint32_t val)
 | 
			
		||||
{
 | 
			
		||||
	WriteRaw32(devaddr, off, HostToLittle(val));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t Read16(uint32_t devaddr, uint8_t off)
 | 
			
		||||
{
 | 
			
		||||
	ASSERT((off & 0x1) == 0);
 | 
			
		||||
	uint8_t alignedoff = off & ~0x3;
 | 
			
		||||
	union { uint16_t val16[2]; uint32_t val32; };
 | 
			
		||||
	val32 = ReadRaw32(devaddr, alignedoff);
 | 
			
		||||
	uint16_t ret = off & 0x2 ? val16[0] : val16[1];
 | 
			
		||||
	return LittleToHost(ret);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t Read8(uint32_t devaddr, uint8_t off)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t alignedoff = off & ~0x1;
 | 
			
		||||
	union { uint8_t val8[2]; uint32_t val16; };
 | 
			
		||||
	val16 = HostToLittle(Read16(devaddr, alignedoff));
 | 
			
		||||
	uint8_t ret = off & 0x1 ? val8[0] : val8[1];
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t CheckDevice(uint8_t bus, uint8_t slot, uint8_t func)
 | 
			
		||||
{
 | 
			
		||||
	return Read32(MakeDevAddr(bus, slot, func), 0x0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pciid_t GetDeviceId(uint32_t devaddr)
 | 
			
		||||
{
 | 
			
		||||
	pciid_t ret;
 | 
			
		||||
	ret.deviceid = Read16(devaddr, 0x00);
 | 
			
		||||
	ret.vendorid = Read16(devaddr, 0x02);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pcitype_t GetDeviceType(uint32_t devaddr)
 | 
			
		||||
{
 | 
			
		||||
	pcitype_t ret;
 | 
			
		||||
	ret.classid = Read8(devaddr, 0x08);
 | 
			
		||||
	ret.subclassid = Read8(devaddr, 0x09);
 | 
			
		||||
	ret.progif = Read8(devaddr, 0x0A);
 | 
			
		||||
	ret.revid = Read8(devaddr, 0x0B);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool MatchesSearchCriteria(uint32_t devaddr, pcifind_t pcifind)
 | 
			
		||||
{
 | 
			
		||||
	pciid_t id = GetDeviceId(devaddr);
 | 
			
		||||
	if ( id.vendorid == 0xFFFF && id.deviceid == 0xFFFF )
 | 
			
		||||
		return false;
 | 
			
		||||
	pcitype_t type = GetDeviceType(devaddr);
 | 
			
		||||
	if ( pcifind.vendorid != 0xFFFF && id.vendorid != pcifind.vendorid )
 | 
			
		||||
		return false;
 | 
			
		||||
	if ( pcifind.deviceid != 0xFFFF && id.deviceid != pcifind.deviceid )
 | 
			
		||||
		return false;
 | 
			
		||||
	if ( pcifind.classid != 0xFF && type.classid != pcifind.classid )
 | 
			
		||||
		return false;
 | 
			
		||||
	if ( pcifind.subclassid != 0xFF && type.subclassid != pcifind.subclassid )
 | 
			
		||||
		return false;
 | 
			
		||||
	if ( pcifind.progif != 0xFF && type.progif != pcifind.progif )
 | 
			
		||||
		return false;
 | 
			
		||||
	if ( pcifind.revid != 0xFF && type.revid != pcifind.revid )
 | 
			
		||||
		return false;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t SearchForDeviceOnBus(uint8_t bus, pcifind_t pcifind)
 | 
			
		||||
{
 | 
			
		||||
	for ( unsigned slot = 0; slot < 32; slot++ )
 | 
			
		||||
	{
 | 
			
		||||
		const uint16_t Config_Address = 0xCF8;
 | 
			
		||||
		const uint16_t Config_Data = 0xCFC;
 | 
			
		||||
 | 
			
		||||
		uint32_t SwapBytes(uint32_t I)
 | 
			
		||||
		unsigned numfuncs = 1;
 | 
			
		||||
		for ( unsigned func = 0; func < numfuncs; func++ )
 | 
			
		||||
		{
 | 
			
		||||
			return (I >> 24) | ((I >> 8) & 0x0000FF00) | ((I << 8) & 0x00FF0000) | (I << 24);
 | 
			
		||||
			uint32_t devaddr = MakeDevAddr(bus, slot, func);
 | 
			
		||||
			if ( MatchesSearchCriteria(devaddr, pcifind) )
 | 
			
		||||
				return devaddr;
 | 
			
		||||
			uint8_t header = Read8(devaddr, 0x0D); // Secondary Bus Number.
 | 
			
		||||
			if ( header & 0x80 ) // Multi function device.
 | 
			
		||||
				numfuncs = 8;
 | 
			
		||||
			if ( (header & 0x7F) == 0x01 ) // PCI to PCI bus.
 | 
			
		||||
			{
 | 
			
		||||
				uint8_t subbusid = Read8(devaddr, 0x1A);
 | 
			
		||||
				uint32_t recret = SearchForDeviceOnBus(subbusid, pcifind);
 | 
			
		||||
				if ( recret )
 | 
			
		||||
					return recret;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		const char* ToDeviceDesc(uint32_t ProductInfo, uint32_t DeviceType)
 | 
			
		||||
		{
 | 
			
		||||
			uint32_t Class			=	(DeviceType) >> 24;
 | 
			
		||||
			uint32_t SubClass		=	(DeviceType >> 16) & 0xFF;
 | 
			
		||||
			uint32_t ProgIF			=	(DeviceType >> 8) & 0xFF;
 | 
			
		||||
			uint32_t RevisionID		=	(DeviceType) & 0xFF;
 | 
			
		||||
uint32_t SearchForDevice(pcifind_t pcifind)
 | 
			
		||||
{
 | 
			
		||||
	// Search on bus 0 and recurse on other detected busses.
 | 
			
		||||
	return SearchForDeviceOnBus(0, pcifind);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
			if ( Class == 0x00 )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Any device except for VGA-Compatible devices"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "VGA-Compatible Device"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x01 )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "SCSI Bus Controller"; }
 | 
			
		||||
				if ( SubClass == 0x01 ) { return "IDE Controller"; }
 | 
			
		||||
				if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "Floppy Disk Controller"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "IPI Bus Controller"; }
 | 
			
		||||
				if ( SubClass == 0x04 && ProgIF == 0x00 ) { return "RAID Controller"; }
 | 
			
		||||
				if ( SubClass == 0x05 && ProgIF == 0x20 ) { return "ATA Controller (Single DMA)"; }
 | 
			
		||||
				if ( SubClass == 0x05 && ProgIF == 0x30 ) { return "ATA Controller (Chained DMA)"; }
 | 
			
		||||
				if ( SubClass == 0x06 && ProgIF == 0x00 ) { return "Serial ATA (Direct Port Access)"; }
 | 
			
		||||
				if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Mass Storage Controller"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x02 )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Ethernet Controller"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "Token Ring Controller"; }
 | 
			
		||||
				if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "FDDI Controller"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "ATM Controller"; }
 | 
			
		||||
				if ( SubClass == 0x04 && ProgIF == 0x00 ) { return "ISDN Controller"; }
 | 
			
		||||
				if ( SubClass == 0x05 && ProgIF == 0x00 ) { return "WorldFip Controller"; }
 | 
			
		||||
				if ( SubClass == 0x05 && ProgIF == 0x00 ) { return "ATA Controller (Chained DMA)"; }
 | 
			
		||||
				if ( SubClass == 0x06 ) { return "PICMG 2.14 Multi Computing"; }
 | 
			
		||||
				if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Network Controller"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x03 )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "VGA-Compatible Controller"; }
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x01 ) { return "8512-Compatible Controller"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "XGA Controller"; }
 | 
			
		||||
				if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "3D Controller (Not VGA-Compatible)"; }
 | 
			
		||||
				if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Display Controller"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x04 )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Video Device"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "Audio Device"; }
 | 
			
		||||
				if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "Computer Telephony Device"; }
 | 
			
		||||
				if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Multimedia Device"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x05 )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "RAM Controller"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "Flash Controller"; }
 | 
			
		||||
				if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Memory Controller"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x06 )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Host Bridge"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "ISA Bridge"; }
 | 
			
		||||
				if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "EISA Bridge"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "MCA Bridge"; }
 | 
			
		||||
				if ( SubClass == 0x04 && ProgIF == 0x00 ) { return "PCI-to-PCI Bridge"; }
 | 
			
		||||
				if ( SubClass == 0x04 && ProgIF == 0x01 ) { return "PCI-to-PCI Bridge (Subtractive Decode)"; }
 | 
			
		||||
				if ( SubClass == 0x05 && ProgIF == 0x00 ) { return "PCMCIA Bridge"; }
 | 
			
		||||
				if ( SubClass == 0x06 && ProgIF == 0x00 ) { return "NuBus Bridge"; }
 | 
			
		||||
				if ( SubClass == 0x07 && ProgIF == 0x00 ) { return "CardBus Bridge"; }
 | 
			
		||||
				if ( SubClass == 0x08 ) { return "RACEway Bridge"; }
 | 
			
		||||
				if ( SubClass == 0x09 && ProgIF == 0x40 ) { return "PCI-to-PCI Bridge (Semi-Transparent, Primary)"; }
 | 
			
		||||
				if ( SubClass == 0x09 && ProgIF == 0x80 ) { return "PCI-to-PCI Bridge (Semi-Transparent, Secondary)"; }
 | 
			
		||||
				if ( SubClass == 0x0A && ProgIF == 0x00 ) { return "InfiniBrand-to-PCI Host Bridge"; }
 | 
			
		||||
				if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Bridge Device"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x07 )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Generic XT-Compatible Serial Controller"; }
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x01 ) { return "16450-Compatible Serial Controller"; }
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x02 ) { return "16550-Compatible Serial Controller"; }
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x03 ) { return "16650-Compatible Serial Controller"; }
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x04 ) { return "16750-Compatible Serial Controller"; }
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x05 ) { return "16850-Compatible Serial Controller"; }
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x06 ) { return "16950-Compatible Serial Controller"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "Parallel Port"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x01 ) { return "Bi-Directional Parallel Port"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x02 ) { return "ECP 1.X Compliant Parallel Port"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x03 ) { return "IEEE 1284 Controller"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0xFE ) { return "IEEE 1284 Target Device"; }
 | 
			
		||||
				if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "Multiport Serial Controller"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "Generic Modem"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x01 ) { return "Hayes Compatible Modem (16450-Compatible Interface)"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x02 ) { return "Hayes Compatible Modem (16550-Compatible Interface)"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x03 ) { return "Hayes Compatible Modem (16650-Compatible Interface)"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x04 ) { return "Hayes Compatible Modem (16750-Compatible Interface)"; }
 | 
			
		||||
				if ( SubClass == 0x04 && ProgIF == 0x00 ) { return "IEEE 488.1/2 (GPIB) Controller"; }
 | 
			
		||||
				if ( SubClass == 0x05 && ProgIF == 0x00 ) { return "Smart Card"; }
 | 
			
		||||
				if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Communications Device"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x08 )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Generic 8259 PIC"; }
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x01 ) { return "ISA PIC"; }
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x02 ) { return "EISA PIC"; }
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x10 ) { return "I/O APIC Interrupt Controller"; }
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x20 ) { return "I/O(x) APIC Interrupt Controller"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "Generic 8237 DMA Controller"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x01 ) { return "ISA DMA Controller"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x02 ) { return "EISA DMA Controller"; }
 | 
			
		||||
				if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "Generic 8254 System Timer"; }
 | 
			
		||||
				if ( SubClass == 0x02 && ProgIF == 0x01 ) { return "ISA System Timer"; }
 | 
			
		||||
				if ( SubClass == 0x02 && ProgIF == 0x02 ) { return "EISA System Timer"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "Generic RTC Controller"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x01 ) { return "ISA RTC Controller"; }
 | 
			
		||||
				if ( SubClass == 0x04 && ProgIF == 0x01 ) { return "Generic PCI Hot-Plug Controller"; }
 | 
			
		||||
				if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other System Peripheral"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x09 )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Keyboard Controller"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "Digitizer"; }
 | 
			
		||||
				if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "Mouse Controller"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "Scanner Controller"; }
 | 
			
		||||
				if ( SubClass == 0x04 && ProgIF == 0x00 ) { return "Gameport Controller (Generic)"; }
 | 
			
		||||
				if ( SubClass == 0x04 && ProgIF == 0x10 ) { return "Gameport Controller (Legacy)"; }
 | 
			
		||||
				if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Input Controller"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x0A )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Generic Docking Station"; }
 | 
			
		||||
				if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Docking Station"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x0B )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "386 Processor"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "486 Processor"; }
 | 
			
		||||
				if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "Pentium Processor"; }
 | 
			
		||||
				if ( SubClass == 0x10 && ProgIF == 0x00 ) { return "Alpha Processor"; }
 | 
			
		||||
				if ( SubClass == 0x20 && ProgIF == 0x00 ) { return "PowerPC Processor"; }
 | 
			
		||||
				if ( SubClass == 0x30 && ProgIF == 0x00 ) { return "MIPS Processor"; }
 | 
			
		||||
				if ( SubClass == 0x40 && ProgIF == 0x00 ) { return "Co-Processor"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x0C )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "IEEE 1394 Controller (FireWire)"; }
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x10 ) { return "IEEE 1394 Controller (1394 OpenHCI Spec)"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "ACCESS.bus"; }
 | 
			
		||||
				if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "SSA"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "USB (Universal Host Controller Spec)"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x10 ) { return "USB (Open Host Controller Spec)"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x20 ) { return "USB2 Host Controller (Intel Enhanced Host Controller Interface)"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x80 ) { return "USB"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0xFE ) { return "USB (Not Host Controller)"; }
 | 
			
		||||
				if ( SubClass == 0x04 && ProgIF == 0x00 ) { return "Fibre Channel"; }
 | 
			
		||||
				if ( SubClass == 0x05 && ProgIF == 0x00 ) { return "SMBus"; }
 | 
			
		||||
				if ( SubClass == 0x06 && ProgIF == 0x00 ) { return "InfiniBand"; }
 | 
			
		||||
				if ( SubClass == 0x07 && ProgIF == 0x00 ) { return "IPMI SMIC Interface"; }
 | 
			
		||||
				if ( SubClass == 0x07 && ProgIF == 0x01 ) { return "IPMI Kybd Controller Style Interface"; }
 | 
			
		||||
				if ( SubClass == 0x07 && ProgIF == 0x02 ) { return "IPMI Block Transfer Interface"; }
 | 
			
		||||
				if ( SubClass == 0x08 && ProgIF == 0x02 ) { return "SERCOS Interface Standard (IEC 61491)"; }
 | 
			
		||||
				if ( SubClass == 0x09 && ProgIF == 0x00 ) { return "CANbus"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x0E )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Message FIFO"; }
 | 
			
		||||
				if ( SubClass == 0x00 ) { return "I20 Architecture"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x0F )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "TV Controller"; }
 | 
			
		||||
				if ( SubClass == 0x02 && ProgIF == 0x00 ) { return "Audio Controller"; }
 | 
			
		||||
				if ( SubClass == 0x03 && ProgIF == 0x00 ) { return "Voice Controller"; }
 | 
			
		||||
				if ( SubClass == 0x04 && ProgIF == 0x00 ) { return "Data Controller"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x10 )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "Network and Computing Encryption/Decryption"; }
 | 
			
		||||
				if ( SubClass == 0x10 && ProgIF == 0x00 ) { return "Entertainment Encryption/Decryption"; }
 | 
			
		||||
				if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Encryption/Decryption"; }
 | 
			
		||||
			}
 | 
			
		||||
			if ( Class == 0x11 )
 | 
			
		||||
			{
 | 
			
		||||
				if ( SubClass == 0x00 && ProgIF == 0x00 ) { return "DPIO Modules"; }
 | 
			
		||||
				if ( SubClass == 0x01 && ProgIF == 0x00 ) { return "Performance Counters"; }
 | 
			
		||||
				if ( SubClass == 0x10 && ProgIF == 0x00 ) { return "Communications Syncrhonization Plus Time and Frequency Test/Measurment"; }
 | 
			
		||||
				if ( SubClass == 0x20 && ProgIF == 0x00 ) { return "Management Card"; }
 | 
			
		||||
				if ( SubClass == 0x80 && ProgIF == 0x00 ) { return "Other Data Acquisition/Signal Processing Controller"; }
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		void Init()
 | 
			
		||||
		{
 | 
			
		||||
			ATA::Init();
 | 
			
		||||
#if 0
 | 
			
		||||
			Log::Print("PCI Devices: ");
 | 
			
		||||
 | 
			
		||||
			for ( nat Bus = 0; Bus < 256; Bus++ )
 | 
			
		||||
			{
 | 
			
		||||
				for ( nat Slot = 0; Slot < 32; Slot++ )
 | 
			
		||||
				{
 | 
			
		||||
					for ( nat Function = 0; Function < 8; Function++ )
 | 
			
		||||
					{
 | 
			
		||||
						uint32_t ProductInfo = CheckDevice(Bus, Slot, Function);
 | 
			
		||||
 | 
			
		||||
						if ( ProductInfo == 0xFFFFFFFF ) { continue; }
 | 
			
		||||
 | 
			
		||||
						uint32_t DeviceType = ReadLong(Bus, Slot, Function, 0x08);
 | 
			
		||||
 | 
			
		||||
						const char* DeviceDesc = ToDeviceDesc(ProductInfo, DeviceType);
 | 
			
		||||
 | 
			
		||||
						if ( DeviceDesc != NULL )
 | 
			
		||||
						{
 | 
			
		||||
							Log::PrintF("%s, ", DeviceDesc);
 | 
			
		||||
						}
 | 
			
		||||
						else
 | 
			
		||||
						{
 | 
			
		||||
							Log::PrintF("Unknown PCI Device @ %x:%x.%x (ProductInfo=0x%x, DeviceType=0x%x), ", Bus, Slot, Function, ProductInfo, DeviceType);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			Log::Print("\b\b\n");
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		uint32_t ReadLong(uint8_t Bus, uint8_t Slot, uint8_t Function, uint8_t Offset)
 | 
			
		||||
		{
 | 
			
		||||
			unsigned long LBus = (unsigned long) Bus;
 | 
			
		||||
			unsigned long LSlot = (unsigned long) Slot;
 | 
			
		||||
			unsigned long LFunc = (unsigned long) Function;
 | 
			
		||||
 | 
			
		||||
			// create configuration address.
 | 
			
		||||
			unsigned long Address = (unsigned long) ( (LBus << 16) | (LSlot << 11) | (LFunc << 8) | (Offset & 0xFC) | ((uint32_t) 0x80000000));
 | 
			
		||||
 | 
			
		||||
			// Write out the address.
 | 
			
		||||
			CPU::OutPortL(Config_Address, Address);
 | 
			
		||||
 | 
			
		||||
			// Read in the data.
 | 
			
		||||
			return CPU::InPortL(Config_Data);
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		uint32_t CheckDevice(uint8_t Bus, uint8_t Slot, uint8_t Function)
 | 
			
		||||
		{
 | 
			
		||||
			return ReadLong(Bus, Slot, Function, 0);
 | 
			
		||||
		}
 | 
			
		||||
// TODO: This is just a hack but will do for now.
 | 
			
		||||
addr_t ParseDevBar0(uint32_t devaddr)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t bar0 = Read32(devaddr, 0x10);
 | 
			
		||||
	if ( bar0 & 0x1 ) // IO Space
 | 
			
		||||
		return bar0 & ~0x7UL;
 | 
			
		||||
	else // Memory Space
 | 
			
		||||
	{
 | 
			
		||||
		//uint32_t type = bar0 >> 1 & 0x3;
 | 
			
		||||
		//uint32_t prefetchable = bar0 >> 3 & 0x1;
 | 
			
		||||
		//if ( type == 0x01 )
 | 
			
		||||
		//	// TODO: Support 16-bit addresses here.
 | 
			
		||||
		//if ( type == 0x02 )
 | 
			
		||||
		//	// TODO: Support 64-bit addresses here.
 | 
			
		||||
		return bar0 & ~0xFUL;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Init()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace PCI
 | 
			
		||||
} // namespace Sortix
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										39
									
								
								sortix/pci.h
									
										
									
									
									
								
							
							
						
						
									
										39
									
								
								sortix/pci.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,39 +0,0 @@
 | 
			
		|||
/******************************************************************************
 | 
			
		||||
 | 
			
		||||
	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2011.
 | 
			
		||||
 | 
			
		||||
	This file is part of Sortix.
 | 
			
		||||
 | 
			
		||||
	Sortix is free software: you can redistribute it and/or modify it under the
 | 
			
		||||
	terms of the GNU General Public License as published by the Free Software
 | 
			
		||||
	Foundation, either version 3 of the License, or (at your option) any later
 | 
			
		||||
	version.
 | 
			
		||||
 | 
			
		||||
	Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
 | 
			
		||||
	WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
			
		||||
	FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 | 
			
		||||
	details.
 | 
			
		||||
 | 
			
		||||
	You should have received a copy of the GNU General Public License along
 | 
			
		||||
	with Sortix. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
	pci.h
 | 
			
		||||
	Handles basic PCI bus stuff.
 | 
			
		||||
 | 
			
		||||
******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef SORTIX_PCI_H
 | 
			
		||||
#define SORTIX_PCI_H
 | 
			
		||||
 | 
			
		||||
namespace Sortix
 | 
			
		||||
{
 | 
			
		||||
	namespace PCI
 | 
			
		||||
	{
 | 
			
		||||
		void Init();
 | 
			
		||||
		uint32_t ReadLong(uint8_t Bus, uint8_t Slot, uint8_t Function, uint8_t Offset);
 | 
			
		||||
		uint32_t CheckDevice(uint8_t Bus, uint8_t Slot, uint8_t Function = 0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue