⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arch_pci_pb1500.c

📁 MIPS下的boottloader yamon 的源代码
💻 C
字号:
#include <sysdefs.h>
#include <syserror.h>
#include <syscon_api.h>
#include <sys_api.h>
#include <syserror.h>
#include <pb1000.h>
#include <pci_api.h>
#include <arch_pci_pb1500.h>

#include <stdio.h>


void	sys_tlb_write();
UINT32	CP0_prid_read();
void	CP0_wired_write();

/*
 *	arch_pci_pb1500.c
 *
 *	pb1500 PCI initialization
 *
 *	Copyright 2001, Alchemy Semiconductor, Inc.
 *	Matt Brandt
 */

/************************************************************************
 *
 *                          pci_init
 *  Description :
 *  -------------
 *
 *  PCI module initialization function
 *
 *	Uses the first three entries of the MMU to map the following 32 MB areas:
 *
 *		0	0x40000000 - 0x41ffffff		PCI non-cacheable memory space
 *		1	0x50000000 - 0x51ffffff		PCI I/O space
 *		2								reserved for config access
 *
 *  Return values :
 *  ---------------
 *
 *  OK if no error, else error code
 *
 ************************************************************************/

UINT32	pci_init(
			UINT32	mem_start,	// ignores these parameters
			UINT32	mem_size,
			UINT32	mem_offset,
			UINT32	io_start,
			UINT32	io_size,
			UINT32	io_offset
			)
{
	UINT32	prid;
	int		i;
	UINT32	pte[5];

	prid = CP0_prid_read();			// get processor ID
	if( (prid & 0xffff0000) != 0x01030000 && (prid & 0xffff0000) != 0x03030000)
	{
		printf("-not present-\n");
		printf("PRID = %08x\n",prid);
		return OK;					// exit if not Au1500
	}

	if ( (prid & 0xffff0000) == 0x01030000)
		DISP_STR("(Au1500)");
	if ( (prid & 0xffff0000) == 0x03030000)
		DISP_STR("(Au1550)");
    DISP_STR(" PCI Enabled...");

	// NOTE: Au15x0 PCI init code located into reset_pb15x0.S

	//	map physical address 0x400xxxxx to 0x40xxxxxx for PCI memory

	pte[0] = 0;			// entry 0
	pte[1] = 0x01ffe000;		// 16MB pages for memory
	pte[2] = 0x40000000;		// logical VPN
	pte[3] = (0x40000000 >> 2)	// 0x4_0000_0000 physical address
			| 0x0017;		// non-cacheable, d, v, and g bits set
	pte[4] = (0x40100000 >> 2)	// 0x4_0100_0000 physical address
			| 0x0017;		// non-cacheable, d, v, and g bits set
//	printf("TLB = %d %08x %08x %08x %08x\n",pte[0],pte[1],pte[2],pte[3],pte[4]);
	sys_tlb_write(pte);

	//	map physical address 0x500xxxxx to 0x50xxxxxx for PCI I/O

	pte[0] = 1;				// entry 1
	pte[1] = 0x01ffe000;		// 16MB pages for I/O
	pte[2] = 0x50000000;		// logical VPN
	pte[3] = (0x50000000 >> 2)	// 0x5_0000_0000 physical address
			| 0x0017;			// non-cacheable, d, v, and g bits set
	pte[4] = (0x50100000 >> 2)	// 0x5_0100_0000 physical address
			| 0x0017;			// non-cacheable, d, v, and g bits set
//	printf("TLB = %d %08x %08x %08x %08x\n",pte[0],pte[1],pte[2],pte[3],pte[4]);
	sys_tlb_write(pte);

	sys_tlb_read(0,pte);
//	printf("TLB 0 = %08x %08x %08x %08x\n",pte[0],pte[1],pte[2],pte[3]);
	sys_tlb_read(1,pte);
//	printf("TLB 1 = %08x %08x %08x %08x\n",pte[0],pte[1],pte[2],pte[3]);

	CP0_wired_write(4);			// keep 4 entries fixed

	return OK;
}

