diff options
author | Per Fogelstrom <pefo@cvs.openbsd.org> | 1997-03-12 19:17:04 +0000 |
---|---|---|
committer | Per Fogelstrom <pefo@cvs.openbsd.org> | 1997-03-12 19:17:04 +0000 |
commit | 63e70c1bce393b8e92002c93029eeb1a67f80fcc (patch) | |
tree | 1ffb854bd1045ee6f0999913b74a788a879368bc /sys/arch/arc/algor | |
parent | fd5a4621c16957714dbc7335eb5afa6b0f28b29e (diff) |
Addition of support for a PCI based Vr4300 board from Algorithmics, the P-4032.
Changes to io macros were done to handle sparse bus addressing dynamically.
This is a first cut (rough).
Diffstat (limited to 'sys/arch/arc/algor')
-rw-r--r-- | sys/arch/arc/algor/algor.h | 111 | ||||
-rw-r--r-- | sys/arch/arc/algor/algorbus.c | 438 |
2 files changed, 549 insertions, 0 deletions
diff --git a/sys/arch/arc/algor/algor.h b/sys/arch/arc/algor/algor.h new file mode 100644 index 00000000000..bfe02f65104 --- /dev/null +++ b/sys/arch/arc/algor/algor.h @@ -0,0 +1,111 @@ +/* $OpenBSD: algor.h,v 1.1 1997/03/12 19:16:33 pefo Exp $ */ + +/* + * Copyright (c) 1996 Per Fogelstrom + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed under OpenBSD by + * Per Fogelstrom. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _ALGOR_H_ +#define _ALGOR_H_ 1 + +/* + * P-4032's Physical address space + */ + +#define P4032_PHYS_MIN 0x00000000 /* 256 Meg */ +#define P4032_PHYS_MAX 0x0fffffff + +/* + * Memory map + */ + +#define P4032_PHYS_MEMORY_START 0x00000000 +#define P4032_PHYS_MEMORY_END 0x0fffffff /* 256 Meg in 2 slots */ + +/* + * I/O map + */ + +#define P4032_V96x 0xbef00000 /* PCI Bus bridge ctrlregs */ + +#define P4032_CLOCK 0xbff00000 /* RTC clock ptr reg */ +#define P4032_KEYB 0xbff10000 /* PC Keyboard controller */ +#define P4032_LED 0xbff20010 /* 4 Char LED display */ +#define P4032_LCD 0xbff30000 /* LCD option display */ +#define P4032_GPIO 0xbff40000 /* General purpose I/O */ +#define P4032_GPIO_IACK 0xbff50000 /* General purpose I/O Iack */ +#define P4032_FPY 0xbff807c0 /* Floppy controller */ +#define P4032_COM1 0xbff80fe0 +#define P4032_COM2 0xbff80be0 +#define P4032_IMR 0xbff90000 /* Int mask reg (wr) */ +#define P4032_IRR 0xbff90000 /* Int request reg (rd) */ +#define P4032_EIRR 0xbff90004 /* Error int request reg (rd) */ +#define P4032_ICR 0xbff90004 /* Int clear register (wr) */ +#define P4032_PCIIMR 0xbff90008 /* PCI Int mask reg (wr) */ +#define P4032_PCIIRR 0xbff90008 /* PCI Int req reg (rd) */ +#define P4032_IXR0 0xbff9000c /* Int crossbar register 0 */ +#define P4032_IXR1 0xbff90010 /* Int crossbar register 0 */ +#define P4032_IXR2 0xbff90014 /* Int crossbar register 0 */ + +/* + * Interrupt controller interrupt masks + */ + +#define P4032_IM_RTC 0x80 /* RT Clock */ +#define P4032_IM_GPIO 0x40 /* General purpose I/O */ +#define P4032_IM_CENTR 0x20 /* Centronics paralell port */ +#define P4032_IM_COM2 0x10 /* Serial port 2 */ +#define P4032_IM_COM1 0x08 /* Serial port 1 */ +#define P4032_IM_KEYB 0x04 /* PC Keyboard IFC */ +#define P4032_IM_FPY 0x02 /* Floppy disk */ +#define P4032_IM_PCI 0x01 /* PCI controller */ + +#define P4032_IRR_BER 0x04 /* Bus error */ +#define P4032_IRR_PFAIL 0x02 /* Power fail */ +#define P4032_IRR_DBG 0x01 /* Debug switch */ + +#define P4032_PCI_IRQ3 0x80 /* PCI interrupt request 3 */ +#define P4032_PCI_IRQ2 0x40 /* PCI interrupt request 2 */ +#define P4032_PCI_IRQ1 0x20 /* PCI interrupt request 1 */ +#define P4032_PCI_IRQ0 0x10 /* PCI interrupt request 0 */ +#define P4032_FPY_DMA 0x08 /* FPY "DMA" interrupt request */ +/* + * Interrupt vector descriptor for device on pica bus. + */ +struct algor_int_desc { + int int_mask; /* Mask used in PICA_SYS_LB_IE */ + intr_handler_t int_hand; /* Interrupt handler */ + void *param; /* Parameter to send to handler */ + int spl_mask; /* Spl mask for interrupt */ +}; + +int algor_intrnull __P((void *)); + +#endif /* _ALGOR_H_ */ diff --git a/sys/arch/arc/algor/algorbus.c b/sys/arch/arc/algor/algorbus.c new file mode 100644 index 00000000000..b6fc840471a --- /dev/null +++ b/sys/arch/arc/algor/algorbus.c @@ -0,0 +1,438 @@ +/* $OpenBSD: algorbus.c,v 1.1 1997/03/12 19:16:35 pefo Exp $ */ + +/* + * Copyright (c) 1996 Per Fogelstrom + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed under OpenBSD by + * Per Fogelstrom. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/param.h> +#include <sys/device.h> + +#include <machine/cpu.h> +#include <machine/pio.h> +#include <machine/intr.h> +#include <machine/autoconf.h> + +#include <arc/arc/arctype.h> +#include <arc/algor/algor.h> + +#include <dev/ic/mc146818reg.h> + +struct algor_softc { + struct device sc_dv; + struct abus sc_bus; + struct algor_dev *sc_devs; +}; + +/* Definition of the driver for autoconfig. */ +int algormatch(struct device *, void *, void *); +void algorattach(struct device *, struct device *, void *); +int algorprint(void *, const char *); + +struct cfattach algor_ca = { + sizeof(struct algor_softc), algormatch, algorattach +}; +struct cfdriver algor_cd = { + NULL, "algor", DV_DULL, NULL, 0 +}; + +void algor_intr_establish __P((struct confargs *, int (*)(void *), void *)); +void algor_intr_disestablish __P((struct confargs *)); +caddr_t algor_cvtaddr __P((struct confargs *)); +int algor_matchname __P((struct confargs *, char *)); +int algor_iointr __P((unsigned, struct clockframe *)); +int algor_clkintr __P((unsigned, struct clockframe *)); +int algor_errintr __P((unsigned, struct clockframe *)); + +extern int cputype; + +int p4032_imask = 0; +int p4032_ixr = 0; + +/* + * Interrupt dispatch table. + */ +static struct algor_int_desc int_table[] = { + {0, algor_intrnull, (void *)NULL, 0 }, /* 0 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 1 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 2 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 3 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 4 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 5 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 6 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 7 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 8 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 9 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 10 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 11 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 12 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 13 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 14 */ + {0, algor_intrnull, (void *)NULL, 0 }, /* 15 */ +}; +#define NUM_INT_SLOTS (sizeof(int_table) / sizeof(struct algor_int_desc)) + +struct algor_dev { + struct confargs ps_ca; + u_int8_t ps_mask; + u_int8_t ps_ipl; + u_int16_t ps_route; + intr_handler_t ps_handler; + void *ps_base; +}; +struct algor_dev algor_4032_cpu[] = { + {{ "dallas_rtc", 0, 0, }, + P4032_IM_RTC, IPL_CLOCK, 0xc000, algor_intrnull, (void *)P4032_CLOCK, }, + {{ "com", 1, 0, }, + P4032_IM_COM1, IPL_TTY, 0x00c0, algor_intrnull, (void *)P4032_COM1, }, + {{ "com", 2, 0, }, + P4032_IM_COM2, IPL_TTY, 0x0300, algor_intrnull, (void *)P4032_COM2, }, + {{ NULL, -1, NULL, }, + 0, 0x0000, NULL, (void *)NULL, }, +}; +#define NUM_ALGOR_DEVS (sizeof(algor_4032_cpu) / sizeof(struct algor_dev)) + +/* IPL routing values */ +static int ipxrtab[] = { + 0x000000, /* IPL_BIO */ + 0x555555, /* IPL_NET */ + 0xaaaaaa, /* IPL_TTY */ + 0xffffff, /* IPL_CLOCK */ +}; + + + +struct algor_dev *algor_cpu_devs[] = { + NULL, /* Unused */ + NULL, /* Unused */ + NULL, /* Unused */ + NULL, /* Unused */ + NULL, /* Unused */ + NULL, /* Unused */ + algor_4032_cpu, /* 6 = ALGORITHMICS R4032 Board */ + NULL, +}; +int nalgor_cpu_devs = sizeof algor_cpu_devs / sizeof algor_cpu_devs[0]; + +int +algormatch(parent, cfdata, aux) + struct device *parent; + void *cfdata; + void *aux; +{ + struct cfdata *cf = cfdata; + struct confargs *ca = aux; + + /* Make sure that we're looking for a ALGORITHMICS BUS */ + if (strcmp(ca->ca_name, algor_cd.cd_name) != 0) + return (0); + + /* Make sure that unit exists. */ + if (cf->cf_unit != 0 || + cputype > nalgor_cpu_devs || algor_cpu_devs[cputype] == NULL) + return (0); + + return (1); +} + +void +algorattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct algor_softc *sc = (struct algor_softc *)self; + struct confargs *nca; + int i; + + printf("\n"); + + /* keep our CPU device description handy */ + sc->sc_devs = algor_cpu_devs[cputype]; + + /* set up interrupt handlers */ + set_intr(INT_MASK_1, algor_iointr, 2); + set_intr(INT_MASK_4, algor_errintr, 0); + + sc->sc_bus.ab_dv = (struct device *)sc; + sc->sc_bus.ab_type = BUS_ALGOR; + sc->sc_bus.ab_intr_establish = algor_intr_establish; + sc->sc_bus.ab_intr_disestablish = algor_intr_disestablish; + sc->sc_bus.ab_cvtaddr = algor_cvtaddr; + sc->sc_bus.ab_matchname = algor_matchname; + + /* Try to configure each ALGOR attached device */ + for (i = 0; sc->sc_devs[i].ps_ca.ca_slot >= 0; i++) { + + if(sc->sc_devs[i].ps_ca.ca_name == NULL) + continue; /* Empty slot */ + + nca = &sc->sc_devs[i].ps_ca; + nca->ca_bus = &sc->sc_bus; + + /* Tell the autoconfig machinery we've found the hardware. */ + config_found(self, nca, algorprint); + } +} + +int +algorprint(aux, pnp) + void *aux; + const char *pnp; +{ + struct confargs *ca = aux; + + if (pnp) + printf("%s at %s", ca->ca_name, pnp); + printf(" slot %ld offset 0x%lx", ca->ca_slot, ca->ca_offset); + return (UNCONF); +} + +caddr_t +algor_cvtaddr(ca) + struct confargs *ca; +{ + struct algor_softc *sc = algor_cd.cd_devs[0]; + + return(sc->sc_devs[ca->ca_slot].ps_base + ca->ca_offset); + +} + +void +algor_intr_establish(ca, handler, arg) + struct confargs *ca; + intr_handler_t handler; + void *arg; +{ + struct algor_softc *sc = algor_cd.cd_devs[0]; + int slot = ca->ca_slot; + struct algor_dev *dev = &sc->sc_devs[slot]; + int ipl = dev->ps_ipl; + + if(int_table[slot].int_mask != 0) { + panic("algor intr already set"); + } + else { + int_table[slot].int_mask = dev->ps_mask; + int_table[slot].int_hand = handler; + int_table[slot].param = arg; + } + p4032_ixr |= ipxrtab[ipl] & dev->ps_route; + outb(P4032_IXR0, p4032_ixr); + outb(P4032_IXR1, p4032_ixr >> 8); + outb(P4032_IXR2, p4032_ixr >> 16); + + if(slot == 0) { /* Slot 0 is special, clock */ + set_intr(INT_MASK_0 << ipl, algor_clkintr, ipl + 1); + } + else { + set_intr(INT_MASK_0 << ipl, algor_iointr, ipl + 1); + } + + p4032_imask |= dev->ps_mask; + outb(P4032_IMR, p4032_imask); + outb(P4032_PCIIMR, p4032_imask >> 8); +} + +void * +algor_pci_intr_establish(ih, level, handler, arg, name) + int level; + intr_handler_t handler; + void *arg; + void *name; +{ + int imask; + int route; + int slot; + + if(level < IPL_BIO || level >= IPL_CLOCK) { + panic("pci intr: ipl level out of range"); + } + if(ih < 0 || ih >= 4) { + panic("pci intr: irq out of range"); + } + + imask = (0x1000 << ih); + route = (0x30000 << ih+ih); + + slot = NUM_INT_SLOTS; + while(slot > 0) { + if(int_table[slot].int_mask == 0) + break; + slot--; + } + if(slot < 0) { + panic("pci intr: out of int slots"); + } + + int_table[slot].int_mask = imask; + int_table[slot].int_hand = handler; + int_table[slot].param = arg; + + p4032_ixr |= ipxrtab[level] & route; + outb(P4032_IXR0, p4032_ixr); + outb(P4032_IXR1, p4032_ixr >> 8); + outb(P4032_IXR2, p4032_ixr >> 16); + + set_intr(INT_MASK_0 << level, algor_iointr, level + 1); + + p4032_imask |= imask; + outb(P4032_IMR, p4032_imask); + outb(P4032_PCIIMR, p4032_imask >> 8); + + return((void *)slot); +} + +void +algor_intr_disestablish(ca) + struct confargs *ca; +{ + struct algor_softc *sc = algor_cd.cd_devs[0]; + + int slot; + + slot = ca->ca_slot; + p4032_imask &= ~int_table[slot].int_mask; + outb(P4032_IMR, p4032_imask); + outb(P4032_PCIIMR, p4032_imask >> 8); + + if(slot = 0) { /* Slot 0 is special, clock */ + } + else { + int_table[slot].int_mask = 0; + int_table[slot].int_hand = algor_intrnull; + int_table[slot].param = (void *)NULL; + } +} + +void +algor_pci_intr_disestablish(cookie) + void *cookie; +{ + int slot = (int)cookie; + + p4032_imask &= ~int_table[slot].int_mask; + outb(P4032_IMR, p4032_imask); + outb(P4032_PCIIMR, p4032_imask >> 8); + + int_table[slot].int_mask = 0; + int_table[slot].int_hand = algor_intrnull; + int_table[slot].param = (void *)NULL; +} + +int +algor_matchname(ca, name) + struct confargs *ca; + char *name; +{ + return (strcmp(name, ca->ca_name) == 0); +} + +int +algor_intrnull(val) + void *val; +{ + panic("uncaught ALGOR intr for slot %d\n", val); +} + +/* + * Handle algor i/o interrupt. + */ +int +algor_iointr(mask, cf) + unsigned mask; + struct clockframe *cf; +{ + int i; + int pend; + + pend = inb(P4032_IRR); + pend |= inb(P4032_PCIIRR) << 8; + pend &= p4032_imask; + + for(i = 0; i < NUM_INT_SLOTS; i++) { + if(pend & int_table[i].int_mask) + (*int_table[i].int_hand)(int_table[i].param); + } + return(~0); /* Dont reenable */ +} + +/* + * Handle algor interval clock interrupt. + */ +int +algor_clkintr(mask, cf) + unsigned mask; + struct clockframe *cf; +{ + int temp; + + /* Ack clock interrupt */ + outb(P4032_CLOCK, MC_REGC); + (void) inb(P4032_CLOCK + 4); + + hardclock(cf); + + /* Re-enable clock interrupts */ + splx(INT_MASK_0 << IPL_CLOCK | SR_INT_ENAB); + + return(~(INT_MASK_0 << IPL_CLOCK)); /* Keep clock interrupts enabled */ +} + +/* + * Handle algor interval clock interrupt. + */ +int +algor_errintr(mask, cf) + unsigned mask; + struct clockframe *cf; +{ + int why; + + why = inb(P4032_EIRR); + + if(why & P4032_IRR_BER) { + printf("Bus error interrupt\n"); + outb(P4032_ICR, P4032_IRR_BER); + } + if(why & P4032_IRR_PFAIL) { + printf("Power failure!\n"); + } + if(why & P4032_IRR_DBG) { + printf("Debug switch\n"); + outb(P4032_ICR, P4032_IRR_DBG); +#ifdef DEBUG + mdbpanic(); +#else + printf("Not DEBUG compiled, sorry!\n"); +#endif + } + return(~0); +} |