summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/mvme2307/pci
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/powerpc/mvme2307/pci')
-rw-r--r--c/src/lib/libbsp/powerpc/mvme2307/pci/Makefile.in70
-rw-r--r--c/src/lib/libbsp/powerpc/mvme2307/pci/NOTES41
-rw-r--r--c/src/lib/libbsp/powerpc/mvme2307/pci/interrupts.c353
-rw-r--r--c/src/lib/libbsp/powerpc/mvme2307/pci/isa_interrupts.c70
-rw-r--r--c/src/lib/libbsp/powerpc/mvme2307/pci/pci.c87
5 files changed, 621 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/mvme2307/pci/Makefile.in b/c/src/lib/libbsp/powerpc/mvme2307/pci/Makefile.in
new file mode 100644
index 0000000000..ae6a5ccbb4
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme2307/pci/Makefile.in
@@ -0,0 +1,70 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ../../../..
+subdir = libbsp/powerpc/mvme2307/pci
+
+RTEMS_ROOT = @RTEMS_ROOT@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+VPATH = @srcdir@
+
+PGM=${ARCH}/pci.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=interrupts pci
+C_FILES=$(C_PIECES:%=%.c)
+C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
+
+H_FILES=
+
+# Assembly source names, if any, go here -- minus the .S
+S_PIECES=
+S_FILES=$(S_PIECES:%=%.S)
+S_O_FILES=$(S_FILES:%.S=${ARCH}/%.o)
+
+SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES)
+OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+INSTALL_CHANGE = @INSTALL_CHANGE@
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+CPPFLAGS +=
+CFLAGS +=
+
+LD_PATHS +=
+LD_LIBS +=
+LDFLAGS +=
+
+#
+# Add your list of files to delete here. The config files
+# already know how to delete some stuff, so you may want
+# to just run 'make clean' first to see what gets missed.
+# 'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+${PGM}: ${SRCS} ${OBJS}
+ $(make-rel)
+
+all: ${ARCH} $(SRCS) $(PGM)
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+install: all
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/c/src/lib/libbsp/powerpc/mvme2307/pci/NOTES b/c/src/lib/libbsp/powerpc/mvme2307/pci/NOTES
new file mode 100644
index 0000000000..ea7948ad22
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme2307/pci/NOTES
@@ -0,0 +1,41 @@
+Device at 0,0,0: Motorola Raven
+ cmd/status: 22800006
+ class/rev: 06000001
+ iobase: not mapped
+ membase: 3c000000
+
+Device at 0,11,0: Winbond 83C553
+ cmd/status: 02000007
+ class/rev: 06010005
+ iobase: 00000000
+ membase: 00000000
+
+Device at 0,11,1: Winbond 82C105
+ cmd/status: 02800005
+ class/rev: 01018f05
+ iobase: 010000a1
+ membase: not mapped
+
+Device at 0,13,0: Tundra CA91C042
+ cmd/status: 02000006
+ class/rev: 06800000
+ iobase: not mapped
+ membase: 00000000
+
+Device at 0,14,0: DEC 21140
+ cmd/status: 02800007
+ class/rev: 02000022
+ iobase: 01000001
+ membase: 3bfeff80
+
+Device at 0,17,0: Intel i960 PCI bridge
+ cmd/status: 02800007
+ class/rev: ff040003
+ iobase: 00000000
+ membase: 00000000
+
+Device at 0,17,1: Intel i960 ATU
+ cmd/status: 02800106
+ class/rev: 05800003
+ iobase: not mapped
+ membase: 00000000
diff --git a/c/src/lib/libbsp/powerpc/mvme2307/pci/interrupts.c b/c/src/lib/libbsp/powerpc/mvme2307/pci/interrupts.c
new file mode 100644
index 0000000000..b3873fbe01
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme2307/pci/interrupts.c
@@ -0,0 +1,353 @@
+#include <rtems.h>
+#include <rtems/error.h>
+#include <bsp.h>
+
+#define NUMBER_INTERRUPTS (IRQ_RAVEN_ERROR + 1)
+
+#define DISABLE_IRQ 0x80000000
+
+static rtems_isr raven_interrupt_handler(rtems_vector_number vector);
+static rtems_isr default_interrupt_handler(rtems_vector_number vector);
+static rtems_isr spurious_interrupt_handler(rtems_vector_number vector);
+
+
+static rtems_isr_entry handlers[NUMBER_INTERRUPTS];
+static int *vec_prio_reg_addresses[NUMBER_INTERRUPTS] = {0};
+static void *raven_base = 0;
+static int timer_frequency = 0;
+
+rtems_status_code interrupt_controller_init(void) {
+ int i;
+ int raven_config = pci_find_by_devid(RAVEN_VENDOR_ID, RAVEN_DEVICE_ID, 0);
+ rtems_isr_entry old_handler;
+ rtems_status_code sc;
+
+ /* get base address of raven registers in LOCAL space */
+ raven_base =
+ (void *)PCI_TO_LOCAL(pci_conf_read32(raven_config, PCI_BASE_ADDRESS_1));
+
+ /* set cascade mode in global configuration register */
+ st_le32(raven_base + 0x01020, 0x20000000);
+
+ /* set spurious interrupt vector */
+ st_le32(raven_base + 0x010e0, IRQ_SPURIOUS);
+
+ /* get the timer frequency */
+ timer_frequency = ld_le32(raven_base + 0x010f0);
+
+ /* fill in vector/priority register addresses */
+ vec_prio_reg_addresses[IRQ_PIC_CASCADE] = raven_base + 0x10000;
+ vec_prio_reg_addresses[IRQ_FALCON_ECC] = raven_base + 0x10020;
+ vec_prio_reg_addresses[IRQ_ETHERNET] = raven_base + 0x10040;
+ vec_prio_reg_addresses[IRQ_VME_LINT0] = raven_base + 0x100a0;
+ vec_prio_reg_addresses[IRQ_VME_LINT1] = raven_base + 0x100c0;
+ vec_prio_reg_addresses[IRQ_VME_LINT2] = raven_base + 0x100e0;
+ vec_prio_reg_addresses[IRQ_VME_LINT3] = raven_base + 0x10100;
+ vec_prio_reg_addresses[IRQ_PMC1A_PMC2B] = raven_base + 0x10120;
+ vec_prio_reg_addresses[IRQ_PMC1B_PMC2C] = raven_base + 0x10140;
+ vec_prio_reg_addresses[IRQ_PMC1C_PMC2D] = raven_base + 0x10160;
+ vec_prio_reg_addresses[IRQ_PMC1D_PMC2A] = raven_base + 0x10180;
+ vec_prio_reg_addresses[IRQ_LM_SIG_0] = raven_base + 0x101a0;
+ vec_prio_reg_addresses[IRQ_LM_SIG_1] = raven_base + 0x101c0;
+ vec_prio_reg_addresses[IRQ_TIMER_0] = raven_base + 0x01120;
+ vec_prio_reg_addresses[IRQ_TIMER_1] = raven_base + 0x01160;
+ vec_prio_reg_addresses[IRQ_TIMER_2] = raven_base + 0x011a0;
+ vec_prio_reg_addresses[IRQ_TIMER_3] = raven_base + 0x011e0;
+ vec_prio_reg_addresses[IRQ_IPI_0] = raven_base + 0x010a0;
+ vec_prio_reg_addresses[IRQ_IPI_1] = raven_base + 0x010b0;
+ vec_prio_reg_addresses[IRQ_IPI_2] = raven_base + 0x010c0;
+ vec_prio_reg_addresses[IRQ_IPI_3] = raven_base + 0x010d0;
+ vec_prio_reg_addresses[IRQ_RAVEN_ERROR] = raven_base + 0x10200;
+
+ /* initialize all vector/priority registers to level 0, disabled */
+ for (i = 0; i < NUMBER_INTERRUPTS; i++) {
+ if (vec_prio_reg_addresses[i]) {
+ st_le32(vec_prio_reg_addresses[i], DISABLE_IRQ | i);
+ }
+ }
+
+ /* initialize all interrupt destination registers to processor 0 */
+ st_le32(raven_base + 0x01130, 1);
+ st_le32(raven_base + 0x01170, 1);
+ st_le32(raven_base + 0x011b0, 1);
+ st_le32(raven_base + 0x011f0, 1);
+ st_le32(raven_base + 0x10010, 1);
+ st_le32(raven_base + 0x10030, 1);
+ st_le32(raven_base + 0x10050, 1);
+ st_le32(raven_base + 0x10070, 1);
+ st_le32(raven_base + 0x10090, 1);
+ st_le32(raven_base + 0x100b0, 1);
+ st_le32(raven_base + 0x100d0, 1);
+ st_le32(raven_base + 0x100f0, 1);
+ st_le32(raven_base + 0x10110, 1);
+ st_le32(raven_base + 0x10130, 1);
+ st_le32(raven_base + 0x10150, 1);
+ st_le32(raven_base + 0x10170, 1);
+ st_le32(raven_base + 0x10190, 1);
+ st_le32(raven_base + 0x101b0, 1);
+ st_le32(raven_base + 0x101d0, 1);
+ st_le32(raven_base + 0x101f0, 1);
+ st_le32(raven_base + 0x10210, 1);
+
+ /* set up default interrupt handlers */
+ for (i = 0; i < NUMBER_INTERRUPTS; i++) {
+ handlers[i] = default_interrupt_handler;
+ }
+ handlers[IRQ_SPURIOUS] = spurious_interrupt_handler;
+
+ /* enable 8259 PIC interrupt at level 8 */
+ st_le32(vec_prio_reg_addresses[IRQ_PIC_CASCADE],
+ 0x00c00000 | (PRIORITY_ISA_INT << 16) | IRQ_PIC_CASCADE);
+
+ /* attach interrupt handler and enable interrupts */
+ sc = rtems_interrupt_catch(raven_interrupt_handler, PPC_IRQ_EXTERNAL,
+ &old_handler);
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_panic("can't catch interrupt for raven pic\n");
+ }
+ return set_interrupt_task_priority(0);
+}
+
+#define PCI_Interrupt_Ack_Addr ((unsigned32 *) 0xFEFF0030)
+#define NonspecificEOI 0x20
+#define PIC1_OCW2 (*(volatile char *)IO_TO_LOCAL(0x20))
+#define PIC2_OCW2 (*(volatile char *)IO_TO_LOCAL(0xA0))
+
+static rtems_isr raven_interrupt_handler(rtems_vector_number vector) {
+ int raven_vector;
+ int msr_value;
+
+ /* read Raven interrupt acknowledge register */
+ raven_vector = ld_le32(raven_base + 0x200a0);
+
+ if (raven_vector == IRQ_PIC_CASCADE) {
+ /* read PCI interrupt acknowledge register */
+ int piack_image = ld_le32(PCI_Interrupt_Ack_Addr);
+ int isa_vector = piack_image & 0x07;
+ int pic_id = (piack_image >> 3) & 0x1f;
+
+ if (pic_id == 0x10) {
+ isa_vector += 8;
+ } else if (pic_id != 0x01) {
+ rtems_panic("unrecognized PIACK value: %08x\n", piack_image);
+ }
+
+ /* set MSRee = 1 */
+ _CPU_MSR_Value(msr_value);
+ msr_value |= PPC_MSR_EE;
+ _CPU_MSR_SET(msr_value);
+
+ /* signal EOI to Raven */
+ st_le32(raven_base + 0x200b0, 0);
+
+ /* call handler */
+ handlers[isa_vector](isa_vector);
+
+ /* signal EOI to 8259 PIC */
+ PIC1_OCW2 = NonspecificEOI;
+ if (isa_vector >= 8) {
+ PIC2_OCW2 = NonspecificEOI;
+ }
+ } else {
+ /* set MSRee = 1 */
+ _CPU_MSR_Value(msr_value);
+ msr_value |= PPC_MSR_EE;
+ _CPU_MSR_SET(msr_value);
+
+ /* call handler */
+ handlers[raven_vector](raven_vector);
+
+ /* signal EOI to Raven */
+ st_le32(raven_base + 0x200b0, 0);
+
+ }
+}
+
+static rtems_isr default_interrupt_handler(rtems_vector_number vector) {
+ rtems_panic("unhandled interrupt: %d\n", vector);
+}
+
+static rtems_isr spurious_interrupt_handler(rtems_vector_number vector) {
+ rtems_panic("spurious interrupt\n");
+}
+
+rtems_status_code bsp_interrupt_catch(rtems_isr_entry new_isr_handler,
+ rtems_vector_number vector,
+ rtems_isr_entry *old_isr_handler) {
+ if (!old_isr_handler || ((int)new_isr_handler & 3) != 0) {
+ return RTEMS_INVALID_ADDRESS;
+ }
+ switch (vector) {
+ case IRQ_ISA_TIMER: case IRQ_UART: case IRQ_ISA_LM_SIG:
+ case IRQ_ABORT_SWITCH: case IRQ_ISA_ETHERNET: case IRQ_ISA_UNIVERSE:
+ case IRQ_ISA_PMC_PCIX: case IRQ_FALCON_ECC: case IRQ_ETHERNET:
+ case IRQ_VME_LINT0: case IRQ_VME_LINT1: case IRQ_VME_LINT2:
+ case IRQ_VME_LINT3: case IRQ_PMC1A_PMC2B: case IRQ_PMC1B_PMC2C:
+ case IRQ_PMC1C_PMC2D: case IRQ_PMC1D_PMC2A: case IRQ_LM_SIG_0:
+ case IRQ_LM_SIG_1: case IRQ_TIMER_0: case IRQ_TIMER_1:
+ case IRQ_TIMER_2: case IRQ_TIMER_3: case IRQ_IPI_0:
+ case IRQ_IPI_1: case IRQ_IPI_2: case IRQ_IPI_3:
+ case IRQ_RAVEN_ERROR:
+ *old_isr_handler = handlers[vector];
+ handlers[vector] = new_isr_handler;
+ return RTEMS_SUCCESSFUL;
+ default:
+ return RTEMS_INVALID_NUMBER;
+ }
+}
+
+#define PIC1_Mask (*(unsigned8 *) IO_TO_LOCAL(0x21))
+#define PIC2_Mask (*(unsigned8 *) IO_TO_LOCAL(0xA1))
+
+
+rtems_status_code bsp_interrupt_enable(rtems_vector_number vector,
+ int priority) {
+ switch (vector) {
+ case IRQ_ISA_TIMER: case IRQ_UART: case IRQ_ISA_LM_SIG:
+ case IRQ_ABORT_SWITCH: case IRQ_ISA_ETHERNET: case IRQ_ISA_UNIVERSE:
+ case IRQ_ISA_PMC_PCIX:
+ if (priority != PRIORITY_ISA_INT) {
+ return RTEMS_INVALID_NUMBER;
+ }
+ if (vector < 8) {
+ PIC1_Mask &= ~ (1 << vector);
+ } else {
+ PIC2_Mask &= ~ (1 << (vector - 8));
+ }
+ return RTEMS_SUCCESSFUL;
+
+ case IRQ_ETHERNET: case IRQ_VME_LINT0: case IRQ_VME_LINT1:
+ case IRQ_VME_LINT2: case IRQ_VME_LINT3: case IRQ_PMC1A_PMC2B:
+ case IRQ_PMC1B_PMC2C: case IRQ_PMC1C_PMC2D: case IRQ_PMC1D_PMC2A:
+ case IRQ_LM_SIG_0: case IRQ_LM_SIG_1:
+ if (priority & ~15) {
+ return RTEMS_INVALID_NUMBER;
+ }
+ st_le32(vec_prio_reg_addresses[vector],
+ 0x00400000 | (priority << 16) | vector);
+ return RTEMS_SUCCESSFUL;
+
+ case IRQ_FALCON_ECC: case IRQ_TIMER_0: case IRQ_TIMER_1:
+ case IRQ_TIMER_2: case IRQ_TIMER_3: case IRQ_IPI_0:
+ case IRQ_IPI_1: case IRQ_IPI_2: case IRQ_IPI_3:
+ case IRQ_RAVEN_ERROR:
+ if (priority & ~15) {
+ return RTEMS_INVALID_NUMBER;
+ }
+ st_le32(vec_prio_reg_addresses[vector], (priority << 16) | vector);
+ return RTEMS_SUCCESSFUL;
+
+ default:
+ return RTEMS_INVALID_NUMBER;
+ }
+}
+
+rtems_status_code bsp_interrupt_disable(rtems_vector_number vector) {
+ switch (vector) {
+ case IRQ_ISA_TIMER: case IRQ_UART: case IRQ_ISA_LM_SIG:
+ case IRQ_ABORT_SWITCH: case IRQ_ISA_ETHERNET: case IRQ_ISA_UNIVERSE:
+ case IRQ_ISA_PMC_PCIX:
+ if (vector < 8) {
+ PIC1_Mask |= (1 << vector);
+ } else {
+ PIC2_Mask |= (1 << (vector - 8));
+ }
+ return RTEMS_SUCCESSFUL;
+
+ case IRQ_FALCON_ECC: case IRQ_ETHERNET: case IRQ_VME_LINT0:
+ case IRQ_VME_LINT1: case IRQ_VME_LINT2: case IRQ_VME_LINT3:
+ case IRQ_PMC1A_PMC2B: case IRQ_PMC1B_PMC2C: case IRQ_PMC1C_PMC2D:
+ case IRQ_PMC1D_PMC2A: case IRQ_LM_SIG_0: case IRQ_LM_SIG_1:
+ case IRQ_TIMER_0: case IRQ_TIMER_1: case IRQ_TIMER_2:
+ case IRQ_TIMER_3: case IRQ_IPI_0: case IRQ_IPI_1:
+ case IRQ_IPI_2: case IRQ_IPI_3: case IRQ_RAVEN_ERROR:
+ st_le32(vec_prio_reg_addresses[vector], DISABLE_IRQ | vector);
+ return RTEMS_SUCCESSFUL;
+
+ default:
+ return RTEMS_INVALID_NUMBER;
+ }
+}
+
+rtems_status_code bsp_start_timer(int timer, int period_usec) {
+ double counts = (double)period_usec * timer_frequency / 1.0e6 + 0.5;
+ if (counts < 1.0 || counts > (double)0x7fffffff) {
+ return RTEMS_INVALID_NUMBER;
+ }
+ switch (timer) {
+ case 0:
+ st_le32(raven_base + 0x01110, (int)counts);
+ break;
+ case 1:
+ st_le32(raven_base + 0x01150, (int)counts);
+ break;
+ case 2:
+ st_le32(raven_base + 0x01190, (int)counts);
+ break;
+ case 3:
+ st_le32(raven_base + 0x011d0, (int)counts);
+ break;
+ default:
+ return RTEMS_INVALID_NUMBER;
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code bsp_stop_timer(int timer) {
+ switch (timer) {
+ case 0:
+ st_le32(raven_base + 0x01110, 0x80000000);
+ break;
+ case 1:
+ st_le32(raven_base + 0x01150, 0x80000000);
+ break;
+ case 2:
+ st_le32(raven_base + 0x01190, 0x80000000);
+ break;
+ case 3:
+ st_le32(raven_base + 0x011d0, 0x80000000);
+ break;
+ default:
+ return RTEMS_INVALID_NUMBER;
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code bsp_read_timer(int timer, int *value) {
+ switch (timer) {
+ case 0:
+ *value = ld_le32(raven_base + 0x01100) & 0x7fffffff;
+ break;
+ case 1:
+ *value = ld_le32(raven_base + 0x01140) & 0x7fffffff;
+ break;
+ case 2:
+ *value = ld_le32(raven_base + 0x01180) & 0x7fffffff;
+ break;
+ case 3:
+ *value = ld_le32(raven_base + 0x011c0) & 0x7fffffff;
+ break;
+ default:
+ return RTEMS_INVALID_NUMBER;
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code generate_interprocessor_interrupt(int interrupt) {
+ int *dispatch_reg = raven_base + 0x20040;
+
+ if (interrupt & ~3) {
+ return RTEMS_INVALID_NUMBER;
+ }
+ dispatch_reg[interrupt << 2] = 1;
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code set_interrupt_task_priority(int priority) {
+ if (priority & ~15) {
+ return RTEMS_INVALID_NUMBER;
+ }
+ st_le32(raven_base + 0x20080, priority);
+ return RTEMS_SUCCESSFUL;
+}
+
diff --git a/c/src/lib/libbsp/powerpc/mvme2307/pci/isa_interrupts.c b/c/src/lib/libbsp/powerpc/mvme2307/pci/isa_interrupts.c
new file mode 100644
index 0000000000..33734d64e9
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme2307/pci/isa_interrupts.c
@@ -0,0 +1,70 @@
+#include <bsp.h>
+
+#define PCI_Interrupt_Ack (*(volatile unsigned32 *) 0xFEFF0030)
+#define PIC1_OCW2 (*(volatile char *)IO_TO_LOCAL(0x0020))
+#define PIC2_OCW2 (*(volatile char *)IO_TO_LOCAL(0x00A0))
+#define NonspecificEOI 0x20
+
+#define Master_PIC_Mask (*(unsigned8 *) IO_TO_LOCAL(0x0021))
+#define Slave_PIC_Mask (*(unsigned8 *) IO_TO_LOCAL(0x00A1))
+
+rtems_isr_entry isa_handlers[16] = {0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+
+rtems_status_code isa_interrupt_enable(rtems_vector_number vector) {
+ if (vector < 0 || vector > 15 || vector == 2) {
+ return RTEMS_INVALID_NUMBER;
+ }
+ if (vector < 8) {
+ Master_PIC_Mask &= ~ (1 << vector);
+ } else {
+ Slave_PIC_Mask &= ~ (1 << (vector - 8));
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code isa_interrupt_disable(rtems_vector_number vector) {
+ if (vector < 0 || vector > 15 || vector == 2) {
+ return RTEMS_INVALID_NUMBER;
+ }
+ if (vector < 8) {
+ Master_PIC_Mask |= (1 << vector);
+ } else {
+ Slave_PIC_Mask |= (1 << (vector - 8));
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code isa_interrupt_catch(rtems_isr_entry new_isr_handler,
+ rtems_vector_number vector,
+ rtems_isr_entry *old_isr_handler) {
+ if (vector < 0 || vector > 15 || vector == 2) {
+ return RTEMS_INVALID_NUMBER;
+ }
+ if (!old_isr_handler || ((int)new_isr_handler & 3) != 0) {
+ return RTEMS_INVALID_ADDRESS;
+ }
+ *old_isr_handler = isa_handlers[vector];
+ isa_handlers[vector] = new_isr_handler;
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_isr isa_interrupt_handler(rtems_vector_number vector) {
+ unsigned32 piack_image = PCI_Interrupt_Ack;
+ int pic_id = piack_image >> 27;
+ rtems_vector_number isa_vector = (piack_image >> 24) & 7;
+
+ if (pic_id == 0x10) {
+ isa_vector += 8;
+ } else if (pic_id != 0x01) {
+ printk("unrecognized PIACK value: %08x\n", piack_image);
+ return;
+ }
+ if (isa_handlers[isa_vector] != 0) {
+ isa_handlers[isa_vector](isa_vector);
+ }
+ PIC1_OCW2 = NonspecificEOI;
+ if (isa_vector >= 8) {
+ PIC2_OCW2 = NonspecificEOI;
+ }
+}
diff --git a/c/src/lib/libbsp/powerpc/mvme2307/pci/pci.c b/c/src/lib/libbsp/powerpc/mvme2307/pci/pci.c
new file mode 100644
index 0000000000..e9bebd3f78
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme2307/pci/pci.c
@@ -0,0 +1,87 @@
+#include <bsp.h>
+
+static const void *PciConfAddr = IO_TO_LOCAL(0x0cf8);
+static const void *PciConfData = IO_TO_LOCAL(0x0cfc);
+
+int pci_make_devsig(int bus, int device, int function) {
+ return ((bus & 255) << 16) | ((device & 31) << 11) |
+ ((function & 7) << 8) | 0x80000000;
+}
+
+int pci_conf_read8(int sig, int off) {
+ st_le32(PciConfAddr, sig + (off & 252));
+ synchronize_io();
+ return *(unsigned char *)(PciConfData + (off & 3));
+}
+
+int pci_conf_read16(int sig, int off) {
+ st_le32(PciConfAddr, sig + (off & 252));
+ synchronize_io();
+ return ld_le16(PciConfData + (off & 3));
+}
+
+int pci_conf_read32(int sig, int off) {
+ st_le32(PciConfAddr, sig + (off & 252));
+ synchronize_io();
+ return ld_le32(PciConfData);
+}
+
+void pci_conf_write8(int sig, int off, unsigned int data) {
+ st_le32(PciConfAddr, sig + (off & 252));
+ synchronize_io();
+ *(unsigned char *)(PciConfData + (off & 3)) = data;
+}
+
+void pci_conf_write16(int sig, int off, unsigned int data) {
+ st_le32(PciConfAddr, sig + (off & 252));
+ synchronize_io();
+ st_le16(PciConfData + (off & 3), data);
+}
+
+void pci_conf_write32(int sig, int off, unsigned int data) {
+ st_le32(PciConfAddr, sig + (off & 252));
+ synchronize_io();
+ st_le32(PciConfData + (off & 3), data);
+}
+
+static int recursive_find(int bus, int devid_venid, int idx, int *count) {
+ int devsig, dev, func, max_func, idreg, class, secondary_bus;
+ char header_type;
+
+ for (dev = 0; dev < 32; dev++) {
+ devsig = pci_make_devsig(bus, dev, 0);
+ header_type = pci_conf_read8(devsig, 0x0e);
+ max_func = (header_type & 0x80) ? 8 : 1; /* multi-function device? */
+ for (func = 0; func < max_func; func++) {
+ devsig = pci_make_devsig(bus, dev, func);
+ idreg = pci_conf_read32(devsig, 0x00);
+ if (idreg == 0xffffffff) {
+ break; /* empty slot */
+ }
+ if (idreg == devid_venid) {
+ /* id's match - is it the right instance? */
+ if (*count == idx) {
+ return devsig;
+ } else {
+ (*count)++;
+ }
+ }
+ class = pci_conf_read32(devsig, 0x08) & 0xffff0000;
+ if (class == 0x06040000) { /* pci-pci bridge? */
+ secondary_bus = pci_conf_read8(devsig, 0x19);
+ devsig = recursive_find(secondary_bus, devid_venid, idx, count);
+ if (devsig != PCI_NOT_FOUND) {
+ return devsig;
+ }
+ }
+ }
+ }
+ return PCI_NOT_FOUND;
+}
+
+int pci_find_by_devid(int vendorId, int devId, int idx) {
+ int count = 0;
+ int devid_venid = ((devId << 16) & 0xffff0000) | (vendorId & 0xffff);
+
+ return recursive_find(0, devid_venid, idx, &count);
+}