NetBSD/sys/arch/pica/pica/pica.c
1998-01-12 20:04:24 +00:00

323 lines
7.9 KiB
C

/* $NetBSD: pica.c,v 1.7 1998/01/12 20:04:32 thorpej 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/systm.h>
#include <sys/device.h>
#include <machine/cpu.h>
#include <machine/pio.h>
#include <machine/autoconf.h>
#include <pica/pica/pica.h>
#include <pica/pica/picatype.h>
struct pica_softc {
struct device sc_dv;
struct abus sc_bus;
struct pica_dev *sc_devs;
};
/* Definition of the driver for autoconfig. */
int picamatch(struct device *, void *, void *);
void picaattach(struct device *, struct device *, void *);
int picaprint(void *, const char *);
struct cfattach pica_ca = {
sizeof (struct pica_softc), picamatch, picaattach
};
extern struct cfdriver pica_cd;
void pica_intr_establish __P((struct confargs *, int (*)(void *), void *));
void pica_intr_disestablish __P((struct confargs *));
caddr_t pica_cvtaddr __P((struct confargs *));
int pica_matchname __P((struct confargs *, char *));
int pica_iointr __P((void *));
int pica_clkintr __P((unsigned, unsigned, unsigned, unsigned));
extern int cputype;
/*
* Interrupt dispatch table.
*/
struct pica_int_desc int_table[] = {
{0, pica_intrnull, (void *)NULL, 0 }, /* 0 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 1 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 2 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 3 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 4 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 5 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 6 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 7 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 8 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 9 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 10 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 11 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 12 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 13 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 14 */
{0, pica_intrnull, (void *)NULL, 0 }, /* 15 */
};
struct pica_dev {
struct confargs ps_ca;
u_int ps_mask;
intr_handler_t ps_handler;
void *ps_base;
};
#ifdef ACER_PICA_61
struct pica_dev acer_pica_61_cpu[] = {
{{ "dallas_rtc",0, 0, },
0, pica_intrnull, (void *)PICA_SYS_CLOCK, },
{{ "lpt", 1, 0, },
PICA_SYS_LB_IE_PAR1, pica_intrnull, (void *)PICA_SYS_PAR1, },
{{ "fdc", 2, 0, },
PICA_SYS_LB_IE_FLOPPY,pica_intrnull, (void *)PICA_SYS_FLOPPY, },
{{ NULL, 3, NULL, },
0, pica_intrnull, (void *)NULL, },
{{ NULL, 4, NULL, },
0, pica_intrnull, (void *)NULL, },
{{ "sonic", 5, 0, },
PICA_SYS_LB_IE_SONIC, pica_intrnull, (void *)PICA_SYS_SONIC, },
{{ "asc", 6, 0, },
PICA_SYS_LB_IE_SCSI, pica_intrnull, (void *)PICA_SYS_SCSI, },
{{ "pc", 7, 0, },
PICA_SYS_LB_IE_KBD, pica_intrnull, (void *)PICA_SYS_KBD, },
{{ "pms", 8, NULL, },
PICA_SYS_LB_IE_MOUSE, pica_intrnull, (void *)PICA_SYS_KBD, },
{{ "com", 9, 0, },
PICA_SYS_LB_IE_COM1, pica_intrnull, (void *)PICA_SYS_COM1, },
{{ "com", 10, 0, },
PICA_SYS_LB_IE_COM2, pica_intrnull, (void *)PICA_SYS_COM2, },
{{ NULL, -1, NULL, },
0, NULL, (void *)NULL, },
};
#endif
struct pica_dev *pica_cpu_devs[] = {
NULL, /* Unused */
#ifdef ACER_PICA_61
acer_pica_61_cpu, /* Acer PICA */
#else
NULL,
#endif
};
int npica_cpu_devs = sizeof pica_cpu_devs / sizeof pica_cpu_devs[0];
int local_int_mask = 0; /* Local interrupt enable mask */
int
picamatch(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 PICA. */
if (strcmp(ca->ca_name, pica_cd.cd_name) != 0)
return (0);
/* Make sure that unit exists. */
if (cf->cf_unit != 0 ||
cputype > npica_cpu_devs || pica_cpu_devs[cputype] == NULL)
return (0);
return (1);
}
void
picaattach(parent, self, aux)
struct device *parent;
struct device *self;
void *aux;
{
struct pica_softc *sc = (struct pica_softc *)self;
struct confargs *nca;
int i;
printf("\n");
/* keep our CPU device description handy */
sc->sc_devs = pica_cpu_devs[cputype];
/* set up interrupt handlers */
set_intr(MIPS_INT_MASK_1, pica_iointr, 2);
sc->sc_bus.ab_dv = (struct device *)sc;
sc->sc_bus.ab_type = BUS_PICA;
sc->sc_bus.ab_intr_establish = pica_intr_establish;
sc->sc_bus.ab_intr_disestablish = pica_intr_disestablish;
sc->sc_bus.ab_cvtaddr = pica_cvtaddr;
sc->sc_bus.ab_matchname = pica_matchname;
/* Initialize PICA Dma */
picaDmaInit();
/* Try to configure each PICA 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, picaprint);
}
}
int
picaprint(aux, pnp)
void *aux;
const char *pnp;
{
struct confargs *ca = aux;
if (pnp)
printf("%s at %s", ca->ca_name, pnp);
printf(" slot %d offset 0x%x", ca->ca_slot, ca->ca_offset);
return (UNCONF);
}
caddr_t
pica_cvtaddr(ca)
struct confargs *ca;
{
struct pica_softc *sc = pica_cd.cd_devs[0];
return(sc->sc_devs[ca->ca_slot].ps_base + ca->ca_offset);
}
void
pica_intr_establish(ca, handler, val)
struct confargs *ca;
intr_handler_t handler;
void *val;
{
struct pica_softc *sc = pica_cd.cd_devs[0];
int slot;
slot = ca->ca_slot;
if(slot == 0) { /* Slot 0 is special, clock */
set_intr(MIPS_INT_MASK_4, pica_clkintr, 1);
}
if(int_table[slot].int_mask != 0) {
panic("pica intr already set");
}
else {
int_table[slot].int_mask = sc->sc_devs[slot].ps_mask;;
local_int_mask |= int_table[slot].int_mask;
int_table[slot].int_hand = handler;
int_table[slot].param = val;
}
out16(PICA_SYS_LB_IE, local_int_mask);
}
void
pica_intr_disestablish(ca)
struct confargs *ca;
{
struct pica_softc *sc = pica_cd.cd_devs[0];
int slot;
slot = ca->ca_slot;
if(slot == 0) { /* Slot 0 is special, clock */
}
else {
local_int_mask &= ~int_table[slot].int_mask;
int_table[slot].int_mask = 0;
int_table[slot].int_hand = pica_intrnull;
int_table[slot].param = (void *)NULL;
}
}
int
pica_matchname(ca, name)
struct confargs *ca;
char *name;
{
return (strcmp(name, ca->ca_name) == 0);
}
int
pica_intrnull(val)
void *val;
{
panic("uncaught PICA intr for slot %p\n", val);
}
/*
* Handle pica i/o interrupt.
*/
int
pica_iointr(val)
void *val;
{
int vector;
while((vector = inb(PVIS) >> 2) != 0) {
(*int_table[vector].int_hand)(int_table[vector].param);
}
return(~0); /* Dont reenable */
}
/*
* Handle pica interval clock interrupt.
*/
int
pica_clkintr(mask, pc, statusReg, causeReg)
unsigned mask;
unsigned pc;
unsigned statusReg;
unsigned causeReg;
{
struct clockframe cf;
int temp;
temp = inw(PICA_SYS_IT_STAT);
cf.pc = pc;
cf.sr = statusReg;
hardclock(&cf);
/* Re-enable clock interrupts */
splx(MIPS_INT_MASK_4 | MIPS_SR_INT_ENAB);
return(~MIPS_INT_MASK_4); /* Keep clock interrupts enabled */
}