2001-05-14 Till Straumann <strauman@slac.stanford.edu>

Per PR216, "libbsp/powerpc/shared" BSP has been modified considerably
	with the goal to make it more flexible and reusable by other
	BSPs. The main strategies were:
	    - eliminate hardcoded base addresses; devices use offsets
	      and a BSP defined base address.
	    - separate functionality into different files (e.g. reboot from
	      inch.c to reboot.c) which can be overridden by a 'derived' BSP.
	    - separate initialization code into separate files (e.g.  PCI
	      bridge detection/initialization was separated from the more
	      generic PCI access routines), also to make it easier for
	      'derived' BSPs to substitute their own initialization code.
	There are also a couple of enhancements and fixes:
	    - IRQ handling code now has a hook for attaching a VME bridge.
	    - OpenPIC is now explicitely initialized (polarities, senses).
	      Eliminated the implicit assumption on the presence of an ISA PIC.
	    - UART and console driver now supports more than 1 port. The current
	      maximum of 2 can easily be extended by enlarging a table (it
	      would even be easier if the ISR API was not broken by design).
	    - fixed polled_io.c so it correctly supports console on COM2
	    - fixed TLB invalidation code (start.S).
	    - exception handler prints a stack backtrace.
	    - added BSP_pciFindDevice() to scan the pci bus for a particular
	      vendor/device/instance.
