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

📄 ixp1200pci.c

📁 ixp1200EB vxworks pci BSP
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ixp1200Pci.c - Intel IXP1200 PCI Unit driver */

/* Copyright 1998 Wind River Systems, Inc.; Copyright 1999 Intel Corp. */
#include "copyright_wrs.h"

/*
modification history
--------------------
01d,06Oct00,jdg  Added Big-Endian support
01c,14dec00,jdg  added automatic pci address configuration
01b,13aug99,jdg  changed name from vbsa1200 to ixp1200eb
01a,25may99,jdg  created from ebsa sysLib.c, version 01j
*/

/*
DESCRIPTION
This device driver code for the Intel IXP1200 PCI unit.

It the function sysPciInit(), which should be called from
sysHwInit() to initialize the PCI unit on the IXP1200.

If we are the central function, it sets up PCI space as:
 I/O Space:
  0000 0000: Ethernet card
  0000 F000: IXP1200 CSRs (128 bytes)
 Mem Space:
  0000 0000: IXP1200 SDRAM (16 Meg)
  4000 0000: IXP1200 CSRs  (128 bytes)

It also contains the function sysPciAssignAddrs() which will 
(if we are central function) examine PCI space and program ourself
and all other PCI devices dynamically, based on how much addresses
space each device needs.

*/

#include "vxWorks.h"
#include "config.h"
#include "ixp1200Pci.h"
#ifdef AUTO_PCI_CONFIG
#ifdef INCLUDE_AUTO_PCI_CONFIG_SHOW_ROUTINE
#include <stdio.h>
#endif
#endif
#include "taskLib.h"

/* local defines  */

#ifdef AUTO_PCI_CONFIG
#define MAX_BARS 30
#define MAX_DEVICES 6

#ifndef INITIAL_PCI_CMD
#define INITIAL_PCI_CMD PCI_CMD_IO_ENABLE
#endif
#endif /* ifdef AUTO_PCI_CONFIG */

/* locals */

#ifdef AUTO_PCI_CONFIG

static PciDevice devices[MAX_DEVICES];
static int nDevices;

#endif /* ifdef AUTO_PCI_CONFIG */


/* function prototypes */

void sysPciAssignAddrs(void);

/* driver functions */

/******************************************************************************
*
* sysPciIsCentralFunc - returns a boolean indicating whether we are central func
*
* This function returns whether we are central function or not
*
* RETURNS: true if central function
*/

LOCAL int sysPciIsCentralFunc()
{
    int central_func;
#if defined(IXM1200) || defined(PA1104)
    central_func = 1;
#else
    central_func =
        IXP1200_SA_CONTROL_PCF & *(UINT32 *)IXP1200_SA_CONTROL;
#endif
    return central_func;
}


/*******************************************************************************
*
* sysPciInit - initialise PCI bridge controller
*
* This function initialises the PCI controlling parts.
*
* In particular, it will:
*   Reset the PCI bus
*   Reset the Doorbell registers
*   Set the PCI address Extension register to 0x00000000
*   Unreset the PCI bus
*   Set the Base Address Mask Register based on LOCAL_MEM_SIZE_ACTUAL
*   Set the CSR Memory BAR to 0x40000000 (IXP1200 CSRs in PCI Mem space)
*   Set the CSR BAR        to 0x0000F000 (IXP1200 CSRs in PCI I/O space)
*   Set the SDRAM BAR      to 0x00000000 (IXP1200 SDRAM in PCI Mem space)
*   Allow the PCI unit to be bus master, respond to I/O and Mem space,
*     and to generate Master Write and Invalidate transactions.
*   Allow the PCI unit to respond to PCI configuration cycles
* 
* RETURNS: N/A
*/