/************************************************************************
 *
 *                          pci_iack
 *  Description :
 *  -------------
 *
 *  Perform PCI Interrupt Acknowledge Cycle
 *
 *  Return values :
 *  ---------------
 *
 *  Vector obtained from cycle
 *
 ************************************************************************/
UINT32	pci_iack( void )
{
	return au_pci_spec_intack;
}

/*
 *	map_config_address()
 *
 *	This function maps the address given to PCI configuration space and
 *	returns a pointer to where the access should occur.
 */

void	*map_config_address(UINT32 addr)
{
	UINT32		pte[5];
	UINT32		pfn;

	// grab 32M page of address and fix PFN[35:32] to PCI config space
	pfn = ((addr & 0xfe000000) >> 4) | 0x60000000;

	pte[0] = 3;				// entry 3
	pte[1] = 0x01ffe000;		// 16MB pages for I/O
	pte[2] = 0x60000000;		// logical VPN
	pte[3] = (pfn >> 2)	// even physical address
			| 0x0017;			// non-cacheable, d, v, and g bits set
	pte[4] = ((pfn | 0x00100000)  >> 2)	// odd physical address
			| 0x0017;			// non-cacheable, d, v, and g bits set
	sys_tlb_write(pte);

	return (void *)((addr & 0x01ffffff) | 0x60000000);
}

/************************************************************************
 *
 *                          pci_config_read32/16/8
 *  Description :
 *  -------------
 *
 *  Low level pci configuration space read routines (32/16/8 bit)
 *
 *  Return values :
 *  ---------------
 *
 *  0 (No error) or ERROR_PCI_ABORT
 *
 ************************************************************************/


UINT32	pci_config_read32(
				UINT32 busnum,	/* IN   bus number           */
				UINT32 devnum,	/* IN   device number        */
				UINT32 func,	/* IN   function number      */
				UINT32 reg,		/* IN   address		     */
				UINT32 *data )	/* OUT  pointer to data read */
{
	UINT32		cfgaddr;

	if( busnum == 0 )		// if local bus
	{
		cfgaddr = (0x00000800 << devnum)
				| ((func & 0x07) << 8)
				| (reg & 0x000000fc);
	}
	else					// else create type 1 address
	{
		cfgaddr = ((busnum & 0x00ff) << 16)
				| ((devnum & 0x001f) << 11)
				| ((func & 0x0007) << 8)
				| (reg & 0x00fc)
				| 0x80000000;			// type 1 flag
	}
	*data = *((UINT32 *)map_config_address(cfgaddr));
	return 0;
}

UINT32	pci_config_read16(
				UINT32 busnum,	/* IN   bus number           */
				UINT32 devnum,	/* IN   device number        */
				UINT32 func,	/* IN   function number      */
				UINT32 reg,		/* IN   address		     */
				UINT16  *data )	/* OUT  pointer to data read */
{
	UINT32		cfgaddr, rdata;
	int			offset;

	if( busnum == 0 )		// if local bus
	{
		cfgaddr = (0x00000800 << devnum)
				| ((func & 0x07) << 8)
				| (reg & 0x000000fe);
	}
	else					// else create type 1 address
	{
		cfgaddr = ((busnum & 0x00ff) << 16)
				| ((devnum & 0x001f) << 11)
				| ((func & 0x0007) << 8)
				| (reg & 0x00fc)
				| 0x80000000;			// type 1 flag
	}
	*data = *((UINT16 *)map_config_address(cfgaddr));
	return 0;
}