This commit is contained in:
Joel Sherrill
2002-05-14 17:28:05 +00:00
parent 58507208eb
commit 9966204602
4 changed files with 233 additions and 0 deletions
@@ -0,0 +1,51 @@
/* inline routines for console i/o
*
* The purpose of this file is to provide generic inline functions,
* i.e. not using hardcoded base addresses. These are provided by
* the BSP header.
*
* $Id$
*/
#include <bsp.h>
#define INL_IN_DECL(name,base) \
static inline unsigned char name(int off) \
{ \
return in_8((unsigned char*)(((unsigned long)base) + off)); \
}
#define INL_OUT_DECL(name,base) \
static inline void name(int off, unsigned int val) \
{ \
out_8((unsigned char*)(((unsigned long)base) + off), val); \
}
#ifdef BSP_UART_IOBASE_COM1
INL_IN_DECL(com1_inb, BSP_UART_IOBASE_COM1)
INL_OUT_DECL(com1_outb, BSP_UART_IOBASE_COM1)
#endif
#ifdef BSP_UART_IOBASE_COM2
INL_IN_DECL(com2_inb, BSP_UART_IOBASE_COM2)
INL_OUT_DECL(com2_outb, BSP_UART_IOBASE_COM2)
#endif
#if defined(BSP_CONSOLE_PORT)
#if (BSP_CONSOLE_PORT == BSP_UART_COM1) && defined(BSP_UART_IOBASE_COM1)
#define INL_CONSOLE_INB com1_inb
#define INL_CONSOLE_OUTB com1_outb
#elif (BSP_CONSOLE_PORT == BSP_UART_COM2) && defined(BSP_UART_IOBASE_COM2)
#define INL_CONSOLE_INB com2_inb
#define INL_CONSOLE_OUTB com2_outb
#endif
#endif
#ifdef BSP_KBD_IOBASE
INL_IN_DECL(kbd_inb, BSP_KBD_IOBASE)
INL_OUT_DECL(kbd_outb, BSP_KBD_IOBASE)
#endif
#ifdef BSP_VGA_IOBASE
INL_OUT_DECL(vga_outb, BSP_VGA_IOBASE)
#endif
@@ -0,0 +1,16 @@
/* $Id$ */
#include "console.inl"
/*-------------------------------------------------------------------------+
| Function: rtemsReboot
| Description: Reboot the PC.
| Global Variables: None.
| Arguments: None.
| Returns: Nothing.
+--------------------------------------------------------------------------*/
void rtemsReboot(void)
{
/* shutdown and reboot */
kbd_outb(0x4, 0xFE); /* use keyboard controler to do the job... */
} /* rtemsReboot */
@@ -0,0 +1,111 @@
/*
* $Id$
*/
#include <libcpu/io.h>
#include <bsp.h>
#include <bsp/pci.h>
#include <bsp/consoleIo.h>
#include <bsp/residual.h>
#include <bsp/openpic.h>
#define RAVEN_MPIC_IOSPACE_ENABLE 0x1
#define RAVEN_MPIC_MEMSPACE_ENABLE 0x2
#define RAVEN_MASTER_ENABLE 0x4
#define RAVEN_PARITY_CHECK_ENABLE 0x40
#define RAVEN_SYSTEM_ERROR_ENABLE 0x100
#define RAVEN_CLEAR_EVENTS_MASK 0xf9000000
#define pci BSP_pci_configuration
extern const pci_config_access_functions pci_direct_functions;
extern const pci_config_access_functions pci_indirect_functions;
void detect_host_bridge()
{
PPC_DEVICE *hostbridge;
unsigned int id0;
unsigned int tmp;
/*
* This code assumes that the host bridge is located at
* bus 0, dev 0, func 0 AND that the old pre PCI 2.1
* standart devices detection mecahnism that was used on PC
* (still used in BSD source code) works.
*/
hostbridge=residual_find_device(&residualCopy, PROCESSORDEVICE, NULL,
BridgeController,
PCIBridge, -1, 0);
if (hostbridge) {
if (hostbridge->DeviceId.Interface==PCIBridgeIndirect) {
pci.pci_functions=&pci_indirect_functions;
/* Should be extracted from residual data,
* indeed MPC106 in CHRP mode is different,
* but we should not use residual data in
* this case anyway.
*/
pci.pci_config_addr = ((volatile unsigned char *)
(ptr_mem_map->io_base+0xcf8));
pci.pci_config_data = ptr_mem_map->io_base+0xcfc;
} else if(hostbridge->DeviceId.Interface==PCIBridgeDirect) {
pci.pci_functions=&pci_direct_functions;
pci.pci_config_data=(unsigned char *) 0x80800000;
} else {
}
} else {
/* Let us try by experimentation at our own risk! */
pci.pci_functions = &pci_direct_functions;
/* On all direct bridges I know the host bridge itself
* appears as device 0 function 0.
*/
pci_read_config_dword(0, 0, 0, PCI_VENDOR_ID, &id0);
if (id0==~0U) {
pci.pci_functions = &pci_indirect_functions;
pci.pci_config_addr = ((volatile unsigned char*)
(ptr_mem_map->io_base+0xcf8));
pci.pci_config_data = ((volatile unsigned char*)ptr_mem_map->io_base+0xcfc);
}
/* Here we should check that the host bridge is actually
* present, but if it not, we are in such a desperate
* situation, that we probably can't even tell it.
*/
}
pci_read_config_dword(0, 0, 0, 0, &id0);
if(id0 == PCI_VENDOR_ID_MOTOROLA +
(PCI_DEVICE_ID_MOTOROLA_RAVEN<<16)) {
/*
* We have a Raven bridge. We will get information about its settings
*/
pci_read_config_dword(0, 0, 0, PCI_COMMAND, &id0);
#ifdef SHOW_RAVEN_SETTING
printk("RAVEN PCI command register = %x\n",id0);
#endif
id0 |= RAVEN_CLEAR_EVENTS_MASK;
pci_write_config_dword(0, 0, 0, PCI_COMMAND, id0);
pci_read_config_dword(0, 0, 0, PCI_COMMAND, &id0);
#ifdef SHOW_RAVEN_SETTING
printk("After error clearing RAVEN PCI command register = %x\n",id0);
#endif
if (id0 & RAVEN_MPIC_IOSPACE_ENABLE) {
pci_read_config_dword(0, 0, 0,PCI_BASE_ADDRESS_0, &tmp);
#ifdef SHOW_RAVEN_SETTING
printk("Raven MPIC is accessed via IO Space Access at address : %x\n",(tmp & ~0x1));
#endif
}
if (id0 & RAVEN_MPIC_MEMSPACE_ENABLE) {
pci_read_config_dword(0, 0, 0,PCI_BASE_ADDRESS_1, &tmp);
#ifdef SHOW_RAVEN_SETTING
printk("Raven MPIC is accessed via memory Space Access at address : %x\n", tmp);
#endif
OpenPIC=(volatile struct OpenPIC *) (tmp + PREP_ISA_MEM_BASE);
printk("OpenPIC found at %p.\n",
OpenPIC);
}
}
if (OpenPIC == (volatile struct OpenPIC *)0) {
BSP_panic("OpenPic Not found\n");
}
}
@@ -0,0 +1,55 @@
/* Author: Till Straumann <strauman@slac.stanford.edu>, 2001 */
/* find a particular PCI device
* (we assume, the firmware configured the PCI bus[es] for us)
*
* $Id$
*/
#define PCI_INVALID_VENDORDEVICEID 0xffffffff
#define PCI_MULTI_FUNCTION 0x80
#include <bsp/pci.h>
#include <rtems/bspIo.h>
int
BSP_pciFindDevice(unsigned short vendorid, unsigned short deviceid,
int instance, int *pbus, int *pdev, int *pfun)
{
unsigned int d;
unsigned short s;
unsigned char bus,dev,fun,hd;
for (bus=0; bus<BusCountPCI(); bus++) {
for (dev=0; dev<PCI_MAX_DEVICES; dev++) {
pci_read_config_byte(bus,dev,0, PCI_HEADER_TYPE, &hd);
hd = (hd & PCI_MULTI_FUNCTION ? PCI_MAX_FUNCTIONS : 1);
for (fun=0; fun<hd; fun++) {
/*
* The last devfn id/slot is special; must skip it
*/
if (PCI_MAX_DEVICES-1==dev && PCI_MAX_FUNCTIONS-1 == fun)
break;
(void)pci_read_config_dword(bus,dev,fun,PCI_VENDOR_ID,&d);
if (PCI_INVALID_VENDORDEVICEID == d)
continue;
#ifdef PCI_DEBUG
printk("BSP_pciFindDevice: found 0x%08x at %i/%i/%i\n",d,bus,dev,fun);
#endif
(void) pci_read_config_word(bus,dev,fun,PCI_VENDOR_ID,&s);
if (vendorid != s)
continue;
(void) pci_read_config_word(bus,dev,fun,PCI_DEVICE_ID,&s);
if (deviceid == s) {
if (instance--) continue;
*pbus=bus; *pdev=dev; *pfun=fun;
return 0;
}
}
}
}
return -1;
}