void sysPciInit (void)
    {
    volatile int i, j;
    int central_func;

    /* assert PCI reset */

    *(UINT32 *)(IXP1200_SA_CONTROL) =
	    (*(UINT32 *)(IXP1200_SA_CONTROL)) & ~IXP1200_SA_CONTROL_PNR;

    /* wait a few usecs to settle the device and PCI bus (no timers yet) */

    for (i = 0; i < 50 ; i++)
        j = i + 1;


    /* Disable Outbound & Doorbell Ints in Outbound Interrupt Mask Register*/

    *(UINT32 *)(IXP1200_OUTB_INT_MASK) = 0xC;


    /* Disable doorbell interrupts to PCI in Doorbell PCI Mask Register */

    *(UINT32 *)(IXP1200_DBELL_PCI_MASK) = 0;


    /* Disable doorbell interrupts to SA-110 in Doorbell SA-110 Mask Reg */

    *(UINT32 *)(IXP1200_DBELL_SA_MASK) = 0;


    /* Set PCI Address Extension Register to known state */

    *(UINT32 *)(IXP1200_PCI_ADDR_EXT) = 0x00000000;


    /* Set Int pin */
    *(UINT32 *)(IXP1200_PCI_INT_LAT) = 1 << 8;

    /* Negate PCI reset (has no effect if we are not central function) */

    *(UINT32 *)(IXP1200_SA_CONTROL) =
	    (*(UINT32 *)(IXP1200_SA_CONTROL)) | IXP1200_SA_CONTROL_PNR;

    /* wait a few usecs to settle the device and PCI bus (no timers yet) */

    for (i = 0; i < 50 ; i++)
        j = i + 1;


    /* Setup SDRAM Base Address Mask Reg: LOCAL_MEM_SIZE_ACTUAL window (32Meg)
       from PCI into SDRAM */

    *(UINT32 *)(IXP1200_DRAM_BASE_ADDR_MASK) = LOCAL_MEM_SIZE_ACTUAL - 0x00040000; 


    /* Set up CSR Base Address Mask Reg. 
     * Due to a Pass-A HW bug, we need to ask for at least 1 Meg. */

    *(UINT32 *)(IXP1200_CSR_BASE_ADDR_MASK) = 0x000c0000;

    /* Stop IXP1200 from responding to any PCI transactions */

    sysWrite16 ((volatile UINT16 *)(IXP1200_PCI_COMMAND), 0);


    /* Check to see if we are central function, if not then do not
     * set up BARs */

#if defined(IXM1200) || defined(PA1104)
    central_func = 1;
#else
    central_func =
        IXP1200_SA_CONTROL_PCF & *(UINT32 *)IXP1200_SA_CONTROL;
#endif
    if (central_func)
        {

        /* Set CSR Memory Base Address Register */

        *(UINT32 *)(IXP1200_PCI_MEM_BAR) = 0x40000000;


        /*
         * Set CSR I/O Base Address Register: set base address of CSRs from PCI,
         * CSR Base Address Mask Register will setup 128 byte window.
         */

        *(UINT32 *)(IXP1200_PCI_IO_BAR) = 0x0000F000;


        /* Setup SDRAM Base Address Register: */

        *(UINT32 *)(IXP1200_PCI_DRAM_BAR) = 0x00000000;


        /*
         * Enable IXP1200 as Bus master and respond to I/O space and memory space
         * transactions as target
         */

        sysWrite16 ((volatile UINT16 *)(IXP1200_PCI_COMMAND),
                    IXP1200_PCI_COMMAND_IOSE |  /* I/O Space Enable */
                    IXP1200_PCI_COMMAND_MSE  |  /* Mem Space Enable */
                    IXP1200_PCI_COMMAND_ME   |  /* Master Enable */
                    IXP1200_PCI_COMMAND_MWI     /* Master Wr & Invalidate En */
            );

        }

    /*
     * Compute Big Endian PCI setting
     */

#if (_BYTE_ORDER == _BIG_ENDIAN)
#define BE_PCI (IXP1200_SA_CONTROL_BEO | \
                IXP1200_SA_CONTROL_DEO | \
                IXP1200_SA_CONTROL_BEI | \
                IXP1200_SA_CONTROL_DEI )
#else
#define BE_PCI 0
#endif

    /*
     * Set Initialise Complete in PCI Control Register: allow IXP1200 to
     * respond to PCI configuration cycles.
     */

    *(UINT32 *)(IXP1200_SA_CONTROL) =
	    (*(UINT32 *)(IXP1200_SA_CONTROL)) | (0x00000001 | BE_PCI);

#if defined(INCLUDE_PCI) && defined(INCLUDE_HPC)
    /*
     * We need to do this here because some BIOS's are too quick for
     * the spawned thread to correct things. So we'll do it for a short
     * while here, and then spawn a task later to fix later ones.
     */
    if ((sysCpuRev == 1) && (!central_func)) {
        int i,j;

        /* Fix B0 bug where some BIOS will clobber the INT_LAT reg */
        DEBUG_LED(0x77);
        for (i=0; i<5000000; i++) {
            j = *(volatile UINT32*)(IXP1200_PCI_INT_LAT);
            if ((j & ~0xFF) != (1<<8)) {
                *(volatile UINT32*)(IXP1200_PCI_INT_LAT) =
                    (1<<8) | (j & 0xFF);
            }
        }
        DEBUG_LED(0x88);
    }
#endif

    /* Fix C0/Hyannis PCI CSR bug */
    *(volatile int*)(IXP1200_RESET);
    return;
    }


/*******************************************************************************
*
* sysPciFix1 - Fix PCI config registers due to B0 chip bug
*
* Some BIOS's will clobber parts of the PCI INT_LAT register that should
* have been read only. So we poll for a while, and if it gets clobbered,
* we fix it.
*
* RETURNS: N/A
*/

void sysPciFix1 (void)
{
    int i,j;

    /* Fix B0 bug where some BIOS will clobber the INT_LAT reg */
    for (i=0; i<60*60; i++) {
        j = *(volatile UINT32*)(IXP1200_PCI_INT_LAT);
        if ((j & ~0xFF) != (1<<8)) {
            *(volatile UINT32*)(IXP1200_PCI_INT_LAT) =
                (1<<8) | (j & 0xFF);
        }
        taskDelay(1);
    }
}

/*******************************************************************************
*
* sysPciFix - spawn a task to fix PCI config registers due to B0 chip bug
*
* Some BIOS's will clobber parts of the PCI INT_LAT register that should
* have been read only. So we poll for a while, and if it gets clobbered,
* we fix it. This is done in a separate task so that we don't hold up the boot.
*
* RETURNS: N/A
*/

void sysPciFix (void)
{
#if !( defined(IXM1200) || defined(PA1104) )
    int central_func;

    central_func =
        IXP1200_SA_CONTROL_PCF & *(UINT32 *)IXP1200_SA_CONTROL;

    if (!central_func)
        {
        taskSpawn ("tPciFix",
                   5,    /* priority, 255==lowest */
                   0,    /* options */
                   1024, /* stack size (bytes) */
                   (FUNCPTR)sysPciFix1,
                   0,0,0,0,0,0,0,0,0,0);
        }
#endif
}

/******************************************************************************
*
* sysPciToPhys - translate a Pci address to a physical address
*
* This function converts a Pci address to a physical address. This only works
* for PCI Memory space.
*
* RETURNS: the physical adddress
*/

void * sysPciToPhys
    (
    void *	PciAddr	/* PCI address */
    )
    {
    if (((UINT32) PciAddr) < LOCAL_MEM_SIZE_ACTUAL) 
        { 
        /* SDRAM address */

⌨️ 快捷键说明

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