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

📄 pci.c

📁 MIPS YAMON, a famous monitor inc. source, make file and PDF manuals.
💻 C
📖 第 1 页 / 共 3 页
字号:
/************************************************************************ * *  pci.c * *  Generic PCI code * * ###################################################################### * * mips_start_of_legal_notice *  * Copyright (c) 2004 MIPS Technologies, Inc. All rights reserved. * * * Unpublished rights (if any) reserved under the copyright laws of the * United States of America and other countries. * * This code is proprietary to MIPS Technologies, Inc. ("MIPS * Technologies"). Any copying, reproducing, modifying or use of this code * (in whole or in part) that is not expressly permitted in writing by MIPS * Technologies or an authorized third party is strictly prohibited. At a * minimum, this code is protected under unfair competition and copyright * laws. Violations thereof may result in criminal penalties and fines. * * MIPS Technologies reserves the right to change this code to improve * function, design or otherwise. MIPS Technologies does not assume any * liability arising out of the application or use of this code, or of any * error or omission in such code. Any warranties, whether express, * statutory, implied or otherwise, including but not limited to the implied * warranties of merchantability or fitness for a particular purpose, are * excluded. Except as expressly provided in any written license agreement * from MIPS Technologies or an authorized third party, the furnishing of * this code does not give recipient any license to any intellectual * property rights, including any patent rights, that cover this code. * * This code shall not be exported, reexported, transferred, or released, * directly or indirectly, in violation of the law of any country or * international law, regulation, treaty, Executive Order, statute, * amendments or supplements thereto. Should a conflict arise regarding the * export, reexport, transfer, or release of this code, the laws of the * United States of America shall be the governing law. * * This code constitutes one or more of the following: commercial computer * software, commercial computer software documentation or other commercial * items. If the user of this code, or any related documentation of any * kind, including related technical data or manuals, is an agency, * department, or other entity of the United States government * ("Government"), the use, duplication, reproduction, release, * modification, disclosure, or transfer of this code, or any related * documentation of any kind, is restricted in accordance with Federal * Acquisition Regulation 12.212 for civilian agencies and Defense Federal * Acquisition Regulation Supplement 227.7202 for military agencies. The use * of this code by the Government is further restricted in accordance with * the terms of the license agreement(s) and/or applicable contract terms * and conditions covering this code from MIPS Technologies or an authorized * third party. * * * *  * mips_end_of_legal_notice *  * ************************************************************************//************************************************************************ *  Include files ************************************************************************/#include <sysdefs.h>#include <syserror.h>#include <pci.h>#include <pci_api.h>#include <product.h>#include <atlas.h>#include <syscon_api.h>#include <sys_api.h>#include <shell_api.h>#include <string.h>#include <stdio.h>/************************************************************************ *  Definitions ************************************************************************//* Determine whether devices is of type 0 or 1 based on header type */#define DEV_PPB(dev)		( (dev)->ht == PCI_HEADERTYPE1 )/* PCI bus definition */typedef struct{    bool       fastb2b;    t_pci_bar  *mem_largest_ptr;    t_pci_bar  *io_largest_ptr;    UINT32     start_mem;    UINT32     start_io;    bool       prefetch;}t_pci_cfg_bus;/* Determine whether device IDs equal device data */#define DEV_EQUAL( dev, vendor, device, func )		\	(						\	    (dev->vendorid == vendor) &&		\	    (dev->devid    == device) &&		\	    (dev->function == func)			\	)/* Determine whether a device is known to YAMON */#define KNOWN_DEV( dev, known_dev )			\	    DEV_EQUAL( dev, known_dev.vendorid, known_dev.devid, known_dev.function )#define KNOWN_BAR( dev, pos, bar_req )		\	    (KNOWN_DEV( dev, bar_req ) &&	\	    (pos == bar_req.bar.pos))/* Search for known device */#define SEARCH_KNOWN( dev, loopvar )			\	for( loopvar=0;					\	       (loopvar < known_devs_count) &&		\	       !KNOWN_DEV( dev, known_devs[loopvar] );	\	     loopvar++ )				\	{						\	   ;						\	}	        /************************************************************************ *  Public variables ************************************************************************/bool pci_alloc_err;/************************************************************************ *  Static variables ************************************************************************//* Variables for device and bus data */static t_pci_cfg_dev  dev_data[PCI_MAX_DEV];static t_pci_cfg_bus  bus_data[PCI_MAX_BUS];static UINT32         dev_count;static UINT8	      bus_count;/* Variables for holding parameters used by several functions */static t_known_dev    *known_devs;static UINT32         known_devs_count;static t_pci_bar_req  *bar_reqs;static UINT32	      bar_reqs_count;/*  Offsets : *    The system controller supports remapping of memory *    and IO ranges so that the addresses seen on the CPU side (SysAD) of *    the controller and the addresses seen on PCI are offset by some amount. *    The CPU side start address is found by adding the offset to the *    PCI side start address. */static UINT32         pci_mem_offset;static UINT32         pci_io_offset;/* Error strings */static char* error_strings[] ={    /* ERROR_PCI_MALLOC		*/ "Not enough space for autoconfiguration",    /* ERROR_PCI_RANGE		*/ "Illegal ram range",    /* ERROR_PCI_UNKNOWN_DEVICE */ "Unknown PCI device",    /* ERROR_PCI_ABORT		*/ "PCI master or target abort",    /* ERROR_PCI_STRUCTURE	*/ "Structural error in PCI module"};/************************************************************************ *  Static function prototypes ************************************************************************/static UINT32detect_devices(    UINT32 maxbus,    UINT32 maxdev );static UINT32config_system(     UINT32 freemem_start,		/* First valid mem address	*/    UINT32 freemem_end, 		/* First non valid mem address	*/    UINT32 freeio_start,		/* First valid IO address	*/    UINT32 freeio_end,			/* First non valid IO address	*/    UINT32 maxbus );static UINT32config_dev(     t_pci_cfg_dev   *dev,		/* Device data			*/    UINT32	    memlimit,		/* Max valid mem address	*/    UINT32	    iolimit );		/* Max valid io address		*/static UINT32query_dev(     UINT32        bus,                  /* Bus number                   */    UINT32        devnum,		/* Device number		*/    UINT32	  function,		/* Device function		*/    t_pci_cfg_dev *dev,			/* Device data			*/    UINT32	  maxbus );static boolfixed_memory_alloc(    t_pci_cfg_dev *dev,    UINT32        bar_index );static voidsetup_fixed_memory_alloc(     t_pci_cfg_dev *dev );static UINT32alloc_space(    UINT32 red_start,	/* redpage, 0 -> IO space, !=0 -> memory space	*/    UINT32 red_end,    UINT32 mem_start,    UINT32 mem_end );static UINT32align(    UINT32    addr,			/* Address to be aligned	*/    UINT32    alignment );		/* Alignment requirement	*/static INT32 error_lookup(     t_sys_error_string *param );/************************************************************************ *  Implementation : Public functions ************************************************************************//************************************************************************ * *                          pci_init *  Description : *  ------------- * *  PCI module initialisation function * *  Return values : *  --------------- * *  OK if no error, else error code * ************************************************************************/UINT32pci_init( void ){    t_sys_error_lookup_registration registration;    /* register error lookup function */    registration.prefix = SYSERROR_DOMAIN( ERROR_PCI );    registration.lookup = error_lookup;    SYSCON_write( SYSCON_ERROR_REGISTER_LOOKUP_ID,                  &registration,                  sizeof( registration ) );    /* Call platform specific configuration function */    return pci_config();}    /************************************************************************ * *                          pci_autoconfig *  Description : *  ------------- * *  Configure PCI based on platform requirements. * *  Return values : *  --------------- * *     0: no pci error, else error * ************************************************************************/UINT32pci_autoconfig(    t_pci_bar_req  *bar_req,		/* Special BAR requirements	*/    UINT32	   bar_req_count,	/* Number of special BARs       */    t_known_dev    *known_dev,		/* Array of known devices	*/    UINT32	   known_dev_count )	/* Count of known devices	*/{    UINT32 rc, i;    UINT32	  mem_start;	/* Start of PCI memory range		*/    UINT32	  mem_size;	/* Size of PCI memory range		*/    UINT32	  io_start;	/* Start of PCI io range		*/    UINT32	  io_size;	/* Size of PCI io range			*/    UINT32 maxbus, maxdev;    /* Store data used by other functions */    known_devs       = known_dev;    known_devs_count = known_dev_count;    bar_reqs	     = bar_req;    bar_reqs_count   = bar_req_count;    /*  Determine ranges :     *     *  1) Start of range as seen from PCI.     *  2) Size of range.     *  3) Offset of range. The system controller supports remapping of memory     *     and IO ranges so that the addresses seen on the CPU side (SysAD) of     *     the controller and the addresses seen on PCI are offset by some amount.     *     The CPU side start address is found by adding the offset to the     *     PCI side start address.     */    SYSCON_read( SYSCON_CORE_PCI_MEM_START, 		 (void *)&mem_start, sizeof(UINT32) );    SYSCON_read( SYSCON_CORE_PCI_MEM_SIZE,		 (void *)&mem_size, sizeof(UINT32) );    SYSCON_read( SYSCON_CORE_PCI_MEM_OFFSET, 		 (void *)&pci_mem_offset, sizeof(UINT32) );    SYSCON_read( SYSCON_CORE_PCI_IO_START, 		 (void *)&io_start, sizeof(UINT32) );    SYSCON_read( SYSCON_CORE_PCI_IO_SIZE,		 (void *)&io_size, sizeof(UINT32) );    SYSCON_read( SYSCON_CORE_PCI_IO_OFFSET,		 (void *)&pci_io_offset, sizeof(UINT32) );    /* Determine max number of busses and devices */    maxbus = PCI_MAX_BUS;		/* Max number of PCI busses	*/    maxdev = PCI_MAX_DEV;		/* Max number of PCI devices    */    /* Detect devices */    rc = detect_devices( maxbus, maxdev );    if( rc != OK ) return rc;    /* Configure system */    rc = config_system( mem_start, mem_start + mem_size, 			io_start,  io_start  + io_size,			maxbus );    if( rc != OK ) return rc;    /* Configure devices */    for(i=0; i<dev_count; i++)    {        rc = config_dev( &dev_data[i], 			 mem_start + mem_size - 1,			 io_start   + io_size - 1 );        if( rc != OK ) return rc;    }        return OK;}/************************************************************************ * *                          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,    UINT32 devnum,    UINT32 func,    UINT32 reg,    UINT32 data ){    return arch_pci_config_access( busnum, devnum, func, reg,				   TRUE, sizeof(UINT32), (void *)&data );}UINT32 pci_config_write16(     UINT32 busnum,    UINT32 devnum,    UINT32 func,    UINT32 reg,    UINT16 data ){    return arch_pci_config_access( busnum, devnum, func, reg,				   TRUE, sizeof(UINT16), (void *)&data );}UINT32 pci_config_write8(     UINT32 busnum,    UINT32 devnum,    UINT32 func,    UINT32 reg,    UINT8  data ){    return arch_pci_config_access( busnum, devnum, func, reg,				   TRUE, sizeof(UINT8), (void *)&data );}/************************************************************************ * *                          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     * ************************************************************************/UINT32pci_config_read32(      UINT32 busnum,    UINT32 devnum,    UINT32 func,    UINT32 reg,    UINT32 *data ){    return arch_pci_config_access( busnum, devnum, func, reg,				   FALSE, sizeof(UINT32), (void *)data );}UINT32pci_config_read16(      UINT32 busnum,    UINT32 devnum,    UINT32 func,    UINT32 reg,    UINT16 *data ){    return arch_pci_config_access( busnum, devnum, func, reg,				   FALSE, sizeof(UINT16), (void *)data );}UINT32pci_config_read8(      UINT32 busnum,    UINT32 devnum,    UINT32 func,    UINT32 reg,    UINT8  *data ){    return arch_pci_config_access( busnum, devnum, func, reg,				   FALSE, sizeof(UINT8), (void *)data );}/************************************************************************ * *                          pci_lookup_bar *  Description : *  ------------- * *  Determine base address (physical) of specific BAR of specific device. * *  Return values : *  --------------- * *  TRUE  : BAR found *  FALSE : BAR not found * ************************************************************************/boolpci_lookup_bar(    UINT8         busnum,		/* Bus number			*/    UINT8         devnum,		/* Device number		*/    UINT8	  func,			/* Function number		*/    UINT8	  bar,			/* Address of BAR register	*/    void	  **param )		/* OUT : Base address of BAR	*/{    t_pci_cfg_dev *dev;    UINT32	  i;    /* Default */    *param = NULL;    for( i=0; i<dev_count; i++ )    {        dev = &dev_data[i];	if (dev->bus == busnum && dev->dev == devnum && dev->function == func)	    break;    }    if( i<dev_count )    {        for( i=0; i<dev->bar_count; i++ )	{	    if( dev->bar[i].pos == bar )	    {                *param = 		    (void *) ( dev->bar[i].start +			       (dev->bar[i].io ?			           pci_io_offset :			           pci_mem_offset) );

⌨️ 快捷键说明

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