ISA and PCI support for DEC AlphaStations
This commit is contained in:
parent
5cc82e159a
commit
549f126f4b
|
@ -0,0 +1,47 @@
|
|||
/* $NetBSD: isa_dma.h,v 1.1 1995/06/28 01:24:50 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
struct isadma_fcns {
|
||||
int (*isadma_map) __P((caddr_t addr, vm_size_t size,
|
||||
vm_offset_t *mappings, int flags));
|
||||
void (*isadma_unmap) __P((caddr_t addr, vm_size_t size,
|
||||
int nmappings, vm_offset_t *mappings));
|
||||
void (*isadma_copytobuf) __P((caddr_t addr, vm_size_t size,
|
||||
int nmappings, vm_offset_t *mappings));
|
||||
void (*isadma_copyfrombuf) __P((caddr_t addr, vm_size_t size,
|
||||
int nmappings, vm_offset_t *mappings));
|
||||
};
|
||||
|
||||
/*
|
||||
* Global which tells which set of functions are correct
|
||||
* for this machine.
|
||||
*/
|
||||
struct isadma_fcns *isadma_fcns;
|
||||
|
||||
struct isadma_fcns apecs_isadma_fcns; /* APECS DMA mapping */
|
|
@ -0,0 +1,54 @@
|
|||
/* $NetBSD: isa_intr.h,v 1.1 1995/06/28 01:24:57 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
/* Prototypes for ISA-ish I/O interrupt functions. */
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* XXX THIS WILL LIKELY HAVE TO BE COMPLETELY CHANGED.
|
||||
* XXX
|
||||
*/
|
||||
|
||||
struct isa_intr_fcns {
|
||||
void (*isa_intr_setup) __P((void));
|
||||
|
||||
void *(*isa_intr_establish) __P((int irq, isa_intrtype type,
|
||||
isa_intrlevel level, int (*ih_fun)(void *), void *ih_arg));
|
||||
void (*isa_intr_disestablish) __P((void *handler));
|
||||
|
||||
void (*isa_iointr) __P((void *framep, int vec));
|
||||
};
|
||||
|
||||
/*
|
||||
* Global which tells which set of functions are correct
|
||||
* for this machine.
|
||||
*/
|
||||
struct isa_intr_fcns *isa_intr_fcns;
|
||||
|
||||
struct isa_intr_fcns sio_intr_fcns; /* SIO ISA ICU handling */
|
|
@ -0,0 +1,169 @@
|
|||
/* $NetBSD: isa_machdep.c,v 1.1 1995/06/28 01:24:59 cgd 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/kernel.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <machine/autoconf.h>
|
||||
#include <machine/pio.h>
|
||||
#include <machine/rpb.h>
|
||||
#include <machine/vmparam.h>
|
||||
#include <machine/pte.h>
|
||||
|
||||
#include <dev/isa/isareg.h>
|
||||
#include <dev/isa/isavar.h>
|
||||
#include <dev/isa/isadmavar.h>
|
||||
|
||||
#include <alpha/isa/isa_intr.h>
|
||||
#include <alpha/isa/isa_dma.h>
|
||||
|
||||
int isamatch __P((struct device *, void *, void *));
|
||||
void isaattach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct cfdriver isacd = {
|
||||
NULL, "isa", isamatch, isaattach, DV_DULL, sizeof(struct isa_softc), 1
|
||||
};
|
||||
|
||||
int
|
||||
isamatch(parent, cfdata, aux)
|
||||
struct device *parent;
|
||||
void *cfdata, *aux;
|
||||
{
|
||||
struct cfdata *cf = cfdata;
|
||||
struct confargs *ca = aux;
|
||||
|
||||
#if 0 /* XXX -- Assume that it's valid if unit number OK */
|
||||
/* It can only occur on the mainbus. */
|
||||
if (ca->ca_bus->ab_type != BUS_MAIN)
|
||||
return (0);
|
||||
|
||||
/* Make sure that we're looking for this type of device. */
|
||||
if (!BUS_MATCHNAME(ca, "isa"))
|
||||
return (0);
|
||||
#endif /* XXX */
|
||||
|
||||
/* See if the unit number is valid. */
|
||||
switch (hwrpb->rpb_type) {
|
||||
#if defined(DEC_2100_A50)
|
||||
case ST_DEC_2100_A50:
|
||||
if (cf->cf_unit > 0)
|
||||
return (0);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
isaattach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct isa_softc *sc = (struct isa_softc *)self;
|
||||
|
||||
printf("\n");
|
||||
|
||||
TAILQ_INIT(&sc->sc_subdevs);
|
||||
|
||||
/* XXX set up ISA DMA controllers? */
|
||||
|
||||
config_scan(isascan, self);
|
||||
}
|
||||
|
||||
void *
|
||||
isa_intr_establish(irq, type, level, ih_fun, ih_arg)
|
||||
int irq;
|
||||
isa_intrtype type;
|
||||
isa_intrlevel level;
|
||||
int (*ih_fun)(void *);
|
||||
void *ih_arg;
|
||||
{
|
||||
|
||||
return (*isa_intr_fcns->isa_intr_establish)(irq, type, level,
|
||||
ih_fun, ih_arg);
|
||||
}
|
||||
|
||||
void
|
||||
isa_intr_disestablish(handler)
|
||||
void *handler;
|
||||
{
|
||||
|
||||
(*isa_intr_fcns->isa_intr_disestablish)(handler);
|
||||
}
|
||||
|
||||
int
|
||||
isadma_map(addr, size, mappings, flags)
|
||||
caddr_t addr;
|
||||
vm_size_t size;
|
||||
vm_offset_t *mappings;
|
||||
int flags;
|
||||
{
|
||||
|
||||
(*isadma_fcns->isadma_map)(addr, size, mappings, flags);
|
||||
}
|
||||
|
||||
void
|
||||
isadma_unmap(addr, size, nmappings, mappings)
|
||||
caddr_t addr;
|
||||
vm_size_t size;
|
||||
int nmappings;
|
||||
vm_offset_t *mappings;
|
||||
{
|
||||
|
||||
(*isadma_fcns->isadma_unmap)(addr, size, nmappings, mappings);
|
||||
}
|
||||
|
||||
void
|
||||
isadma_copytobuf(addr, size, nmappings, mappings)
|
||||
caddr_t addr;
|
||||
vm_size_t size;
|
||||
int nmappings;
|
||||
vm_offset_t *mappings;
|
||||
{
|
||||
|
||||
(*isadma_fcns->isadma_copytobuf)(addr, size, nmappings, mappings);
|
||||
}
|
||||
|
||||
void
|
||||
isadma_copyfrombuf(addr, size, nmappings, mappings)
|
||||
caddr_t addr;
|
||||
vm_size_t size;
|
||||
int nmappings;
|
||||
vm_offset_t *mappings;
|
||||
{
|
||||
|
||||
(*isadma_fcns->isadma_copyfrombuf)(addr, size, nmappings, mappings);
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
#include <machine/pio.h>
|
||||
#include <machine/pte.h>
|
||||
|
||||
static u_int8_t jensen_inb __P((int port));
|
||||
/* static void jensen_insb __P((int port, void *addr, int cnt)); */
|
||||
static u_int16_t jensen_inw __P((int port));
|
||||
/* static void jensen_insw __P((int port, void *addr, int cnt)); */
|
||||
u_int32_t jensen_inl __P((int port));
|
||||
/* static void jensen_insl __P((int port, void *addr, int cnt)); */
|
||||
|
||||
static void jensen_outb __P((int port, u_int8_t datum));
|
||||
/* static void jensen_outsb __P((int port, void *addr, int cnt)); */
|
||||
static void jensen_outw __P((int port, u_int16_t datum));
|
||||
/* static void jensen_outsw __P((int port, void *addr, int cnt)); */
|
||||
static void jensen_outl __P((int port, u_int32_t datum));
|
||||
/* static void jensen_outsl __P((int port, void *addr, int cnt)); */
|
||||
|
||||
struct alpha_isafcndesc jensen_isafcns = {
|
||||
jensen_inb, 0 /* jensen_insb */,
|
||||
jensen_inw, 0 /* jensen_insw */,
|
||||
jensen_inl, 0 /* jensen_insl */,
|
||||
jensen_outb, 0 /* jensen_outsb */,
|
||||
jensen_outw, 0 /* jensen_outsw */,
|
||||
jensen_outl, 0 /* jensen_outsl */,
|
||||
};
|
||||
|
||||
u_int8_t
|
||||
jensen_inb(ioaddr)
|
||||
int ioaddr;
|
||||
{
|
||||
u_int32_t *port, val;
|
||||
u_int8_t rval;
|
||||
int offset;
|
||||
|
||||
offset = ioaddr & 3;
|
||||
port = (int32_t *)phystok0seg(0x300000000L | 0 << 5 | ioaddr << 7);
|
||||
val = *port;
|
||||
rval = ((val) >> (8 * offset)) & 0xff;
|
||||
rval = val & 0xff;
|
||||
|
||||
printf("inb(0x%x) => 0x%x @ %p => 0x%x\n", ioaddr, val, port, rval);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
u_int16_t
|
||||
jensen_inw(ioaddr)
|
||||
int ioaddr;
|
||||
{
|
||||
u_int32_t *port, val;
|
||||
u_int16_t rval;
|
||||
int offset;
|
||||
|
||||
offset = ioaddr & 3;
|
||||
port = (int32_t *)phystok0seg(0x300000000L | 1 << 5 | ioaddr << 7);
|
||||
val = *port;
|
||||
rval = ((val) >> (8 * offset)) & 0xffff;
|
||||
rval = val & 0xffff;
|
||||
|
||||
panic("inw(0x%x) => 0x%x @ %p => 0x%x\n", ioaddr, val, port, rval);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
jensen_inl(ioaddr)
|
||||
int ioaddr;
|
||||
{
|
||||
u_int32_t *port, val;
|
||||
u_int32_t rval;
|
||||
int offset;
|
||||
|
||||
offset = ioaddr & 3;
|
||||
port = (int32_t *)phystok0seg(0x300000000L | 3 << 5 | ioaddr << 7);
|
||||
val = *port;
|
||||
rval = ((val) >> (8 * offset)) & 0xffffffff;
|
||||
rval = val & 0xffffffff;
|
||||
|
||||
printf("inl(0x%x) => 0x%x @ %p => 0x%x\n", ioaddr, val, port, rval);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
void
|
||||
jensen_outb(ioaddr, val)
|
||||
int ioaddr;
|
||||
u_int8_t val;
|
||||
{
|
||||
u_int32_t *port, nval;
|
||||
int offset;
|
||||
|
||||
offset = ioaddr & 3;
|
||||
nval = val /*<< (8 * offset)*/;
|
||||
port = (int32_t *)phystok0seg(0x300000000L | 0 << 5 | ioaddr << 7);
|
||||
|
||||
printf("outb(0x%x, 0x%x) => 0x%x @ %p\n", ioaddr, val, nval, port);
|
||||
|
||||
*port = nval;
|
||||
}
|
||||
|
||||
void
|
||||
jensen_outw(ioaddr, val)
|
||||
int ioaddr;
|
||||
u_int16_t val;
|
||||
{
|
||||
u_int32_t *port, nval;
|
||||
int offset;
|
||||
|
||||
offset = ioaddr & 3;
|
||||
nval = val /*<< (8 * offset)*/;
|
||||
port = (int32_t *)phystok0seg(0x300000000L | 1 << 5 | ioaddr << 7);
|
||||
|
||||
printf("outb(0x%x, 0x%x) => 0x%x @ %p\n", ioaddr, val, nval, port);
|
||||
|
||||
*port = nval;
|
||||
}
|
||||
|
||||
void
|
||||
jensen_outl(ioaddr, val)
|
||||
int ioaddr;
|
||||
u_int32_t val;
|
||||
{
|
||||
u_int32_t *port, nval;
|
||||
int offset;
|
||||
|
||||
offset = ioaddr & 3;
|
||||
nval = val /*<< (8 * offset)*/;
|
||||
port = (int32_t *)phystok0seg(0x300000000L | 3 << 5 | ioaddr << 7);
|
||||
|
||||
printf("outb(0x%x, 0x%x) => 0x%x @ %p\n", ioaddr, val, nval, port);
|
||||
|
||||
*port = nval;
|
||||
}
|
|
@ -0,0 +1,258 @@
|
|||
/* $NetBSD: apecs.c,v 1.1 1995/06/28 01:25:18 cgd 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/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/device.h>
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <machine/autoconf.h>
|
||||
#include <machine/pio.h>
|
||||
#include <machine/rpb.h>
|
||||
|
||||
#include <dev/isa/isareg.h>
|
||||
#include <dev/isa/isavar.h>
|
||||
#include <alpha/isa/isa_dma.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <alpha/pci/pci_chipset.h>
|
||||
#include <alpha/pci/apecsreg.h>
|
||||
|
||||
int apecsmatch __P((struct device *, void *, void *));
|
||||
void apecsattach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct cfdriver apecscd = {
|
||||
NULL, "apecs", apecsmatch, apecsattach, DV_DULL, sizeof(struct device)
|
||||
};
|
||||
|
||||
static int apecsprint __P((void *, char *pnp));
|
||||
|
||||
#ifdef DEC_2100_A50
|
||||
extern void pci_2100_a50_pickintr __P((void));
|
||||
#endif
|
||||
|
||||
#define REGVAL(r) (*(int32_t *)phystok0seg(r))
|
||||
|
||||
static int nsgmapent = 1024;
|
||||
static vm_offset_t sgmap_pci_base = 0x800000;
|
||||
/*static */struct sgmapent *sgmap;
|
||||
static char /* * */ sgbitmap[1024 / NBBY];
|
||||
|
||||
int
|
||||
apecsmatch(parent, match, aux)
|
||||
struct device *parent;
|
||||
void *match, *aux;
|
||||
{
|
||||
struct cfdata *cf = match;
|
||||
struct confargs *pa = aux;
|
||||
|
||||
/* XXX */
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
apecsattach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct confargs *ca = aux;
|
||||
struct confargs nca;
|
||||
int pass2_comanche, widemem, pass2_epic;
|
||||
|
||||
pass2_comanche = (REGVAL(COMANCHE_ED) & COMANCHE_ED_PASS2) != 0;
|
||||
widemem = (REGVAL(COMANCHE_GCR) & COMANCHE_GCR_WIDEMEM) != 0;
|
||||
pass2_epic = (REGVAL(EPIC_DCSR) & EPIC_DCSR_PASS2) != 0;
|
||||
|
||||
sgmap = (struct sgmapent *)malloc(1024 * sizeof(struct sgmapent),
|
||||
M_DEVBUF, M_WAITOK);
|
||||
|
||||
printf(": DECchip %s Core Logic chipset\n",
|
||||
widemem ? "21072" : "21071");
|
||||
printf("%s: DC21071-CA pass %d, %d-bit memory bus\n",
|
||||
self->dv_xname, pass2_comanche ? 2 : 1, widemem ? 128 : 64);
|
||||
printf("%s: DC21071-DA pass %d\n", self->dv_xname, pass2_epic ? 2 : 1);
|
||||
/* XXX print bcache size */
|
||||
|
||||
if (!pass2_epic)
|
||||
printf("WARNING: 21071-DA NOT PASS2... NO BETS...\n");
|
||||
|
||||
/* set up the chipset's functions */
|
||||
isadma_fcns = &apecs_isadma_fcns;
|
||||
isa_pio_fcns = &apecs_pio_fcns;
|
||||
if (!pass2_epic)
|
||||
pci_cs_fcns = &apecs_p1e_cs_fcns;
|
||||
else
|
||||
pci_cs_fcns = &apecs_p2e_cs_fcns;
|
||||
|
||||
switch (hwrpb->rpb_type) {
|
||||
#if defined(DEC_2100_A50)
|
||||
case ST_DEC_2100_A50:
|
||||
pci_2100_a50_pickintr();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
panic("apecsattach: shouldn't be here, really...");
|
||||
}
|
||||
|
||||
/* attach the PCI bus that hangs off of it... */
|
||||
nca.ca_name = "pci";
|
||||
nca.ca_slot = 0;
|
||||
nca.ca_offset = 0;
|
||||
nca.ca_bus = NULL;
|
||||
if (!config_found(self, &nca, apecsprint))
|
||||
panic("apecsattach: couldn't attach PCI bus");
|
||||
}
|
||||
|
||||
static int
|
||||
apecsprint(aux, pnp)
|
||||
void *aux;
|
||||
char *pnp;
|
||||
{
|
||||
register struct confargs *ca = aux;
|
||||
|
||||
if (pnp)
|
||||
printf("%s at %s", ca->ca_name, pnp);
|
||||
return (UNCONF);
|
||||
}
|
||||
|
||||
vm_offset_t /* XXX? */
|
||||
apecs_sgmap_alloc(va, npg, nocross, waitok)
|
||||
caddr_t va;
|
||||
int npg;
|
||||
vm_size_t nocross;
|
||||
int waitok;
|
||||
{
|
||||
int s;
|
||||
int base, i, stride;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
/* Quick sanity checks. */
|
||||
if ((vm_offset_t)va & PGOFSET)
|
||||
panic("apecs_sgmap_alloc: va not page aligned");
|
||||
if ((nocross & (nocross - 1)) != 0 || nocross == 0)
|
||||
panic("apecs_sgmap_alloc: bogus alignment 0x%lx", nocross);
|
||||
if (npg <= 0)
|
||||
panic("apecs_sgmap_alloc: not allocating anything");
|
||||
if (npg > nsgmapent)
|
||||
panic("apecs_sgmap_alloc: insane allocation");
|
||||
if (ptoa(npg) > nocross)
|
||||
panic("apecs_sgmap_alloc: must cross boundary");
|
||||
#endif
|
||||
|
||||
stride = atop(nocross);
|
||||
#ifdef DIAGNOSTIC
|
||||
if (stride > nsgmapent)
|
||||
panic("apecs_sgmap_alloc: cheesy implementation loses");
|
||||
#endif
|
||||
|
||||
top:
|
||||
s = splhigh();
|
||||
for (base = 0; base < nsgmapent; base += stride) {
|
||||
for (i = base; i < base + npg; i++)
|
||||
if (isset(sgbitmap, i))
|
||||
goto nextstride;
|
||||
break;
|
||||
nextstride:
|
||||
}
|
||||
if (base < nsgmapent) /* found a free chunk, claim it */
|
||||
for (i = base; i < base + npg; i++)
|
||||
setbit(sgbitmap, i);
|
||||
splx(s);
|
||||
|
||||
if (base >= nsgmapent) { /* didn't find a free chunk */
|
||||
if (!waitok)
|
||||
return 0;
|
||||
tsleep(&sgmap, PRIBIO+1, "sgmap", 0);
|
||||
goto top;
|
||||
}
|
||||
|
||||
for (i = base; i < base + npg; i++) {
|
||||
#ifdef DIAGNOSTIC
|
||||
if ((sgmap[i].val & SGMAPENT_EVAL) != 0)
|
||||
panic("apecs_sgmap_alloc: unallocated entry valid");
|
||||
#endif
|
||||
sgmap[i].val = SGMAP_MAKEENTRY(atop(vtophys(va)));
|
||||
va += PAGE_SIZE;
|
||||
}
|
||||
|
||||
/* Invalidate old cached entries. */
|
||||
REGVAL(EPIC_TBIA) = 1;
|
||||
|
||||
/* Return the PCI address. */
|
||||
return (ptoa(base) + sgmap_pci_base);
|
||||
}
|
||||
|
||||
void
|
||||
apecs_sgmap_dealloc(pa, npg)
|
||||
vm_offset_t pa;
|
||||
int npg;
|
||||
{
|
||||
int i, pfn;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
/* Quick sanity checks. */
|
||||
if (pa & PGOFSET)
|
||||
panic("apecs_sgmap_dealloc: pa not page aligned");
|
||||
if (npg <= 0)
|
||||
panic("apecs_sgmap_dealloc: not deallocating anything");
|
||||
if (npg > nsgmapent)
|
||||
panic("apecs_sgmap_dealloc: insane deallocation");
|
||||
#endif
|
||||
|
||||
pfn = atop(pa - sgmap_pci_base);
|
||||
#ifdef DIAGNOSTIC
|
||||
/* Bounds check the deallocation range. Paranoid about wraparound. */
|
||||
if (pfn < 0 || pfn >= nsgmapent || (pfn + npg) >= nsgmapent)
|
||||
panic("apecs_sgmap_dealloc: pa out of range (%s)",
|
||||
pfn < 0 ? "too low" : "too high");
|
||||
#endif
|
||||
|
||||
for (i = 0; i < npg; i++) {
|
||||
#ifdef DIAGNOSTIC
|
||||
/* Make sure it's actually allocated. */
|
||||
if (isclr(sgbitmap, i + pfn))
|
||||
panic("apecs_sgmap_dealloc: multiple frees: entry %d",
|
||||
i + pfn);
|
||||
#endif
|
||||
|
||||
/* Clear the entries and the allocation map bits. */
|
||||
clrbit(sgbitmap, i + pfn);
|
||||
sgmap[i + pfn].val &= ~SGMAPENT_EVAL;
|
||||
}
|
||||
|
||||
/* Invalidate old cached entries. */
|
||||
REGVAL(EPIC_TBIA) = 1;
|
||||
|
||||
/* Wake up anybody waiting for map entries. */
|
||||
wakeup(&sgmap);
|
||||
}
|
|
@ -0,0 +1,343 @@
|
|||
/* $NetBSD: apecs_isa.c,v 1.1 1995/06/28 01:25:24 cgd 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/malloc.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <machine/pio.h>
|
||||
|
||||
#include <dev/isa/isareg.h>
|
||||
#include <dev/isa/isadmavar.h>
|
||||
#include <alpha/isa/isa_dma.h>
|
||||
|
||||
#include <alpha/pci/apecsreg.h>
|
||||
|
||||
static u_int8_t apecs_inb __P((int port));
|
||||
/* static void apecs_insb __P((int port, void *addr, int cnt)); */
|
||||
#define apecs_insb 0 /* XXX */
|
||||
static u_int16_t apecs_inw __P((int port));
|
||||
/* static void apecs_insw __P((int port, void *addr, int cnt)); */
|
||||
#define apecs_insw 0 /* XXX */
|
||||
u_int32_t apecs_inl __P((int port));
|
||||
/* static void apecs_insl __P((int port, void *addr, int cnt)); */
|
||||
#define apecs_insl 0 /* XXX */
|
||||
|
||||
static void apecs_outb __P((int port, u_int8_t datum));
|
||||
/* static void apecs_outsb __P((int port, void *addr, int cnt)); */
|
||||
#define apecs_outsb 0 /* XXX */
|
||||
static void apecs_outw __P((int port, u_int16_t datum));
|
||||
/* static void apecs_outsw __P((int port, void *addr, int cnt)); */
|
||||
#define apecs_outsw 0 /* XXX */
|
||||
static void apecs_outl __P((int port, u_int32_t datum));
|
||||
/* static void apecs_outsl __P((int port, void *addr, int cnt)); */
|
||||
#define apecs_outsl 0 /* XXX */
|
||||
|
||||
struct isa_pio_fcns apecs_pio_fcns = {
|
||||
apecs_inb, apecs_insb,
|
||||
apecs_inw, apecs_insw,
|
||||
apecs_inl, apecs_insl,
|
||||
apecs_outb, apecs_outsb,
|
||||
apecs_outw, apecs_outsw,
|
||||
apecs_outl, apecs_outsl,
|
||||
};
|
||||
|
||||
static int apecs_isadma_map __P((caddr_t addr, vm_size_t size,
|
||||
vm_offset_t *mappings, int flags));
|
||||
static void apecs_isadma_unmap __P((caddr_t addr, vm_size_t size,
|
||||
int nmappings, vm_offset_t *mappings));
|
||||
static void apecs_isadma_copytobuf __P((caddr_t addr, vm_size_t size,
|
||||
int nmappings, vm_offset_t *mappings));
|
||||
static void apecs_isadma_copyfrombuf __P((caddr_t addr, vm_size_t size,
|
||||
int nmappings, vm_offset_t *mappings));
|
||||
|
||||
struct isadma_fcns apecs_isadma_fcns = {
|
||||
apecs_isadma_map, apecs_isadma_unmap,
|
||||
apecs_isadma_copytobuf, apecs_isadma_copyfrombuf,
|
||||
};
|
||||
|
||||
u_int8_t
|
||||
apecs_inb(ioaddr)
|
||||
int ioaddr;
|
||||
{
|
||||
u_int32_t *port, val;
|
||||
u_int8_t rval;
|
||||
int offset;
|
||||
|
||||
MB();
|
||||
offset = ioaddr & 3;
|
||||
port = (int32_t *)phystok0seg(APECS_PCI_SIO | 0 << 3 | ioaddr << 5);
|
||||
val = *port;
|
||||
rval = ((val) >> (8 * offset)) & 0xff;
|
||||
/* rval = val & 0xff; */
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
u_int16_t
|
||||
apecs_inw(ioaddr)
|
||||
int ioaddr;
|
||||
{
|
||||
u_int32_t *port, val;
|
||||
u_int16_t rval;
|
||||
int offset;
|
||||
|
||||
MB();
|
||||
offset = ioaddr & 3;
|
||||
port = (int32_t *)phystok0seg(APECS_PCI_SIO | 1 << 3 | ioaddr << 5);
|
||||
val = *port;
|
||||
rval = ((val) >> (8 * offset)) & 0xffff;
|
||||
rval = val & 0xffff;
|
||||
|
||||
panic("inw(0x%x) => 0x%x @ %p => 0x%x\n", ioaddr, val, port, rval);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
apecs_inl(ioaddr)
|
||||
int ioaddr;
|
||||
{
|
||||
u_int32_t *port, val;
|
||||
u_int32_t rval;
|
||||
int offset;
|
||||
|
||||
MB();
|
||||
offset = ioaddr & 3;
|
||||
port = (int32_t *)phystok0seg(APECS_PCI_SIO | 3 << 3 | ioaddr << 5);
|
||||
val = *port;
|
||||
rval = ((val) >> (8 * offset)) & 0xffffffff;
|
||||
rval = val & 0xffffffff;
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
void
|
||||
apecs_outb(ioaddr, val)
|
||||
int ioaddr;
|
||||
u_int8_t val;
|
||||
{
|
||||
u_int32_t *port, nval;
|
||||
int offset;
|
||||
|
||||
offset = ioaddr & 3;
|
||||
nval = val /*<< (8 * offset)*/;
|
||||
nval = val << (8 * offset);
|
||||
port = (int32_t *)phystok0seg(APECS_PCI_SIO | 0 << 3 | ioaddr << 5);
|
||||
|
||||
*port = nval;
|
||||
MB();
|
||||
}
|
||||
|
||||
void
|
||||
apecs_outw(ioaddr, val)
|
||||
int ioaddr;
|
||||
u_int16_t val;
|
||||
{
|
||||
u_int32_t *port, nval;
|
||||
int offset;
|
||||
|
||||
offset = ioaddr & 3;
|
||||
nval = val /*<< (8 * offset)*/;
|
||||
port = (int32_t *)phystok0seg(APECS_PCI_SIO | 1 << 3 | ioaddr << 5);
|
||||
|
||||
*port = nval;
|
||||
MB();
|
||||
}
|
||||
|
||||
void
|
||||
apecs_outl(ioaddr, val)
|
||||
int ioaddr;
|
||||
u_int32_t val;
|
||||
{
|
||||
u_int32_t *port, nval;
|
||||
int offset;
|
||||
|
||||
offset = ioaddr & 3;
|
||||
nval = val /*<< (8 * offset)*/;
|
||||
port = (int32_t *)phystok0seg(APECS_PCI_SIO | 3 << 3 | ioaddr << 5);
|
||||
|
||||
*port = nval;
|
||||
MB();
|
||||
}
|
||||
|
||||
static caddr_t bounced_addr;
|
||||
static caddr_t bounce_buffer;
|
||||
static vm_size_t bounce_size;
|
||||
|
||||
int
|
||||
apecs_isadma_map(addr, size, mappings, flags)
|
||||
caddr_t addr;
|
||||
vm_size_t size;
|
||||
vm_offset_t *mappings;
|
||||
int flags;
|
||||
{
|
||||
vm_offset_t off, truncaddr;
|
||||
vm_offset_t isa_truncpa; /* XXX? */
|
||||
vm_size_t alignment;
|
||||
int i, npages, waitok;
|
||||
|
||||
/*
|
||||
* ISADMA_MAP_{,NO}BOUNCE and ISADMA_MAP_{CONTIG,SCATTER} are
|
||||
* completely ignored, because all allocations will be in the
|
||||
* low 16M and will be contiguous. I LOVE VIRTUAL DMA!
|
||||
*/
|
||||
|
||||
truncaddr = trunc_page(addr);
|
||||
off = (vm_offset_t)addr - truncaddr;
|
||||
npages = num_pages(size + off);
|
||||
if (npages == 0)
|
||||
panic("apecs_isadma_map: map nothing");
|
||||
|
||||
alignment = 64 * 1024;
|
||||
if ((flags & ISADMA_MAP_16BIT) != 0)
|
||||
alignment <<= 1;
|
||||
waitok = (flags & ISADMA_MAP_WAITOK) != 0;
|
||||
|
||||
if (npages > atop(alignment)) {
|
||||
int s;
|
||||
void *tmpbb;
|
||||
|
||||
/*
|
||||
* Allocate a bounce buffer.
|
||||
*/
|
||||
s = splhigh();
|
||||
retry:
|
||||
while (bounce_buffer != NULL) {
|
||||
/*
|
||||
* If a bounce buffer is in use and we can't
|
||||
* wait, bug out now, otherwise sleep.
|
||||
*/
|
||||
if (!waitok) {
|
||||
splx(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tsleep(&bounce_buffer, PRIBIO+1, "apecsbb", 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to allocate a bounce buffer.
|
||||
*/
|
||||
tmpbb = malloc(alignment, M_DEVBUF,
|
||||
waitok ? M_WAITOK : M_NOWAIT);
|
||||
if (tmpbb == NULL) { /* couldn't wait, and failed */
|
||||
splx(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we slept in malloc() and somebody else got it,
|
||||
* give it up and try it again!
|
||||
*/
|
||||
if (bounce_buffer != NULL) {
|
||||
free(tmpbb, M_DEVBUF);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/*
|
||||
* It's ours, all ours!
|
||||
*/
|
||||
bounce_buffer = tmpbb;
|
||||
splx(s);
|
||||
|
||||
bounced_addr = addr;
|
||||
bounce_size = size;
|
||||
truncaddr = (vm_offset_t)bounce_buffer;
|
||||
npages = atop(alignment);
|
||||
}
|
||||
|
||||
isa_truncpa = apecs_sgmap_alloc(truncaddr, npages, alignment, waitok);
|
||||
|
||||
mappings[0] = isa_truncpa + off;
|
||||
for (i = 1; i < npages; i++)
|
||||
mappings[i] = isa_truncpa + ptoa(i);
|
||||
|
||||
return (npages);
|
||||
}
|
||||
|
||||
void
|
||||
apecs_isadma_unmap(addr, size, nmappings, mappings)
|
||||
caddr_t addr;
|
||||
vm_size_t size;
|
||||
int nmappings;
|
||||
vm_offset_t *mappings;
|
||||
{
|
||||
int npages;
|
||||
|
||||
npages = nmappings;
|
||||
if (npages == 0)
|
||||
panic("apecs_isadma_unmap: unmap nothing");
|
||||
apecs_sgmap_dealloc(trunc_page(mappings[0]), npages);
|
||||
|
||||
if (addr == bounced_addr) {
|
||||
/*
|
||||
* Free the bounce buffer and wake up anybody who
|
||||
* wants to bounce.
|
||||
*/
|
||||
bounced_addr = NULL;
|
||||
bounce_size = 0;
|
||||
free(bounce_buffer, M_DEVBUF);
|
||||
bounce_buffer = NULL;
|
||||
wakeup(&bounce_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
apecs_isadma_copytobuf(addr, size, nmappings, mappings)
|
||||
caddr_t addr;
|
||||
vm_size_t size;
|
||||
int nmappings;
|
||||
vm_offset_t *mappings;
|
||||
{
|
||||
|
||||
if (addr != bounced_addr)
|
||||
return;
|
||||
|
||||
log(LOG_NOTICE, "apecs_isa_copytobuf: copied %d byte buffer\n",
|
||||
bounce_size);
|
||||
bcopy(addr, bounce_buffer, bounce_size);
|
||||
}
|
||||
|
||||
void
|
||||
apecs_isadma_copyfrombuf(addr, size, nmappings, mappings)
|
||||
caddr_t addr;
|
||||
vm_size_t size;
|
||||
int nmappings;
|
||||
vm_offset_t *mappings;
|
||||
{
|
||||
|
||||
if (addr != bounced_addr)
|
||||
return;
|
||||
|
||||
log(LOG_NOTICE, "apecs_isa_copyfrombuf: copied %d byte buffer\n",
|
||||
bounce_size);
|
||||
bcopy(bounce_buffer, addr, bounce_size);
|
||||
}
|
|
@ -0,0 +1,339 @@
|
|||
/* $NetBSD: apecs_pci.c,v 1.1 1995/06/28 01:25:30 cgd 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/kernel.h>
|
||||
#include <sys/device.h>
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <machine/autoconf.h>
|
||||
#include <machine/pio.h>
|
||||
|
||||
#include <dev/isa/isavar.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <alpha/pci/pci_chipset.h>
|
||||
#include <alpha/pci/apecsreg.h>
|
||||
|
||||
void apecs_setup __P((void));
|
||||
pcitag_t apecs_make_tag __P((int, int, int));
|
||||
pcireg_t apecs_conf_read __P((pcitag_t, int));
|
||||
void apecs_conf_write __P((pcitag_t, int, pcireg_t));
|
||||
int apecs_map_mem __P((pcitag_t, int, vm_offset_t *, vm_offset_t *));
|
||||
int apecs_pcidma_map __P((caddr_t, vm_size_t, vm_offset_t *));
|
||||
void apecs_pcidma_unmap __P((caddr_t, vm_size_t, int, vm_offset_t *));
|
||||
|
||||
struct pci_cs_fcns apecs_p1e_cs_fcns = { /* XXX WHAT'S DIFFERENT? */
|
||||
apecs_setup,
|
||||
apecs_make_tag,
|
||||
apecs_conf_read,
|
||||
apecs_conf_write,
|
||||
apecs_map_mem,
|
||||
apecs_pcidma_map,
|
||||
apecs_pcidma_unmap,
|
||||
};
|
||||
|
||||
struct pci_cs_fcns apecs_p2e_cs_fcns = { /* XXX WHAT'S DIFFERENT? */
|
||||
apecs_setup,
|
||||
apecs_make_tag,
|
||||
apecs_conf_read,
|
||||
apecs_conf_write,
|
||||
apecs_map_mem,
|
||||
apecs_pcidma_map,
|
||||
apecs_pcidma_unmap,
|
||||
};
|
||||
|
||||
#define REGVAL(r) (*(u_int32_t *)phystok0seg(r))
|
||||
|
||||
void
|
||||
apecs_setup()
|
||||
{
|
||||
|
||||
/*
|
||||
* Set up PCI bus mastering DMA windows on the APECS chip.
|
||||
*
|
||||
* What the PROM wants:
|
||||
* a 1G direct-mapped window that maps the PCI address
|
||||
* space from 4G -> 5G to memory addresses 0 -> 1G,
|
||||
* set up in window two.
|
||||
*
|
||||
* What we want:
|
||||
* a 1G direct-mapped window that maps the PCI address
|
||||
* space from 0 -> 1G to memory addresses 0 -> 1G.
|
||||
*
|
||||
* Unless we satisfy the PROM, we can't live through a reboot.
|
||||
* If we don't do what we want, I have to write more code.
|
||||
|
||||
* So:
|
||||
* Leave window two alone, map window 1 the way I want it.
|
||||
*
|
||||
* XXX verify that windows don't overlap
|
||||
* XXX be trickier
|
||||
* XXX magic numbers
|
||||
*/
|
||||
|
||||
#if 0 /* should be routine to dump regs */
|
||||
printf("old base1 was 0x%x\n", REGVAL(EPIC_PCI_BASE_1));
|
||||
printf("old mask1 was 0x%x\n", REGVAL(EPIC_PCI_MASK_1));
|
||||
printf("old tbase1 was 0x%x\n", REGVAL(EPIC_TBASE_1));
|
||||
|
||||
printf("old base2 was 0x%x\n", REGVAL(EPIC_PCI_BASE_2));
|
||||
printf("old mask2 was 0x%x\n", REGVAL(EPIC_PCI_MASK_2));
|
||||
printf("old tbase2 was 0x%x\n", REGVAL(EPIC_TBASE_2));
|
||||
#endif
|
||||
|
||||
#if 0 /* XXX STUPID PROM; MUST LEAVE WINDOW 2 ALONE. See above */
|
||||
/* Turn off DMA window enables in PCI Base Reg 2. */
|
||||
REGVAL(EPIC_PCI_BASE_2) = 0;
|
||||
|
||||
/* Set up Translated Base Register 2; translate to sybBus addr 0. */
|
||||
REGVAL(EPIC_TBASE_2) = 0;
|
||||
|
||||
/* Set up PCI mask register 2; map 1G space. */
|
||||
REGVAL(EPIC_PCI_MASK_2) = 0x3ff00000;
|
||||
|
||||
/* Enable window 2; from PCI address 4G, direct mapped. */
|
||||
REGVAL(EPIC_PCI_BASE_2) = 0x40080000;
|
||||
#endif /* STUPID PROM */
|
||||
|
||||
/* Turn off DMA window enables in PCI Base Reg 1. */
|
||||
REGVAL(EPIC_PCI_BASE_1) = 0;
|
||||
|
||||
/* Set up Translated Base Register 1; translate to sybBus addr 0. */
|
||||
{ /* XXX */
|
||||
extern struct sgmapent *sgmap;
|
||||
REGVAL(EPIC_TBASE_1) = vtophys(sgmap) >> 1;
|
||||
} /* XXX */
|
||||
|
||||
/* Set up PCI mask register 1; map 8MB space. */
|
||||
REGVAL(EPIC_PCI_MASK_1) = 0x00700000;
|
||||
|
||||
/* Enable window 1; from PCI address 8MB, direct mapped. */
|
||||
REGVAL(EPIC_PCI_BASE_1) = 0x008c0000;
|
||||
|
||||
/*
|
||||
* Should set up HAXR1 and HAXR2... However, the PROM again
|
||||
* wants them where they're set to be...
|
||||
*/
|
||||
#if 0
|
||||
printf("old haxr0 was 0x%x\n", REGVAL(EPIC_HAXR0));
|
||||
printf("old haxr1 was 0x%x\n", REGVAL(EPIC_HAXR1));
|
||||
printf("old haxr2 was 0x%x\n", REGVAL(EPIC_HAXR2));
|
||||
#endif
|
||||
|
||||
#if 0 /* XXX STUPID PROM */
|
||||
/* HAXR0 is wired zero; no op. */
|
||||
REGVAL(EPIC_HAXR0) = 0;
|
||||
|
||||
/* HAXR1: maps PCI memory space above 16M. 16M -> 2G+16M. */
|
||||
REGVAL(EPIC_HAXR1) = 0x80000000;
|
||||
|
||||
/* HAXR2: maps PCI I/O space above 256K. 256K -> 256k. */
|
||||
REGVAL(EPIC_HAXR2) = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
pcitag_t
|
||||
apecs_make_tag(bus, device, function)
|
||||
int bus, device, function;
|
||||
{
|
||||
pcitag_t tag;
|
||||
|
||||
if (bus >= 256 || device >= 32 || function >= 8)
|
||||
panic("apecs_make_tag: bad request");
|
||||
|
||||
tag = (bus << 21) | (device << 16) | (function << 13);
|
||||
#if 0
|
||||
printf("apecs_make_tag: bus %d, device %d, function %d -> 0x%lx\n", bus,
|
||||
device, function, tag);
|
||||
#endif
|
||||
return tag;
|
||||
}
|
||||
|
||||
pcireg_t
|
||||
apecs_conf_read(tag, offset)
|
||||
pcitag_t tag;
|
||||
int offset; /* XXX */
|
||||
{
|
||||
pcireg_t *datap, data;
|
||||
int reg = offset >> 2; /* XXX */
|
||||
|
||||
if ((tag & 0x1fe00000) != 0) {
|
||||
panic("apecs_conf_read: bus != 0?");
|
||||
}
|
||||
/* XXX FILL IN HAXR2 bits. */
|
||||
|
||||
datap = (pcireg_t *)
|
||||
phystok0seg(APECS_PCI_CONF | tag | reg << 7 | 0 << 5 | 0x3 << 3);
|
||||
if (badaddr(datap, sizeof *datap))
|
||||
return ((pcireg_t)-1);
|
||||
data = *datap;
|
||||
#if 0
|
||||
printf("apecs_conf_read: tag 0x%lx, reg 0x%lx -> %x @ %p\n", tag, reg,
|
||||
data, datap);
|
||||
#endif
|
||||
return data;
|
||||
}
|
||||
|
||||
void
|
||||
apecs_conf_write(tag, offset, data)
|
||||
pcitag_t tag;
|
||||
int offset; /* XXX */
|
||||
pcireg_t data;
|
||||
{
|
||||
pcireg_t *datap;
|
||||
int reg = offset >> 2; /* XXX */
|
||||
|
||||
if ((tag & 0x1fe00000) != 0) {
|
||||
panic("apecs_conf_read: bus != 0?");
|
||||
}
|
||||
/* XXX FILL IN HAXR2 bits. */
|
||||
|
||||
datap = (pcireg_t *)
|
||||
phystok0seg(APECS_PCI_CONF | tag | reg << 7 | 0 << 5 | 0x3 << 3);
|
||||
#if 0
|
||||
printf("apecs_conf_write: tag 0x%lx, reg 0x%lx -> 0x%x @ %p\n", tag,
|
||||
reg, data, datap);
|
||||
#endif
|
||||
*datap = data;
|
||||
}
|
||||
|
||||
#ifndef APECS_PCI_PMEM_START
|
||||
#define APECS_PCI_PMEM_START 0x00100000 /* WAY XXX */
|
||||
#endif
|
||||
|
||||
vm_offset_t apecs_pci_paddr = APECS_PCI_PMEM_START;
|
||||
|
||||
int
|
||||
apecs_map_mem(tag, reg, vap, pap)
|
||||
pcitag_t tag;
|
||||
int reg;
|
||||
vm_offset_t *vap, *pap;
|
||||
{
|
||||
pcireg_t data;
|
||||
vm_offset_t pci_pa, sb_pa;
|
||||
|
||||
if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3))
|
||||
panic("apecs_map_mem: bad request");
|
||||
|
||||
/*
|
||||
* "HERE WE GO AGAIN!!!"
|
||||
*
|
||||
* The PROM has already mapped the device for us. The PROM is
|
||||
* our friend. We wouldn't want to make the PROM unhappy.
|
||||
*
|
||||
* So, we take the address that's been assigned (already) to
|
||||
* the register, and figure out what physical and virtual addresses
|
||||
* go with it...
|
||||
*/
|
||||
/*
|
||||
* Section 6.2.5.1, `Address Maps', says that a device which wants 2^n
|
||||
* bytes of memory will hardwire the bottom n bits of the address to 0.
|
||||
* As recommended, we write all 1s and see what we get back.
|
||||
*/
|
||||
data = pci_conf_read(tag, reg);
|
||||
|
||||
if (data & PCI_MAP_IO)
|
||||
panic("apecs_map_mem: attempt to memory map an I/O region");
|
||||
|
||||
switch (data & PCI_MAP_MEMORY_TYPE_MASK) {
|
||||
case PCI_MAP_MEMORY_TYPE_32BIT:
|
||||
break;
|
||||
case PCI_MAP_MEMORY_TYPE_32BIT_1M:
|
||||
printf("apecs_map_mem: attempt to map restricted 32-bit region\n");
|
||||
return EOPNOTSUPP;
|
||||
case PCI_MAP_MEMORY_TYPE_64BIT:
|
||||
printf("apecs_map_mem: attempt to map 64-bit region\n");
|
||||
return EOPNOTSUPP;
|
||||
default:
|
||||
printf("apecs_map_mem: reserved mapping type\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (data & PCI_MAP_MEMORY_CACHABLE) {
|
||||
/* XXX probably should impact mapping location? */
|
||||
printf("apecs_map_mem: memory wants to be cacheable.\n");
|
||||
}
|
||||
|
||||
/* figure out where it was mapped... */
|
||||
pci_pa = data & PCI_MAP_MEMORY_ADDRESS_MASK; /* PCI bus address */
|
||||
sb_pa = ((data & 0x7fffffc) << 5) | (2L << 32); /* sysBus address */
|
||||
|
||||
/* and tell the driver. */
|
||||
*vap = phystok0seg(sb_pa);
|
||||
*pap = pci_pa;
|
||||
|
||||
#if 0
|
||||
printf("pci_map_mem: memory mapped at 0x%lx\n", *pap);
|
||||
printf("pci_map_mem: virtual 0x%lx\n", *vap);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
apecs_pcidma_map(addr, size, mappings)
|
||||
caddr_t addr;
|
||||
vm_size_t size;
|
||||
vm_offset_t *mappings;
|
||||
{
|
||||
vm_offset_t va;
|
||||
long todo;
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
va = (vm_offset_t)addr;
|
||||
todo = size;
|
||||
|
||||
while (todo > 0) {
|
||||
mappings[i] = vtophys(va) | 0x40000000;
|
||||
#if 0
|
||||
printf("a_pd_m mapping %d: %lx -> %lx -> %lx\n", i, va,
|
||||
vtophys(va), mappings[i]);
|
||||
#endif
|
||||
i++;
|
||||
todo -= PAGE_SIZE - (va - trunc_page(va));
|
||||
va += PAGE_SIZE - (va - trunc_page(va));
|
||||
}
|
||||
return (i);
|
||||
}
|
||||
|
||||
void
|
||||
apecs_pcidma_unmap(addr, size, nmappings, mappings)
|
||||
caddr_t addr;
|
||||
vm_size_t size;
|
||||
int nmappings;
|
||||
vm_offset_t *mappings;
|
||||
{
|
||||
|
||||
/* maybe XXX if diagnostic, check that mapping happened. */
|
||||
printf("apecs_pcidma_unmap: nada\n");
|
||||
}
|
|
@ -0,0 +1,325 @@
|
|||
/* $NetBSD: apecsreg.h,v 1.1 1995/06/28 01:25:36 cgd 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* APECS Chipset registers and constants.
|
||||
*
|
||||
* Taken from ``DECchip 21071 and DECchip 21072 Core Logic Chipsets Data
|
||||
* Sheet'' (DEC order number EC-QAEMA-TE), pages 4-1 - 4-27, 10-21 - 10-38.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Base addresses
|
||||
*/
|
||||
#define COMANCHE_BASE 0x180000000L /* 21071-CA Regs */
|
||||
#define EPIC_BASE 0x1a0000000L /* 21071-DA Regs */
|
||||
#define APECS_PCI_IACK 0x1b0000000L /* PCI Int. Ack. */
|
||||
#define APECS_PCI_SIO 0x1c0000000L /* PCI Sp. I/O Space */
|
||||
#define APECS_PCI_CONF 0x1e0000000L /* PCI Conf. Space */
|
||||
#define APECS_PCI_SPARSE 0x200000000L /* PCI Sparse Space */
|
||||
#define APECS_PCI_DENSE 0x300000000L /* PCI Dense Space */
|
||||
|
||||
|
||||
/*
|
||||
* 21071-CA Registers
|
||||
*/
|
||||
|
||||
/*
|
||||
* 21071-CA General Registers
|
||||
*/
|
||||
#define COMANCHE_GCR (COMANCHE_BASE + 0x0000) /* General Control */
|
||||
#define COMANCHE_GCR_RSVD 0xc009
|
||||
#define COMANCHE_GCR_SYSARB 0x0006
|
||||
#define COMANCHE_GCR_WIDEMEM 0x0010
|
||||
#define COMANCHE_GCR_BC_EN 0x0020
|
||||
#define COMANCHE_GCR_BC_NOALLOC 0x0040
|
||||
#define COMANCHE_GCR_BC_LONGWR 0x0080
|
||||
#define COMANCHE_GCR_BC_IGNTAG 0x0100
|
||||
#define COMANCHE_GCR_BC_FRCTAG 0x0200
|
||||
#define COMANCHE_GCR_BC_FRCD 0x0400
|
||||
#define COMANCHE_GCR_BC_FRCV 0x0800
|
||||
#define COMANCHE_GCR_BC_FRCP 0x1000
|
||||
#define COMANCHE_GCR_BC_BADAP 0x2000
|
||||
|
||||
#define COMANCHE_RSVD (COMANCHE_BASE + 0x0020) /* Reserved */
|
||||
|
||||
#define COMANCHE_ED (COMANCHE_BASE + 0x0040) /* Err & Diag Status */
|
||||
#define COMANCHE_ED_LOSTERR 0x0001
|
||||
#define COMANCHE_ED_BC_TAPERR 0x0002
|
||||
#define COMANCHE_ED_BC_TCPERR 0x0004
|
||||
#define COMANCHE_ED_NXMERR 0x0008
|
||||
#define COMANCHE_ED_DMACAUSE 0x0010
|
||||
#define COMANCHE_ED_VICCAUSE 0x0020
|
||||
#define COMANCHE_ED_CREQCAUSE 0x01c0
|
||||
#define COMANCHE_ED_RSVD 0x1e00
|
||||
#define COMANCHE_ED_PASS2 0x2000
|
||||
#define COMANCHE_ED_IDXLLOCK 0x4000
|
||||
#define COMANCHE_ED_WRPEND 0x8000
|
||||
|
||||
#define COMANCHE_TAGENB (COMANCHE_BASE + 0x0060) /* Tag Enable */
|
||||
#define COMANCHE_TAGENB_RSVD 0x0001
|
||||
|
||||
#define COMANCHE_TAGENB_C_4G 0x0000
|
||||
#define COMANCHE_TAGENB_C_2G 0x8000
|
||||
#define COMANCHE_TAGENB_C_1G 0xc000
|
||||
#define COMANCHE_TAGENB_C_512M 0xe000
|
||||
#define COMANCHE_TAGENB_C_256M 0xf000
|
||||
#define COMANCHE_TAGENB_C_128M 0xf800
|
||||
#define COMANCHE_TAGENB_C_64M 0xfc00
|
||||
#define COMANCHE_TAGENB_C_32M 0xfe00
|
||||
#define COMANCHE_TAGENB_C_16M 0xff00
|
||||
#define COMANCHE_TAGENB_C_8M 0xff80
|
||||
#define COMANCHE_TAGENB_C_4M 0xffc0
|
||||
#define COMANCHE_TAGENB_C_2M 0xffe0
|
||||
#define COMANCHE_TAGENB_C_1M 0xfff0
|
||||
#define COMANCHE_TAGENB_C_512K 0xfff8
|
||||
#define COMANCHE_TAGENB_C_256K 0xfffc
|
||||
#define COMANCHE_TAGENB_C_128K 0xfffe
|
||||
|
||||
#define COMANCHE_TAGENB_M_4G 0xffff
|
||||
#define COMANCHE_TAGENB_M_2G 0x7fff
|
||||
#define COMANCHE_TAGENB_M_1G 0x3fff
|
||||
#define COMANCHE_TAGENB_M_512M 0x1fff
|
||||
#define COMANCHE_TAGENB_M_256M 0x0fff
|
||||
#define COMANCHE_TAGENB_M_128M 0x07ff
|
||||
#define COMANCHE_TAGENB_M_64M 0x03ff
|
||||
#define COMANCHE_TAGENB_M_32M 0x01ff
|
||||
#define COMANCHE_TAGENB_M_16M 0x00ff
|
||||
#define COMANCHE_TAGENB_M_8M 0x007f
|
||||
#define COMANCHE_TAGENB_M_4M 0x003f
|
||||
#define COMANCHE_TAGENB_M_2M 0x001f
|
||||
#define COMANCHE_TAGENB_M_1M 0x000e
|
||||
#define COMANCHE_TAGENB_M_512K 0x0006
|
||||
#define COMANCHE_TAGENB_M_256K 0x0002
|
||||
#define COMANCHE_TAGENB_M_128K 0x0000
|
||||
|
||||
#define COMANCHE_ERR_LO (COMANCHE_BASE + 0x0080) /* Error Low Address */
|
||||
|
||||
#define COMANCHE_ERR_HI (COMANCHE_BASE + 0x00a0) /* Error High Address */
|
||||
#define COMANCHE_ERR_HI_RSVD 0xe000
|
||||
|
||||
#define COMANCHE_LCK_LO (COMANCHE_BASE + 0x00c0) /* LDx_L Low Address */
|
||||
|
||||
#define COMANCHE_LCK_HI (COMANCHE_BASE + 0x00e0) /* LDx_L High Address */
|
||||
#define COMANCHE_LOCK_HI_RSVD 0xe000
|
||||
|
||||
/*
|
||||
* 21071-CA Memory Registers
|
||||
*/
|
||||
#define COMANCHE_GTIM (COMANCHE_BASE + 0x0200) /* Global Timing */
|
||||
#define COMANCHE_LOCK_HI_RSVD 0xe000
|
||||
|
||||
#define COMANCHE_RTIM (COMANCHE_BASE + 0x0220) /* Refresh Timing */
|
||||
|
||||
#define COMANCHE_VFP (COMANCHE_BASE + 0x0240) /* Video Frame Ptr. */
|
||||
#define COMANCHE_VFP_COL 0x001f
|
||||
#define COMANCHE_VFP_ROW 0x3fe0
|
||||
#define COMANCHE_VFP_SUBBANK 0x4000
|
||||
#define COMANCHE_VFP_RSVD 0x8000
|
||||
|
||||
#define COMANCHE_PD_LO (COMANCHE_BASE + 0x0260) /* Pres Detect Low */
|
||||
|
||||
#define COMANCHE_PD_HI (COMANCHE_BASE + 0x0280) /* Pres Detect High */
|
||||
|
||||
/*
|
||||
* 21071-CA Memory banks' Base Address Register format
|
||||
*/
|
||||
#define COMANCHE_B0_BAR (COMANCHE_BASE + 0x0800) /* Bank 0 BA */
|
||||
#define COMANCHE_B1_BAR (COMANCHE_BASE + 0x0820) /* Bank 1 BA */
|
||||
#define COMANCHE_B2_BAR (COMANCHE_BASE + 0x0840) /* Bank 2 BA */
|
||||
#define COMANCHE_B3_BAR (COMANCHE_BASE + 0x0860) /* Bank 3 BA */
|
||||
#define COMANCHE_B4_BAR (COMANCHE_BASE + 0x0880) /* Bank 4 BA */
|
||||
#define COMANCHE_B5_BAR (COMANCHE_BASE + 0x08a0) /* Bank 5 BA */
|
||||
#define COMANCHE_B6_BAR (COMANCHE_BASE + 0x08c0) /* Bank 6 BA */
|
||||
#define COMANCHE_B7_BAR (COMANCHE_BASE + 0x08e0) /* Bank 7 BA */
|
||||
#define COMANCHE_B8_BAR (COMANCHE_BASE + 0x0900) /* Bank 8 BA */
|
||||
#define COMANCHE_BAR_RSVD 0x001f
|
||||
|
||||
/*
|
||||
* 21071-CA Memory banks' Configuration Register format
|
||||
*/
|
||||
#define COMANCHE_B0_CR (COMANCHE_BASE + 0x0a00) /* Bank 0 Config */
|
||||
#define COMANCHE_B1_CR (COMANCHE_BASE + 0x0a20) /* Bank 1 Config */
|
||||
#define COMANCHE_B2_CR (COMANCHE_BASE + 0x0a40) /* Bank 2 Config */
|
||||
#define COMANCHE_B3_CR (COMANCHE_BASE + 0x0a60) /* Bank 3 Config */
|
||||
#define COMANCHE_B4_CR (COMANCHE_BASE + 0x0a80) /* Bank 4 Config */
|
||||
#define COMANCHE_B5_CR (COMANCHE_BASE + 0x0aa0) /* Bank 5 Config */
|
||||
#define COMANCHE_B6_CR (COMANCHE_BASE + 0x0ac0) /* Bank 6 Config */
|
||||
#define COMANCHE_B7_CR (COMANCHE_BASE + 0x0ae0) /* Bank 7 Config */
|
||||
#define COMANCHE_B8_CR (COMANCHE_BASE + 0x0b00) /* Bank 8 Config */
|
||||
#define COMANCHE_CR_VALID 0x0001
|
||||
#define COMANCHE_CR_SIZE 0x001e
|
||||
#define COMANCHE_CR_SUBENA 0x0020
|
||||
#define COMANCHE_CR_COLSEL 0x01c0
|
||||
#define COMANCHE_CR_S0_RSVD 0xfe00
|
||||
#define COMANCHE_CR_S8_CHECK 0x0200
|
||||
#define COMANCHE_CR_S8_RSVD 0xfc00
|
||||
|
||||
/*
|
||||
* 21071-CA Memory banks' Timing Register A format
|
||||
*/
|
||||
#define COMANCHE_B0_TRA (COMANCHE_BASE + 0x0c00) /* Bank 0 Timing A */
|
||||
#define COMANCHE_B1_TRA (COMANCHE_BASE + 0x0c20) /* Bank 1 Timing A */
|
||||
#define COMANCHE_B2_TRA (COMANCHE_BASE + 0x0c40) /* Bank 2 Timing A */
|
||||
#define COMANCHE_B3_TRA (COMANCHE_BASE + 0x0c60) /* Bank 3 Timing A */
|
||||
#define COMANCHE_B4_TRA (COMANCHE_BASE + 0x0c80) /* Bank 4 Timing A */
|
||||
#define COMANCHE_B5_TRA (COMANCHE_BASE + 0x0ca0) /* Bank 5 Timing A */
|
||||
#define COMANCHE_B6_TRA (COMANCHE_BASE + 0x0cc0) /* Bank 6 Timing A */
|
||||
#define COMANCHE_B7_TRA (COMANCHE_BASE + 0x0ce0) /* Bank 7 Timing A */
|
||||
#define COMANCHE_B8_TRA (COMANCHE_BASE + 0x0d00) /* Bank 8 Timing A */
|
||||
#define COMANCHE_TRA_ROWSETUP 0x0003
|
||||
#define COMANCHE_TRA_ROWHOLD 0x000c
|
||||
#define COMANCHE_TRA_COLSETUP 0x0070
|
||||
#define COMANCHE_TRA_COLHOLD 0x0180
|
||||
#define COMANCHE_TRA_RDLYROW 0x0e00
|
||||
#define COMANCHE_TRA_RDLYCOL 0x7000
|
||||
#define COMANCHE_TRA_RSVD 0x8000
|
||||
|
||||
/*
|
||||
* 21071-CA Memory banks' Timing Register B format
|
||||
*/
|
||||
#define COMANCHE_B0_TRB (COMANCHE_BASE + 0x0e00) /* Bank 0 Timing B */
|
||||
#define COMANCHE_B1_TRB (COMANCHE_BASE + 0x0e20) /* Bank 1 Timing B */
|
||||
#define COMANCHE_B2_TRB (COMANCHE_BASE + 0x0e40) /* Bank 2 Timing B */
|
||||
#define COMANCHE_B3_TRB (COMANCHE_BASE + 0x0e60) /* Bank 3 Timing B */
|
||||
#define COMANCHE_B4_TRB (COMANCHE_BASE + 0x0e80) /* Bank 4 Timing B */
|
||||
#define COMANCHE_B5_TRB (COMANCHE_BASE + 0x0ea0) /* Bank 5 Timing B */
|
||||
#define COMANCHE_B6_TRB (COMANCHE_BASE + 0x0ec0) /* Bank 6 Timing B */
|
||||
#define COMANCHE_B7_TRB (COMANCHE_BASE + 0x0ee0) /* Bank 7 Timing B */
|
||||
#define COMANCHE_B8_TRB (COMANCHE_BASE + 0x0f00) /* Bank 8 Timing B */
|
||||
#define COMANCHE_TRB_RTCAS 0x0007
|
||||
#define COMANCHE_TRB_WTCAS 0x0038
|
||||
#define COMANCHE_TRB_TCP 0x00c0
|
||||
#define COMANCHE_TRB_WHOLD0ROW 0x0700
|
||||
#define COMANCHE_TRB_WHOLD0COL 0x3800
|
||||
#define COMANCHE_TRB_RSVD 0xc000
|
||||
|
||||
|
||||
/*
|
||||
* 21071-DA Registers
|
||||
*/
|
||||
#define EPIC_DCSR (EPIC_BASE + 0x0000) /* Diagnostic CSR */
|
||||
#define EPIC_DCSR_TENB 0x00000001
|
||||
#define EPIC_DCSR_RSVD 0x7fc00082
|
||||
#define EPIC_DCSR_PENB 0x00000004
|
||||
#define EPIC_DCSR_DCEI 0x00000008
|
||||
#define EPIC_DCSR_DPEC 0x00000010
|
||||
#define EPIC_DCSR_IORT 0x00000020
|
||||
#define EPIC_DCSR_LOST 0x00000040
|
||||
#define EPIC_DCSR_DDPE 0x00000100
|
||||
#define EPIC_DCSR_IOPE 0x00000200
|
||||
#define EPIC_DCSR_TABT 0x00000400
|
||||
#define EPIC_DCSR_NDEV 0x00000800
|
||||
#define EPIC_DCSR_CMRD 0x00001000
|
||||
#define EPIC_DCSR_UMRD 0x00002000
|
||||
#define EPIC_DCSR_IPTL 0x00004000
|
||||
#define EPIC_DCSR_MERR 0x00008000
|
||||
#define EPIC_DCSR_DBYP 0x00030000
|
||||
#define EPIC_DCSR_PCMD 0x003c0000
|
||||
#define EPIC_DCSR_PASS2 0x80000000
|
||||
|
||||
#define EPIC_PEAR (EPIC_BASE + 0x0020) /* PCI Err Addr. */
|
||||
|
||||
#define EPIC_SEAR (EPIC_BASE + 0x0040) /* sysBus Err Addr. */
|
||||
#define EPIC_SEAR_RSVD 0x0000000f
|
||||
#define EPIC_SEAR_SYS_ERR 0xfffffff0
|
||||
|
||||
#define EPIC_DUMMY_1 (EPIC_BASE + 0x0060) /* Dummy 1 */
|
||||
#define EPIC_DUMMY_2 (EPIC_BASE + 0x0080) /* Dummy 2 */
|
||||
#define EPIC_DUMMY_3 (EPIC_BASE + 0x00a0) /* Dummy 3 */
|
||||
|
||||
#define EPIC_TBASE_1 (EPIC_BASE + 0x00c0) /* Trans. Base 1 */
|
||||
#define EPIC_TBASE_2 (EPIC_BASE + 0x00e0) /* Trans. Base 2 */
|
||||
#define EPIC_TBASE_RSVD 0x000001ff
|
||||
#define EPIC_TBASE_T_BASE 0xfffffe00
|
||||
|
||||
#define EPIC_PCI_BASE_1 (EPIC_BASE + 0x0100) /* PCI Base 1 */
|
||||
#define EPIC_PCI_BASE_2 (EPIC_BASE + 0x0120) /* PCI Base 2 */
|
||||
#define EPIC_PCI_BASE_RSVD 0x0003ffff
|
||||
#define EPIC_PCI_BASE_SGEN 0x00040000
|
||||
#define EPIC_PCI_BASE_WENB 0x00080000
|
||||
#define EPIC_PCI_BASE_PCI_BASE 0xfff00000
|
||||
|
||||
#define EPIC_PCI_MASK_1 (EPIC_BASE + 0x0140) /* PCI Mask 1 */
|
||||
#define EPIC_PCI_MASK_2 (EPIC_BASE + 0x0160) /* PCI Maxk 2 */
|
||||
#define EPIC_PCI_MASK_RSVD 0x000fffff
|
||||
#define EPIC_PCI_MASK_PCI_MASK 0xfff00000
|
||||
|
||||
#define EPIC_HAXR0 (EPIC_BASE + 0x0180) /* Host Addr Extn 0 */
|
||||
|
||||
#define EPIC_HAXR1 (EPIC_BASE + 0x01a0) /* Host Addr Extn 1 */
|
||||
#define EPIC_HAXR1_RSVD 0x07ffffff
|
||||
#define EPIC_HAXR1_EADDR 0xf8000000
|
||||
|
||||
#define EPIC_HAXR2 (EPIC_BASE + 0x01c0) /* Host Addr Extn 2 */
|
||||
#define EPIC_HAXR2_CONF_ADDR 0x00000003
|
||||
#define EPIC_HAXR2_RSVD 0x00fffffc
|
||||
#define EPIC_HAXR2_EADDR 0xff000000
|
||||
|
||||
#define EPIC_PMLT (EPIC_BASE + 0x01e0) /* PCI Mstr Lat Tmr */
|
||||
#define EPIC_PMLT_PMLC 0x000000ff
|
||||
#define EPIC_PMLT_RSVD 0xffffff00
|
||||
|
||||
#define EPIC_TLB_TAG_0 (EPIC_BASE + 0x0200) /* TLB Tag 0 */
|
||||
#define EPIC_TLB_TAG_1 (EPIC_BASE + 0x0220) /* TLB Tag 1 */
|
||||
#define EPIC_TLB_TAG_2 (EPIC_BASE + 0x0240) /* TLB Tag 2 */
|
||||
#define EPIC_TLB_TAG_3 (EPIC_BASE + 0x0260) /* TLB Tag 3 */
|
||||
#define EPIC_TLB_TAG_4 (EPIC_BASE + 0x0280) /* TLB Tag 4 */
|
||||
#define EPIC_TLB_TAG_5 (EPIC_BASE + 0x02a0) /* TLB Tag 5 */
|
||||
#define EPIC_TLB_TAG_6 (EPIC_BASE + 0x02c0) /* TLB Tag 6 */
|
||||
#define EPIC_TLB_TAG_7 (EPIC_BASE + 0x02e0) /* TLB Tag 7 */
|
||||
#define EPIC_TLB_TAG_RSVD 0x00000fff
|
||||
#define EPIC_TLB_TAG_EVAL 0x00001000
|
||||
#define EPIC_TLB_TAG_PCI_PAGE 0xffffe000
|
||||
|
||||
#define EPIC_TLB_DATA_0 (EPIC_BASE + 0x0300) /* TLB Data 0 */
|
||||
#define EPIC_TLB_DATA_1 (EPIC_BASE + 0x0320) /* TLB Data 1 */
|
||||
#define EPIC_TLB_DATA_2 (EPIC_BASE + 0x0340) /* TLB Data 2 */
|
||||
#define EPIC_TLB_DATA_3 (EPIC_BASE + 0x0360) /* TLB Data 3 */
|
||||
#define EPIC_TLB_DATA_4 (EPIC_BASE + 0x0380) /* TLB Data 4 */
|
||||
#define EPIC_TLB_DATA_5 (EPIC_BASE + 0x03a0) /* TLB Data 5 */
|
||||
#define EPIC_TLB_DATA_6 (EPIC_BASE + 0x03c0) /* TLB Data 6 */
|
||||
#define EPIC_TLB_DATA_7 (EPIC_BASE + 0x03e0) /* TLB Data 7 */
|
||||
#define EPIC_TLB_DATA_RSVD 0xffe00001
|
||||
#define EPIC_TLB_DATA_CPU_PAGE 0x001ffffe
|
||||
|
||||
#define EPIC_TBIA (EPIC_BASE + 0x0400) /* TLB Invl All */
|
||||
|
||||
/*
|
||||
* EPIC Scatter-Gather Map Entries
|
||||
*/
|
||||
|
||||
struct sgmapent {
|
||||
u_int64_t val;
|
||||
};
|
||||
#define SGMAPENT_EVAL 0x0000000000000001L
|
||||
#define SGMAPENT_PFN 0x00000000001ffffeL
|
||||
#define SGMAPENT_RSVD 0xffffffffffe00000L
|
||||
|
||||
#define SGMAP_MAKEENTRY(pfn) (SGMAPENT_EVAL | ((pfn) << 1))
|
|
@ -0,0 +1,189 @@
|
|||
/* $NetBSD: pci_2100_a50.c,v 1.1 1995/06/28 01:25:43 cgd 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/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <dev/isa/isavar.h>
|
||||
#include <alpha/isa/isa_intr.h>
|
||||
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <alpha/pci/pci_chipset.h>
|
||||
|
||||
void pci_2100_a50_attach __P((struct device *, struct device *, void *));
|
||||
void *pci_2100_a50_map_int __P((pcitag_t, pci_intrlevel, int (*) (void *),
|
||||
void *, int));
|
||||
|
||||
struct pci_cfg_fcns pci_2100_a50_sio1_cfg_fcns = { /* XXX diff? */
|
||||
pci_2100_a50_attach, pci_2100_a50_map_int,
|
||||
};
|
||||
|
||||
struct pci_cfg_fcns pci_2100_a50_sio2_cfg_fcns = {
|
||||
pci_2100_a50_attach, pci_2100_a50_map_int,
|
||||
};
|
||||
|
||||
void
|
||||
pci_2100_a50_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
int bus, device;
|
||||
|
||||
#if 0
|
||||
for (bus = 0; bus <= 255; bus++)
|
||||
#else
|
||||
/*
|
||||
* XXX
|
||||
* Some current chipsets do wacky things with bus numbers > 0.
|
||||
* This seems like a violation of protocol, but the PCI BIOS does
|
||||
* allow one to query the maximum bus number, and eventually we
|
||||
* should do so.
|
||||
*/
|
||||
for (bus = 0; bus <= 0; bus++)
|
||||
#endif
|
||||
for (device = 0; device <= 31; device++)
|
||||
pci_attach_subdev(self, bus, device);
|
||||
}
|
||||
|
||||
void *
|
||||
pci_2100_a50_map_int(tag, level, func, arg, pin)
|
||||
pcitag_t tag;
|
||||
pci_intrlevel level;
|
||||
int (*func) __P((void *));
|
||||
void *arg;
|
||||
int pin;
|
||||
{
|
||||
int bus, device, pirq;
|
||||
pcireg_t pirqreg;
|
||||
u_int8_t line;
|
||||
|
||||
bus = (tag >> 21) & 0xff; /* XXX */
|
||||
device = (tag >> 16) & 0x1f;
|
||||
|
||||
if (bus != 0) /* XXX */
|
||||
return NULL;
|
||||
|
||||
switch (device) {
|
||||
case 6: /* NCR SCSI */
|
||||
pirq = 3;
|
||||
break;
|
||||
|
||||
case 11: /* slot 1 */
|
||||
switch (pin) {
|
||||
case PCI_INTERRUPT_PIN_A:
|
||||
case PCI_INTERRUPT_PIN_D:
|
||||
pirq = 0;
|
||||
break;
|
||||
case PCI_INTERRUPT_PIN_B:
|
||||
pirq = 2;
|
||||
break;
|
||||
case PCI_INTERRUPT_PIN_C:
|
||||
pirq = 1;
|
||||
break;
|
||||
};
|
||||
break;
|
||||
|
||||
case 12: /* slot 2 */
|
||||
switch (pin) {
|
||||
case PCI_INTERRUPT_PIN_A:
|
||||
case PCI_INTERRUPT_PIN_D:
|
||||
pirq = 1;
|
||||
break;
|
||||
case PCI_INTERRUPT_PIN_B:
|
||||
pirq = 0;
|
||||
break;
|
||||
case PCI_INTERRUPT_PIN_C:
|
||||
pirq = 2;
|
||||
break;
|
||||
};
|
||||
break;
|
||||
|
||||
case 13: /* slot 3 */
|
||||
switch (pin) {
|
||||
case PCI_INTERRUPT_PIN_A:
|
||||
case PCI_INTERRUPT_PIN_D:
|
||||
pirq = 2;
|
||||
break;
|
||||
case PCI_INTERRUPT_PIN_B:
|
||||
pirq = 1;
|
||||
break;
|
||||
case PCI_INTERRUPT_PIN_C:
|
||||
pirq = 0;
|
||||
break;
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
pirqreg = pci_conf_read(pci_make_tag(0, 7, 0), 0x60); /* XXX */
|
||||
#if 0
|
||||
printf("pci_2100_a50_map_int: device %d pin %c: pirq %d, reg = %x\n",
|
||||
device, '@' + pin, pirq, pirqreg);
|
||||
#endif
|
||||
line = (pirqreg >> (pirq * 8)) & 0xff;
|
||||
if ((line & 0x80) != 0)
|
||||
return 0; /* not routed? */
|
||||
line &= 0xf;
|
||||
|
||||
#if 0
|
||||
printf("pci_2100_a50_map_int: device %d pin %c: mapped to line %d\n",
|
||||
device, '@' + pin, line);
|
||||
#endif
|
||||
|
||||
return isa_intr_establish(line, ISA_IST_LEVEL, pcilevel_to_isa(level),
|
||||
func, arg);
|
||||
}
|
||||
|
||||
void
|
||||
pci_2100_a50_pickintr()
|
||||
{
|
||||
pcireg_t sioclass;
|
||||
int sioII;
|
||||
|
||||
/* XXX MAGIC NUMBER */
|
||||
sioclass = pci_conf_read(pci_make_tag(0, 7, 0), PCI_CLASS_REG);
|
||||
sioII = (sioclass & 0xff) >= 3;
|
||||
if (!sioII)
|
||||
printf("WARNING: SIO NOT SIO II... NO BETS...\n");
|
||||
|
||||
if (!sioII)
|
||||
pci_cfg_fcns = &pci_2100_a50_sio1_cfg_fcns;
|
||||
else
|
||||
pci_cfg_fcns = &pci_2100_a50_sio2_cfg_fcns;
|
||||
|
||||
isa_intr_fcns = &sio_intr_fcns;
|
||||
(*isa_intr_fcns->isa_intr_setup)();
|
||||
set_iointr(isa_intr_fcns->isa_iointr);
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/* $NetBSD: pci_chipset.h,v 1.1 1995/06/28 01:25:50 cgd 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Function switch to implement the various PCI bus interfaces.
|
||||
* XXX this probably needs some work...
|
||||
*/
|
||||
|
||||
struct pci_cs_fcns {
|
||||
void (*cs_setup) __P((void));
|
||||
pcitag_t (*cs_make_tag) __P((int, int, int));
|
||||
pcireg_t (*cs_conf_read) __P((pcitag_t, int));
|
||||
void (*cs_conf_write) __P((pcitag_t, int, pcireg_t));
|
||||
int (*cs_map_mem) __P((pcitag_t, int, vm_offset_t *,
|
||||
vm_offset_t *));
|
||||
int (*cs_pcidma_map) __P((caddr_t, vm_size_t,
|
||||
vm_offset_t *));
|
||||
void (*cs_pcidma_unmap) __P((caddr_t, vm_size_t, int,
|
||||
vm_offset_t *));
|
||||
};
|
||||
|
||||
struct pci_cs_fcns *pci_cs_fcns;
|
||||
extern struct pci_cs_fcns apecs_p1e_cs_fcns;
|
||||
extern struct pci_cs_fcns apecs_p2e_cs_fcns;
|
||||
extern struct pci_cs_fcns lca_cs_fcns;
|
||||
|
||||
|
||||
/*
|
||||
* Function switch to implement the various PCI configuration schemes.
|
||||
* XXX this probably needs some work...
|
||||
*/
|
||||
|
||||
struct pci_cfg_fcns {
|
||||
void (*cfg_attach) __P((struct device *, struct
|
||||
device *, void *));
|
||||
void *(*cfg_map_int) __P((pcitag_t, pci_intrlevel,
|
||||
int (*) (void *), void *, int));
|
||||
};
|
||||
|
||||
struct pci_cfg_fcns *pci_cfg_fcns;
|
||||
extern struct pci_cfg_fcns pci_2100_a50_sio1_cfg_fcns;
|
||||
extern struct pci_cfg_fcns pci_2100_a50_sio2_cfg_fcns;
|
||||
|
||||
/*
|
||||
* Miscellaneous functions.
|
||||
*/
|
||||
isa_intrlevel pcilevel_to_isa __P((pci_intrlevel));
|
|
@ -0,0 +1,200 @@
|
|||
/* $NetBSD: pci_machdep.c,v 1.1 1995/06/28 01:25:56 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Charles Hannum. All rights reserved.
|
||||
*
|
||||
* 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 by Charles Hannum.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Machine-specific functions for PCI autoconfiguration.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
#include <dev/isa/isavar.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <alpha/pci/pci_chipset.h>
|
||||
|
||||
int pcimatch __P((struct device *, void *, void *));
|
||||
void pciattach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct cfdriver pcicd = {
|
||||
NULL, "pci", pcimatch, pciattach, DV_DULL, sizeof(struct device)
|
||||
};
|
||||
|
||||
int
|
||||
pcimatch(parent, match, aux)
|
||||
struct device *parent;
|
||||
void *match, *aux;
|
||||
{
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
pciattach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
|
||||
printf("\n");
|
||||
(*pci_cs_fcns->cs_setup)();
|
||||
(*pci_cfg_fcns->cfg_attach)(parent, self, aux);
|
||||
}
|
||||
|
||||
pcitag_t
|
||||
pci_make_tag(bus, device, function)
|
||||
int bus, device, function;
|
||||
{
|
||||
|
||||
return (*pci_cs_fcns->cs_make_tag)(bus, device, function);
|
||||
}
|
||||
|
||||
pcireg_t
|
||||
pci_conf_read(tag, offset)
|
||||
pcitag_t tag;
|
||||
int offset; /* XXX */
|
||||
{
|
||||
|
||||
return (*pci_cs_fcns->cs_conf_read)(tag, offset);
|
||||
}
|
||||
|
||||
void
|
||||
pci_conf_write(tag, offset, data)
|
||||
pcitag_t tag;
|
||||
int offset; /* XXX */
|
||||
pcireg_t data;
|
||||
{
|
||||
|
||||
(*pci_cs_fcns->cs_conf_write)(tag, offset, data);
|
||||
}
|
||||
|
||||
int
|
||||
pci_map_io(tag, reg, iobasep)
|
||||
pcitag_t tag;
|
||||
int reg;
|
||||
int *iobasep;
|
||||
{
|
||||
|
||||
/*
|
||||
* XXX should be a chipset-dependent function, but...
|
||||
* what would it do, and what would use it?
|
||||
*/
|
||||
panic("pci_map_io: not implemented");
|
||||
}
|
||||
|
||||
int
|
||||
pci_map_mem(tag, reg, vap, pap)
|
||||
pcitag_t tag;
|
||||
int reg;
|
||||
vm_offset_t *vap, *pap;
|
||||
{
|
||||
|
||||
return (*pci_cs_fcns->cs_map_mem)(tag, reg, vap, pap);
|
||||
}
|
||||
|
||||
int
|
||||
pcidma_map(addr, size, mappings)
|
||||
caddr_t addr;
|
||||
vm_size_t size;
|
||||
vm_offset_t *mappings;
|
||||
{
|
||||
|
||||
return (*pci_cs_fcns->cs_pcidma_map)(addr, size, mappings);
|
||||
}
|
||||
|
||||
void
|
||||
pcidma_unmap(addr, size, nmappings, mappings)
|
||||
caddr_t addr;
|
||||
vm_size_t size;
|
||||
int nmappings;
|
||||
vm_offset_t *mappings;
|
||||
{
|
||||
|
||||
(*pci_cs_fcns->cs_pcidma_unmap)(addr, size, nmappings, mappings);
|
||||
}
|
||||
|
||||
void *
|
||||
pci_map_int(tag, level, func, arg)
|
||||
pcitag_t tag;
|
||||
pci_intrlevel level;
|
||||
int (*func) __P((void *));
|
||||
void *arg;
|
||||
{
|
||||
pcireg_t data;
|
||||
int pin;
|
||||
|
||||
data = pci_conf_read(tag, PCI_INTERRUPT_REG);
|
||||
|
||||
pin = PCI_INTERRUPT_PIN(data);
|
||||
|
||||
if (pin == 0) {
|
||||
/* No IRQ used. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pin > 4) {
|
||||
printf("pci_map_int: bad interrupt pin %d\n", pin);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (*pci_cfg_fcns->cfg_map_int)(tag, level, func, arg, pin);
|
||||
}
|
||||
|
||||
isa_intrlevel
|
||||
pcilevel_to_isa(level)
|
||||
pci_intrlevel level;
|
||||
{
|
||||
|
||||
switch (level) {
|
||||
case PCI_IPL_NONE:
|
||||
return (ISA_IPL_NONE);
|
||||
|
||||
case PCI_IPL_BIO:
|
||||
return (ISA_IPL_BIO);
|
||||
|
||||
case PCI_IPL_NET:
|
||||
return (ISA_IPL_NET);
|
||||
|
||||
case PCI_IPL_TTY:
|
||||
return (ISA_IPL_TTY);
|
||||
|
||||
case PCI_IPL_CLOCK:
|
||||
return (ISA_IPL_CLOCK);
|
||||
|
||||
default:
|
||||
panic("pcilevel_to_isa: unknown level %d\n", level);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* $NetBSD: pci_machdep.h,v 1.1 1995/06/28 01:26:01 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1994 Charles Hannum. All rights reserved.
|
||||
*
|
||||
* 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 by Charles Hannum.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Machine-specific definitions for PCI autoconfiguration.
|
||||
*
|
||||
* See the comments in pci_machdep.c for more explanation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Configuration tag; created from a {bus,device,function} triplet by
|
||||
* pci_make_tag(), and passed to pci_conf_read() and pci_conf_write().
|
||||
* We could instead always pass the {bus,device,function} triplet to
|
||||
* the read and write routines, but this would cause extra overhead.
|
||||
*/
|
||||
typedef u_long pcitag_t;
|
||||
|
||||
/*
|
||||
* Type of a value read from or written to a configuration register.
|
||||
* Always 32 bits.
|
||||
*/
|
||||
typedef u_int32_t pcireg_t;
|
||||
|
||||
extern int pci_mode;
|
||||
extern int pci_mode_detect __P((void));
|
|
@ -0,0 +1,107 @@
|
|||
/* $NetBSD: sio.c,v 1.1 1995/06/28 01:26:07 cgd 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/kernel.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcidevs.h>
|
||||
|
||||
#include <machine/autoconf.h>
|
||||
|
||||
int siomatch __P((struct device *, void *, void *));
|
||||
void sioattach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct cfdriver siocd = {
|
||||
NULL, "sio", siomatch, sioattach, DV_DULL, sizeof(struct device)
|
||||
};
|
||||
|
||||
static int sioprint __P((void *, char *pnp));
|
||||
|
||||
int
|
||||
siomatch(parent, match, aux)
|
||||
struct device *parent;
|
||||
void *match, *aux;
|
||||
{
|
||||
struct cfdata *cf = match;
|
||||
struct pci_attach_args *pa = aux;
|
||||
|
||||
if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL ||
|
||||
PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_SIO)
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
sioattach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct pci_attach_args *pa = aux;
|
||||
struct confargs nca;
|
||||
u_int rev;
|
||||
char *type;
|
||||
|
||||
rev = pa->pa_class & 0xff;
|
||||
if (rev < 3) {
|
||||
type = "I";
|
||||
/* XXX PCI IRQ MAPPING FUNCTION */
|
||||
} else {
|
||||
type = "II";
|
||||
/* XXX PCI IRQ MAPPING FUNCTION */
|
||||
}
|
||||
printf(": Saturn %s PCI->ISA bridge (revision 0x%x)\n", type, rev);
|
||||
if (rev < 3)
|
||||
printf("%s: WARNING: SIO I SUPPORT UNTESTED\n",
|
||||
parent->dv_xname);
|
||||
|
||||
/* attach the ISA bus that hangs off of it... */
|
||||
nca.ca_name = "isa";
|
||||
nca.ca_slot = 0;
|
||||
nca.ca_offset = 0;
|
||||
nca.ca_bus = NULL;
|
||||
if (!config_found(self, &nca, sioprint))
|
||||
panic("sioattach: couldn't attach ISA bus");
|
||||
}
|
||||
|
||||
static int
|
||||
sioprint(aux, pnp)
|
||||
void *aux;
|
||||
char *pnp;
|
||||
{
|
||||
register struct confargs *ca = aux;
|
||||
|
||||
if (pnp)
|
||||
printf("%s at %s", ca->ca_name, pnp);
|
||||
return (UNCONF);
|
||||
}
|
|
@ -0,0 +1,378 @@
|
|||
/* $NetBSD: sio_pic.c,v 1.1 1995/06/28 01:26:13 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 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 <sys/malloc.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include <dev/isa/isavar.h>
|
||||
#include <dev/isa/isareg.h>
|
||||
#include <alpha/isa/isa_intr.h>
|
||||
|
||||
#include <machine/pio.h>
|
||||
|
||||
/*
|
||||
* To add to the long history of wonderful PROM console traits,
|
||||
* AlphaStation PROMs don't reset themselves completely on boot!
|
||||
* Therefore, if an interrupt was turned on when the kernel was
|
||||
* started, we're not going to EVER turn it off... I don't know
|
||||
* what will happen if new interrupts (that the PROM console doesn't
|
||||
* want) are turned on. I'll burn that bridge when I come to it.
|
||||
*/
|
||||
#define BROKEN_PROM_CONSOLE
|
||||
|
||||
static void sio_intr_setup __P((void));
|
||||
static void *sio_intr_establish __P((int intr, isa_intrtype type,
|
||||
isa_intrlevel level, int (*ih_fun)(void *), void *ih_arg));
|
||||
static void sio_intr_disestablish __P((void *handler));
|
||||
static void sio_iointr __P((void *framep, int vec));
|
||||
|
||||
struct isa_intr_fcns sio_intr_fcns = {
|
||||
sio_intr_setup, sio_intr_establish,
|
||||
sio_intr_disestablish, sio_iointr,
|
||||
};
|
||||
|
||||
static void sio_strayintr __P((int irq));
|
||||
|
||||
/*
|
||||
* Interrupt handler chains. sio_intr_establish() inserts a handler into
|
||||
* the list. The handler is called with its (single) argument.
|
||||
*/
|
||||
struct intrhand {
|
||||
int (*ih_fun)();
|
||||
void *ih_arg;
|
||||
u_long ih_count;
|
||||
struct intrhand *ih_next;
|
||||
int ih_level;
|
||||
int ih_irq;
|
||||
};
|
||||
|
||||
#define ICU_LEN 16 /* number of ISA IRQs */
|
||||
|
||||
static struct intrhand *sio_intrhand[ICU_LEN];
|
||||
static isa_intrtype sio_intrtype[ICU_LEN];
|
||||
static u_long sio_strayintrcnt[ICU_LEN];
|
||||
|
||||
#ifndef STRAY_MAX
|
||||
#ifdef BROKEN_PROM_CONSOLE
|
||||
/*
|
||||
* If prom console is broken, because initial interrupt settings
|
||||
* must be kept, there's no way to escape stray interrupts.
|
||||
*/
|
||||
#define STRAY_MAX 0
|
||||
#else
|
||||
#define STRAY_MAX 5
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BROKEN_PROM_CONSOLE
|
||||
/*
|
||||
* If prom console is broken, must remember the initial interrupt
|
||||
* settings and enforce them. WHEE!
|
||||
*/
|
||||
u_int8_t initial_ocw1[2];
|
||||
u_int8_t initial_elcr[2];
|
||||
#define INITIALLY_ENABLED(irq) \
|
||||
((initial_ocw1[(irq) / 8] & (1 << ((irq) % 8))) == 0)
|
||||
#define INITIALLY_LEVEL_TRIGGERED(irq) \
|
||||
((initial_elcr[(irq) / 8] & (1 << ((irq) % 8))) != 0)
|
||||
#else
|
||||
#define INITIALLY_ENABLED(irq) ((irq) == 2 ? 1 : 0)
|
||||
#define INITIALLY_LEVEL_TRIGGERED(irq) 0
|
||||
#endif
|
||||
|
||||
void
|
||||
sio_setirqstat(irq, enabled, type)
|
||||
int irq, enabled;
|
||||
isa_intrtype type;
|
||||
{
|
||||
u_int8_t ocw1[2], elcr[2];
|
||||
int icu, bit;
|
||||
|
||||
#if 0
|
||||
printf("sio_setirqstat: irq %d, %s, %s\n", irq,
|
||||
enabled ? "enabled" : "disabled", isa_intr_typename(type));
|
||||
#endif
|
||||
|
||||
sio_intrtype[irq] = type;
|
||||
|
||||
icu = irq / 8;
|
||||
bit = irq % 8;
|
||||
|
||||
ocw1[0] = inb(IO_ICU1 + 1);
|
||||
ocw1[1] = inb(IO_ICU2 + 1);
|
||||
elcr[0] = inb(0x4d0); /* XXX */
|
||||
elcr[1] = inb(0x4d1); /* XXX */
|
||||
|
||||
/*
|
||||
* interrupt enable: set bit to mask (disable) interrupt.
|
||||
*/
|
||||
if (enabled)
|
||||
ocw1[icu] &= ~(1 << bit);
|
||||
else
|
||||
ocw1[icu] |= 1 << bit;
|
||||
|
||||
/*
|
||||
* interrupt type select: set bit to get level-triggered.
|
||||
*/
|
||||
if (type == ISA_IST_LEVEL)
|
||||
elcr[icu] |= 1 << bit;
|
||||
else
|
||||
elcr[icu] &= ~(1 << bit);
|
||||
|
||||
#ifdef not_here
|
||||
/* see the init function... */
|
||||
ocw1[0] &= ~0x04; /* always enable IRQ2 on first PIC */
|
||||
elcr[0] &= ~0x07; /* IRQ[0-2] must be edge-triggered */
|
||||
elcr[1] &= ~0x21; /* IRQ[13,8] must be edge-triggered */
|
||||
#endif
|
||||
|
||||
#ifdef BROKEN_PROM_CONSOLE
|
||||
/*
|
||||
* make sure that the initially clear bits (unmasked interrupts)
|
||||
* are never set, and that the initially-level-triggered
|
||||
* intrrupts always remain level-triggered, to keep the prom happy.
|
||||
*/
|
||||
if ((ocw1[0] & ~initial_ocw1[0]) != 0 ||
|
||||
(ocw1[1] & ~initial_ocw1[1]) != 0 ||
|
||||
(elcr[0] & initial_elcr[0]) != initial_elcr[0] ||
|
||||
(elcr[1] & initial_elcr[1]) != initial_elcr[1]) {
|
||||
printf("sio_sis: initial: ocw = (%2x,%2x), elcr = (%2x,%2X)\n",
|
||||
initial_ocw1[0], initial_ocw1[1],
|
||||
initial_elcr[0], initial_elcr[1]);
|
||||
printf(" current: ocw = (%2x,%2x), elcr = (%2x,%2X)\n",
|
||||
ocw1[0], ocw1[1], elcr[0], elcr[1]);
|
||||
panic("sio_setirqstat: hosed");
|
||||
}
|
||||
#endif
|
||||
|
||||
outb(IO_ICU1 + 1, ocw1[0]);
|
||||
outb(IO_ICU2 + 1, ocw1[1]);
|
||||
outb(0x4d0, elcr[0]); /* XXX */
|
||||
outb(0x4d1, elcr[1]); /* XXX */
|
||||
}
|
||||
|
||||
void
|
||||
sio_intr_setup()
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef BROKEN_PROM_CONSOLE
|
||||
/*
|
||||
* Remember the initial values, because the prom is stupid.
|
||||
*/
|
||||
initial_ocw1[0] = inb(IO_ICU1 + 1);
|
||||
initial_ocw1[1] = inb(IO_ICU2 + 1);
|
||||
initial_elcr[0] = inb(0x4d0); /* XXX */
|
||||
initial_elcr[1] = inb(0x4d1); /* XXX */
|
||||
#if 0
|
||||
printf("initial_ocw1[0] = 0x%x\n", initial_ocw1[0]);
|
||||
printf("initial_ocw1[1] = 0x%x\n", initial_ocw1[1]);
|
||||
printf("initial_elcr[0] = 0x%x\n", initial_elcr[0]);
|
||||
printf("initial_elcr[1] = 0x%x\n", initial_elcr[1]);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* set up initial values for interrupt enables.
|
||||
*/
|
||||
for (i = 0; i < ICU_LEN; i++) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 8:
|
||||
case 13:
|
||||
/*
|
||||
* IRQs 0, 1, 8, and 13 must always be
|
||||
* edge-triggered.
|
||||
*/
|
||||
if (INITIALLY_LEVEL_TRIGGERED(i))
|
||||
printf("sio_intr_setup: %d LT!\n", i);
|
||||
sio_setirqstat(i, INITIALLY_ENABLED(i), ISA_IST_EDGE);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/*
|
||||
* IRQ 2 must be edge-triggered, and should be
|
||||
* enabled (otherwise IRQs 8-15 are ignored).
|
||||
*/
|
||||
if (INITIALLY_LEVEL_TRIGGERED(i))
|
||||
printf("sio_intr_setup: %d LT!\n", i);
|
||||
if (!INITIALLY_ENABLED(i))
|
||||
printf("sio_intr_setup: %d not enabled!\n", i);
|
||||
sio_setirqstat(i, 1, ISA_IST_EDGE);
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* Otherwise, disable the IRQ and set its
|
||||
* type to (effectively) "unknown."
|
||||
*/
|
||||
sio_setirqstat(i, INITIALLY_ENABLED(i),
|
||||
INITIALLY_LEVEL_TRIGGERED(i) ? ISA_IST_LEVEL :
|
||||
ISA_IST_NONE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
sio_intr_establish(irq, type, level, ih_fun, ih_arg)
|
||||
int irq;
|
||||
isa_intrtype type;
|
||||
isa_intrlevel level;
|
||||
int (*ih_fun)(void *);
|
||||
void *ih_arg;
|
||||
{
|
||||
struct intrhand **p, *c, *ih;
|
||||
extern int cold;
|
||||
|
||||
/* no point in sleeping unless someone can free memory. */
|
||||
ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
|
||||
if (ih == NULL)
|
||||
panic("sio_intr_establish: can't malloc handler info");
|
||||
|
||||
if (irq < 0 || irq > ICU_LEN || type == ISA_IST_NONE)
|
||||
panic("sio_intr_establish: bogus irq or type");
|
||||
|
||||
switch (sio_intrtype[irq]) {
|
||||
case ISA_IST_EDGE:
|
||||
case ISA_IST_LEVEL:
|
||||
if (type == sio_intrtype[irq])
|
||||
break;
|
||||
case ISA_IST_PULSE:
|
||||
if (type != ISA_IST_NONE)
|
||||
panic("intr_establish: can't share %s with %s",
|
||||
isa_intr_typename(sio_intrtype[irq]),
|
||||
isa_intr_typename(type));
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out where to put the handler.
|
||||
* This is O(N^2), but we want to preserve the order, and N is
|
||||
* generally small.
|
||||
*/
|
||||
for (p = &sio_intrhand[irq]; (c = *p) != NULL; p = &c->ih_next)
|
||||
;
|
||||
|
||||
/*
|
||||
* Poke the real handler in now.
|
||||
*/
|
||||
ih->ih_fun = ih_fun;
|
||||
ih->ih_arg = ih_arg;
|
||||
ih->ih_count = 0;
|
||||
ih->ih_next = NULL;
|
||||
ih->ih_level = 0; /* XXX meaningless on alpha */
|
||||
ih->ih_irq = irq;
|
||||
*p = ih;
|
||||
|
||||
sio_setirqstat(irq, 1, type);
|
||||
|
||||
return ih;
|
||||
}
|
||||
|
||||
void
|
||||
sio_intr_disestablish(handler)
|
||||
void *handler;
|
||||
{
|
||||
|
||||
printf("sio_intr_disestablish(%lx)\n", handler);
|
||||
/* XXX */
|
||||
|
||||
/* XXX NEVER ALLOW AN INITIALLY-ENABLED INTERRUPT TO BE DISABLED */
|
||||
/* XXX NEVER ALLOW AN INITIALLY-LT INTERRUPT TO BECOME UNTYPED */
|
||||
}
|
||||
|
||||
/*
|
||||
* caught a stray interrupt; notify if not too many seen already.
|
||||
*/
|
||||
void
|
||||
sio_strayintr(irq)
|
||||
int irq;
|
||||
{
|
||||
|
||||
if (++sio_strayintrcnt[irq] <= STRAY_MAX)
|
||||
log(LOG_ERR, "stray interrupt %d%s\n", irq,
|
||||
sio_strayintrcnt[irq] >= STRAY_MAX ?
|
||||
"; stopped logging" : "");
|
||||
}
|
||||
|
||||
void
|
||||
sio_iointr(framep, vec)
|
||||
void *framep;
|
||||
int vec;
|
||||
{
|
||||
int irq, handled;
|
||||
struct intrhand *ih;
|
||||
|
||||
irq = (vec - 0x800) >> 4;
|
||||
#ifdef DIAGNOSTIC
|
||||
if (irq > ICU_LEN || irq < 0)
|
||||
panic("sio_iointr: irq out of range (%d)", irq);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We cdr down the intrhand chain, calling each handler with
|
||||
* its appropriate argument;
|
||||
*
|
||||
* The handler returns one of three values:
|
||||
* 0 - This interrupt wasn't for me.
|
||||
* 1 - This interrupt was for me.
|
||||
* -1 - This interrupt might have been for me, but I don't know.
|
||||
* If there are no handlers, or they all return 0, we flags it as a
|
||||
* `stray' interrupt. On a system with level-triggered interrupts,
|
||||
* we could terminate immediately when one of them returns 1; but
|
||||
* this is PC-ish!
|
||||
*/
|
||||
for (ih = sio_intrhand[irq], handled = 0; ih != NULL;
|
||||
ih = ih->ih_next) {
|
||||
int rv;
|
||||
|
||||
rv = (*ih->ih_fun)(ih->ih_arg);
|
||||
|
||||
ih->ih_count++;
|
||||
handled = handled || (rv != 0);
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
sio_strayintr(irq);
|
||||
|
||||
/*
|
||||
* Some versions of the machines which use the SIO
|
||||
* (or is it some PALcode revisions on those machines?)
|
||||
* require the non-specific EOI to be fed to the PIC(s)
|
||||
* by the interrupt handler.
|
||||
*/
|
||||
if (irq > 7)
|
||||
outb(IO_ICU2 + 0, 0x20 | (irq & 0x07)); /* XXX */
|
||||
outb(IO_ICU1 + 0, 0x20 | (irq > 7 ? 2 : irq)); /* XXX */
|
||||
}
|
Loading…
Reference in New Issue