From 19e02269b256ab661737a6e542fc89f50b33c137 Mon Sep 17 00:00:00 2001 From: jonathan Date: Mon, 7 Aug 1995 07:07:43 +0000 Subject: [PATCH] New-style config (config.new) autoconfiguration code for Decstation turhsturbochannel machines. Lifted wholesale from cgd's Alpha turbochannel code, with changes that reflect the slightly different bus topology and `slot' numbering on Decstations. --- sys/arch/pmax/tc/asic.c | 385 +++++++++++++++++++++++++++ sys/arch/pmax/tc/ds-asic-conf.c | 91 +++++++ sys/arch/pmax/tc/ds-tc-conf.c | 139 ++++++++++ sys/arch/pmax/tc/tc.c | 444 ++++++++++++++++++++++++++++++++ sys/arch/pmax/tc/tc.h | 117 +++++++++ 5 files changed, 1176 insertions(+) create mode 100644 sys/arch/pmax/tc/asic.c create mode 100644 sys/arch/pmax/tc/ds-asic-conf.c create mode 100644 sys/arch/pmax/tc/ds-tc-conf.c create mode 100644 sys/arch/pmax/tc/tc.c create mode 100644 sys/arch/pmax/tc/tc.h diff --git a/sys/arch/pmax/tc/asic.c b/sys/arch/pmax/tc/asic.c new file mode 100644 index 000000000000..3abb64aac58d --- /dev/null +++ b/sys/arch/pmax/tc/asic.c @@ -0,0 +1,385 @@ +/* $NetBSD: asic.c,v 1.1 1995/08/07 07:07:43 jonathan Exp $ */ + +/* + * Copyright (c) 1994, 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Keith Bostic, Chris G. Demetriou, Jonathan Stone + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include +#include +#include +#include + +#include +#include + +#if 0 +#include +#include +#include +#endif + +#ifdef pmax +#include +#include +#include +#include +#include +#include +#include +#include /* interrupt enable declaration */ + +#include +#include +#include +#include + +extern int cputype; +#endif + +struct asic_softc { + struct device sc_dv; + struct abus sc_bus; + caddr_t sc_base; +}; + +/* Definition of the driver for autoconfig. */ +int asicmatch __P((struct device *, void *, void *)); +void asicattach __P((struct device *, struct device *, void *)); +int asicprint(void *, char *); +struct cfdriver asiccd = + { NULL, "asic", asicmatch, asicattach, DV_DULL, sizeof(struct asic_softc) }; + +void asic_intr_establish __P((struct confargs *, intr_handler_t, + handler_arg_t)); +void asic_intr_disestablish __P((struct confargs *)); +caddr_t asic_cvtaddr __P((struct confargs *)); +int asic_matchname __P((struct confargs *, char *)); + +#ifndef pmax +int asic_intr __P((void *)); +#endif + +int asic_intrnull __P((handler_arg_t)); + +struct asic_slot { + struct confargs as_ca; + u_int as_bits; + intr_handler_t as_handler; + void *as_val; +}; + +#ifdef pmax +struct asic_slot *asic_slots; + +#include "ds-asic-conf.c" + +#else /*!pmax*/ +struct asic_slot asic_slots[ASIC_MAX_NSLOTS] = + +{ + { { "lance", /* XXX */ 0, 0x000c0000, }, + ASIC_INTR_LANCE, asic_intrnull, (void *)(long)ASIC_SLOT_LANCE, }, + { { "scc", /* XXX */ 1, 0x00100000, }, + ASIC_INTR_SCC_0, asic_intrnull, (void *)(long)ASIC_SLOT_SCC0, }, + { { "scc", /* XXX */ 2, 0x00180000, }, + ASIC_INTR_SCC_1, asic_intrnull, (void *)(long)ASIC_SLOT_SCC1, }, + { { "dallas_rtc", /* XXX */ 3, 0x00200000, }, + 0, asic_intrnull, (void *)(long)ASIC_SLOT_RTC, }, + { { "AMD79c30", /* XXX */ 4, 0x00240000, }, + 0 /* XXX */, asic_intrnull, (void *)(long)ASIC_SLOT_ISDN, }, +}; +#endif /*!pmax*/ + +caddr_t asic_base; /* XXX XXX XXX */ + +int +asicmatch(parent, cfdata, aux) + struct device *parent; + void *cfdata; + void *aux; +{ + struct cfdata *cf = cfdata; + struct confargs *ca = aux; + + /* It can only occur on the turbochannel, anyway. */ + if (ca->ca_bus->ab_type != BUS_TC) + return (0); + + /* The 3MAX (kn02) is special. */ + if (BUS_MATCHNAME(ca, KN02_ASIC_NAME)) { + printf("(configuring KN02 system slot as asic)\n"); + goto gotasic; + } + + /* Make sure that we're looking for this type of device. */ + if (!BUS_MATCHNAME(ca, "IOCTL ")) + return (0); +gotasic: + + /* See if the unit number is valid. */ + switch (cputype) { + case DS_3MIN: + if (cf->cf_unit > 0) + return (0); + asic_slots = NULL; + break; + case DS_MAXINE: + if (cf->cf_unit > 0) + return (0); + asic_slots = NULL; + break; + case DS_3MAX: + if (cf->cf_unit > 0) + return (0); + asic_slots = kn02_asic_slots; + break; + case DS_3MAXPLUS: + if (cf->cf_unit > 0) + return (0); + asic_slots = kn03_asic_slots; + break; + default: + printf("no ASIC config table for this machine\n"); + return (0); + } + + return (1); +} + +void +asicattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct asic_softc *sc = (struct asic_softc *)self; + struct confargs *ca = aux; + struct confargs *nca; + int i; + extern int cputype; + + if (asic_slots == NULL) + panic("asicattach: no asic_slot map\n"); + + sc->sc_base = BUS_CVTADDR(ca); + asic_base = sc->sc_base; /* XXX XXX XXX */ + + sc->sc_bus.ab_dv = (struct device *)sc; + sc->sc_bus.ab_type = BUS_ASIC; + sc->sc_bus.ab_intr_establish = asic_intr_establish; + sc->sc_bus.ab_intr_disestablish = asic_intr_disestablish; + sc->sc_bus.ab_cvtaddr = asic_cvtaddr; + sc->sc_bus.ab_matchname = asic_matchname; + +#ifndef pmax /* Alpha AXP: select ASIC speed */ +#ifdef DEC_3000_300 + if (cputype == ST_DEC_3000_300) { + *(volatile u_int *)ASIC_REG_CSR(sc->sc_base) |= + ASIC_CSR_FASTMODE; + MB(); + printf(": slow mode\n"); + } else +#endif + printf(": fast mode\n"); + + /* Decstations use hand-craft code to enable asic interrupts */ + BUS_INTR_ESTABLISH(ca, asic_intr, sc); + +#endif /*!pmax*/ + + +/* The MAXINE has seven pseudo-slots in its system slot */ +#define ASIC_MAX_NSLOTS 7 /*XXX*/ + + /* Try to configure each CPU-internal device */ + for (i = 0; i < ASIC_MAX_NSLOTS; i++) { + +#ifdef DEBUG + printf("asicattach: entry %d\n", i); /*XXX*/ +#endif + + nca = &asic_slots[i].as_ca; + if (nca == NULL) panic ("bad asic table\n"); + if (nca->ca_name == NULL && nca->ca_bus == NULL) + break; + nca->ca_bus = &sc->sc_bus; + +#ifdef DEBUG + printf(" adding %s subslot %d offset %x\n", /*XXX*/ + nca->ca_name, nca->ca_slot, nca->ca_offset); +#endif + + /* Tell the autoconfig machinery we've found the hardware. */ + config_found(self, nca, asicprint); + } + +} + +int +asicprint(aux, pnp) + void *aux; + char *pnp; +{ + struct confargs *ca = aux; + + if (pnp) + printf("%s at %s", ca->ca_name, pnp); + printf(" offset 0x%lx", ca->ca_offset); + return (UNCONF); +} + +/* + * Save interrupt slotname and enable mask (??) + * On decstaitons this isn't useful, as the turbochannel + * decstations all have incompatible ways of mapping interrupts + * to IO ASIC or r3000 interrupt bits. + * Instead of writing "as_bits" directly into an IOASIC interrupt-enable + * register, Decstations use a machine-dependent function that + * interpret (pseudo-) slot numbers and do ``the right thing'' to enable + * or disable interrupts for a specific slot (or pseudo-slot), by + * slot number, on that given CPU. + */ +void +asic_intr_establish(ca, handler, val) + struct confargs *ca; + intr_handler_t handler; + handler_arg_t val; +{ + +#ifdef DIAGNOSTIC + if (ca->ca_slot == ASIC_SLOT_RTC) + panic("setting clock interrupt incorrectly"); +#endif /*DIAGNOSTIC*/ + + /* XXX SHOULD NOT BE THIS LITERAL */ + if (asic_slots[ca->ca_slot].as_handler != asic_intrnull) + /*panic*/ printf("asic_intr_establish: slot %d twice", ca->ca_slot); + + /* + * XXX We need to invent a better interface to machine-dependent + * interrupt-enable code, or redo the Decstation configuration + * tables with unused entries, so that slot is always equal + * to "priority" (software pseudo-slot number). + */ +#ifdef pmax +#ifdef DEBUG + printf("asic:%s%d: intr for entry %d(%d) slot %d\n", + ca->ca_name, val, ca->ca_slot, ca->ca_slotpri, + asic_slots[ca->ca_slot].as_val); + tc_enable_interrupt(ca->ca_slotpri, handler, (int)val, 1); +#endif /*DEBUG*/ + +#else /* Alpha AXP */ + + /* Save handler info so it can be enabled later (??) */ + asic_slots[ca->ca_slot].as_handler = handler; + asic_slots[ca->ca_slot].as_val = val; +#endif /* Alpha AXP */ +} + +void +asic_intr_disestablish(ca) + struct confargs *ca; +{ + +#ifdef pmax + panic("asic_intr_disestablish: shouldn't ever be called\n"); +#else + if (ca->ca_slot == ASIC_SLOT_RTC) + panic("asic_intr_disestablish: can't do clock interrupt"); + + /* XXX SHOULD NOT BE THIS LITERAL */ + if (asic_slots[ca->ca_slot].as_handler == asic_intrnull) + panic("asic_intr_disestablish: slot %d missing intr", + ca->ca_slot); + + asic_slots[ca->ca_slot].as_handler = dsasic_intrnull; + asic_slots[ca->ca_slot].as_val = (void *)(long)ca->ca_slot; +#endif +} + +caddr_t +asic_cvtaddr(ca) + struct confargs *ca; +{ + + return + (((struct asic_softc *)ca->ca_bus->ab_dv)->sc_base + ca->ca_offset); +} + +int +asic_matchname(ca, name) + struct confargs *ca; + char *name; +{ + + return (strcmp(name, ca->ca_name) == 0); +} + +#ifndef pmax +/* + * asic_intr -- + * ASIC interrupt handler. + */ +int +asic_intr(val) + void *val; +{ + register struct asic_softc *sc = val; + register int i, ifound; + int gifound; + u_int32_t sir, junk; + volatile u_int32_t *sirp, *junkp; + + sirp = (volatile u_int32_t *)ASIC_REG_INTR(sc->sc_base); + + gifound = 0; + do { + ifound = 0; + MB(); + MAGIC_READ; + MB(); + + sir = *sirp; + for (i = 0; i < ASIC_MAX_NSLOTS; i++) + if (sir & asic_slots[i].as_bits) { + (void)(*asic_slots[i].as_handler) + (asic_slots[i].as_val); + ifound = 1; + } + gifound |= ifound; + } while (ifound); + + return (gifound); +} +#endif /*!pmax*/ + +int +asic_intrnull(val) + handler_arg_t val; +{ + + panic("uncaught IOCTL ASIC intr for slot %ld\n", (long)val); +} diff --git a/sys/arch/pmax/tc/ds-asic-conf.c b/sys/arch/pmax/tc/ds-asic-conf.c new file mode 100644 index 000000000000..818e8af5870f --- /dev/null +++ b/sys/arch/pmax/tc/ds-asic-conf.c @@ -0,0 +1,91 @@ +/* $NetBSD: ds-asic-conf.c,v 1.1 1995/08/07 07:07:45 jonathan Exp $ */ + +/* + * Copyright (c) 1995 Jonathan Stone + * All rights reserved. + * + * DECstation IO ASIC subslot configuration + */ + +#if 0 +struct asic_slot { + struct confargs as_ca; + u_int as_bits; + intr_handler_t as_handler; + void *as_val; +}; +#endif + +/* Initial handler must be asic_intrnull or the ASIC newconf code panics */ + +struct asic_slot kn03_asic_slots[] = +{ + { { "lance", 0, KN03_LANCE_SLOT, (u_int) (3 * 0x40000), }, + KN03_INTR_LANCE, asic_intrnull, (void*) KN03_LANCE_SLOT, }, + + { { "scc", 1, KN03_SCC0_SLOT, (u_int) (4 * 0x40000), }, + KN03_INTR_SCC_0, asic_intrnull, (void *)KN03_SCC0_SLOT, }, + + { { "scc", 2, KN03_SCC1_SLOT, (u_int) (6 * 0x40000), }, + KN03_INTR_SCC_1, asic_intrnull, (void*)KN03_SCC1_SLOT, }, + + { { "dallas_rtc", 3, 0 /*XXX*/, (u_int) (8* 0x40000), }, + 0, asic_intrnull, (void *)(long) 16 /*XXX*/, }, + + { { "asc", 4, KN03_SCSI_SLOT, (u_int) (12 * 0x40000), }, + 0, asic_intrnull, (void*)KN03_SCSI_SLOT, }, + + { { NULL, 0, 0, 0 }, 0, NULL, NULL } +}; + +/* UNTESTED*/ +struct asic_slot xine_asic_slots[] = +{ + { { "lance", 0, KN03_LANCE_SLOT, (u_int) (3 * 0x40000), }, + KN03_INTR_LANCE, asic_intrnull, (void*) KN03_LANCE_SLOT, }, + + { { "scc", 1, KN03_SCC0_SLOT, (u_int) (4 * 0x40000), }, + KN03_INTR_SCC_0, asic_intrnull, (void *)KN03_SCC0_SLOT, }, + + { { "dallas_rtc", 2, 0, (u_int) (8* 0x40000), }, + 0, asic_intrnull, (void *)(long) 16 /*XXX*/, }, + + { { "isdn", 3, XINE_ISDN_SLOT, (u_int) (9* 0x40000), }, + 0, asic_intrnull, (void *)(long) XINE_ISDN_SLOT, }, + + { { "dtop", 4, XINE_DTOP_SLOT, (u_int) (10* 0x40000), }, + 0, asic_intrnull, (void *)(long) XINE_DTOP_SLOT, }, + + { { "fdc", 5, XINE_FLOPPY_SLOT, (u_int) (11* 0x40000), }, + 0, asic_intrnull, (void *)(long) XINE_FLOPPY_SLOT, }, + + { { "asc", 6, XINE_SCSI_SLOT, (u_int) (12 * 0x40000), }, + XINE_INTR_SCSI, asic_intrnull, (void*)XINE_SCSI_SLOT, }, +#if 0 + { { "frc", 3, (u_int) XINE_SLOT_FRC, (15* 0x40000), }, + 0, asic_intrnull, (void *)(long) XINE_SLOT_FRC, }, +#endif + { { NULL, 0, 0, }, 0, NULL, NULL } +}; + +/* + * The 3MAX (KN02) doesn't even have an asic but for now, + * configure its system slot as if it did. + * Instead there's a 4 Mbyte "system" slot with eight 512 Kbyte subslots + * for system devices: + * 0=ROM, 1=(reserved), 2=CHKSYN, 3=ERRADDR, 4=DZ, 5=CLOCK, 6=CSR, 7=ROM1 + * These are mapped onto slot numbers as + * tc0=1, tc1=1, tc2=2, unsed=3, unused=4, scsi=5, ether=6, dc=7 + */ + +struct asic_slot kn02_asic_slots[] = { + { { "dc", 0, 7, (u_int) (4 * 0x80000), }, + KN03_INTR_SCC_0, asic_intrnull, (void *) 7, }, + + { { "dallas_rtc", 0, (u_int) (5 * 0x80000), }, + 0, asic_intrnull, (void *) 16 /*XXX*/, }, + + { { NULL, 0, 0 }, 0, NULL, NULL } +}; + + diff --git a/sys/arch/pmax/tc/ds-tc-conf.c b/sys/arch/pmax/tc/ds-tc-conf.c new file mode 100644 index 000000000000..649019e5616b --- /dev/null +++ b/sys/arch/pmax/tc/ds-tc-conf.c @@ -0,0 +1,139 @@ +/* $NetBSD: ds-tc-conf.c,v 1.1 1995/08/07 07:07:47 jonathan Exp $ */ + +/* + * Copyright (c) 1995 Jonathan Stone + * All rights reserved. + */ + +/* + * 3MIN and 3MAXPLUS turbochannel slots. + * The kmin (3MIN) and kn03 (3MAXPLUS) have the same number of slots. + * We can share one configuration-struct table and use two slot-address + * tables to handle the fact that the turbochannel slot size and base + * addresses are different on the two machines. + * (thankfully the IOASIC subslots are all the same size.) + */ +struct confargs tc3_devs[4] = { + /* name entry pri xxx */ + { "IOCTL ", 3, -1, /*0x040000*/ 0x0, }, + { NULL, 2, 2, 0x0, }, + { NULL, 1, 1, 0x0, }, + { NULL, 0, 0, 0x0, } + +}; + +/* 3MAXPLUS slot addreseses */ + static struct tc_slot_desc kn03_slot_addrs [4] = { + { KV(KN03_PHYS_TC_0_START), }, /* slot 0 - tc option slot 0 */ + { KV(KN03_PHYS_TC_1_START), }, /* slot 1 - tc option slot 1 */ + { KV(KN03_PHYS_TC_2_START), }, /* slot 2 - tc option slot 2 */ + { KV(KN03_PHYS_TC_3_START), } /* slot 3 - IOCTL asic on CPU board */ +}; + +/* 3MAXPLUS turbochannel autoconfiguration table */ +struct tc_cpu_desc kn03_tc_desc = +{ + kn03_slot_addrs, KN03_TC_NSLOTS, + tc3_devs, KN03_TC_NSLOTS, /*XXX*/ + tc_ds_ioasic_intr_setup, + tc_ds_ioasic_intr_establish, + tc_ds_ioasic_intr_disestablish, + (void*)-1 +}; + +/************************************************************************/ + +/* 3MIN slot addreseses */ +static struct tc_slot_desc kmin_slot_addrs [4] = { + { KV(KMIN_PHYS_TC_0_START), }, /* slot 0 - tc option slot 0 */ + { KV(KMIN_PHYS_TC_1_START), }, /* slot 1 - tc option slot 1 */ + { KV(KMIN_PHYS_TC_2_START), }, /* slot 2 - tc option slot 2 */ + { KV(KMIN_PHYS_TC_3_START), } /* slot 3 - IOCTL asic on CPU board */ +}; + +/* 3MIN turbochannel autoconfiguratin table */ +struct tc_cpu_desc kmin_tc_desc = +{ + kmin_slot_addrs, KMIN_TC_NSLOTS, + tc3_devs, 7, /*XXX*/ + tc_ds_ioasic_intr_setup, + tc_ds_ioasic_intr_establish, + tc_ds_ioasic_intr_disestablish, + kmin_intr +}; + +/************************************************************************/ + +/* MAXINE turbochannel slots */ +struct confargs xine_devs[3] = { + { "IOCTL ", 2, -1, 0x0, }, + /*{ "PMAG-DV ", ?, ?, 0x0, },*/ /* xcfb ? */ + { NULL, 1, 1, 0x0, }, + { NULL, 0, 0, 0x0, } +}; + +/* MAXINE slot addreseses */ +static struct tc_slot_desc xine_slot_addrs [4] = { + { KV(XINE_PHYS_TC_0_START), }, /* slot 0 - tc option slot 0 */ + { KV(XINE_PHYS_TC_1_START), }, /* slot 1 - tc option slot 1 */ + { KV(XINE_PHYS_TC_3_START), } /* slot 2 - IOCTL asic on CPU board */ +}; + +struct tc_cpu_desc xine_tc_desc = +{ + xine_slot_addrs, XINE_TC_NSLOTS, + xine_devs, 11, /*XXX*/ + tc_ds_ioasic_intr_setup, + tc_ds_ioasic_intr_establish, + tc_ds_ioasic_intr_disestablish, + xine_intr +}; + +/************************************************************************/ + +#if 0 +#define TC_SCSI "PMAZ-AA " +#define TC_ETHER "PMAD-AA " +#else +#define TC_SCSI NULL +#define TC_ETHER NULL +#endif + +/* 3MAX (kn02) turbochannel slots */ +struct confargs kn02_devs[8] = { + /* The 3max supposedly has "KN02 " at 0xbffc0410 */ + + /* name entry pri xxx */ + { KN02_ASIC_NAME, 7, -1, 0x0, }, /* System CSR and subslots */ + { TC_ETHER, 6, 6, 0x0, }, /* slot 6: Ether on cpu board*/ + { TC_SCSI, 5, 5, 0x0, }, /* slot 5: SCSI on cpu board */ +/*XXX*/ { NULL, 4, 0, -1, }, /* slot 3 reserved */ +/*XXX*/ { NULL, 3, 0, -1, }, /* slot 3 reserved */ + { NULL, 2, 2, 0x0, }, /* slot 2 - TC option slot 2 */ + { NULL, 1, 1, 0x0, }, /* slot 1 - TC option slot 1 */ + { NULL, 0, 0, 0x0, } /* slot 0 - TC option slot 0 */ +}; + +/* slot addreseses */ +static struct tc_slot_desc kn02_slot_addrs [8] = { + { KV(KN02_PHYS_TC_0_START), }, /* slot 0 - tc option slot 0 */ + { KV(KN02_PHYS_TC_1_START), }, /* slot 1 - tc option slot 1 */ + { KV(KN02_PHYS_TC_2_START), }, /* slot 2 - tc option slot 2 */ + { KV(KN02_PHYS_TC_3_START), }, /* slot 3 - reserved */ + { KV(KN02_PHYS_TC_4_START), }, /* slot 4 - reserved */ + { KV(KN02_PHYS_TC_5_START), }, /* slot 5 - SCSI on cpu board */ + { KV(KN02_PHYS_TC_6_START), }, /* slot 6 - Ether on cpu board */ + { KV(KN02_PHYS_TC_7_START), } /* slot 7 - system devices */ + +}; + + +struct tc_cpu_desc kn02_tc_desc = +{ + kn02_slot_addrs, KN02_TC_NSLOTS, + kn02_devs, 8, /*XXX*/ + tc_ds_ioasic_intr_setup, + tc_ds_ioasic_intr_establish, + tc_ds_ioasic_intr_disestablish, + /*kn02_intr*/ (void*) -1 +}; diff --git a/sys/arch/pmax/tc/tc.c b/sys/arch/pmax/tc/tc.c new file mode 100644 index 000000000000..3aec721fe9ed --- /dev/null +++ b/sys/arch/pmax/tc/tc.c @@ -0,0 +1,444 @@ +/* $NetBSD: tc.c,v 1.1 1995/08/07 07:07:49 jonathan Exp $ */ + +/* + * Copyright (c) 1994, 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include +#include + +#include +/*#include */ + +/*#include */ +#include + +struct tc_softc { + struct device sc_dv; + struct abus sc_bus; + struct tc_cpu_desc *sc_desc; +}; + +/* Definition of the driver for autoconfig. */ +int tcmatch(struct device *, void *, void *); +void tcattach(struct device *, struct device *, void *); +int tcprint(void *, char *); +struct cfdriver tccd = + { NULL, "tc", tcmatch, tcattach, DV_DULL, sizeof (struct tc_softc) }; + +void tc_intr_establish __P((struct confargs *, intr_handler_t handler, + handler_arg_t)); +void tc_intr_disestablish __P((struct confargs *)); +caddr_t tc_cvtaddr __P((struct confargs *)); +int tc_matchname __P((struct confargs *, char *)); + +extern int cputype; + + +/*XXX*/ /* should be in separate source file */ + +/* + * tc config structures for DECstations. + * Since there will never be new decstations, we just + * bash it in here, for now. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +void tc_ds_ioasic_intr_setup __P((void)); +void tc_ds_ioasic_intr_establish + __P((struct confargs *, intr_handler_t, void *)); +void tc_ds_ioasic_intr_disestablish __P((struct confargs *)); +void tc_ds_ioasic_iointr __P((void *, int)); +int tc_ds_ioasic_getdev __P((struct confargs *)); + + +/* XXX*/ +/* should be handled elsewhere? */ +typedef void (*tc_enable_t) __P ((u_int slotno, intr_handler_t, + int unit, int on)); +typedef void (*tc_handler_t) __P((int unit)); + +extern void (*tc_enable_interrupt) __P ((u_int slotno, tc_handler_t, + int unit, int on)); +extern void kn03_enable_intr __P((u_int slot, tc_handler_t, + int unit, int on)); +extern void kn02_enable_intr __P ((u_int slot, tc_handler_t, + int unit, int on)); +extern void kmin_enable_intr __P ((u_int slot, tc_handler_t, + int unit, int on)); +extern void xine_enable_intr __P ((u_int slot, tc_handler_t, + int unit, int on)); + +/* + * configuration tables for the four models of + * Decstation that have turbochannels. + * None of the four are the same. + */ +#include "ds-tc-conf.c" + + +/* + * Mapping from CPU type to a tc_cpu_desc for that CPU type. + * (Alpha-specific.) + */ +struct tc_cpu_desc *tc_cpu_devs[] = { + NULL, /* Unused */ + NULL, /* ST_ADU */ + NULL, /* ST_DEC_4000 */ + NULL, /* ST_DEC_7000 */ +#ifdef DEC_3000_500 + &dec_3000_500_cpu, /* ST_DEC_3000_500 */ +#else + NULL, +#endif + NULL, /* Unused */ + NULL, /* ST_DEC_2000_300 */ +#ifdef DEC_3000_300 + &dec_3000_300_cpu, /* ST_DEC_3000_300 */ +#else + NULL, +#endif +}; +int ntc_cpu_devs = sizeof tc_cpu_devs / sizeof tc_cpu_devs[0]; + +/* + * Function to map from a CPU code to a tc_cpu_desc. + * This hould really be in machine-dependent code, where + * it could even be a macro. + */ +struct tc_cpu_desc * +cpu_tcdesc(cpu) + int cpu; +{ + /*XXX*/ +#ifdef pmax + if (cputype == DS_3MAXPLUS) { + DPRINTF(("tcattach: 3MAXPLUS turbochannel\n")); + tc_enable_interrupt = kn03_enable_intr; + return &kn03_tc_desc; + } else if (cputype == DS_3MAX) { + DPRINTF(("tcattach: 3MAX turbochannel\n")); + tc_enable_interrupt = kn02_enable_intr; + return &kn02_tc_desc; + } else if (cputype == DS_3MIN) { + DPRINTF(("tcattach: 3MIN Turbochannel\n")); + tc_enable_interrupt = kmin_enable_intr; + return &kmin_tc_desc; + } else if (cputype == DS_MAXINE) { + DPRINTF(("MAXINE turbochannel\n")); + tc_enable_interrupt = xine_enable_intr; + return &xine_tc_desc; + } else if (cputype == DS_PMAX) { + DPRINTF(("tcattach: PMAX (no tc, but configured as one)\n")); + return NULL; + } else { + panic("tcattach: Unrecognized bus type 0x%x\n", cputype); + } + +#else /* alpha?*/ + return tc_cpu_devs[cputype]; +#endif /* alpha?*/ +} + +int +tcmatch(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 TC. */ + if (strcmp(ca->ca_name, tccd.cd_name) != 0) + return (0); + + /* Make sure that unit exists. */ + if (cf->cf_unit != 0 || +#ifdef pmax + 0 +#else + cputype > ntc_cpu_devs || tc_cpu_devs[cputype] == NULL +#endif + ) + return (0); + + return (1); +} + +/* + * Attach a turbochannel bus. Once the turbochannel is attached, + * search recursively for a system slot (which contains registers + * for baseboard devices in "subslots"), and for "real" on-board or + * option turbochannel slots (that have their own turbochannel ROM + * signature. + */ +void +tcattach(parent, self, aux) + struct device *parent; + struct device *self; + void *aux; +{ + struct tc_softc *sc = (struct tc_softc *)self; + struct confargs *nca; + char namebuf[TC_ROM_LLEN+1]; + int i; + + printf("\n"); + + /* keep our CPU description handy */ + sc->sc_desc = cpu_tcdesc(cputype); + +#ifndef pmax /*XXX*/ + /* set up interrupt handlers */ + (*sc->sc_desc->tc_intr_setup)(); + set_iointr(sc->sc_desc->tc_iointr); +#endif /*!PMAX*/ + + sc->sc_bus.ab_dv = (struct device *)sc; + sc->sc_bus.ab_type = BUS_TC; + sc->sc_bus.ab_intr_establish = tc_intr_establish; + sc->sc_bus.ab_intr_disestablish = tc_intr_disestablish; + sc->sc_bus.ab_cvtaddr = tc_cvtaddr; + sc->sc_bus.ab_matchname = tc_matchname; + + if (sc->sc_desc == NULL) + return; + + /* Try to configure each turbochannel (or CPU-internal) device */ + for (i = 0; i < sc->sc_desc->tcd_ndevs; i++) { + + nca = &sc->sc_desc->tcd_devs[i]; + if (nca == NULL) { + printf("tcattach: bad config for slot %d\n", i); + break; + } + nca->ca_bus = &sc->sc_bus; + +#if defined(DIAGNOSTIC) || defined(DEBUG) + if (nca->ca_slot > sc->sc_desc->tcd_nslots) + panic("tcattach: dev slot > number of slots for %s", + nca->ca_name); +#endif + + if (tc_checkdevmem(nca) == 0) + continue; + + /* If no name, we have to see what might be there. */ + if (nca->ca_name == NULL) { + if (tc_checkslot(nca, namebuf) == 0) + continue; + nca->ca_name = namebuf; + } + /* Tell the autoconfig machinery we've found the hardware. */ + config_found(self, nca, tcprint); + } +} + +int +tcprint(aux, pnp) + void *aux; + 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 +tc_cvtaddr(ca) + struct confargs *ca; +{ + struct tc_softc *sc = tccd.cd_devs[0]; + + return (sc->sc_desc->tcd_slots[ca->ca_slot].tsd_dense + ca->ca_offset); + +} + +void +tc_intr_establish(ca, handler, val) + struct confargs *ca; + intr_handler_t handler; + handler_arg_t val; +{ + struct tc_softc *sc = tccd.cd_devs[0]; + + (*sc->sc_desc->tc_intr_establish)(ca, handler, val); +} + +void +tc_intr_disestablish(ca) + struct confargs *ca; +{ + struct tc_softc *sc = tccd.cd_devs[0]; + + (*sc->sc_desc->tc_intr_disestablish)(ca); +} + +int +tc_matchname(ca, name) + struct confargs *ca; + char *name; +{ + + return (bcmp(name, ca->ca_name, TC_ROM_LLEN) == 0); +} + +int +tc_checkdevmem(ca) + struct confargs *ca; +{ + u_int32_t *datap; + + datap = (u_int32_t *)BUS_CVTADDR(ca); + + /* Return non-zero if memory was there (i.e. address wasn't bad). */ + return (!badaddr(datap, sizeof (u_int32_t))); +} + +u_int tc_slot_romoffs[] = { TC_SLOT_ROM, TC_SLOT_PROTOROM }; +int ntc_slot_romoffs = sizeof tc_slot_romoffs / sizeof tc_slot_romoffs[0]; + +int +tc_checkslot(ca, namep) + struct confargs *ca; + char *namep; +{ + struct tc_rommap *romp; + int i, j; + + for (i = 0; i < ntc_slot_romoffs; i++) { + romp = (struct tc_rommap *) + (BUS_CVTADDR(ca) + tc_slot_romoffs[i]); + + switch (romp->tcr_width.v) { + case 1: + case 2: + case 4: + break; + + default: + continue; + } + + if (romp->tcr_stride.v != 4) + continue; + + for (j = 0; j < 4; j++) + if (romp->tcr_test[j+0*romp->tcr_stride.v] != 0x55 || + romp->tcr_test[j+1*romp->tcr_stride.v] != 0x00 || + romp->tcr_test[j+2*romp->tcr_stride.v] != 0xaa || + romp->tcr_test[j+3*romp->tcr_stride.v] != 0xff) + continue; + + for (j = 0; j < TC_ROM_LLEN; j++) + namep[j] = romp->tcr_modname[j].v; + namep[TC_ROM_LLEN] = '\0'; + return (1); + } + return (0); +} + +int +tc_intrnull(val) + void *val; +{ + + panic("uncaught TC intr for slot %ld\n", (long)val); +} + + +/* hack for kn03 */ + +void +tc_ds_ioasic_intr_setup () +{ + printf("not setting up TC intrs\n"); +} + +void +tc_ds_ioasic_intr_establish(ca, handler, val) + struct confargs *ca; + intr_handler_t handler; + void *val; +{ + int unit = (int) val; + + if (BUS_MATCHNAME(ca, "IOCTL ")) { + printf("(no interrupt for asic"); + return; + } + + /* The kn02 doesn't really have an ASIC */ + if (BUS_MATCHNAME(ca, KN02_ASIC_NAME)) { + printf("(no interrupt for proto-asic)\n"); + return; + } + + printf("tc_enable %s%d slot %d\n", + ca->ca_name, (int)unit, ca->ca_slotpri); + +#ifdef 1 /*DIAGNOSTIC*/ /*XXX*/ + if (tc_enable_interrupt == NULL) + panic("tc_intr_establish: tc_enable not set\n"); +#endif + + (*tc_enable_interrupt) (ca->ca_slotpri, handler, unit, 1); +} + +void +tc_ds_ioasic_intr_disestablish(args) + struct confargs *args; +{ + /*(*tc_enable_interrupt) (ca->ca_slot, handler, 0);*/ + printf("cannot dis-establish TC intrs\n"); +} + +void +tc_ds_ioasic_iointr (framep, vec) + void * framep; + int vec; + + +{ + printf("bogus interrupt handler\n"); +} diff --git a/sys/arch/pmax/tc/tc.h b/sys/arch/pmax/tc/tc.h new file mode 100644 index 000000000000..5e65c408af5a --- /dev/null +++ b/sys/arch/pmax/tc/tc.h @@ -0,0 +1,117 @@ +/* $NetBSD: tc.h,v 1.1 1995/08/07 07:07:50 jonathan Exp $ */ + +/* + * Copyright (c) 1994, 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +/* + * TurboChannel-specific functions and structures. + */ + +/* + * A junk address to read from, to make sure writes are complete. See + * System Programmer's Manual, section 9.3 (p. 9-4), and sacrifice a + * chicken. + */ +#define MAGIC_READ do { \ + extern u_int32_t no_optimize; \ + no_optimize = *(u_int32_t *)phystok0seg(0x00000001f0080220); \ +} while (0); + +#define TC_SPACE_IND 0xffffffffe0000003 +#define TC_SPACE_DENSE 0x0000000000000000 +#define TC_SPACE_DENSE_OFFSET 0x0000000007fffffc +#define TC_SPACE_SPARSE 0x0000000010000000 +#define TC_SPACE_SPARSE_OFFSET 0x000000000ffffff8 + +#define TC_DENSE_TO_SPARSE(addr) \ + ((void *) \ + (((u_int64_t)addr & TC_SPACE_IND) | \ + TC_SPACE_SPARSE | \ + (((u_int64_t)addr & TC_SPACE_DENSE_OFFSET) << 1))) + +#define TC_SPARSE_TO_DENSE(addr) \ + ((void *) \ + (((u_int64_t)addr & TC_SPACE_IND) | \ + TC_SPACE_DENSE | \ + (((u_int64_t)addr & TC_SPACE_SPARSE_OFFSET) >> 1))) + + +#define TC_ROM_LLEN 8 +#define TC_ROM_SLEN 4 +#define TC_ROM_TEST_SIZE 16 + +#define TC_SLOT_ROM 0x000003e0 +#define TC_SLOT_PROTOROM 0x003c03e0 + +typedef struct tc_padchar { + u_int8_t v; + u_int8_t pad[3]; +} tc_padchar_t; + +struct tc_rommap { + tc_padchar_t tcr_width; + tc_padchar_t tcr_stride; + tc_padchar_t tcr_rsize; + tc_padchar_t tcr_ssize; + u_int8_t tcr_test[TC_ROM_TEST_SIZE]; + tc_padchar_t tcr_rev[TC_ROM_LLEN]; + tc_padchar_t tcr_vendname[TC_ROM_LLEN]; + tc_padchar_t tcr_modname[TC_ROM_LLEN]; + tc_padchar_t tcr_firmtype[TC_ROM_SLEN]; +}; + +/* The contents of a cfdata->cf_loc for a TurboChannel device */ +struct tc_cfloc { + int cf_slot; /* Slot number */ + int cf_offset; /* XXX? Offset into slot. */ + int cf_vec; + int cf_ipl; +}; + +#define TC_SLOT_WILD -1 /* wildcarded slot */ +#define TC_OFFSET_WILD -1 /* wildcarded offset */ +#define TC_VEC_WILD -1 /* wildcarded vec */ +#define TC_IPL_WILD -1 /* wildcarded ipl */ + +struct tc_slot_desc { + caddr_t tsd_dense; +}; + +struct tc_cpu_desc { + struct tc_slot_desc *tcd_slots; + long tcd_nslots; + struct confargs *tcd_devs; + long tcd_ndevs; + void (*tc_intr_setup) __P((void)); + void (*tc_intr_establish) + __P((struct confargs *, intr_handler_t, void *)); + void (*tc_intr_disestablish) __P((struct confargs *)); + int (*tc_iointr) __P((u_int mask, u_int pc, + u_int statusReg, u_int causeReg)); +}; + +int tc_intrnull __P((void *));