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.
This commit is contained in:
jonathan 1995-08-07 07:07:43 +00:00
parent 8e77047f2c
commit 19e02269b2
5 changed files with 1176 additions and 0 deletions

385
sys/arch/pmax/tc/asic.c Normal file
View File

@ -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 <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <machine/autoconf.h>
#include <machine/pte.h>
#if 0
#include <machine/rpb.h>
#include <alpha/tc/tc.h>
#include <alpha/tc/asic.h>
#endif
#ifdef pmax
#include <pmax/pmax/pmaxtype.h>
#include <pmax/pmax/asic.h>
#include <pmax/pmax/kn01.h>
#include <pmax/pmax/kn02.h>
#include <pmax/pmax/kmin.h>
#include <pmax/pmax/maxine.h>
#include <pmax/pmax/kn03.h>
#include <pmax/pmax/turbochannel.h> /* interrupt enable declaration */
#include <pmax/pmax/kn03.h>
#include <pmax/pmax/kmin.h>
#include <machine/machConst.h>
#include <pmax/pmax/nameglue.h>
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);
}

View File

@ -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 }
};

View File

@ -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
};

444
sys/arch/pmax/tc/tc.c Normal file
View File

@ -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 <sys/param.h>
#include <sys/device.h>
#include <machine/autoconf.h>
/*#include <machine/rpb.h>*/
/*#include <alpha/tc/tc.h>*/
#include <pmax/tc/tc.h>
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 <machine/machConst.h>
#include <pmax/pmax/pmaxtype.h>
#include <pmax/pmax/trap.h>
#include <pmax/pmax/asic.h>
#include <pmax/pmax/kn03.h>
#include <pmax/pmax/kn02.h>
#include <pmax/pmax/kmin.h>
#include <pmax/pmax/maxine.h>
#include <pmax/pmax/turbochannel.h>
#include <pmax/pmax/nameglue.h>
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");
}

117
sys/arch/pmax/tc/tc.h Normal file
View File

@ -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 *));