UINT32	pci_config_read8(
				UINT32 busnum,	/* IN   bus number           */
				UINT32 devnum,	/* IN   device number        */
				UINT32 func,	/* IN   function number      */
				UINT32 reg,		/* IN   address		     */
				UINT8  *data )	/* OUT  pointer to data read */
{
	UINT32		cfgaddr, rdata;
	int			offset;

	offset = ((int)data & 0x0003);

	if( busnum == 0 )		// if local bus
	{
		cfgaddr = (0x00000800 << devnum)
				| ((func & 0x07) << 8)
				| (reg & 0x000000ff);
	}
	else					// else create type 1 address
	{
		cfgaddr = ((busnum & 0x00ff) << 16)
				| ((devnum & 0x001f) << 11)
				| ((func & 0x0007) << 8)
				| (reg & 0x00fc)
				| 0x80000000;					// type 1 flag
	}
	*data = *((UINT8 *)map_config_address(cfgaddr));
	return 0;
}


/************************************************************************
 *
 *                          pci_config_write32/16/8
 *  Description :
 *  -------------
 *
 *  Low level pci configuration space write routines (32/16/8 bit)
 *
 *  Return values :
 *  ---------------
 *
 *  0 (No error) or ERROR_PCI_ABORT
 *
 ************************************************************************/

UINT32	pci_config_write32(
    UINT32 busnum,	/* IN   bus number      */
    UINT32 devnum,	/* IN   device number   */
    UINT32 func,	/* IN   function number */
    UINT32 reg,		/* IN   address		*/
    UINT32 data )	/* IN   data to write   */
{
	UINT32		cfgaddr;

	if( busnum == 0 )		// if local bus
	{
		cfgaddr = (0x00000800 << devnum)
				| ((func & 0x07) << 8)
				| (reg & 0x000000fc);
	}
	else					// else create type 1 address
	{
		cfgaddr = ((busnum & 0x00ff) << 16)
				| ((devnum & 0x001f) << 11)
				| ((func & 0x0007) << 8)
				| (reg & 0x00fc)
				| 0x80000000;					// type 1 flag
	}
	*((UINT32 *)map_config_address(cfgaddr)) = data;
	return 0;
}

UINT32	pci_config_write16(
    UINT32 busnum,	/* IN   bus number      */
    UINT32 devnum,	/* IN   device number   */
    UINT32 func,	/* IN   function number */
    UINT32 reg,		/* IN   address		*/
    UINT16 data )	/* IN   data to write   */
{
	UINT32		cfgaddr, rdata;
	int			offset;

	offset = ((int)data & 0x0003);

	if( busnum == 0 )		// if local bus
	{
		cfgaddr = (0x00000800 << devnum)
				| ((func & 0x07) << 8)
				| (reg & 0x000000fe);
	}
	else					// else create type 1 address
	{
		cfgaddr = ((busnum & 0x00ff) << 16)
				| ((devnum & 0x001f) << 11)
				| ((func & 0x0007) << 8)
				| (reg & 0x00fc)
				| 0x80000000;					// type 1 flag
	}
	*((UINT16 *)map_config_address(cfgaddr)) = data;
	return 0;
}

UINT32	pci_config_write8(
    UINT32 busnum,	/* IN   bus number      */
    UINT32 devnum,	/* IN   device number   */
    UINT32 func,	/* IN   function number */
    UINT32 reg,		/* IN   address		*/
    UINT8  data )	/* IN   data to write   */
{
	UINT32		cfgaddr, rdata;
	int			offset;

	offset = ((int)data & 0x0003);

	if( busnum == 0 )		// if local bus
	{
		cfgaddr = (0x00000800 << devnum)
				| ((func & 0x07) << 8)
				| (reg & 0x000000fc);
	}
	else					// else create type 1 address
	{
		cfgaddr = ((busnum & 0x00ff) << 16)
				| ((devnum & 0x001f) << 11)
				| ((func & 0x0007) << 8)
				| (reg & 0x00fc)
				| 0x80000000;		// type 1 flag
	}
	*((UINT8 *)map_config_address(cfgaddr)) = data;
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -