📄 ixm1200pci.c
字号:
/* ixm1200Pci.c - Intel IXM1200 PCI Unit driver *//* Copyright 1998 Wind River Systems, Inc.; Copyright 1999 Intel Corp. */#include "copyright_wrs.h"/*modification history--------------------01i,12sep01,scm Change allocation strategy to support fixed 1200 addresses...01h,30aug01,scm adjust to reflect ixm1200...01g,26jun01,scm Fix compile time warning01f,26jun01,scm Adding Intel changes01e,26jun01,scm Adding support for new End drivers01d,06Oct00,jdg Added Big-Endian support01c,14dec00,jdg added automatic pci address configuration01b,13aug99,jdg changed name from vbsa1200 to ixp1200eb01a,25may99,jdg created from ebsa sysLib.c, version 01j*//*DESCRIPTIONThis device driver code for the Intel IXM1200 PCI unit.It the function sysPciInit(), which should be called fromsysHwInit() to initialize the PCI unit on the IXM1200.If we are the central function, it sets up PCI space as: I/O Space: 0000 0000: Ethernet card 0000 F000: IXM1200 CSRs (128 bytes) Mem Space: 0000 0000: IXM1200 SDRAM (16 Meg) 4000 0000: IXM1200 CSRs (128 bytes)It also contains the function sysPciAssignAddrs() which will (if we are central function) examine PCI space and program ourselfand all other PCI devices dynamically, based on how much addressesspace each device needs.*/#include "vxWorks.h"#include "config.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 */#include "ixm1200Pci.h"/* locals */#ifdef AUTO_PCI_CONFIGstatic 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; central_func = 1; 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 (IXM1200 CSRs in PCI Mem space)* Set the CSR BAR to 0x0000F000 (IXM1200 CSRs in PCI I/O space)* Set the SDRAM BAR to 0x00000000 (IXM1200 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 *)(IXM1200_SA_CONTROL) = (*(UINT32 *)(IXM1200_SA_CONTROL)) & ~IXM1200_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 *)(IXM1200_OUTB_INT_MASK) = 0xC; /* Disable doorbell interrupts to PCI in Doorbell PCI Mask Register */ *(UINT32 *)(IXM1200_DBELL_PCI_MASK) = 0; /* Disable doorbell interrupts to SA-110 in Doorbell SA-110 Mask Reg */ *(UINT32 *)(IXM1200_DBELL_SA_MASK) = 0; /* Set PCI Address Extension Register to known state */ *(UINT32 *)(IXM1200_PCI_ADDR_EXT) = 0x00000000; /* Set Int pin */ *(UINT32 *)(IXM1200_PCI_INT_LAT) = 1 << 8; /* Negate PCI reset (has no effect if we are not central function) */ *(UINT32 *)(IXM1200_SA_CONTROL) = (*(UINT32 *)(IXM1200_SA_CONTROL)) | IXM1200_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 *)(IXM1200_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 *)(IXM1200_CSR_BASE_ADDR_MASK) = 0x000c0000; /* Stop IXM1200 from responding to any PCI transactions */ sysWrite16 ((volatile UINT16 *)(IXM1200_PCI_COMMAND), 0); /* Check to see if we are central function, if not then do not * set up BARs */ central_func = 1; if (central_func) { /* Set CSR Memory Base Address Register */ *(UINT32 *)(IXM1200_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 *)(IXM1200_PCI_IO_BAR) = 0x0000F000; /* Setup SDRAM Base Address Register: */ *(UINT32 *)(IXM1200_PCI_DRAM_BAR) = 0x00000000; /* * Enable IXM1200 as Bus master and respond to I/O space and memory space * transactions as target */ sysWrite16 ((volatile UINT16 *)(IXM1200_PCI_COMMAND), IXM1200_PCI_COMMAND_IOSE | /* I/O Space Enable */ IXM1200_PCI_COMMAND_MSE | /* Mem Space Enable */ IXM1200_PCI_COMMAND_ME | /* Master Enable */ IXM1200_PCI_COMMAND_MWI /* Master Wr & Invalidate En */ ); } /* * Compute Big Endian PCI setting */#if (_BYTE_ORDER == _BIG_ENDIAN)#define BE_PCI (IXM1200_SA_CONTROL_BEO | \ IXM1200_SA_CONTROL_DEO | \ IXM1200_SA_CONTROL_BEI | \ IXM1200_SA_CONTROL_DEI )#else#define BE_PCI 0#endif /* * Set Initialise Complete in PCI Control Register: allow IXM1200 to * respond to PCI configuration cycles. */ *(UINT32 *)(IXM1200_SA_CONTROL) = (*(UINT32 *)(IXM1200_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*)(IXM1200_PCI_INT_LAT); if ((j & ~0xFF) != (1<<8)) { *(volatile UINT32*)(IXM1200_PCI_INT_LAT) = (1<<8) | (j & 0xFF); } } DEBUG_LED(0x88); }#endif /* Fix C0/Hyannis PCI CSR bug */ *(volatile int*)(IXM1200_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*)(IXM1200_PCI_INT_LAT); if ((j & ~0xFF) != (1<<8)) { *(volatile UINT32*)(IXM1200_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) ) int central_func; central_func = IXM1200_SA_CONTROL_PCF & *(UINT32 *)IXM1200_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 */ return (void*) (((UINT32) PciAddr) + SDRAM_PHYS_BASE); } else { /* Other Memspace address */ return (void*) (((UINT32) PciAddr) + PCI_MEM_BASE); } }/******************************************************************************** sysPhysToPci - translate a physical address to a Pci address** This function converts a physical address to a Pci address. This only works* for PCI Memory space.** RETURNS: the Pci adddress*/void * sysPhysToPci ( void * PhysAddr /* Physical address */ ) { if ((((UINT32) PhysAddr) >= SDRAM_VIRT_OFFSET) && (((UINT32) PhysAddr) < SDRAM_PF_BASE)) { /* SDRAM address */ return (void*) (((UINT32) PhysAddr) - SDRAM_PHYS_BASE); } else { /* Other Memspace address */ return (void*) (((UINT32) PhysAddr) - PCI_MEM_BASE); } }#ifdef AUTO_PCI_CONFIG/******************************************************************************** sortBars - Sort Bars largest to smallest and assign addresses** This function takes in an array of pointers to BARs.* Then it will sort the BARS from smallest to largest. It will* then assign each unassigned BAR at the lowest address that doesn't conflict* with the others.** RETURNS: N/A*/static voidsortBars ( PciBar *Bars[], /* Array of pointers to BARs */ const int nBars /* Number of BARs in array */ ){ int i, j; PciBar *tmp; UINT32 addr; /* Sort smallest to biggest */ for (i = 0; i < nBars-1; i++) { for (j = i+1; j < nBars; j++) { if (Bars[j]->size < Bars[i]->size) { /* swap them */ tmp = Bars[i]; Bars[i] = Bars[j]; Bars[j] = tmp; } } /* end for j */ } /* end for i */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -