/*
 * Acess2 Kernel
 * - By John Hodge (thePowersGang)
 *
 * drv/vpci.c
 * - Virtual PCI Bus
 */
#include <virtual_pci.h>

// === 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;
	// 1: Command[0:15], Status[16:31]
	case 2:	// Class Code
		tmp_dword = Dev->Class;
		break;
	// 3: Cache Line Size, Latency Timer, Header Type, BIST
	case 4 ... 9:	// 4-9: BARs
		tmp_dword = Dev->BARs[ (Offset>>2) - 4 ];
		break;
	// 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:
		if( Dev->Read )
			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 ;
	}

	if( Size != 4 && Dev->Read )
		tmp_dword = Dev->Read(Dev->Ptr, Offset>>2);
	else
		tmp_dword = 0;
	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);
	if( Dev->Write )
		Dev->Write(Dev->Ptr, Offset>>2, tmp_dword);
}
