diff options
Diffstat (limited to 'sys/arch/alpha/pci')
34 files changed, 3485 insertions, 1268 deletions
diff --git a/sys/arch/alpha/pci/apecs.c b/sys/arch/alpha/pci/apecs.c index 7648f2cdd7e..76fd9fec019 100644 --- a/sys/arch/alpha/pci/apecs.c +++ b/sys/arch/alpha/pci/apecs.c @@ -1,4 +1,4 @@ -/* $NetBSD: apecs.c,v 1.3 1995/08/03 01:16:47 cgd Exp $ */ +/* $NetBSD: apecs.c,v 1.4 1995/11/23 02:37:11 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -35,37 +35,31 @@ #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> +#include <alpha/pci/apecsvar.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) + NULL, "apecs", apecsmatch, apecsattach, DV_DULL, + sizeof(struct apecs_softc) }; 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]; +/* There can be only one. */ +int apecsfound; +struct apecs_config apecs_configuration; int apecsmatch(parent, match, aux) @@ -73,9 +67,14 @@ apecsmatch(parent, match, aux) void *match, *aux; { struct cfdata *cf = match; - struct confargs *pa = aux; + struct confargs *ca = aux; - /* XXX */ + /* Make sure that we're looking for an APECS. */ + if (strcmp(ca->ca_name, apecscd.cd_name) != 0) + return (0); + + if (apecsfound) + return (0); return (1); } @@ -84,18 +83,36 @@ apecsmatch(parent, match, aux) * Set up the chipset's function pointers. */ void -apecs_init() +apecs_init(acp) + struct apecs_config *acp; { - int pass2_epic; - - pass2_epic = (REGVAL(EPIC_DCSR) & EPIC_DCSR_PASS2) != 0; - 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; + acp->ac_comanche_pass2 = + (REGVAL(COMANCHE_ED) & COMANCHE_ED_PASS2) != 0; + acp->ac_memwidth = + (REGVAL(COMANCHE_GCR) & COMANCHE_GCR_WIDEMEM) != 0 ? 128 : 64; + acp->ac_epic_pass2 = + (REGVAL(EPIC_DCSR) & EPIC_DCSR_PASS2) != 0; + + /* + * Can't set up SGMAP data here; can be called before malloc(). + */ + + acp->ac_conffns = &apecs_conf_fns; + acp->ac_confarg = acp; + acp->ac_dmafns = &apecs_dma_fns; + acp->ac_dmaarg = acp; + /* Interrupt routines set up in 'attach' */ + acp->ac_memfns = &apecs_mem_fns; + acp->ac_memarg = acp; + acp->ac_piofns = &apecs_pio_fns; + acp->ac_pioarg = acp; + + /* Turn off DMA window enables in PCI Base Reg 1. */ + REGVAL(EPIC_PCI_BASE_1) = 0; + wbflush(); + + /* XXX SGMAP? */ } void @@ -104,46 +121,61 @@ apecsattach(parent, self, aux) void *aux; { struct confargs *ca = aux; - struct confargs nca; - int pass2_comanche, widemem, pass2_epic; + struct apecs_softc *sc = (struct apecs_softc *)self; + struct apecs_config *acp; + struct pci_attach_args pa; - 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; + /* note that we've attached the chipset; can't have 2 APECSes. */ + apecsfound = 1; - sgmap = (struct sgmapent *)malloc(1024 * sizeof(struct sgmapent), - M_DEVBUF, M_WAITOK); + /* + * set up the chipset's info; done once at console init time + * (maybe), but doesn't hurt to do twice. + */ + acp = sc->sc_acp = &apecs_configuration; + apecs_init(acp); + + /* XXX SGMAP FOO */ printf(": DECchip %s Core Logic chipset\n", - widemem ? "21072" : "21071"); + acp->ac_memwidth == 128 ? "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); + self->dv_xname, acp->ac_comanche_pass2 ? 2 : 1, acp->ac_memwidth); + printf("%s: DC21071-DA pass %d\n", self->dv_xname, + acp->ac_epic_pass2 ? 2 : 1); /* XXX print bcache size */ - if (!pass2_epic) + if (!acp->ac_epic_pass2) printf("WARNING: 21071-DA NOT PASS2... NO BETS...\n"); - /* set up the chipset's functions */ - apecs_init(); - switch (hwrpb->rpb_type) { #if defined(DEC_2100_A50) case ST_DEC_2100_A50: - pci_2100_a50_pickintr(); + pci_2100_a50_pickintr(acp->ac_conffns, acp->ac_confarg, + acp->ac_piofns, acp->ac_pioarg, + &acp->ac_intrfns, &acp->ac_intrarg); 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"); + pa.pa_bus = 0; + pa.pa_maxdev = 32; + pa.pa_burstlog2 = 8; + + pa.pa_conffns = acp->ac_conffns; + pa.pa_confarg = acp->ac_confarg; + pa.pa_dmafns = acp->ac_dmafns; + pa.pa_dmaarg = acp->ac_dmaarg; + pa.pa_intrfns = acp->ac_intrfns; + pa.pa_intrarg = acp->ac_intrarg; + pa.pa_memfns = acp->ac_memfns; + pa.pa_memarg = acp->ac_memarg; + pa.pa_piofns = acp->ac_piofns; + pa.pa_pioarg = acp->ac_pioarg; + + config_found(self, &pa, apecsprint); } static int @@ -151,121 +183,11 @@ 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; + register struct pci_attach_args *pa = aux; - /* Wake up anybody waiting for map entries. */ - wakeup(&sgmap); + /* only PCIs can attach to APECSes; easy. */ + if (pnp) + printf("pci at %s", pnp); + printf(" bus %d", pa->pa_bus); + return (UNCONF); } diff --git a/sys/arch/alpha/pci/apecs_isa.c b/sys/arch/alpha/pci/apecs_isa.c index d4bdb482f08..1d2729475dc 100644 --- a/sys/arch/alpha/pci/apecs_isa.c +++ b/sys/arch/alpha/pci/apecs_isa.c @@ -1,4 +1,4 @@ -/* $NetBSD: apecs_isa.c,v 1.3 1995/08/03 01:16:53 cgd Exp $ */ +/* $NetBSD: apecs_isa.c,v 1.4 1995/11/23 02:37:13 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -30,65 +30,88 @@ #include <sys/param.h> #include <sys/malloc.h> #include <sys/syslog.h> +#include <sys/device.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 <dev/isa/isavar.h> #include <alpha/pci/apecsreg.h> +#include <alpha/pci/apecsvar.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 */ +/* + * Allocation/deallocation functions. + */ +int apecs_pio_alloc __P((void *, isa_iooffset_t, isa_iosize_t)); +int apecs_pio_dealloc __P((void *, isa_iooffset_t, isa_iosize_t)); -static void apecs_outb __P((int port, u_int8_t datum)); -/* static void apecs_outsb __P((int port, void *addr, int cnt)); */ +/* + * Byte functions. + */ +isa_byte_t apecs_inb __P((void *, isa_iooffset_t)); +#define apecs_insb 0 /* XXX */ +void apecs_outb __P((void *, isa_iooffset_t, isa_byte_t)); #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)); */ + +/* + * Word functions. + */ +isa_word_t apecs_inw __P((void *, isa_iooffset_t)); +#define apecs_insw 0 /* XXX */ +void apecs_outw __P((void *, isa_iooffset_t, isa_word_t)); #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)); */ + +/* + * Longword functions. + */ +isa_long_t apecs_inl __P((void *, isa_iooffset_t)); +#define apecs_insl 0 /* XXX */ +void apecs_outl __P((void *, isa_iooffset_t, isa_long_t)); #define apecs_outsl 0 /* XXX */ -struct isa_pio_fcns apecs_pio_fcns = { +__const struct pci_pio_fns apecs_pio_fns = { + /* Allocation/deallocation functions. */ + apecs_pio_alloc, apecs_pio_dealloc, + + /* Byte functions. */ apecs_inb, apecs_insb, - apecs_inw, apecs_insw, - apecs_inl, apecs_insl, apecs_outb, apecs_outsb, + + /* Word functions. */ + apecs_inw, apecs_insw, apecs_outw, apecs_outsw, + + /* Longword functions. */ + apecs_inl, apecs_insl, 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, -}; +int +apecs_pio_alloc(ipfarg, start, size) + void *ipfarg; + isa_iooffset_t start; + isa_iosize_t size; +{ -u_int8_t -apecs_inb(ioaddr) - int ioaddr; + /* XXX should do something */ +} + +int +apecs_pio_dealloc(ipfarg, start, size) + void *ipfarg; + isa_iooffset_t start; + isa_iosize_t size; +{ + + /* XXX should do something */ +} + +isa_byte_t +apecs_inb(ipfa, ioaddr) + void *ipfa; + isa_iooffset_t ioaddr; { u_int32_t *port, val; - u_int8_t rval; + isa_byte_t rval; int offset; wbflush(); @@ -101,81 +124,86 @@ apecs_inb(ioaddr) return rval; } -u_int16_t -apecs_inw(ioaddr) - int ioaddr; +void +apecs_outb(ipfa, ioaddr, val) + void *ipfa; + isa_iooffset_t ioaddr; + isa_byte_t val; { - u_int32_t *port, val; - u_int16_t rval; + u_int32_t *port, nval; int offset; - wbflush(); 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); + nval = val /*<< (8 * offset)*/; + nval = val << (8 * offset); + port = (int32_t *)phystok0seg(APECS_PCI_SIO | 0 << 3 | ioaddr << 5); - return rval; + *port = nval; + wbflush(); } -u_int32_t -apecs_inl(ioaddr) - int ioaddr; +isa_word_t +apecs_inw(ipfa, ioaddr) + void *ipfa; + isa_iooffset_t ioaddr; { u_int32_t *port, val; - u_int32_t rval; + isa_word_t rval; int offset; wbflush(); offset = ioaddr & 3; - port = (int32_t *)phystok0seg(APECS_PCI_SIO | 3 << 3 | ioaddr << 5); + port = (int32_t *)phystok0seg(APECS_PCI_SIO | 1 << 3 | ioaddr << 5); val = *port; - rval = ((val) >> (8 * offset)) & 0xffffffff; - rval = val & 0xffffffff; + rval = ((val) >> (8 * offset)) & 0xffff; + rval = val & 0xffff; + +panic("inw(0x%x) => 0x%x @ %p => 0x%x\n", ioaddr, val, port, rval); return rval; } void -apecs_outb(ioaddr, val) - int ioaddr; - u_int8_t val; +apecs_outw(ipfa, ioaddr, val) + void *ipfa; + isa_iooffset_t ioaddr; + isa_word_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 = (int32_t *)phystok0seg(APECS_PCI_SIO | 1 << 3 | ioaddr << 5); *port = nval; wbflush(); } -void -apecs_outw(ioaddr, val) - int ioaddr; - u_int16_t val; +isa_long_t +apecs_inl(ipfa, ioaddr) + void *ipfa; + isa_iooffset_t ioaddr; { - u_int32_t *port, nval; + u_int32_t *port, val; + isa_long_t rval; int offset; + wbflush(); offset = ioaddr & 3; - nval = val /*<< (8 * offset)*/; - port = (int32_t *)phystok0seg(APECS_PCI_SIO | 1 << 3 | ioaddr << 5); + port = (int32_t *)phystok0seg(APECS_PCI_SIO | 3 << 3 | ioaddr << 5); + val = *port; + rval = ((val) >> (8 * offset)) & 0xffffffff; + rval = val & 0xffffffff; - *port = nval; - wbflush(); + return rval; } void -apecs_outl(ioaddr, val) - int ioaddr; - u_int32_t val; +apecs_outl(ipfa, ioaddr, val) + void *ipfa; + isa_iooffset_t ioaddr; + isa_long_t val; { u_int32_t *port, nval; int offset; @@ -188,156 +216,131 @@ apecs_outl(ioaddr, val) wbflush(); } -static caddr_t bounced_addr; -static caddr_t bounce_buffer; -static vm_size_t bounce_size; +/* XXX XXX XXX */ + +#define pf(fn, args) fn args { panic(__STRING(fn)); } + +void pf(apecs_dma_cascade, (void *idfa, isa_drq_t chan)) +void pf(apecs_dma_copytobuf, ()) +void pf(apecs_dma_copyfrombuf, ()) +void pf(apecs_dma_start, (void *idfa, vm_offset_t addr, + isa_msize_t size, isa_drq_t chan, int flags)) +void pf(apecs_dma_abort, (void *idfa, isa_drq_t chan)) +void pf(apecs_dma_done, (void *idfa, isa_drq_t chan)) + +int apecs_dma_map __P((void *, vm_offset_t, isa_msize_t, + isa_moffset_t *, int)); +void apecs_dma_unmap __P((void *, vm_offset_t, isa_msize_t, int, + isa_moffset_t *)); + +__const struct isa_dma_fns apecs_dma_fns = { + apecs_dma_cascade, + apecs_dma_map, + apecs_dma_unmap, + apecs_dma_copytobuf, + apecs_dma_copyfrombuf, + apecs_dma_start, + apecs_dma_abort, + apecs_dma_done, +}; int -apecs_isadma_map(addr, size, mappings, flags) - caddr_t addr; - vm_size_t size; - vm_offset_t *mappings; +apecs_dma_map(idfa, va, isasize, mappingsp, flags) + void *idfa; + vm_offset_t va; + isa_msize_t isasize; + isa_moffset_t *mappingsp; 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); + struct apecs_config *acp = idfa; + long todo; + int i; + + if (ISA_DMA_NEEDCONTIG(flags) && isasize > NBPG || + ISA_DMA_SIZEBOUND(flags) != ISA_DMA_SIZEBOUND_NONE || + ISA_DMA_ADDRBOUND(flags) != ISA_DMA_ADDRBOUND_NONE) + panic("apecs_dma_map: punt"); + + i = 0; + todo = isasize; + + while (todo > 0) { + mappingsp[i] = vtophys(va) | 0x40000000; +#if 0 + printf("a_pd_m mapping %d: %lx -> %lx -> %lx\n", i, va, + vtophys(va), mappingsp[i]); +#endif + i++; + todo -= PAGE_SIZE - (va - trunc_page(va)); + va += PAGE_SIZE - (va - trunc_page(va)); } - - 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); + return (i); } void -apecs_isadma_unmap(addr, size, nmappings, mappings) - caddr_t addr; - vm_size_t size; +apecs_dma_unmap(idfa, va, isasize, nmappings, mappingsp) + void *idfa; + vm_offset_t va; + isa_msize_t isasize; int nmappings; - vm_offset_t *mappings; + isa_moffset_t *mappingsp; { - 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); - } + + printf("apecs_dma_unmap: called\n"); } -void -apecs_isadma_copytobuf(addr, size, nmappings, mappings) - caddr_t addr; - vm_size_t size; - int nmappings; - vm_offset_t *mappings; +vm_offset_t apecs_mem_map __P((void *, isa_moffset_t, isa_msize_t, int)); +void apecs_mem_unmap __P((void *, vm_offset_t, isa_msize_t)); + +#if 0 +void apecs_mem_copytoisa __P((void *, char *, vm_offset_t, + isa_moffset_t, isa_msize_t)); +void apecs_mem_copyfromisa __P((void *, char *, vm_offset_t, + isa_moffset_t, isa_msize_t)); +void apecs_mem_zero __P((void *, vm_offset_t, isa_moffset_t, + isa_msize_t)); +#else +void pf(apecs_mem_copytoisa, ()) +void pf(apecs_mem_copyfromisa, ()) +void pf(apecs_mem_zero, ()) +#endif + +__const struct isa_mem_fns apecs_mem_fns = { + apecs_mem_map, + apecs_mem_unmap, + apecs_mem_copytoisa, + apecs_mem_copyfromisa, + apecs_mem_zero, +}; + +vm_offset_t +apecs_mem_map(imfa, isapa, isasize, cacheable) + void *imfa; + isa_moffset_t isapa; + isa_msize_t isasize; + int cacheable; { + vm_offset_t sbpa; - if (addr != bounced_addr) - return; + /* XXX sanity checks on sizes, use of windows, etc. */ - log(LOG_NOTICE, "apecs_isa_copytobuf: copied %d byte buffer\n", - bounce_size); - bcopy(addr, bounce_buffer, bounce_size); + /* XXX MAGIC NUMBERS */ + if (cacheable) + sbpa = (isapa & 0xffffffff) | APECS_PCI_DENSE; + else + sbpa = ((isapa & 0x7ffffff) << 5) | APECS_PCI_SPARSE; + + return phystok0seg(sbpa); } void -apecs_isadma_copyfrombuf(addr, size, nmappings, mappings) - caddr_t addr; - vm_size_t size; - int nmappings; - vm_offset_t *mappings; +apecs_mem_unmap(imfa, va, isasize) + void *imfa; + vm_offset_t va; + isa_msize_t isasize; { - if (addr != bounced_addr) - return; + /* XXX sanity checks on va */ - log(LOG_NOTICE, "apecs_isa_copyfrombuf: copied %d byte buffer\n", - bounce_size); - bcopy(bounce_buffer, addr, bounce_size); + /* Nothing to do; mapping was done in direct-mapped segment. */ } diff --git a/sys/arch/alpha/pci/apecs_pci.c b/sys/arch/alpha/pci/apecs_pci.c index c8ca57bbff7..42be1862efa 100644 --- a/sys/arch/alpha/pci/apecs_pci.c +++ b/sys/arch/alpha/pci/apecs_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: apecs_pci.c,v 1.3 1995/08/03 01:16:57 cgd Exp $ */ +/* $NetBSD: apecs_pci.c,v 1.4 1995/11/23 02:37:16 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -33,330 +33,190 @@ #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> +#include <alpha/pci/apecsvar.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_io __P((pcitag_t, int, int *)); -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 *)); +pci_confreg_t apecs_conf_read __P((void *, pci_conftag_t, pci_confoffset_t)); +void apecs_conf_write __P((void *, pci_conftag_t, + pci_confoffset_t, pci_confreg_t)); +int apecs_find_io __P((void *, pci_conftag_t, + pci_confoffset_t, pci_iooffset_t *, pci_iosize_t *)); +int apecs_find_mem __P((void *, pci_conftag_t, + pci_confoffset_t, pci_moffset_t *, pci_msize_t *, int *)); -struct pci_cs_fcns apecs_p1e_cs_fcns = { /* XXX WHAT'S DIFFERENT? */ - apecs_setup, - apecs_make_tag, +__const struct pci_conf_fns apecs_conf_fns = { apecs_conf_read, apecs_conf_write, - apecs_map_io, - apecs_map_mem, - apecs_pcidma_map, - apecs_pcidma_unmap, + apecs_find_io, + apecs_find_mem, }; -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_io, - 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 */ +pci_confreg_t +apecs_conf_read(cpv, tag, offset) + void *cpv; + pci_conftag_t tag; + pci_confoffset_t offset; { - pcireg_t *datap, data; - int reg = offset >> 2; /* XXX */ + struct apecs_config *acp = cpv; + pci_confreg_t *datap, data; + int s, secondary, ba; + int32_t old_haxr2; /* XXX */ + + secondary = PCI_TAG_BUS(tag) != 0; + if (secondary) { + s = splhigh(); + old_haxr2 = REGVAL(EPIC_HAXR2); + wbflush(); + REGVAL(EPIC_HAXR2) = old_haxr2 | 0x1; + wbflush(); + } - if ((tag & 0x1fe00000) != 0) { - panic("apecs_conf_read: bus != 0?"); + datap = (pci_confreg_t *)phystok0seg(APECS_PCI_CONF | + tag << 5UL | /* XXX */ + (offset & ~0x03) << 5 | /* XXX */ + 0 << 5 | /* XXX */ + 0x3 << 3); /* XXX */ + data = (pci_confreg_t)-1; + if (!(ba = badaddr(datap, sizeof *datap))) + data = *datap; + + if (secondary) { + wbflush(); + REGVAL(EPIC_HAXR2) = old_haxr2; + wbflush(); + splx(s); } - /* 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); + printf("apecs_conf_read: tag 0x%lx, reg 0x%lx -> %x @ %p%s\n", tag, reg, + data, datap, ba ? " (badaddr)" : ""); #endif + return data; } void -apecs_conf_write(tag, offset, data) - pcitag_t tag; - int offset; /* XXX */ - pcireg_t data; +apecs_conf_write(cpv, tag, offset, data) + void *cpv; + pci_conftag_t tag; + pci_confoffset_t offset; + pci_confreg_t data; { - pcireg_t *datap; - int reg = offset >> 2; /* XXX */ + struct apecs_config *acp = cpv; + pci_confreg_t *datap; + int s, secondary; + int32_t old_haxr2; /* XXX */ + + secondary = PCI_TAG_BUS(tag) != 0; + if (secondary) { + s = splhigh(); + old_haxr2 = REGVAL(EPIC_HAXR2); + wbflush(); + REGVAL(EPIC_HAXR2) = old_haxr2 | 0x1; + wbflush(); + } - if ((tag & 0x1fe00000) != 0) { - panic("apecs_conf_read: bus != 0?"); + datap = (pci_confreg_t *)phystok0seg(APECS_PCI_CONF | + tag << 5UL | /* XXX */ + (offset & ~0x03) << 5 | /* XXX */ + 0 << 5 | /* XXX */ + 0x3 << 3); /* XXX */ + *datap = data; + + if (secondary) { + wbflush(); + REGVAL(EPIC_HAXR2) = old_haxr2; + wbflush(); + splx(s); } - /* 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; } int -apecs_map_io(tag, reg, iobasep) - pcitag_t tag; - int reg; - int *iobasep; +apecs_find_io(cpv, tag, reg, iobasep, sizep) + void *cpv; + pci_conftag_t tag; + pci_confoffset_t reg; + pci_iooffset_t *iobasep; + pci_iosize_t *sizep; { - pcireg_t data; - int pci_iobase; + struct apecs_config *acp = cpv; + pci_confreg_t addrdata, sizedata; + pci_iooffset_t pci_iobase; - if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) + if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) panic("apecs_map_io: bad request"); - data = pci_conf_read(tag, reg); + addrdata = PCI_CONF_READ(acp->ac_conffns, acp->ac_confarg, tag, reg); - if ((data & PCI_MAP_IO) == 0) + PCI_CONF_WRITE(acp->ac_conffns, acp->ac_confarg, tag, reg, 0xffffffff); + sizedata = PCI_CONF_READ(acp->ac_conffns, acp->ac_confarg, tag, reg); + PCI_CONF_WRITE(acp->ac_conffns, acp->ac_confarg, tag, reg, addrdata); + + if (PCI_MAPREG_TYPE(addrdata) == PCI_MAPREG_TYPE_MEM) panic("apecs_map_io: attempt to I/O map an memory region"); - /* figure out where it was mapped... */ - pci_iobase = data & PCI_MAP_MEMORY_ADDRESS_MASK; /* PCI I/O addr */ + if (iobasep != NULL) + *iobasep = PCI_MAPREG_IO_ADDRESS(addrdata); + if (sizep != NULL) + *sizep = ~PCI_MAPREG_IO_ADDRESS(sizedata) + 1; - return (pci_iobase); + return (0); } int -apecs_map_mem(tag, reg, vap, pap) - pcitag_t tag; - int reg; - vm_offset_t *vap, *pap; +apecs_find_mem(cpv, tag, reg, paddrp, sizep, cacheablep) + void *cpv; + pci_conftag_t tag; + pci_confoffset_t reg; + pci_moffset_t *paddrp; + pci_msize_t *sizep; + int *cacheablep; { - pcireg_t data; - vm_offset_t pci_pa, sb_pa; + struct apecs_config *acp = cpv; + pci_confreg_t addrdata, sizedata; - if (reg < PCI_MAP_REG_START || reg >= PCI_MAP_REG_END || (reg & 3)) + if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_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... + * The PROM has mapped the device for us. We take the address + * that's been assigned 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); + addrdata = PCI_CONF_READ(acp->ac_conffns, acp->ac_confarg, tag, reg); + + PCI_CONF_WRITE(acp->ac_conffns, acp->ac_confarg, tag, reg, 0xffffffff); + sizedata = PCI_CONF_READ(acp->ac_conffns, acp->ac_confarg, tag, reg); + PCI_CONF_WRITE(acp->ac_conffns, acp->ac_confarg, tag, reg, addrdata); - if (data & PCI_MAP_IO) + if (PCI_MAPREG_TYPE(addrdata) == PCI_MAPREG_TYPE_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: + switch (PCI_MAPREG_MEM_TYPE(addrdata)) { + case PCI_MAPREG_MEM_TYPE_32BIT: + case PCI_MAPREG_MEM_TYPE_32BIT_1M: 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; + case PCI_MAPREG_MEM_TYPE_64BIT: +/* XXX */ printf("apecs_map_mem: attempt to map 64-bit region\n"); +/* XXX */ break; default: printf("apecs_map_mem: reserved mapping type\n"); return EINVAL; } - /* figure out where it was mapped... */ - pci_pa = data & PCI_MAP_MEMORY_ADDRESS_MASK; /* PCI bus address */ - - /* calcluate sysBus address -- should be a better way to get space */ - if (data & PCI_MAP_MEMORY_CACHABLE) { - /* Dense space */ - sb_pa = (pci_pa & 0xffffffff) | (3L << 32); /* XXX */ - } else { - /* Sparse space */ - sb_pa = ((pci_pa & 0x7ffffff) << 5) | (2L << 32); /* XXX */ - } - - /* 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 + if (paddrp != NULL) + *paddrp = PCI_MAPREG_MEM_ADDRESS(addrdata); /* PCI addr */ + if (sizep != NULL) + *sizep = ~PCI_MAPREG_MEM_ADDRESS(sizedata) + 1; + if (cacheablep != NULL) + *cacheablep = PCI_MAPREG_MEM_CACHEABLE(addrdata); 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"); -} diff --git a/sys/arch/alpha/pci/apecsreg.h b/sys/arch/alpha/pci/apecsreg.h index 186173f2bb7..864bfac54fe 100644 --- a/sys/arch/alpha/pci/apecsreg.h +++ b/sys/arch/alpha/pci/apecsreg.h @@ -1,4 +1,4 @@ -/* $NetBSD: apecsreg.h,v 1.2 1995/08/03 01:17:04 cgd Exp $ */ +/* $NetBSD: apecsreg.h,v 1.3 1995/11/23 02:37:19 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -34,6 +34,8 @@ * Sheet'' (DEC order number EC-QAEMA-TE), pages 4-1 - 4-27, 10-21 - 10-38. */ +#define REGVAL(r) (*(int32_t *)phystok0seg(r)) + /* * Base addresses */ @@ -278,7 +280,9 @@ #define EPIC_HAXR1_EADDR 0xf8000000 #define EPIC_HAXR2 (EPIC_BASE + 0x01c0) /* Host Addr Extn 2 */ -#define EPIC_HAXR2_CONF_ADDR 0x00000003 +#define EPIC_HAXR2_CONF_TYPE 0x00000003 +#define EPIC_HAXR2_CONF_TYPO0 0x00000000 +#define EPIC_HAXR2_CONF_TYPE1 0x00000001 #define EPIC_HAXR2_RSVD 0x00fffffc #define EPIC_HAXR2_EADDR 0xff000000 diff --git a/sys/arch/alpha/pci/apecsvar.h b/sys/arch/alpha/pci/apecsvar.h new file mode 100644 index 00000000000..a63cc275922 --- /dev/null +++ b/sys/arch/alpha/pci/apecsvar.h @@ -0,0 +1,72 @@ +/* $NetBSD: apecsvar.h,v 1.1 1995/11/23 02:37:21 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 <dev/isa/isavar.h> +#include <dev/pci/pcivar.h> + +/* + * An APECS chipset's configuration. + * + * All of the information that the chipset-specific functions need to + * do their dirty work (and more!). + */ +struct apecs_config { + int ac_comanche_pass2; + int ac_epic_pass2; + int ac_memwidth; + + __const struct pci_conf_fns *ac_conffns; + void *ac_confarg; + + __const struct pci_dma_fns *ac_dmafns; + void *ac_dmaarg; + + __const struct pci_intr_fns *ac_intrfns; + void *ac_intrarg; + + __const struct pci_mem_fns *ac_memfns; + void *ac_memarg; + + __const struct pci_pio_fns *ac_piofns; + void *ac_pioarg; +}; + +struct apecs_softc { + struct device sc_dev; + + struct apecs_config *sc_acp; +}; + +extern __const struct pci_conf_fns apecs_conf_fns; +extern __const struct pci_dma_fns apecs_dma_fns; +/* pci interrupt functions handled elsewhere */ +extern __const struct pci_mem_fns apecs_mem_fns; +extern __const struct pci_pio_fns apecs_pio_fns; + +void apecs_init __P((struct apecs_config *)); diff --git a/sys/arch/alpha/pci/cia.c b/sys/arch/alpha/pci/cia.c new file mode 100644 index 00000000000..fa2f49fc6cc --- /dev/null +++ b/sys/arch/alpha/pci/cia.c @@ -0,0 +1,176 @@ +/* $NetBSD: cia.c,v 1.1 1995/11/23 02:37:24 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/kernel.h> +#include <sys/malloc.h> +#include <sys/device.h> +#include <vm/vm.h> + +#include <machine/autoconf.h> +#include <machine/rpb.h> + +#include <dev/isa/isareg.h> +#include <dev/isa/isavar.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <alpha/pci/ciareg.h> +#include <alpha/pci/ciavar.h> +#if defined(DEC_KN20AA) +#include <alpha/pci/pci_kn20aa.h> +#endif + +int ciamatch __P((struct device *, void *, void *)); +void ciaattach __P((struct device *, struct device *, void *)); + +struct cfdriver ciacd = { + NULL, "cia", ciamatch, ciaattach, DV_DULL, + sizeof(struct cia_softc) +}; + +static int ciaprint __P((void *, char *pnp)); + +#define REGVAL(r) (*(int32_t *)phystok0seg(r)) + +/* There can be only one. */ +int ciafound; +struct cia_config cia_configuration; + +int +ciamatch(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct cfdata *cf = match; + struct confargs *ca = aux; + + /* Make sure that we're looking for a CIA. */ + if (strcmp(ca->ca_name, ciacd.cd_name) != 0) + return (0); + + if (ciafound) + return (0); + + return (1); +} + +/* + * Set up the chipset's function pointers. + */ +void +cia_init(ccp) + struct cia_config *ccp; +{ + + /* + * Can't set up SGMAP data here; can be called before malloc(). + */ + + ccp->cc_conffns = &cia_conf_fns; + ccp->cc_confarg = ccp; + ccp->cc_dmafns = &cia_dma_fns; + ccp->cc_dmaarg = ccp; + /* Interrupt routines set up in 'attach' */ + ccp->cc_memfns = &cia_mem_fns; + ccp->cc_memarg = ccp; + ccp->cc_piofns = &cia_pio_fns; + ccp->cc_pioarg = ccp; +} + +void +ciaattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct confargs *ca = aux; + struct cia_softc *sc = (struct cia_softc *)self; + struct cia_config *ccp; + struct pci_attach_args pa; + + /* note that we've attached the chipset; can't have 2 CIAs. */ + ciafound = 1; + + /* + * set up the chipset's info; done once at console init time + * (maybe), but doesn't hurt to do twice. + */ + ccp = sc->sc_ccp = &cia_configuration; + cia_init(ccp); + + /* XXX print chipset information */ + printf("\n"); + + switch (hwrpb->rpb_type) { +#if defined(DEC_KN20AA) + case ST_DEC_KN20AA: + pci_kn20aa_pickintr(ccp->cc_conffns, ccp->cc_confarg, + ccp->cc_piofns, ccp->cc_pioarg, + &ccp->cc_intrfns, &ccp->cc_intrarg); +#ifdef EVCNT_COUNTERS + evcnt_attach(self, "intr", &kn20aa_intr_evcnt); +#endif + break; +#endif + default: + panic("ciaattach: shouldn't be here, really..."); + } + + pa.pa_bus = 0; + pa.pa_maxdev = 32; + pa.pa_burstlog2 = 8; + + pa.pa_conffns = ccp->cc_conffns; + pa.pa_confarg = ccp->cc_confarg; + pa.pa_dmafns = ccp->cc_dmafns; + pa.pa_dmaarg = ccp->cc_dmaarg; + pa.pa_intrfns = ccp->cc_intrfns; + pa.pa_intrarg = ccp->cc_intrarg; + pa.pa_memfns = ccp->cc_memfns; + pa.pa_memarg = ccp->cc_memarg; + pa.pa_piofns = ccp->cc_piofns; + pa.pa_pioarg = ccp->cc_pioarg; + + config_found(self, &pa, ciaprint); +} + +static int +ciaprint(aux, pnp) + void *aux; + char *pnp; +{ + register struct pci_attach_args *pa = aux; + + /* only PCIs can attach to CIAs; easy. */ + if (pnp) + printf("pci at %s", pnp); + printf(" bus %d", pa->pa_bus); + return (UNCONF); +} diff --git a/sys/arch/alpha/pci/cia_isa.c b/sys/arch/alpha/pci/cia_isa.c new file mode 100644 index 00000000000..6ccb0ae4a3e --- /dev/null +++ b/sys/arch/alpha/pci/cia_isa.c @@ -0,0 +1,346 @@ +/* $NetBSD: cia_isa.c,v 1.1 1995/11/23 02:37:26 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/malloc.h> +#include <sys/syslog.h> +#include <sys/device.h> +#include <vm/vm.h> + +#include <dev/isa/isavar.h> + +#include <alpha/pci/ciareg.h> +#include <alpha/pci/ciavar.h> + +/* + * Allocation/deallocation functions. + */ +int cia_pio_alloc __P((void *, isa_iooffset_t, isa_iosize_t)); +int cia_pio_dealloc __P((void *, isa_iooffset_t, isa_iosize_t)); + +/* + * Byte functions. + */ +isa_byte_t cia_inb __P((void *, isa_iooffset_t)); +#define cia_insb 0 /* XXX */ +void cia_outb __P((void *, isa_iooffset_t, isa_byte_t)); +#define cia_outsb 0 /* XXX */ + +/* + * Word functions. + */ +isa_word_t cia_inw __P((void *, isa_iooffset_t)); +#define cia_insw 0 /* XXX */ +void cia_outw __P((void *, isa_iooffset_t, isa_word_t)); +#define cia_outsw 0 /* XXX */ + +/* + * Longword functions. + */ +isa_long_t cia_inl __P((void *, isa_iooffset_t)); +#define cia_insl 0 /* XXX */ +void cia_outl __P((void *, isa_iooffset_t, isa_long_t)); +#define cia_outsl 0 /* XXX */ + +__const struct pci_pio_fns cia_pio_fns = { + /* Allocation/deallocation functions. */ + cia_pio_alloc, cia_pio_dealloc, + + /* Byte functions. */ + cia_inb, cia_insb, + cia_outb, cia_outsb, + + /* Word functions. */ + cia_inw, cia_insw, + cia_outw, cia_outsw, + + /* Longword functions. */ + cia_inl, cia_insl, + cia_outl, cia_outsl, +}; + +int +cia_pio_alloc(ipfarg, start, size) + void *ipfarg; + isa_iooffset_t start; + isa_iosize_t size; +{ + + /* XXX should do something */ +} + +int +cia_pio_dealloc(ipfarg, start, size) + void *ipfarg; + isa_iooffset_t start; + isa_iosize_t size; +{ + + /* XXX should do something */ +} + +isa_byte_t +cia_inb(ipfa, ioaddr) + void *ipfa; + isa_iooffset_t ioaddr; +{ + u_int32_t *port, val; + isa_byte_t rval; + int offset; + + wbflush(); + offset = ioaddr & 3; + port = (int32_t *)phystok0seg(CIA_PCI_SIO0 | 0 << 3 | ioaddr << 5); + val = *port; + rval = ((val) >> (8 * offset)) & 0xff; +/* rval = val & 0xff; */ + + return rval; +} + +void +cia_outb(ipfa, ioaddr, val) + void *ipfa; + isa_iooffset_t ioaddr; + isa_byte_t val; +{ + u_int32_t *port, nval; + int offset; + + offset = ioaddr & 3; + nval = val /*<< (8 * offset)*/; + nval = val << (8 * offset); + port = (int32_t *)phystok0seg(CIA_PCI_SIO0 | 0 << 3 | ioaddr << 5); + + *port = nval; + wbflush(); +} + +isa_word_t +cia_inw(ipfa, ioaddr) + void *ipfa; + isa_iooffset_t ioaddr; +{ + u_int32_t *port, val; + isa_word_t rval; + int offset; + + wbflush(); + offset = ioaddr & 3; + port = (int32_t *)phystok0seg(CIA_PCI_SIO0 | 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; +} + +void +cia_outw(ipfa, ioaddr, val) + void *ipfa; + isa_iooffset_t ioaddr; + isa_word_t val; +{ + u_int32_t *port, nval; + int offset; + + offset = ioaddr & 3; + nval = val /*<< (8 * offset)*/; + port = (int32_t *)phystok0seg(CIA_PCI_SIO0 | 1 << 3 | ioaddr << 5); + + *port = nval; + wbflush(); +} + +isa_long_t +cia_inl(ipfa, ioaddr) + void *ipfa; + isa_iooffset_t ioaddr; +{ + u_int32_t *port, val; + isa_long_t rval; + int offset; + + wbflush(); + offset = ioaddr & 3; + port = (int32_t *)phystok0seg(CIA_PCI_SIO0 | 3 << 3 | ioaddr << 5); + val = *port; + rval = ((val) >> (8 * offset)) & 0xffffffff; + rval = val & 0xffffffff; + + return rval; +} + +void +cia_outl(ipfa, ioaddr, val) + void *ipfa; + isa_iooffset_t ioaddr; + isa_long_t val; +{ + u_int32_t *port, nval; + int offset; + + offset = ioaddr & 3; + nval = val /*<< (8 * offset)*/; + port = (int32_t *)phystok0seg(CIA_PCI_SIO0 | 3 << 3 | ioaddr << 5); + + *port = nval; + wbflush(); +} + +/* XXX XXX XXX */ + +#define pf(fn, args) fn args { panic(__STRING(fn)); } + +void pf(cia_dma_cascade, (void *idfa, isa_drq_t chan)) +void pf(cia_dma_copytobuf, ()) +void pf(cia_dma_copyfrombuf, ()) +void pf(cia_dma_start, (void *idfa, vm_offset_t addr, + isa_msize_t size, isa_drq_t chan, int flags)) +void pf(cia_dma_abort, (void *idfa, isa_drq_t chan)) +void pf(cia_dma_done, (void *idfa, isa_drq_t chan)) + +int cia_dma_map __P((void *, vm_offset_t, isa_msize_t, + isa_moffset_t *, int)); +void cia_dma_unmap __P((void *, vm_offset_t, isa_msize_t, int, + isa_moffset_t *)); + +__const struct isa_dma_fns cia_dma_fns = { + cia_dma_cascade, + cia_dma_map, + cia_dma_unmap, + cia_dma_copytobuf, + cia_dma_copyfrombuf, + cia_dma_start, + cia_dma_abort, + cia_dma_done, +}; + +int +cia_dma_map(idfa, va, isasize, mappingsp, flags) + void *idfa; + vm_offset_t va; + isa_msize_t isasize; + isa_moffset_t *mappingsp; + int flags; +{ + struct apecs_config *acp = idfa; + long todo; + int i; + + if (ISA_DMA_NEEDCONTIG(flags) && isasize > NBPG || + ISA_DMA_SIZEBOUND(flags) != ISA_DMA_SIZEBOUND_NONE || + ISA_DMA_ADDRBOUND(flags) != ISA_DMA_ADDRBOUND_NONE) + panic("cia_dma_map: punt"); + + i = 0; + todo = isasize; + + while (todo > 0) { + mappingsp[i] = vtophys(va) | 0x40000000; +#if 0 + printf("a_pd_m mapping %d: %lx -> %lx -> %lx\n", i, va, + vtophys(va), mappingsp[i]); +#endif + i++; + todo -= PAGE_SIZE - (va - trunc_page(va)); + va += PAGE_SIZE - (va - trunc_page(va)); + } + return (i); +} + +void +cia_dma_unmap(idfa, va, isasize, nmappings, mappingsp) + void *idfa; + vm_offset_t va; + isa_msize_t isasize; + int nmappings; + isa_moffset_t *mappingsp; +{ + + printf("cia_dma_unmap: called\n"); +} + +vm_offset_t cia_mem_map __P((void *, isa_moffset_t, isa_msize_t, int)); +void cia_mem_unmap __P((void *, vm_offset_t, isa_msize_t)); + +#if 0 +void cia_mem_copytoisa __P((void *, char *, vm_offset_t, + isa_moffset_t, isa_msize_t)); +void cia_mem_copyfromisa __P((void *, char *, vm_offset_t, + isa_moffset_t, isa_msize_t)); +void cia_mem_zero __P((void *, vm_offset_t, isa_moffset_t, + isa_msize_t)); +#else +void pf(cia_mem_copytoisa, ()) +void pf(cia_mem_copyfromisa, ()) +void pf(cia_mem_zero, ()) +#endif + +__const struct isa_mem_fns cia_mem_fns = { + cia_mem_map, + cia_mem_unmap, + cia_mem_copytoisa, + cia_mem_copyfromisa, + cia_mem_zero, +}; + +vm_offset_t +cia_mem_map(imfa, isapa, isasize, cacheable) + void *imfa; + isa_moffset_t isapa; + isa_msize_t isasize; + int cacheable; +{ + vm_offset_t sbpa; + + /* XXX sanity checks on sizes, use of windows, etc. */ + + /* XXX MAGIC NUMBERS */ + if (cacheable) + sbpa = (isapa & 0xffffffff) | CIA_PCI_DENSE; + else + sbpa = ((isapa & 0x7ffffff) << 5) | CIA_PCI_SPARSE0; + + return phystok0seg(sbpa); +} + +void +cia_mem_unmap(imfa, va, isasize) + void *imfa; + vm_offset_t va; + isa_msize_t isasize; +{ + + /* XXX sanity checks on va */ + + /* Nothing to do; mapping was done in direct-mapped segment. */ +} diff --git a/sys/arch/alpha/pci/cia_pci.c b/sys/arch/alpha/pci/cia_pci.c new file mode 100644 index 00000000000..ef918cd84d6 --- /dev/null +++ b/sys/arch/alpha/pci/cia_pci.c @@ -0,0 +1,222 @@ +/* $NetBSD: cia_pci.c,v 1.1 1995/11/23 02:37:29 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/kernel.h> +#include <sys/device.h> +#include <vm/vm.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <alpha/pci/ciareg.h> +#include <alpha/pci/ciavar.h> + +pci_confreg_t cia_conf_read __P((void *, pci_conftag_t, pci_confoffset_t)); +void cia_conf_write __P((void *, pci_conftag_t, + pci_confoffset_t, pci_confreg_t)); +int cia_find_io __P((void *, pci_conftag_t, + pci_confoffset_t, pci_iooffset_t *, pci_iosize_t *)); +int cia_find_mem __P((void *, pci_conftag_t, + pci_confoffset_t, pci_moffset_t *, pci_msize_t *, int *)); + +__const struct pci_conf_fns cia_conf_fns = { + cia_conf_read, + cia_conf_write, + cia_find_io, + cia_find_mem, +}; + +pci_confreg_t +cia_conf_read(cpv, tag, offset) + void *cpv; + pci_conftag_t tag; + pci_confoffset_t offset; +{ + struct cia_config *acp = cpv; + pci_confreg_t *datap, data; + int s, secondary, ba; + int32_t old_haxr2; /* XXX */ + + secondary = PCI_TAG_BUS(tag) != 0; + if (secondary) { + s = splhigh(); + old_haxr2 = REGVAL(CIA_CSRS + 0x480); /* XXX */ + wbflush(); + REGVAL(CIA_CSRS + 0x480) = old_haxr2 | 0x1; /* XXX */ + wbflush(); + } + + datap = (pci_confreg_t *)phystok0seg(CIA_PCI_CONF | + tag << 5UL | /* XXX */ + (offset & ~0x03) << 5 | /* XXX */ + 0 << 5 | /* XXX */ + 0x3 << 3); /* XXX */ + data = (pci_confreg_t)-1; + if (!(ba = badaddr(datap, sizeof *datap))) + data = *datap; + + if (secondary) { + wbflush(); + REGVAL(CIA_CSRS + 0x480) = old_haxr2; /* XXX */ + wbflush(); + splx(s); + } + +#if 0 + printf("cia_conf_read: tag 0x%lx, reg 0x%lx -> %x @ %p%s\n", tag, reg, + data, datap, ba ? " (badaddr)" : ""); +#endif + + return data; +} + +void +cia_conf_write(cpv, tag, offset, data) + void *cpv; + pci_conftag_t tag; + pci_confoffset_t offset; + pci_confreg_t data; +{ + struct cia_config *acp = cpv; + pci_confreg_t *datap; + int s, secondary; + int32_t old_haxr2; /* XXX */ + + secondary = PCI_TAG_BUS(tag) != 0; + if (secondary) { + s = splhigh(); + old_haxr2 = REGVAL(CIA_CSRS + 0x480); /* XXX */ + wbflush(); + REGVAL(CIA_CSRS + 0x480) = old_haxr2 | 0x1; /* XXX */ + wbflush(); + } + + datap = (pci_confreg_t *)phystok0seg(CIA_PCI_CONF | + tag << 5UL | /* XXX */ + (offset & ~0x03) << 5 | /* XXX */ + 0 << 5 | /* XXX */ + 0x3 << 3); /* XXX */ + *datap = data; + + if (secondary) { + wbflush(); + REGVAL(CIA_CSRS + 0x480) = old_haxr2; /* XXX */ + wbflush(); + splx(s); + } + +#if 0 + printf("cia_conf_write: tag 0x%lx, reg 0x%lx -> 0x%x @ %p\n", tag, + reg, data, datap); +#endif +} + +int +cia_find_io(cpv, tag, reg, iobasep, sizep) + void *cpv; + pci_conftag_t tag; + pci_confoffset_t reg; + pci_iooffset_t *iobasep; + pci_iosize_t *sizep; +{ + struct cia_config *acp = cpv; + pci_confreg_t addrdata, sizedata; + pci_iooffset_t pci_iobase; + + if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) + panic("cia_map_io: bad request"); + + addrdata = PCI_CONF_READ(acp->cc_conffns, acp->cc_confarg, tag, reg); + + PCI_CONF_WRITE(acp->cc_conffns, acp->cc_confarg, tag, reg, 0xffffffff); + sizedata = PCI_CONF_READ(acp->cc_conffns, acp->cc_confarg, tag, reg); + PCI_CONF_WRITE(acp->cc_conffns, acp->cc_confarg, tag, reg, addrdata); + + if (PCI_MAPREG_TYPE(addrdata) == PCI_MAPREG_TYPE_MEM) + panic("cia_map_io: attempt to I/O map an memory region"); + + if (iobasep != NULL) + *iobasep = PCI_MAPREG_IO_ADDRESS(addrdata); + if (sizep != NULL) + *sizep = ~PCI_MAPREG_IO_ADDRESS(sizedata) + 1; + + return (0); +} + +int +cia_find_mem(cpv, tag, reg, paddrp, sizep, cacheablep) + void *cpv; + pci_conftag_t tag; + pci_confoffset_t reg; + pci_moffset_t *paddrp; + pci_msize_t *sizep; + int *cacheablep; +{ + struct cia_config *acp = cpv; + pci_confreg_t addrdata, sizedata; + + if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) + panic("cia_map_mem: bad request"); + + /* + * The PROM has mapped the device for us. We take the address + * that's been assigned to the register, and figure out what + * physical and virtual addresses go with it... + */ + addrdata = PCI_CONF_READ(acp->cc_conffns, acp->cc_confarg, tag, reg); + + PCI_CONF_WRITE(acp->cc_conffns, acp->cc_confarg, tag, reg, 0xffffffff); + sizedata = PCI_CONF_READ(acp->cc_conffns, acp->cc_confarg, tag, reg); + PCI_CONF_WRITE(acp->cc_conffns, acp->cc_confarg, tag, reg, addrdata); + + if (PCI_MAPREG_TYPE(addrdata) == PCI_MAPREG_TYPE_IO) + panic("cia_map_mem: attempt to memory map an I/O region"); + + switch (PCI_MAPREG_MEM_TYPE(addrdata)) { + case PCI_MAPREG_MEM_TYPE_32BIT: + case PCI_MAPREG_MEM_TYPE_32BIT_1M: + break; + case PCI_MAPREG_MEM_TYPE_64BIT: +/* XXX */ printf("cia_map_mem: attempt to map 64-bit region\n"); +/* XXX */ break; + default: + printf("cia_map_mem: reserved mapping type\n"); + return EINVAL; + } + + if (paddrp != NULL) + *paddrp = PCI_MAPREG_MEM_ADDRESS(addrdata); /* PCI addr */ + if (sizep != NULL) + *sizep = ~PCI_MAPREG_MEM_ADDRESS(sizedata) + 1; + if (cacheablep != NULL) + *cacheablep = PCI_MAPREG_MEM_CACHEABLE(addrdata); + + return 0; +} diff --git a/sys/arch/alpha/pci/ciareg.h b/sys/arch/alpha/pci/ciareg.h new file mode 100644 index 00000000000..5fc6ae9435a --- /dev/null +++ b/sys/arch/alpha/pci/ciareg.h @@ -0,0 +1,51 @@ +/* $NetBSD: ciareg.h,v 1.1 1995/11/23 02:37:31 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. + */ + +/* + * 21171 Chipset registers and constants. + * + * Taken from XXX + */ + +#define REGVAL(r) (*(int32_t *)phystok0seg(r)) + +/* + * Base addresses + */ +#define CIA_PCI_SPARSE0 0x8000000000L +#define CIA_PCI_SPARSE1 0x8400000000L +#define CIA_PCI_SPARSE2 0x8500000000L +#define CIA_PCI_SIO0 0x8580000000L +#define CIA_PCI_SIO1 0x85c0000000L +#define CIA_PCI_DENSE 0x8600000000L +#define CIA_PCI_CONF 0x8700000000L +#define CIA_PCI_IACK 0x8720000000L +#define CIA_CSRS 0x8740000000L +#define CIA_PCI_MC_CSRS 0x8750000000L +#define CIA_PCI_ATRANS 0x8760000000L diff --git a/sys/arch/alpha/pci/ciavar.h b/sys/arch/alpha/pci/ciavar.h new file mode 100644 index 00000000000..d9241010d89 --- /dev/null +++ b/sys/arch/alpha/pci/ciavar.h @@ -0,0 +1,69 @@ +/* $NetBSD: ciavar.h,v 1.1 1995/11/23 02:37:35 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 <dev/isa/isavar.h> +#include <dev/pci/pcivar.h> + +/* + * A 21171 chipset's configuration. + * + * All of the information that the chipset-specific functions need to + * do their dirty work (and more!). + */ +struct cia_config { + __const struct pci_conf_fns *cc_conffns; + void *cc_confarg; + + __const struct pci_dma_fns *cc_dmafns; + void *cc_dmaarg; + + __const struct pci_intr_fns *cc_intrfns; + void *cc_intrarg; + + __const struct pci_mem_fns *cc_memfns; + void *cc_memarg; + + __const struct pci_pio_fns *cc_piofns; + void *cc_pioarg; +}; + +struct cia_softc { + struct device sc_dev; + + struct cia_config *sc_ccp; + /* XXX SGMAP info */ +}; + +extern __const struct pci_conf_fns cia_conf_fns; +extern __const struct pci_dma_fns cia_dma_fns; +/* pci interrupt functions handled elsewhere */ +extern __const struct pci_mem_fns cia_mem_fns; +extern __const struct pci_pio_fns cia_pio_fns; + +void cia_init __P((struct cia_config *)); diff --git a/sys/arch/alpha/pci/lca.c b/sys/arch/alpha/pci/lca.c new file mode 100644 index 00000000000..ac6514fee99 --- /dev/null +++ b/sys/arch/alpha/pci/lca.c @@ -0,0 +1,210 @@ +/* $NetBSD: lca.c,v 1.1 1995/11/23 02:37:38 cgd Exp $ */ + +/* + * Copyright (c) 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Jeffrey Hsu + * + * 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/rpb.h> + +#include <dev/isa/isareg.h> +#include <dev/isa/isavar.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <alpha/pci/lcareg.h> +#include <alpha/pci/lcavar.h> + +int lcamatch __P((struct device *, void *, void *)); +void lcaattach __P((struct device *, struct device *, void *)); + +struct cfdriver lcacd = { + NULL, "lca", lcamatch, lcaattach, DV_DULL, + sizeof(struct lca_softc) +}; + +static int lcaprint __P((void *, char *pnp)); + +/* There can be only one. */ +int lcafound; +struct lca_config lca_configuration; + +int +lcamatch(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct cfdata *cf = match; + struct confargs *ca = aux; + + /* Make sure that we're looking for a LCA. */ + if (strcmp(ca->ca_name, lcacd.cd_name) != 0) + return (0); + + if (lcafound) + return (0); + + return (1); +} + +/* + * Set up the chipset's function pointers. + */ +void +lca_init(lcp) + struct lca_config *lcp; +{ + + /* + * Can't set up SGMAP data here; can be called before malloc(). + */ + + lcp->lc_conffns = &lca_conf_fns; + lcp->lc_confarg = lcp; + lcp->lc_dmafns = &lca_dma_fns; + lcp->lc_dmaarg = lcp; + /* Interrupt routines set up in 'attach' */ + lcp->lc_memfns = &lca_mem_fns; + lcp->lc_memarg = lcp; + lcp->lc_piofns = &lca_pio_fns; + lcp->lc_pioarg = lcp; + +/* +printf("lca_init: before IOC_HAE=0x%x\n", REGVAL(LCA_IOC_HAE)); + REGVAL(LCA_IOC_HAE) = 0; */ + + REGVAL(LCA_IOC_CONF) = 0; + + /* Turn off DMA window enables in Window Base Registers */ +/* REGVAL(LCA_IOC_W_BASE0) = 0; + REGVAL(LCA_IOC_W_BASE1) = 0; */ + wbflush(); +} + +#ifdef notdef +void +lca_init_sgmap(lcp) + struct lca_config *lcp; +{ + + /* XXX */ + lcp->lc_sgmap = malloc(1024 * 8, M_DEVBUF, M_WAITOK); + bzero(lcp->lc_sgmap, 1024 * 8); /* clear all entries. */ + + REGVAL(LCA_IOC_W_BASE0) = 0; + wbflush(); + + /* Set up Translated Base Register 1; translate to sybBus addr 0. */ + /* check size against APEC XXX JH */ + REGVAL(LCA_IOC_T_BASE_0) = vtophys(lcp->lc_sgmap) >> 1; + + /* Set up PCI mask register 1; map 8MB space. */ + REGVAL(LCA_IOC_W_MASK0) = 0x00700000; + + /* Enable window 1; from PCI address 8MB, direct mapped. */ + REGVAL(LCA_IOC_W_BASE0) = 0x300800000; + wbflush(); +} +#endif + +void +lcaattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct confargs *ca = aux; + struct lca_softc *sc = (struct lca_softc *)self; + struct lca_config *lcp; + struct pci_attach_args pa; + + /* note that we've attached the chipset; can't have 2 LCAs. */ + /* Um, not sure about this. XXX JH */ + lcafound = 1; + + /* + * set up the chipset's info; done once at console init time + * (maybe), but doesn't hurt to do twice. + */ + lcp = sc->sc_lcp = &lca_configuration; + lca_init(lcp); +#ifdef notdef + lca_init_sgmap(lcp); +#endif + + /* XXX print chipset information */ + printf("\n"); + + switch (hwrpb->rpb_type) { +#if defined(DEC_AXPPCI_33) + case ST_DEC_AXPPCI_33: + pci_axppci_33_pickintr(lcp->lc_conffns, lcp->lc_confarg, + lcp->lc_piofns, lcp->lc_pioarg, + &lcp->lc_intrfns, &lcp->lc_intrarg); + break; +#endif + default: + panic("lcaattach: shouldn't be here, really..."); + } + + pa.pa_bus = 0; + pa.pa_maxdev = 13; + pa.pa_burstlog2 = 8; + + pa.pa_conffns = lcp->lc_conffns; + pa.pa_confarg = lcp->lc_confarg; + pa.pa_dmafns = lcp->lc_dmafns; + pa.pa_dmaarg = lcp->lc_dmaarg; + pa.pa_intrfns = lcp->lc_intrfns; + pa.pa_intrarg = lcp->lc_intrarg; + pa.pa_memfns = lcp->lc_memfns; + pa.pa_memarg = lcp->lc_memarg; + pa.pa_piofns = lcp->lc_piofns; + pa.pa_pioarg = lcp->lc_pioarg; + + config_found(self, &pa, lcaprint); +} + +static int +lcaprint(aux, pnp) + void *aux; + char *pnp; +{ + register struct pci_attach_args *pa = aux; + + /* what does this do? XXX JH */ + /* only PCIs can attach to LCAes; easy. */ + if (pnp) + printf("pci at %s", pnp); + printf(" bus %d", pa->pa_bus); + return (UNCONF); +} diff --git a/sys/arch/alpha/pci/lca_isa.c b/sys/arch/alpha/pci/lca_isa.c new file mode 100644 index 00000000000..205d8708663 --- /dev/null +++ b/sys/arch/alpha/pci/lca_isa.c @@ -0,0 +1,346 @@ +/* $NetBSD: lca_isa.c,v 1.1 1995/11/23 02:37:40 cgd Exp $ */ + +/* + * Copyright (c) 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Jeffrey Hsu + * + * 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 <sys/device.h> +#include <vm/vm.h> + +#include <dev/isa/isavar.h> + +#include <alpha/pci/lcareg.h> +#include <alpha/pci/lcavar.h> + +/* + * Allocation/deallocation functions. + */ +int lca_pio_alloc __P((void *, isa_iooffset_t, isa_iosize_t)); +int lca_pio_dealloc __P((void *, isa_iooffset_t, isa_iosize_t)); + +/* + * Byte functions. + */ +isa_byte_t lca_inb __P((void *, isa_iooffset_t)); +#define lca_insb 0 /* XXX */ +void lca_outb __P((void *, isa_iooffset_t, isa_byte_t)); +#define lca_outsb 0 /* XXX */ + +/* + * Word functions. + */ +isa_word_t lca_inw __P((void *, isa_iooffset_t)); +#define lca_insw 0 /* XXX */ +void lca_outw __P((void *, isa_iooffset_t, isa_word_t)); +#define lca_outsw 0 /* XXX */ + +/* + * Longword functions. + */ +isa_long_t lca_inl __P((void *, isa_iooffset_t)); +#define lca_insl 0 /* XXX */ +void lca_outl __P((void *, isa_iooffset_t, isa_long_t)); +#define lca_outsl 0 /* XXX */ + +__const struct pci_pio_fns lca_pio_fns = { + /* Allocation/deallocation functions. */ + lca_pio_alloc, lca_pio_dealloc, + + /* Byte functions. */ + lca_inb, lca_insb, + lca_outb, lca_outsb, + + /* Word functions. */ + lca_inw, lca_insw, + lca_outw, lca_outsw, + + /* Longword functions. */ + lca_inl, lca_insl, + lca_outl, lca_outsl, +}; + +int +lca_pio_alloc(ipfarg, start, size) + void *ipfarg; + isa_iooffset_t start; + isa_iosize_t size; +{ + + /* XXX should do something */ +} + +int +lca_pio_dealloc(ipfarg, start, size) + void *ipfarg; + isa_iooffset_t start; + isa_iosize_t size; +{ + + /* XXX should do something */ +} + +isa_byte_t +lca_inb(ipfa, ioaddr) + void *ipfa; + isa_iooffset_t ioaddr; +{ + u_int32_t *port, val; + isa_byte_t rval; + int offset; + + wbflush(); + offset = ioaddr & 3; + port = (int32_t *)phystok0seg(LCA_PCI_SIO | 0 << 3 | ioaddr << 5); + val = *port; + rval = ((val) >> (8 * offset)) & 0xff; +/* rval = val & 0xff; */ + + return rval; +} + +void +lca_outb(ipfa, ioaddr, val) + void *ipfa; + isa_iooffset_t ioaddr; + isa_byte_t val; +{ + u_int32_t *port, nval; + int offset; + + offset = ioaddr & 3; + nval = val /*<< (8 * offset)*/; + nval = val << (8 * offset); + port = (int32_t *)phystok0seg(LCA_PCI_SIO | 0 << 3 | ioaddr << 5); + + *port = nval; + wbflush(); +} + +isa_word_t +lca_inw(ipfa, ioaddr) + void *ipfa; + isa_iooffset_t ioaddr; +{ + u_int32_t *port, val; + isa_word_t rval; + int offset; + + wbflush(); + offset = ioaddr & 3; + port = (int32_t *)phystok0seg(LCA_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; +} + +void +lca_outw(ipfa, ioaddr, val) + void *ipfa; + isa_iooffset_t ioaddr; + isa_word_t val; +{ + u_int32_t *port, nval; + int offset; + + offset = ioaddr & 3; + nval = val /*<< (8 * offset)*/; + port = (int32_t *)phystok0seg(LCA_PCI_SIO | 1 << 3 | ioaddr << 5); + + *port = nval; + wbflush(); +} + +isa_long_t +lca_inl(ipfa, ioaddr) + void *ipfa; + isa_iooffset_t ioaddr; +{ + u_int32_t *port, val; + isa_long_t rval; + int offset; + + wbflush(); + offset = ioaddr & 3; + port = (int32_t *)phystok0seg(LCA_PCI_SIO | 3 << 3 | ioaddr << 5); + val = *port; + rval = ((val) >> (8 * offset)) & 0xffffffff; + rval = val & 0xffffffff; + + return rval; +} + +void +lca_outl(ipfa, ioaddr, val) + void *ipfa; + isa_iooffset_t ioaddr; + isa_long_t val; +{ + u_int32_t *port, nval; + int offset; + + offset = ioaddr & 3; + nval = val /*<< (8 * offset)*/; + port = (int32_t *)phystok0seg(LCA_PCI_SIO | 3 << 3 | ioaddr << 5); + + *port = nval; + wbflush(); +} + +/* XXX XXX XXX */ + +#define pf(fn, args) fn args { panic(__STRING(fn)); } + +void pf(lca_dma_cascade, (void *idfa, isa_drq_t chan)) +void pf(lca_dma_copytobuf, ()) +void pf(lca_dma_copyfrombuf, ()) +void pf(lca_dma_start, (void *idfa, vm_offset_t addr, + isa_msize_t size, isa_drq_t chan, int flags)) +void pf(lca_dma_abort, (void *idfa, isa_drq_t chan)) +void pf(lca_dma_done, (void *idfa, isa_drq_t chan)) + +int lca_dma_map __P((void *, vm_offset_t, isa_msize_t, + isa_moffset_t *, int)); +void lca_dma_unmap __P((void *, vm_offset_t, isa_msize_t, int, + isa_moffset_t *)); + +__const struct isa_dma_fns lca_dma_fns = { + lca_dma_cascade, + lca_dma_map, + lca_dma_unmap, + lca_dma_copytobuf, + lca_dma_copyfrombuf, + lca_dma_start, + lca_dma_abort, + lca_dma_done, +}; + +int +lca_dma_map(idfa, va, isasize, mappingsp, flags) + void *idfa; + vm_offset_t va; + isa_msize_t isasize; + isa_moffset_t *mappingsp; + int flags; +{ + struct lca_config *acp = idfa; + long todo; + int i; + + if (ISA_DMA_NEEDCONTIG(flags) && isasize > NBPG || + ISA_DMA_SIZEBOUND(flags) != ISA_DMA_SIZEBOUND_NONE || + ISA_DMA_ADDRBOUND(flags) != ISA_DMA_ADDRBOUND_NONE) + panic("lca_dma_map: punt"); + + i = 0; + todo = isasize; + + while (todo > 0) { + mappingsp[i] = vtophys(va) | 0x40000000; +#if 0 + printf("a_pd_m mapping %d: %lx -> %lx -> %lx\n", i, va, + vtophys(va), mappingsp[i]); +#endif + i++; + todo -= PAGE_SIZE - (va - trunc_page(va)); + va += PAGE_SIZE - (va - trunc_page(va)); + } + return (i); +} + +void +lca_dma_unmap(idfa, va, isasize, nmappings, mappingsp) + void *idfa; + vm_offset_t va; + isa_msize_t isasize; + int nmappings; + isa_moffset_t *mappingsp; +{ + + printf("lca_dma_unmap: called\n"); +} + +vm_offset_t lca_mem_map __P((void *, isa_moffset_t, isa_msize_t, int)); +void lca_mem_unmap __P((void *, vm_offset_t, isa_msize_t)); + +#if 0 +void lca_mem_copytoisa __P((void *, char *, vm_offset_t, + isa_moffset_t, isa_msize_t)); +void lca_mem_copyfromisa __P((void *, char *, vm_offset_t, + isa_moffset_t, isa_msize_t)); +void lca_mem_zero __P((void *, vm_offset_t, isa_moffset_t, + isa_msize_t)); +#else +void pf(lca_mem_copytoisa, ()) +void pf(lca_mem_copyfromisa, ()) +void pf(lca_mem_zero, ()) +#endif + +__const struct isa_mem_fns lca_mem_fns = { + lca_mem_map, + lca_mem_unmap, + lca_mem_copytoisa, + lca_mem_copyfromisa, + lca_mem_zero, +}; + +vm_offset_t +lca_mem_map(imfa, isapa, isasize, cacheable) + void *imfa; + isa_moffset_t isapa; + isa_msize_t isasize; + int cacheable; +{ + vm_offset_t sbpa; + + /* XXX sanity checks on sizes, use of windows, etc. */ + + /* XXX MAGIC NUMBERS */ + if (cacheable) + sbpa = (isapa & 0xffffffff) | LCA_PCI_DENSE; + else + sbpa = ((isapa & 0x7ffffff) << 5) | LCA_PCI_SPARSE; + + return phystok0seg(sbpa); +} + +void +lca_mem_unmap(imfa, va, isasize) + void *imfa; + vm_offset_t va; + isa_msize_t isasize; +{ + + /* XXX sanity checks on va */ + + /* Nothing to do; mapping was done in direct-mapped segment. */ +} diff --git a/sys/arch/alpha/pci/lca_pci.c b/sys/arch/alpha/pci/lca_pci.c new file mode 100644 index 00000000000..1b151dcefb9 --- /dev/null +++ b/sys/arch/alpha/pci/lca_pci.c @@ -0,0 +1,226 @@ +/* $NetBSD: lca_pci.c,v 1.1 1995/11/23 02:37:42 cgd Exp $ */ + +/* + * Copyright (c) 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Jeffrey Hsu + * + * 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 <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <alpha/pci/lcareg.h> +#include <alpha/pci/lcavar.h> + +pci_confreg_t lca_conf_read __P((void *, pci_conftag_t, pci_confoffset_t)); +void lca_conf_write __P((void *, pci_conftag_t, + pci_confoffset_t, pci_confreg_t)); +int lca_find_io __P((void *, pci_conftag_t, + pci_confoffset_t, pci_iooffset_t *, pci_iosize_t *)); +int lca_find_mem __P((void *, pci_conftag_t, + pci_confoffset_t, pci_moffset_t *, pci_msize_t *, int *)); + +__const struct pci_conf_fns lca_conf_fns = { + lca_conf_read, + lca_conf_write, + lca_find_io, + lca_find_mem, +}; + +pci_confreg_t +lca_conf_read(cpv, tag, offset) + void *cpv; + pci_conftag_t tag; + pci_confoffset_t offset; +{ + pci_confreg_t *datap, data; + int s, secondary, ba; + int32_t old_ioc_conf; /* XXX */ + u_int64_t dev_sel; + + dev_sel = 1 << PCI_TAG_DEVICE(tag) + 11; + + secondary = PCI_TAG_BUS(tag) != 0; + if (secondary) { + s = splhigh(); + old_ioc_conf = REGVAL(LCA_IOC_CONF); + wbflush(); + REGVAL(LCA_IOC_CONF) = old_ioc_conf | 0x1; + wbflush(); + } + + datap = (pci_confreg_t *)phystok0seg(LCA_PCI_CONF | + dev_sel << 5UL | /* XXX */ + (offset & ~0x03) << 5 | /* XXX */ + 0 << 5 | /* XXX */ + 0x3 << 3); /* XXX */ + data = (pci_confreg_t)-1; + if (!(ba = badaddr(datap, sizeof *datap))) + data = *datap; + + if (secondary) { + wbflush(); + REGVAL(LCA_IOC_CONF) = old_ioc_conf; + wbflush(); + splx(s); + } + +#if 0 + printf("lca_conf_read: tag 0x%x, offset 0x%x -> %x @ %p%s\n", tag, + offset, data, datap, ba ? " (badaddr)" : ""); +#endif + + return data; +} + +void +lca_conf_write(cpv, tag, offset, data) + void *cpv; + pci_conftag_t tag; + pci_confoffset_t offset; + pci_confreg_t data; +{ + pci_confreg_t *datap; + int s, secondary; + int32_t old_ioc_conf; /* XXX */ + int32_t dev_sel; + + dev_sel = 1 << PCI_TAG_DEVICE(tag) + 11; + + secondary = PCI_TAG_BUS(tag) != 0; + if (secondary) { + s = splhigh(); + old_ioc_conf = REGVAL(LCA_IOC_CONF); + wbflush(); + REGVAL(LCA_IOC_CONF) = old_ioc_conf | 0x1; + wbflush(); + } + + datap = (pci_confreg_t *)phystok0seg(LCA_PCI_CONF | + dev_sel << 5UL | /* XXX */ + (offset & ~0x03) << 5 | /* XXX */ + 0 << 5 | /* XXX */ + 0x3 << 3); /* XXX */ + *datap = data; + + if (secondary) { + wbflush(); + REGVAL(LCA_IOC_CONF) = old_ioc_conf; + wbflush(); + splx(s); + } + +#if 0 + printf("lca_conf_write: tag 0x%x, offset 0x%x -> 0x%x @ %p\n", tag, + offset, data, datap); +#endif +} + +int +lca_find_io(cpv, tag, reg, iobasep, sizep) + void *cpv; + pci_conftag_t tag; + pci_confoffset_t reg; + pci_iooffset_t *iobasep; + pci_iosize_t *sizep; +{ + struct lca_config *lcp = cpv; + pci_confreg_t addrdata, sizedata; + pci_iooffset_t pci_iobase; + + if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) + panic("lca_map_io: bad request"); + + addrdata = PCI_CONF_READ(lcp->lc_conffns, lcp->lc_confarg, tag, reg); + + PCI_CONF_WRITE(lcp->lc_conffns, lcp->lc_confarg, tag, reg, 0xffffffff); + sizedata = PCI_CONF_READ(lcp->lc_conffns, lcp->lc_confarg, tag, reg); + PCI_CONF_WRITE(lcp->lc_conffns, lcp->lc_confarg, tag, reg, addrdata); + + if (PCI_MAPREG_TYPE(addrdata) == PCI_MAPREG_TYPE_MEM) + panic("lca_map_io: attempt to I/O map an memory region"); + + if (iobasep != NULL) + *iobasep = PCI_MAPREG_IO_ADDRESS(addrdata); + if (sizep != NULL) + *sizep = ~PCI_MAPREG_IO_ADDRESS(sizedata) + 1; + + return (0); +} + +int +lca_find_mem(cpv, tag, reg, paddrp, sizep, cacheablep) + void *cpv; + pci_conftag_t tag; + pci_confoffset_t reg; + pci_moffset_t *paddrp; + pci_msize_t *sizep; + int *cacheablep; +{ + struct lca_config *lcp = cpv; + pci_confreg_t addrdata, sizedata; + + if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) + panic("lca_map_mem: bad request"); + + /* + * The PROM has mapped the device for us. We take the address + * that's been assigned to the register, and figure out what + * physical and virtual addresses go with it... + */ + addrdata = PCI_CONF_READ(lcp->lc_conffns, lcp->lc_confarg, tag, reg); + + PCI_CONF_WRITE(lcp->lc_conffns, lcp->lc_confarg, tag, reg, 0xffffffff); + sizedata = PCI_CONF_READ(lcp->lc_conffns, lcp->lc_confarg, tag, reg); + PCI_CONF_WRITE(lcp->lc_conffns, lcp->lc_confarg, tag, reg, addrdata); + + if (PCI_MAPREG_TYPE(addrdata) == PCI_MAPREG_TYPE_IO) + panic("lca_map_mem: attempt to memory map an I/O region"); + + switch (PCI_MAPREG_MEM_TYPE(addrdata)) { + case PCI_MAPREG_MEM_TYPE_32BIT: + case PCI_MAPREG_MEM_TYPE_32BIT_1M: + break; + case PCI_MAPREG_MEM_TYPE_64BIT: +/* XXX */ printf("lca_map_mem: attempt to map 64-bit region\n"); +/* XXX */ break; + default: + printf("lca_map_mem: reserved mapping type\n"); + return EINVAL; + } + + if (paddrp != NULL) + *paddrp = PCI_MAPREG_MEM_ADDRESS(addrdata); /* PCI addr */ + if (sizep != NULL) + *sizep = ~PCI_MAPREG_MEM_ADDRESS(sizedata) + 1; + if (cacheablep != NULL) + *cacheablep = PCI_MAPREG_MEM_CACHEABLE(addrdata); + + return 0; +} diff --git a/sys/arch/alpha/pci/lcareg.h b/sys/arch/alpha/pci/lcareg.h new file mode 100644 index 00000000000..ac876e3110d --- /dev/null +++ b/sys/arch/alpha/pci/lcareg.h @@ -0,0 +1,55 @@ +/* $NetBSD: lcareg.h,v 1.1 1995/11/23 02:37:44 cgd Exp $ */ + +/* + * Copyright (c) 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Jeffrey Hsu + * + * 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. + */ + +/* + * 21066 chip registers + */ + +#define REGVAL(r) (*(int32_t *)phystok0seg(r)) + +/* + * Base addresses + */ +#define LCA_IOC_BASE 0x180000000L /* LCA IOC Regs */ +#define LCA_PCI_SIO 0x1c0000000L /* PCI Sp. I/O Space */ +#define LCA_PCI_CONF 0x1e0000000L /* PCI Conf. Space */ +#define LCA_PCI_SPARSE 0x200000000L /* PCI Sparse Space */ +#define LCA_PCI_DENSE 0x300000000L /* PCI Dense Space */ + +#define LCA_IOC_HAE LCA_IOC_BASE /* Host Address Extension */ + +#define LCA_IOC_CONF (LCA_IOC_BASE + 0x020) /* Configuration Cycle Type */ + +#define LCA_IOC_W_BASE0 (LCA_IOC_BASE + 0x100) /* Window Base */ +#define LCA_IOC_W_MASK0 (LCA_IOC_BASE + 0x140) /* Window Mask */ +#define LCA_IOC_W_T_BASE0 (LCA_IOC_BASE + 0x180) /* Translated Base */ + +#define LCA_IOC_W_BASE1 (LCA_IOC_BASE + 0x120) /* Window Base */ +#define LCA_IOC_W_MASK1 (LCA_IOC_BASE + 0x160) /* Window Mask */ +#define LCA_IOC_W_T_BASE1 (LCA_IOC_BASE + 0x1a0) /* Translated Base */ diff --git a/sys/arch/alpha/pci/lcavar.h b/sys/arch/alpha/pci/lcavar.h new file mode 100644 index 00000000000..80c70807172 --- /dev/null +++ b/sys/arch/alpha/pci/lcavar.h @@ -0,0 +1,68 @@ +/* $NetBSD: lcavar.h,v 1.1 1995/11/23 02:37:47 cgd Exp $ */ + +/* + * Copyright (c) 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Jeffrey Hsu + * + * 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 <dev/isa/isavar.h> +#include <dev/pci/pcivar.h> + +/* + * LCA chipset's configuration. + * + * All of the information that the chipset-specific functions need to + * do their dirty work (and more!). + */ +struct lca_config { + __const struct pci_conf_fns *lc_conffns; + void *lc_confarg; + + __const struct pci_dma_fns *lc_dmafns; + void *lc_dmaarg; + + __const struct pci_intr_fns *lc_intrfns; + void *lc_intrarg; + + __const struct pci_mem_fns *lc_memfns; + void *lc_memarg; + + __const struct pci_pio_fns *lc_piofns; + void *lc_pioarg; +}; + +struct lca_softc { + struct device sc_dev; + + struct lca_config *sc_lcp; +}; + +extern __const struct pci_conf_fns lca_conf_fns; +extern __const struct pci_dma_fns lca_dma_fns; +/* pci interrupt functions handled elsewhere */ +extern __const struct pci_mem_fns lca_mem_fns; +extern __const struct pci_pio_fns lca_pio_fns; + +void lca_init __P((struct lca_config *)); diff --git a/sys/arch/alpha/pci/pci_2100_a50.c b/sys/arch/alpha/pci/pci_2100_a50.c index 9390f581e54..c33a9a83b0e 100644 --- a/sys/arch/alpha/pci/pci_2100_a50.c +++ b/sys/arch/alpha/pci/pci_2100_a50.c @@ -1,4 +1,4 @@ -/* $NetBSD: pci_2100_a50.c,v 1.2 1995/08/03 01:17:10 cgd Exp $ */ +/* $NetBSD: pci_2100_a50.c,v 1.3 1995/11/23 02:37:49 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -33,68 +33,54 @@ #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> +#include <dev/pci/pcivar.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)); +#include <alpha/pci/apecsvar.h> -struct pci_cfg_fcns pci_2100_a50_sio1_cfg_fcns = { /* XXX diff? */ - pci_2100_a50_attach, pci_2100_a50_map_int, -}; +#include <alpha/pci/pci_2100_a50.h> +#include <alpha/pci/siovar.h> -struct pci_cfg_fcns pci_2100_a50_sio2_cfg_fcns = { - pci_2100_a50_attach, pci_2100_a50_map_int, -}; +#include "sio.h" -void -pci_2100_a50_attach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - int bus, device; +void *dec_2100_a50_pci_map_int __P((void *, pci_conftag_t, + pci_intr_pin_t, pci_intr_line_t, pci_intrlevel_t, + int (*func)(void *), void *)); +void dec_2100_a50_pci_unmap_int __P((void *, void *)); -#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); -} +__const struct pci_intr_fns dec_2100_a50_pci_intr_fns = { + dec_2100_a50_pci_map_int, + dec_2100_a50_pci_unmap_int, +}; void * -pci_2100_a50_map_int(tag, level, func, arg, pin) - pcitag_t tag; - pci_intrlevel level; +dec_2100_a50_pci_map_int(acv, tag, pin, line, level, func, arg) + void *acv; + pci_conftag_t tag; + pci_intr_pin_t pin; + pci_intr_line_t line; + pci_intrlevel_t level; int (*func) __P((void *)); void *arg; - int pin; { + struct apecs_config *acp = acv; int bus, device, pirq; - pcireg_t pirqreg; - u_int8_t line; + pci_confreg_t irreg, pirqreg; + u_int8_t pirqline; - bus = (tag >> 21) & 0xff; /* XXX */ - device = (tag >> 16) & 0x1f; + if (pin == 0) { + /* No IRQ used. */ + return 0; + } + if (pin > 4) { + printf("pci_map_int: bad interrupt pin %d\n", pin); + return NULL; + } - if (bus != 0) /* XXX */ - return NULL; + device = PCI_TAG_DEVICE(tag); switch (device) { case 6: /* NCR SCSI */ @@ -147,43 +133,65 @@ pci_2100_a50_map_int(tag, level, func, arg, pin) break; } - pirqreg = pci_conf_read(pci_make_tag(0, 7, 0), 0x60); /* XXX */ + pirqreg = PCI_CONF_READ(acp->ac_conffns, acp->ac_confarg, + 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) + pirqline = (pirqreg >> (pirq * 8)) & 0xff; + if ((pirqline & 0x80) != 0) return 0; /* not routed? */ - line &= 0xf; + pirqline &= 0xf; #if 0 printf("pci_2100_a50_map_int: device %d pin %c: mapped to line %d\n", - device, '@' + pin, line); + device, '@' + pin, pirqline); #endif - return isa_intr_establish(line, ISA_IST_LEVEL, pcilevel_to_isa(level), +#if NSIO + return ISA_INTR_ESTABLISH(&sio_isa_intr_fns, NULL, /* XXX */ + pirqline, ISA_IST_LEVEL, pci_intrlevel_to_isa(level), func, arg); +#else + panic("dec_2100_a50_pci_map_int: no sio!"); +#endif +} + +void +dec_2100_a50_pci_unmap_int(pifa, cookie) + void *pifa; + void *cookie; +{ + + panic("dec_2100_a50_pci_unmap_int not implemented"); /* XXX */ } void -pci_2100_a50_pickintr() +pci_2100_a50_pickintr(pcf, pcfa, ppf, ppfa, pifp, pifap) + __const struct pci_conf_fns *pcf; + __const struct pci_pio_fns *ppf; + void *pcfa, *ppfa; + __const struct pci_intr_fns **pifp; + void **pifap; { - pcireg_t sioclass; + pci_confreg_t sioclass; int sioII; /* XXX MAGIC NUMBER */ - sioclass = pci_conf_read(pci_make_tag(0, 7, 0), PCI_CLASS_REG); + sioclass = PCI_CONF_READ(pcf, pcfa, 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; + printf("WARNING: SIO NOT SIO II... NO BETS...\n"); - isa_intr_fcns = &sio_intr_fcns; - (*isa_intr_fcns->isa_intr_setup)(); - set_iointr(isa_intr_fcns->isa_iointr); + *pifp = &dec_2100_a50_pci_intr_fns; + *pifap = pcfa; /* XXX assumes apecs_config ptr */ +#if NSIO + sio_intr_setup(ppf, ppfa); + set_iointr(&sio_iointr); +#else + panic("pci_2100_a50_pickintr: no I/O interrupt handler (no sio)"); +#endif } diff --git a/sys/arch/alpha/pci/pci_2100_a50.h b/sys/arch/alpha/pci/pci_2100_a50.h new file mode 100644 index 00000000000..08c22aef089 --- /dev/null +++ b/sys/arch/alpha/pci/pci_2100_a50.h @@ -0,0 +1,32 @@ +/* $NetBSD: pci_2100_a50.h,v 1.1 1995/11/23 02:37:51 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. + */ + +void pci_2100_a50_pickintr __P((__const struct pci_conf_fns *, void *, + __const struct pci_pio_fns *, void *, + __const struct pci_intr_fns **, void **)); diff --git a/sys/arch/alpha/pci/pci_axppci_33.c b/sys/arch/alpha/pci/pci_axppci_33.c new file mode 100644 index 00000000000..74fb338e91f --- /dev/null +++ b/sys/arch/alpha/pci/pci_axppci_33.c @@ -0,0 +1,204 @@ +/* $NetBSD: pci_axppci_33.c,v 1.1 1995/11/23 02:37:54 cgd Exp $ */ + +/* + * Copyright (c) 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Jeffrey Hsu + * + * 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 <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> + +#include <alpha/pci/lcavar.h> + +#include <alpha/pci/pci_axppci_33.h> + +#include <alpha/pci/siovar.h> + +#include "sio.h" + +void *dec_axppci_33_pci_map_int __P((void *, pci_conftag_t, + pci_intr_pin_t, pci_intr_line_t, pci_intrlevel_t, + int (*func)(void *), void *)); +void dec_axppci_33_pci_unmap_int __P((void *, void *)); + +__const struct pci_intr_fns dec_axppci_33_pci_intr_fns = { + dec_axppci_33_pci_map_int, + dec_axppci_33_pci_unmap_int, +}; + +void * +dec_axppci_33_pci_map_int(lcv, tag, pin, line, level, func, arg) + void *lcv; + pci_conftag_t tag; + pci_intr_pin_t pin; + pci_intr_line_t line; + pci_intrlevel_t level; + int (*func) __P((void *)); + void *arg; +{ + struct lca_config *lcp = lcv; + int bus, device, pirq; + pci_confreg_t irreg, pirqreg; + u_int8_t pirqline; + + if (pin == 0) { + /* No IRQ used. */ + return 0; + } + if (pin > 4) { + printf("dec_axppci_33_map_int: bad interrupt pin %d\n", pin); + return NULL; + } + + device = PCI_TAG_DEVICE(tag); + + 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 8: /* 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; + default: + printf("dec_axppci_33_pci_map_int: unknown device %d\n", + device); + panic("dec_axppci_33_pci_map_int: bad device number"); + } + +#define LCA_SIO_DEVICE 7 /* XXX */ + + pirqreg = PCI_CONF_READ(lcp->lc_conffns, lcp->lc_confarg, + PCI_MAKE_TAG(0, LCA_SIO_DEVICE, 0), 0x60); /* XXX */ +#if 0 + printf("dec_pci_axppci_33_map_int: device %d pin %c: pirq %d, reg = %x\n", + device, '@' + pin, pirq, pirqreg); +#endif + pirqline = (pirqreg >> (pirq * 8)) & 0xff; + if ((pirqline & 0x80) != 0) + return 0; /* not routed? */ + pirqline &= 0xf; + +#if 0 + printf("dec_pci_axppci_33_map_int: device %d pin %c: mapped to line %d\n", + device, '@' + pin, pirqline); +#endif + +#if NSIO + return ISA_INTR_ESTABLISH(&sio_isa_intr_fns, NULL, /* XXX */ + pirqline, ISA_IST_LEVEL, pci_intrlevel_to_isa(level), + func, arg); +#else + panic("dec_axppci_33_pci_map_int: no sio!"); +#endif +} + +void +dec_axppci_33_pci_unmap_int(pifa, cookie) + void *pifa; + void *cookie; +{ + + panic("dec_axppci_33_pci_unmap_int not implemented"); /* XXX */ +} + +void +pci_axppci_33_pickintr(pcf, pcfa, ppf, ppfa, pifp, pifap) + __const struct pci_conf_fns *pcf; + __const struct pci_pio_fns *ppf; + void *pcfa, *ppfa; + __const struct pci_intr_fns **pifp; + void **pifap; +{ + pci_confreg_t sioclass; + int sioII; + + /* XXX MAGIC NUMBER */ + sioclass = PCI_CONF_READ(pcf, pcfa, PCI_MAKE_TAG(0, LCA_SIO_DEVICE, 0), + PCI_CLASS_REG); + sioII = (sioclass & 0xff) >= 3; + + if (!sioII) + printf("WARNING: SIO NOT SIO II... NO BETS...\n"); + + *pifp = &dec_axppci_33_pci_intr_fns; + *pifap = pcfa; /* XXX assumes apecs_config ptr */ +#if NSIO + sio_intr_setup(ppf, ppfa); + set_iointr(&sio_iointr); +#else + panic("pci_axppci_33_pickintr: no I/O interrupt handler (no sio)"); +#endif +} diff --git a/sys/arch/alpha/pci/pci_axppci_33.h b/sys/arch/alpha/pci/pci_axppci_33.h new file mode 100644 index 00000000000..342eb0dfd71 --- /dev/null +++ b/sys/arch/alpha/pci/pci_axppci_33.h @@ -0,0 +1,32 @@ +/* $NetBSD: pci_axppci_33.h,v 1.1 1995/11/23 02:37:56 cgd Exp $ */ + +/* + * Copyright (c) 1995 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Jeffrey Hsu + * + * 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. + */ + +void pci_axppci_33_pickintr __P((__const struct pci_conf_fns *, void *, + __const struct pci_pio_fns *, void *, + __const struct pci_intr_fns **, void **)); diff --git a/sys/arch/alpha/pci/pci_chipset.h b/sys/arch/alpha/pci/pci_chipset.h deleted file mode 100644 index 4d333aee27e..00000000000 --- a/sys/arch/alpha/pci/pci_chipset.h +++ /dev/null @@ -1,74 +0,0 @@ -/* $NetBSD: pci_chipset.h,v 1.3 1995/08/03 01:17:14 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. - */ - -/* - * 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_io) __P((pcitag_t, int, int *)); - 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)); diff --git a/sys/arch/alpha/pci/pci_kn20aa.c b/sys/arch/alpha/pci/pci_kn20aa.c new file mode 100644 index 00000000000..c5c64d636b8 --- /dev/null +++ b/sys/arch/alpha/pci/pci_kn20aa.c @@ -0,0 +1,294 @@ +/* $NetBSD: pci_kn20aa.c,v 1.1 1995/11/23 02:38:00 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/types.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/systm.h> +#include <sys/errno.h> +#include <sys/malloc.h> +#include <sys/device.h> +#include <sys/syslog.h> + +#include <vm/vm.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> + +#include <alpha/pci/ciareg.h> +#include <alpha/pci/ciavar.h> + +#include <alpha/pci/pci_kn20aa.h> + +#ifndef EVCNT_COUNTERS +#include <machine/intrcnt.h> +#endif + +#include "sio.h" +#if NSIO +#include <alpha/pci/siovar.h> +#endif + +void *kn20aa_pci_map_int __P((void *, pci_conftag_t, pci_intr_pin_t, + pci_intr_line_t, pci_intrlevel_t, int (*func)(void *), void *)); +void kn20aa_pci_unmap_int __P((void *, void *)); + +__const struct pci_intr_fns kn20aa_pci_intr_fns = { + kn20aa_pci_map_int, + kn20aa_pci_unmap_int, +}; + +#define KN20AA_PCEB_IRQ 31 +#define KN20AA_MAX_IRQ 32 +#define PCI_STRAY_MAX 5 + +struct kn20aa_intrhand { + TAILQ_ENTRY(kn20aa_intrhand) ih_q; + int (*ih_fun)(); + void *ih_arg; + u_long ih_count; + int ih_level; +}; +TAILQ_HEAD(kn20aa_intrchain, kn20aa_intrhand); + +struct kn20aa_intrchain kn20aa_pci_intrs[KN20AA_MAX_IRQ]; +int kn20aa_pci_strayintrcnt[KN20AA_MAX_IRQ]; +#ifdef EVCNT_COUNTERS +struct evcnt kn20aa_intr_evcnt; +#endif + +void kn20aa_pci_strayintr __P((int irq)); +void kn20aa_iointr __P((void *framep, int vec)); +void kn20aa_enable_intr __P((int irq)); +struct kn20aa_intrhand *kn20aa_attach_intr __P((struct kn20aa_intrchain *, + pci_intrlevel_t, int (*) (void *), void *)); + +void +pci_kn20aa_pickintr(pcf, pcfa, ppf, ppfa, pifp, pifap) + __const struct pci_conf_fns *pcf; + __const struct pci_pio_fns *ppf; + void *pcfa, *ppfa; + __const struct pci_intr_fns **pifp; + void **pifap; +{ + int i; + struct kn20aa_intrhand *nintrhand; + + + for (i = 0; i < KN20AA_MAX_IRQ; i++) + TAILQ_INIT(&kn20aa_pci_intrs[i]); + + *pifp = &kn20aa_pci_intr_fns; + *pifap = NULL; /* XXX ? */ + +#if NSIO + sio_intr_setup(ppf, ppfa); +#endif + + set_iointr(kn20aa_iointr); + +#if NSIO + kn20aa_enable_intr(KN20AA_PCEB_IRQ); +#if 0 /* XXX init PCEB interrupt handler? */ + kn20aa_attach_intr(&kn20aa_pci_intrs[KN20AA_PCEB_IRQ], ???, ???, ???); +#endif +#endif +} + +void * +kn20aa_pci_map_int(ccv, tag, pin, line, level, func, arg) + void *ccv; + pci_conftag_t tag; + pci_intr_pin_t pin; + pci_intr_line_t line; + pci_intrlevel_t level; + int (*func) __P((void *)); + void *arg; +{ + int device; + int kn20aa_slot, kn20aa_irq; + void *ih; + + if (pin == 0) { + /* No IRQ used. */ + return 0; + } + if (pin > 4) { + printf("pci_map_int: bad interrupt pin %d\n", pin); + return NULL; + } + + /* + * Slot->interrupt translation. Appears to work, though it + * may not hold up forever. + * + * The DEC engineers who did this hardware obviously engaged + * in random drug testing. + */ + switch (device = PCI_TAG_DEVICE(tag)) { + case 11: + case 12: + kn20aa_slot = (device - 11) + 0; + break; + + case 7: + kn20aa_slot = 2; + break; + + case 8: + kn20aa_slot = 4; + break; + + case 9: + kn20aa_slot = 3; + break; + + default: + panic("pci_kn20aa_map_int: invalid device number %d\n", + device); + } + + kn20aa_irq = (kn20aa_slot * 4) + pin - 1; + if (kn20aa_irq > KN20AA_MAX_IRQ) + panic("pci_kn20aa_map_int: kn20aa_irq too large (%d)\n", + kn20aa_irq); + +#if 0 + printf("kn20aa_attach_intr: func 0x%lx, arg 0x%lx, level %d, irq %d\n", + func, arg, level, kn20aa_irq); +#endif + + ih = kn20aa_attach_intr(&kn20aa_pci_intrs[kn20aa_irq], level, + func, arg); + kn20aa_enable_intr(kn20aa_irq); + return (ih); +} + +void +kn20aa_pci_unmap_int(pifa, cookie) + void *pifa; + void *cookie; +{ + + panic("kn20aa_pci_unmap_int not implemented"); /* XXX */ +} + +/* + * caught a stray interrupt; notify if not too many seen already. + */ +void +kn20aa_pci_strayintr(irq) + int irq; +{ + + if (++kn20aa_pci_strayintrcnt[irq] <= PCI_STRAY_MAX) + log(LOG_ERR, "stray PCI interrupt %d%s\n", irq, + kn20aa_pci_strayintrcnt[irq] >= PCI_STRAY_MAX ? + "; stopped logging" : ""); +} + +void +kn20aa_iointr(framep, vec) + void *framep; + int vec; +{ + struct kn20aa_intrhand *ih; + int irq, handled; + + if (vec >= 0x900) { + if (vec >= 0x900 + (KN20AA_MAX_IRQ << 4)) + panic("kn20aa_iointr: vec 0x%x out of range\n", vec); + irq = (vec - 0x900) >> 4; + +#ifdef EVCNT_COUNTERS + kn20aa_intr_evcnt.ev_count++; +#else + if (KN20AA_MAX_IRQ != INTRCNT_KN20AA_IRQ_LEN) + panic("kn20aa interrupt counter sizes inconsistent"); + intrcnt[INTRCNT_KN20AA_IRQ + irq]++; +#endif + + for (ih = kn20aa_pci_intrs[irq].tqh_first, handled = 0; + ih != NULL; ih = ih->ih_q.tqe_next) { + int rv; + + rv = (*ih->ih_fun)(ih->ih_arg); + + ih->ih_count++; + handled = handled || (rv != 0); + } + if (!handled) + kn20aa_pci_strayintr(irq); + return; + } + if (vec >= 0x800) { +#if NSIO + sio_iointr(framep, vec); +#endif + return; + } + panic("kn20aa_iointr: weird vec 0x%x\n", vec); +} + +void +kn20aa_enable_intr(irq) + int irq; +{ + + /* + * From disassembling the OSF/1 source code: + * the following appears to enable a given interrupt request. + * "blech." I'd give valuable body parts for better docs or + * for a good decompiler. + */ + wbflush(); + REGVAL(0x8780000000L + 0x40L) |= (1 << irq); /* XXX */ + wbflush(); +} + +struct kn20aa_intrhand * +kn20aa_attach_intr(chain, level, func, arg) + struct kn20aa_intrchain *chain; + pci_intrlevel_t level; + int (*func) __P((void *)); + void *arg; +{ + struct kn20aa_intrhand *nintrhand; + + nintrhand = (struct kn20aa_intrhand *) + malloc(sizeof *nintrhand, M_DEVBUF, M_WAITOK); + + nintrhand->ih_fun = func; + nintrhand->ih_arg = arg; + nintrhand->ih_count = 0; + nintrhand->ih_level = level; + TAILQ_INSERT_TAIL(chain, nintrhand, ih_q); + + return (nintrhand); +} diff --git a/sys/arch/alpha/pci/pci_kn20aa.h b/sys/arch/alpha/pci/pci_kn20aa.h new file mode 100644 index 00000000000..4e499317ea0 --- /dev/null +++ b/sys/arch/alpha/pci/pci_kn20aa.h @@ -0,0 +1,36 @@ +/* $NetBSD: pci_kn20aa.h,v 1.1 1995/11/23 02:38:05 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. + */ + +void pci_kn20aa_pickintr __P((__const struct pci_conf_fns *, void *, + __const struct pci_pio_fns *, void *, + __const struct pci_intr_fns **, void **)); + +#ifdef EVCNT_COUNTERS +extern struct evcnt kn20aa_intr_evcnt; +#endif diff --git a/sys/arch/alpha/pci/pci_machdep.c b/sys/arch/alpha/pci/pci_machdep.c index bacb5273362..02eb57caeaa 100644 --- a/sys/arch/alpha/pci/pci_machdep.c +++ b/sys/arch/alpha/pci/pci_machdep.c @@ -1,32 +1,30 @@ -/* $NetBSD: pci_machdep.c,v 1.2 1995/08/03 00:33:58 cgd Exp $ */ +/* $NetBSD: pci_machdep.c,v 1.3 1995/11/23 02:38:07 cgd Exp $ */ /* - * Copyright (c) 1994 Charles Hannum. All rights reserved. + * Copyright (c) 1995 Carnegie-Mellon University. + * 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. + * 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 * - * 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. + * 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. */ /* @@ -43,206 +41,56 @@ #include <vm/vm.h> #include <dev/isa/isavar.h> -#include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> -#include <alpha/pci/pci_chipset.h> #include "pcivga.h" -#include "tga.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; -{ - - return (*pci_cs_fcns->cs_map_io)(tag, reg, iobasep); -} - -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); +#if NPCIVGA +#include <alpha/pci/pcivgavar.h> +#endif - default: - panic("pcilevel_to_isa: unknown level %d\n", level); - } -} +#include "tga.h" +#if NTGA +#include <alpha/pci/tgavar.h> +#endif void -pci_display_console(bus, device, function) - int bus, device, function; +pci_display_console(pcf, pcfa, pmf, pmfa, ppf, ppfa, bus, device, function) + __const struct pci_conf_fns *pcf; + __const struct pci_mem_fns *pmf; + __const struct pci_pio_fns *ppf; + void *pcfa, *pmfa, *ppfa; + pci_bus_t bus; + pci_device_t device; + pci_function_t function; { - pcitag_t tag; - pcireg_t id, class; - - /* XXX */ - tag = pci_make_tag(bus, device, function); + pci_conftag_t tag; + pci_confreg_t id, class; - id = pci_conf_read(tag, PCI_ID_REG); + tag = PCI_MAKE_TAG(bus, device, function); + id = PCI_CONF_READ(pcf, pcfa, tag, PCI_ID_REG); if (id == 0 || id == 0xffffffff) panic("pci_display_console: no device at %d/%d/%d", bus, device, function); - class = pci_conf_read(tag, PCI_CLASS_REG); - - if (PCI_CLASS(class) != PCI_CLASS_DISPLAY && - !(PCI_CLASS(class) == PCI_CLASS_PREHISTORIC && - PCI_SUBCLASS(class) == PCI_SUBCLASS_PREHISTORIC_VGA)) - panic("pci_display_console: device at %d/%d/%d not a display", - bus, device, function); + class = PCI_CONF_READ(pcf, pcfa, tag, PCI_CLASS_REG); - if ((PCI_CLASS(class) == PCI_CLASS_DISPLAY && - PCI_SUBCLASS(class) == PCI_SUBCLASS_DISPLAY_VGA) || - (PCI_CLASS(class) == PCI_CLASS_PREHISTORIC && - PCI_SUBCLASS(class) == PCI_SUBCLASS_PREHISTORIC_VGA)) { #if NPCIVGA - pcivga_console(bus, device, function); -#else - panic("pci_display_console: pcivga is console, not configured"); -#endif + if (DEVICE_IS_PCIVGA(class, id)) { + pcivga_console(pcf, pcfa, pmf, pmfa, ppf, ppfa, bus, + device, function); return; } +#endif - if (PCI_VENDOR(id) == PCI_VENDOR_DEC && - PCI_PRODUCT(id) == PCI_PRODUCT_DEC_21030) { #if NTGA - tga_console(bus, device, function); -#else - panic("pci_display_console: tga is console, not configured"); -#endif + if (DEVICE_IS_TGA(class, id)) { + tga_console(pcf, pcfa, pmf, pmfa, ppf, ppfa, bus, + device, function); return; } +#endif - panic("pci_display_console: unsupported device at %d/%d/%d", + panic("pci_display_console: unconfigured device at %d/%d/%d", bus, device, function); } diff --git a/sys/arch/alpha/pci/pci_machdep.h b/sys/arch/alpha/pci/pci_machdep.h deleted file mode 100644 index 6f4a8459b6e..00000000000 --- a/sys/arch/alpha/pci/pci_machdep.h +++ /dev/null @@ -1,53 +0,0 @@ -/* $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)); diff --git a/sys/arch/alpha/pci/pcivga.c b/sys/arch/alpha/pci/pcivga.c index b155f8f5951..10b2f3cbbec 100644 --- a/sys/arch/alpha/pci/pcivga.c +++ b/sys/arch/alpha/pci/pcivga.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcivga.c,v 1.2 1995/08/03 01:17:17 cgd Exp $ */ +/* $NetBSD: pcivga.c,v 1.3 1995/11/23 02:38:11 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -35,7 +35,6 @@ #include <machine/autoconf.h> #include <machine/pte.h> -#include <machine/pio.h> #include <dev/pseudo/ansicons.h> #include <dev/pci/pcireg.h> @@ -43,6 +42,7 @@ #include <dev/pci/pcidevs.h> #include <alpha/pci/pcivgavar.h> +#include <alpha/pci/wsconsvar.h> int pcivgamatch __P((struct device *, void *, void *)); void pcivgaattach __P((struct device *, struct device *, void *)); @@ -52,8 +52,19 @@ struct cfdriver pcivgacd = { sizeof(struct pcivga_softc) }; +void pcivga_getdevconfig __P((__const struct pci_conf_fns *, void *, + __const struct pci_mem_fns *, void *, + __const struct pci_pio_fns *, void *, + pci_conftag_t tag, struct pcivga_devconfig *dc)); + struct pcivga_devconfig pcivga_console_dc; +void pcivga_cursor __P((void *, int, int)); +void pcivga_putstr __P((void *, int, int, char *, int)); +void pcivga_copycols __P((void *, int, int, int,int)); +void pcivga_erasecols __P((void *, int, int, int)); +void pcivga_copyrows __P((void *, int, int, int)); +void pcivga_eraserows __P((void *, int, int)); void pcivga_bell __P((void *)); /* XXX */ struct ansicons_functions pcivga_acf = { @@ -74,54 +85,43 @@ pcivgamatch(parent, match, aux) void *match, *aux; { struct cfdata *cf = match; - struct pci_attach_args *pa = aux; + struct pcidev_attach_args *pda = aux; /* * If it's prehistoric/vga or display/vga, we match. */ - if ((PCI_CLASS(pa->pa_class) == PCI_CLASS_PREHISTORIC && - PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_PREHISTORIC_VGA) || - (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY && - PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA)) + if (PCI_CLASS(pda->pda_class) == PCI_CLASS_PREHISTORIC && + PCI_SUBCLASS(pda->pda_class) == PCI_SUBCLASS_PREHISTORIC_VGA) + return (1); + if (PCI_CLASS(pda->pda_class) == PCI_CLASS_DISPLAY && + PCI_SUBCLASS(pda->pda_class) == PCI_SUBCLASS_DISPLAY_VGA) return (1); return (0); } void -pcivga_getdevconfig(tag, dc) - pcitag_t tag; +pcivga_getdevconfig(pcf, pcfa, pmf, pmfa, ppf, ppfa, tag, dc) + __const struct pci_conf_fns *pcf; + __const struct pci_mem_fns *pmf; + __const struct pci_pio_fns *ppf; + void *pcfa, *pmfa, *ppfa; + pci_conftag_t tag; struct pcivga_devconfig *dc; { + dc->dc_pcf = pcf; + dc->dc_pcfa = pcfa; + dc->dc_pmf = pmf; + dc->dc_pmfa = pmfa; + dc->dc_ppf = ppf; + dc->dc_ppfa = ppfa; dc->dc_pcitag = tag; -#if 0 - vm_offset_t pciva, pcipa; - int i; - - dc->dc_vaddr = 0; - if (pci_map_mem(tag, 0x10, &dc->dc_vaddr, &pcipa)) - return; -#endif - -#if 0 - int i; - pcireg_t old; - - printf("\n"); - for (i = PCI_MAP_REG_START; i < PCI_MAP_REG_END; i += 4) { - old = pci_conf_read(tag, i); - pci_conf_write(tag, i, 0xffffffff); - printf("pcivga_getdevconfig: "); - printf("mapping reg @ %d = 0x%x (mask 0x%x)\n", - i, old, pci_conf_read(tag, i)); - pci_conf_write(tag, i, old); - } - printf("foo"); -#endif + /* XXX deal with mapping foo */ - dc->dc_crtat = (u_short *)phystok0seg(0xb8000 | (3L << 32)); /* XXX */ + /* XXX */ + dc->dc_crtat = (u_short *)PCI_MEM_MAP(pmf, pmfa, 0xb8000, 0x8000, 1); dc->dc_iobase = 0x3d4; /* XXX */ dc->dc_nrow = 25; @@ -141,26 +141,29 @@ pcivgaattach(parent, self, aux) struct device *parent, *self; void *aux; { - struct pci_attach_args *pa = aux; + struct pcidev_attach_args *pda = aux; struct pcivga_softc *sc = (struct pcivga_softc *)self; char devinfo[256]; int console; - console = (pa->pa_tag == pcivga_console_dc.dc_pcitag); + console = (pda->pda_tag == pcivga_console_dc.dc_pcitag); if (console) sc->sc_dc = &pcivga_console_dc; else { sc->sc_dc = (struct pcivga_devconfig *) malloc(sizeof(struct pcivga_devconfig), M_DEVBUF, M_WAITOK); - pcivga_getdevconfig(pa->pa_tag, sc->sc_dc); + pcivga_getdevconfig(pda->pda_conffns, pda->pda_confarg, + pda->pda_memfns, pda->pda_memarg, pda->pda_piofns, + pda->pda_memarg, pda->pda_tag, sc->sc_dc); } if (sc->sc_dc->dc_crtat == NULL) { printf(": couldn't map memory space; punt!\n"); return; } - pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, NULL); - printf(": %s (revision 0x%x)\n", devinfo, PCI_REVISION(pa->pa_class)); + pci_devinfo(pda->pda_id, pda->pda_class, 0, devinfo); + printf(": %s (rev. 0x%02x)\n", devinfo, + PCI_REVISION(pda->pda_class)); #if 0 if (sc->sc_dc->dc_tgaconf == NULL) { @@ -209,21 +212,28 @@ tgammap(dev, offset, nprot) #endif void -pcivga_console(bus, device, function) - int bus, device, function; +pcivga_console(pcf, pcfa, pmf, pmfa, ppf, ppfa, bus, device, function) + __const struct pci_conf_fns *pcf; + __const struct pci_mem_fns *pmf; + __const struct pci_pio_fns *ppf; + void *pcfa, *pmfa, *ppfa; + pci_bus_t bus; + pci_device_t device; + pci_function_t function; { struct pcivga_devconfig *dcp = &pcivga_console_dc; - pcivga_getdevconfig(pci_make_tag(bus, device, function), dcp); + pcivga_getdevconfig(pcf, pcfa, pmf, pmfa, ppf, ppfa, + PCI_MAKE_TAG(bus, device, function), dcp); /* sanity checks */ if (dcp->dc_crtat == NULL) - panic("pcivga_console(%d, %d, %d): couldn't map memory space", - bus, device, function); + panic("pcivga_console(%d, %d): couldn't map memory space", + device, function); #if 0 if (dcp->dc_pcivgaconf == NULL) - panic("pcivga_console(%d, %d, %d): unknown board configuration", - bus, device, function); + panic("pcivga_console(%d, %d): unknown board configuration", + device, function); #endif wsc_console(&dcp->dc_ansicons, &pcivga_acf, dcp, @@ -265,10 +275,10 @@ pcivga_cursor(id, row, col) pos = row * dc->dc_ncol + col; - outb(dc->dc_iobase, 14); - outb(dc->dc_iobase+1, pos >> 8); - outb(dc->dc_iobase, 15); - outb(dc->dc_iobase+1, pos); + OUTB(dc->dc_ppf, dc->dc_ppfa, dc->dc_iobase, 14); + OUTB(dc->dc_ppf, dc->dc_ppfa, dc->dc_iobase+1, pos >> 8); + OUTB(dc->dc_ppf, dc->dc_ppfa, dc->dc_iobase, 15); + OUTB(dc->dc_ppf, dc->dc_ppfa, dc->dc_iobase+1, pos); } void diff --git a/sys/arch/alpha/pci/pcivgavar.h b/sys/arch/alpha/pci/pcivgavar.h index 049fd2dca51..579ad4ca0a4 100644 --- a/sys/arch/alpha/pci/pcivgavar.h +++ b/sys/arch/alpha/pci/pcivgavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: pcivgavar.h,v 1.2 1995/08/03 01:17:21 cgd Exp $ */ +/* $NetBSD: pcivgavar.h,v 1.3 1995/11/23 02:38:13 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -27,8 +27,17 @@ * rights to redistribute these changes. */ +#include <dev/pseudo/ansicons.h> + struct pcivga_devconfig { - pcitag_t dc_pcitag; /* PCI tag */ + __const struct pci_conf_fns *dc_pcf; + void *dc_pcfa; + __const struct pci_mem_fns *dc_pmf; + void *dc_pmfa; + __const struct pci_pio_fns *dc_ppf; + void *dc_ppfa; + + pci_tag_t dc_pcitag; /* PCI tag */ u_int16_t *dc_crtat; /* VGA screen memory */ int dc_iobase; /* VGA I/O address */ @@ -52,9 +61,13 @@ struct pcivga_softc { #define PCIVGA_CURSOR_OFF -1 /* pass to pcivga_cpos to disable */ -void pcivga_cursor __P((void *, int, int)); -void pcivga_putstr __P((void *, int, int, char *, int)); -void pcivga_copycols __P((void *, int, int, int,int)); -void pcivga_erasecols __P((void *, int, int, int)); -void pcivga_copyrows __P((void *, int, int, int)); -void pcivga_eraserows __P((void *, int, int)); +#define DEVICE_IS_PCIVGA(class, id) \ + ((PCI_CLASS(class) == PCI_CLASS_DISPLAY && \ + PCI_SUBCLASS(class) == PCI_SUBCLASS_DISPLAY_VGA) || \ + (PCI_CLASS(class) == PCI_CLASS_PREHISTORIC && \ + PCI_SUBCLASS(class) == PCI_SUBCLASS_PREHISTORIC_VGA)) + +void pcivga_console __P((__const struct pci_conf_fns *, void *, + __const struct pci_mem_fns *, void *, + __const struct pci_pio_fns *, void *, + pci_bus_t, pci_device_t, pci_function_t)); diff --git a/sys/arch/alpha/pci/sio.c b/sys/arch/alpha/pci/sio.c index 5e37a5e0edc..a8b6b8a0a24 100644 --- a/sys/arch/alpha/pci/sio.c +++ b/sys/arch/alpha/pci/sio.c @@ -1,4 +1,4 @@ -/* $NetBSD: sio.c,v 1.2 1995/08/03 01:17:25 cgd Exp $ */ +/* $NetBSD: sio.c,v 1.3 1995/11/23 02:38:16 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -32,11 +32,14 @@ #include <sys/kernel.h> #include <sys/device.h> +#include <dev/isa/isavar.h> +#include <dev/eisa/eisavar.h> + #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> -#include <machine/autoconf.h> +#include <alpha/pci/siovar.h> int siomatch __P((struct device *, void *, void *)); void sioattach __P((struct device *, struct device *, void *)); @@ -45,6 +48,12 @@ struct cfdriver siocd = { NULL, "sio", siomatch, sioattach, DV_DULL, sizeof(struct device) }; +int pcebmatch __P((struct device *, void *, void *)); + +struct cfdriver pcebcd = { + NULL, "pceb", pcebmatch, sioattach, DV_DULL, sizeof(struct device) +}; + static int sioprint __P((void *, char *pnp)); int @@ -53,10 +62,25 @@ siomatch(parent, match, aux) void *match, *aux; { struct cfdata *cf = match; - struct pci_attach_args *pa = aux; + struct pcidev_attach_args *pda = aux; + + if (PCI_VENDOR(pda->pda_id) != PCI_VENDOR_INTEL || + PCI_PRODUCT(pda->pda_id) != PCI_PRODUCT_INTEL_SIO) + return (0); + + return (1); +} + +int +pcebmatch(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct cfdata *cf = match; + struct pcidev_attach_args *pda = aux; - if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL || - PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_INTEL_SIO) + if (PCI_VENDOR(pda->pda_id) != PCI_VENDOR_INTEL || + PCI_PRODUCT(pda->pda_id) != PCI_PRODUCT_INTEL_PCEB) return (0); return (1); @@ -67,31 +91,56 @@ 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 */ + struct pcidev_attach_args *pda = aux; + struct isa_attach_args ia; + struct eisa_attach_args ea; + int sio, haseisa; + char devinfo[256]; + + sio = (PCI_PRODUCT(pda->pda_id) == PCI_PRODUCT_INTEL_SIO); + haseisa = (PCI_PRODUCT(pda->pda_id) == PCI_PRODUCT_INTEL_PCEB); + + pci_devinfo(pda->pda_id, pda->pda_class, 0, devinfo); + printf(": %s (rev. 0x%02x)\n", devinfo, + PCI_REVISION(pda->pda_class)); + + if (sio) { + pci_revision_t rev; + + rev = PCI_REVISION(pda->pda_class); + + if (rev < 3) + printf("%s: WARNING: SIO I SUPPORT UNTESTED\n", + self->dv_xname); + } + +#ifdef EVCNT_COUNTERS + evcnt_attach(self, "intr", &sio_intr_evcnt); +#endif + + ia.ia_bus = BUS_ISA; + ia.ia_dmafns = pda->pda_dmafns; + ia.ia_dmaarg = pda->pda_dmaarg; + ia.ia_intrfns = &sio_isa_intr_fns; + ia.ia_intrarg = NULL; /* XXX needs nothing */ + ia.ia_memfns = pda->pda_memfns; + ia.ia_memarg = pda->pda_memarg; + ia.ia_piofns = pda->pda_piofns; + ia.ia_pioarg = pda->pda_pioarg; + config_found(self, &ia, sioprint); + + if (haseisa) { + ea.ea_bus = BUS_EISA; + ea.ea_dmafns = pda->pda_dmafns; + ea.ea_dmaarg = pda->pda_dmaarg; + ea.ea_intrfns = &sio_isa_intr_fns; + ea.ea_intrarg = NULL; /* XXX needs nothing */ + ea.ea_memfns = pda->pda_memfns; + ea.ea_memarg = pda->pda_memarg; + ea.ea_piofns = pda->pda_piofns; + ea.ea_pioarg = pda->pda_pioarg; + config_found(self, &ea, sioprint); } - 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 @@ -99,9 +148,14 @@ sioprint(aux, pnp) void *aux; char *pnp; { - register struct confargs *ca = aux; + register struct isa_attach_args *ia = aux; + + /* + * XXX Assumes that the first fields of 'struct isa_attach_args' + * XXX and 'struct eisa_attach_args' are the same. + */ if (pnp) - printf("%s at %s", ca->ca_name, pnp); + printf("%s at %s", isa_bustype_name(ia->ia_bus), pnp); return (UNCONF); } diff --git a/sys/arch/alpha/pci/sio_pic.c b/sys/arch/alpha/pci/sio_pic.c index e2f7e8cefdb..ec24ec96c5c 100644 --- a/sys/arch/alpha/pci/sio_pic.c +++ b/sys/arch/alpha/pci/sio_pic.c @@ -1,4 +1,4 @@ -/* $NetBSD: sio_pic.c,v 1.1 1995/06/28 01:26:13 cgd Exp $ */ +/* $NetBSD: sio_pic.c,v 1.2 1995/11/23 02:38:19 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -33,11 +33,15 @@ #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 <dev/isa/isavar.h> +#include <alpha/pci/siovar.h> + +#ifndef EVCNT_COUNTERS +#include <machine/intrcnt.h> +#endif -#include <machine/pio.h> +#include "sio.h" /* * To add to the long history of wonderful PROM console traits, @@ -49,18 +53,25 @@ */ #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)); +/* + * Private functions and variables. + */ +static void *sio_intr_establish __P((void *, isa_irq_t, + isa_intrsharetype_t, isa_intrlevel_t, + int (*)(void *), void *)); +static void sio_intr_disestablish __P((void *, void *)); +static void sio_strayintr __P((isa_irq_t)); -struct isa_intr_fcns sio_intr_fcns = { - sio_intr_setup, sio_intr_establish, - sio_intr_disestablish, sio_iointr, -}; +static __const struct isa_pio_fns *sio_ipf; /* XXX */ +static void *sio_ipfa; /* XXX */ -static void sio_strayintr __P((int irq)); +void sio_intr_setup __P((__const struct isa_pio_fns *, void *)); +void sio_iointr __P((void *framep, int vec)); + +struct isa_intr_fns sio_isa_intr_fns = { + sio_intr_establish, + sio_intr_disestablish, +}; /* * Interrupt handler chains. sio_intr_establish() inserts a handler into @@ -78,8 +89,11 @@ struct intrhand { #define ICU_LEN 16 /* number of ISA IRQs */ static struct intrhand *sio_intrhand[ICU_LEN]; -static isa_intrtype sio_intrtype[ICU_LEN]; +static isa_intrsharetype_t sio_intrsharetype[ICU_LEN]; static u_long sio_strayintrcnt[ICU_LEN]; +#ifdef EVCNT_COUNTERS +struct evcnt sio_intr_evcnt; +#endif #ifndef STRAY_MAX #ifdef BROKEN_PROM_CONSOLE @@ -112,7 +126,7 @@ u_int8_t initial_elcr[2]; void sio_setirqstat(irq, enabled, type) int irq, enabled; - isa_intrtype type; + isa_intrsharetype_t type; { u_int8_t ocw1[2], elcr[2]; int icu, bit; @@ -122,15 +136,15 @@ sio_setirqstat(irq, enabled, type) enabled ? "enabled" : "disabled", isa_intr_typename(type)); #endif - sio_intrtype[irq] = type; + sio_intrsharetype[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 */ + ocw1[0] = INB(sio_ipf, sio_ipfa, IO_ICU1 + 1); + ocw1[1] = INB(sio_ipf, sio_ipfa, IO_ICU2 + 1); + elcr[0] = INB(sio_ipf, sio_ipfa, 0x4d0); /* XXX */ + elcr[1] = INB(sio_ipf, sio_ipfa, 0x4d1); /* XXX */ /* * interrupt enable: set bit to mask (disable) interrupt. @@ -174,25 +188,30 @@ sio_setirqstat(irq, enabled, type) } #endif - outb(IO_ICU1 + 1, ocw1[0]); - outb(IO_ICU2 + 1, ocw1[1]); - outb(0x4d0, elcr[0]); /* XXX */ - outb(0x4d1, elcr[1]); /* XXX */ + OUTB(sio_ipf, sio_ipfa, IO_ICU1 + 1, ocw1[0]); + OUTB(sio_ipf, sio_ipfa, IO_ICU2 + 1, ocw1[1]); + OUTB(sio_ipf, sio_ipfa, 0x4d0, elcr[0]); /* XXX */ + OUTB(sio_ipf, sio_ipfa, 0x4d1, elcr[1]); /* XXX */ } void -sio_intr_setup() +sio_intr_setup(ipf, ipfa) + __const struct isa_pio_fns *ipf; + void *ipfa; { int i; + sio_ipf = ipf; + sio_ipfa = ipfa; + #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 */ + initial_ocw1[0] = INB(sio_ipf, sio_ipfa, IO_ICU1 + 1); + initial_ocw1[1] = INB(sio_ipf, sio_ipfa, IO_ICU2 + 1); + initial_elcr[0] = INB(sio_ipf, sio_ipfa, 0x4d0); /* XXX */ + initial_elcr[1] = INB(sio_ipf, sio_ipfa, 0x4d1); /* XXX */ #if 0 printf("initial_ocw1[0] = 0x%x\n", initial_ocw1[0]); printf("initial_ocw1[1] = 0x%x\n", initial_ocw1[1]); @@ -245,10 +264,11 @@ sio_intr_setup() } void * -sio_intr_establish(irq, type, level, ih_fun, ih_arg) - int irq; - isa_intrtype type; - isa_intrlevel level; +sio_intr_establish(siifa, irq, type, level, ih_fun, ih_arg) + void *siifa; + isa_irq_t irq; + isa_intrsharetype_t type; + isa_intrlevel_t level; int (*ih_fun)(void *); void *ih_arg; { @@ -260,19 +280,19 @@ sio_intr_establish(irq, type, level, ih_fun, ih_arg) if (ih == NULL) panic("sio_intr_establish: can't malloc handler info"); - if (irq < 0 || irq > ICU_LEN || type == ISA_IST_NONE) + if (irq > ICU_LEN || type == ISA_IST_NONE) panic("sio_intr_establish: bogus irq or type"); - switch (sio_intrtype[irq]) { + switch (sio_intrsharetype[irq]) { case ISA_IST_EDGE: case ISA_IST_LEVEL: - if (type == sio_intrtype[irq]) + if (type == sio_intrsharetype[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)); + isa_intrsharetype_name(sio_intrsharetype[irq]), + isa_intrsharetype_name(type)); break; } @@ -301,7 +321,8 @@ sio_intr_establish(irq, type, level, ih_fun, ih_arg) } void -sio_intr_disestablish(handler) +sio_intr_disestablish(siifa, handler) + void *siifa; void *handler; { @@ -317,7 +338,7 @@ sio_intr_disestablish(handler) */ void sio_strayintr(irq) - int irq; + isa_irq_t irq; { if (++sio_strayintrcnt[irq] <= STRAY_MAX) @@ -340,6 +361,14 @@ sio_iointr(framep, vec) panic("sio_iointr: irq out of range (%d)", irq); #endif +#ifdef EVCNT_COUNTERS + sio_intr_evcnt.ev_count++; +#else + if (ICU_LEN != INTRCNT_ISA_IRQ_LEN) + panic("sio interrupt counter sizes inconsistent"); + intrcnt[INTRCNT_ISA_IRQ + irq]++; +#endif + /* * We cdr down the intrhand chain, calling each handler with * its appropriate argument; @@ -373,6 +402,8 @@ sio_iointr(framep, vec) * 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 */ + OUTB(sio_ipf, sio_ipfa, + IO_ICU2 + 0, 0x20 | (irq & 0x07)); /* XXX */ + OUTB(sio_ipf, sio_ipfa, + IO_ICU1 + 0, 0x20 | (irq > 7 ? 2 : irq)); /* XXX */ } diff --git a/sys/arch/alpha/pci/siovar.h b/sys/arch/alpha/pci/siovar.h new file mode 100644 index 00000000000..746b9a89abb --- /dev/null +++ b/sys/arch/alpha/pci/siovar.h @@ -0,0 +1,36 @@ +/* $NetBSD: siovar.h,v 1.1 1995/11/23 02:38:22 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. + */ + +void sio_intr_setup __P((__const struct isa_pio_fns *, void *)); +void sio_iointr __P((void *framep, int vec)); + +#ifdef EVCNT_COUNTERS +extern struct evcnt sio_intr_evcnt; +#endif +extern __const struct isa_intr_fns sio_isa_intr_fns; diff --git a/sys/arch/alpha/pci/tga.c b/sys/arch/alpha/pci/tga.c index 0be0c2dd238..739c0d812c1 100644 --- a/sys/arch/alpha/pci/tga.c +++ b/sys/arch/alpha/pci/tga.c @@ -1,4 +1,4 @@ -/* $NetBSD: tga.c,v 1.2 1995/08/03 01:17:28 cgd Exp $ */ +/* $NetBSD: tga.c,v 1.3 1995/11/23 02:38:25 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -32,8 +32,9 @@ #include <sys/kernel.h> #include <sys/device.h> #include <sys/malloc.h> +#include <sys/conf.h> -#include <dev/pseudo/raster.h> +#include <dev/rcons/raster.h> #include <dev/pseudo/rcons.h> #include <dev/pseudo/ansicons.h> @@ -43,6 +44,7 @@ #include <alpha/pci/tgareg.h> #include <alpha/pci/tgavar.h> #include <alpha/pci/bt485reg.h> +#include <alpha/pci/wsconsvar.h> #include <machine/autoconf.h> #include <machine/pte.h> @@ -54,11 +56,20 @@ struct cfdriver tgacd = { NULL, "tga", tgamatch, tgaattach, DV_DULL, sizeof(struct tga_softc) }; +int tga_identify __P((tga_reg_t *)); +__const struct tga_conf *tga_getconf __P((int)); +void tga_getdevconfig __P((__const struct pci_conf_fns *, void *, + __const struct pci_mem_fns *, void *, + pci_conftag_t tag, struct tga_devconfig *dc)); + +void tga_bell __P((void *)); /* XXX */ + struct tga_devconfig tga_console_dc; -int tga_identify __P((tga_reg_t *)); -struct tga_conf *tga_getconf __P((int)); -void tga_bell __P((void *)); +#if 0 +dev_decl(tga, mmap); +dev_decl(tga, ioctl); +#endif struct ansicons_functions tga_acf = { tga_bell, @@ -72,19 +83,23 @@ struct ansicons_functions tga_acf = { #define TGAUNIT(dev) minor(dev) -struct tga_ramdac_conf tga_ramdac_bt463 = { +void tga_builtin_set_cpos __P((struct tga_devconfig *, int, int)); +void tga_builtin_get_cpos __P((struct tga_devconfig *, int *, int *)); + +__const struct tga_ramdac_conf tga_ramdac_bt463 = { "Bt463", -#if 0 - XXX, - YYY, -#endif + tga_builtin_set_cpos, + tga_builtin_get_cpos, /* XXX */ }; +void tga_bt485_wr_reg __P((volatile tga_reg_t *, u_int, u_int8_t)); +u_int8_t tga_bt485_rd_reg __P((volatile tga_reg_t *, u_int)); + void tga_bt485_set_cpos __P((struct tga_devconfig *, int, int)); void tga_bt485_get_cpos __P((struct tga_devconfig *, int *, int *)); -struct tga_ramdac_conf tga_ramdac_bt485 = { +__const struct tga_ramdac_conf tga_ramdac_bt485 = { "Bt485", tga_bt485_set_cpos, tga_bt485_get_cpos, @@ -96,7 +111,7 @@ struct tga_ramdac_conf tga_ramdac_bt485 = { #undef MB #define MB * 1024 * 1024 -struct tga_conf tga_configs[TGA_TYPE_UNKNOWN] = { +__const struct tga_conf tga_configs[TGA_TYPE_UNKNOWN] = { /* TGA_TYPE_T8_01 */ { "T8-01", @@ -177,10 +192,10 @@ tgamatch(parent, match, aux) void *match, *aux; { struct cfdata *cf = match; - struct pci_attach_args *pa = aux; + struct pcidev_attach_args *pda = aux; - if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_DEC || - PCI_PRODUCT(pa->pa_id) != PCI_PRODUCT_DEC_21030) + if (PCI_VENDOR(pda->pda_id) != PCI_VENDOR_DEC || + PCI_PRODUCT(pda->pda_id) != PCI_PRODUCT_DEC_21030) return (0); return (1); @@ -241,7 +256,7 @@ tga_identify(regs) return (type); } -struct tga_conf * +__const struct tga_conf * tga_getconf(type) int type; { @@ -253,31 +268,51 @@ tga_getconf(type) } void -tga_getdevconfig(tag, dc) - pcitag_t tag; +tga_getdevconfig(pcf, pcfa, pmf, pmfa, tag, dc) + __const struct pci_conf_fns *pcf; + __const struct pci_mem_fns *pmf; + void *pcfa, *pmfa; + pci_conftag_t tag; struct tga_devconfig *dc; { - struct tga_conf *tgac; - struct tga_ramdac_conf *tgar; + __const struct tga_conf *tgac; + __const struct tga_ramdac_conf *tgar; struct raster *rap; struct rcons *rcp; - vm_offset_t pcipa; - int i; + pci_msize_t pcisize; + int i, cacheable; + + dc->dc_pcf = pcf; + dc->dc_pcfa = pcfa; + dc->dc_pmf = pmf; + dc->dc_pmfa = pmfa; dc->dc_pcitag = tag; - dc->dc_vaddr = 0; - if (pci_map_mem(tag, 0x10, &dc->dc_vaddr, &pcipa)) + /* XXX MAGIC NUMBER */ + PCI_FIND_MEM(pcf, pcfa, tag, 0x10, &dc->dc_pcipaddr, &pcisize, + &cacheable); + if (!cacheable) /* sanity */ + panic("tga_getdevconfig: memory not cacheable?"); + + dc->dc_vaddr = PCI_MEM_MAP(pmf, pmfa, dc->dc_pcipaddr, pcisize, 1); + if (dc->dc_vaddr == 0) return; - /* PA filled in by pci_map_mem is the PCI-bus PA, i.e. not shifted */ - dc->dc_paddr = k0segtophys(dc->dc_vaddr); + dc->dc_paddr = k0segtophys(dc->dc_vaddr); /* XXX */ dc->dc_regs = (tga_reg_t *)(dc->dc_vaddr + TGA_MEM_CREGS); dc->dc_tga_type = tga_identify(dc->dc_regs); tgac = dc->dc_tgaconf = tga_getconf(dc->dc_tga_type); if (tgac == NULL) return; + +#if 0 + /* XXX on the Alpha, pcisize = 4 * cspace_size. */ + if (tgac->tgac_cspace_size != pcisize) /* sanity */ + panic("tga_getdevconfig: memory size mismatch?"); +#endif + tgar = tgac->tgac_ramdac; switch (dc->dc_regs[TGA_REG_VHCR] & 0x1ff) { /* XXX */ @@ -306,6 +341,13 @@ tga_getdevconfig(tag, dc) dc->dc_regs[TGA_REG_VVBR] = 1; dc->dc_videobase = dc->dc_vaddr + tgac->tgac_dbuf[0] + 1 * tgac->tgac_vvbr_units; + + /* + * Set all bits in the pixel mask, to enable writes to all pixels. + * It seems that the console firmware clears some of them + * under some circumstances, which causes cute vertical stripes. + */ + dc->dc_regs[TGA_REG_GPXR_P] = 0xffffffff; /* disable the cursor */ (*tgar->tgar_set_cpos)(dc, TGA_CURSOR_OFF, 0); @@ -342,19 +384,19 @@ tgaattach(parent, self, aux) struct device *parent, *self; void *aux; { - struct pci_attach_args *pa = aux; + struct pcidev_attach_args *pda = aux; struct tga_softc *sc = (struct tga_softc *)self; pci_revision_t rev; - pcireg_t pci_intrdata; int console; - console = (pa->pa_tag == tga_console_dc.dc_pcitag); + console = (pda->pda_tag == tga_console_dc.dc_pcitag); if (console) sc->sc_dc = &tga_console_dc; else { sc->sc_dc = (struct tga_devconfig *) malloc(sizeof(struct tga_devconfig), M_DEVBUF, M_WAITOK); - tga_getdevconfig(pa->pa_tag, sc->sc_dc); + tga_getdevconfig(pda->pda_conffns, pda->pda_confarg, + pda->pda_memfns, pda->pda_memarg, pda->pda_tag, sc->sc_dc); } if (sc->sc_dc->dc_vaddr == NULL) { printf(": couldn't map memory space; punt!\n"); @@ -362,7 +404,7 @@ tgaattach(parent, self, aux) } printf(": DC21030 "); - rev = PCI_REVISION(pa->pa_class); + rev = PCI_REVISION(pda->pda_class); switch (rev) { case 1: case 2: case 3: printf("step %c", 'A' + rev - 1); @@ -381,23 +423,11 @@ tgaattach(parent, self, aux) printf("board type %s\n", sc->sc_dc->dc_tgaconf->tgac_name); printf("%s: %d x %d, %dbpp, %s RAMDAC\n", sc->sc_dev.dv_xname, sc->sc_dc->dc_wid, sc->sc_dc->dc_ht, - sc->sc_dc->dc_tgaconf->tgac_phys_depth, + sc->sc_dc->dc_tgaconf->tgac_phys_depth, sc->sc_dc->dc_tgaconf->tgac_ramdac->tgar_name); -#if 0 - /* not done here; printed by wscons attach. */ - if (console) - printf("%s: console\n", sc->sc_dev.dv_xname); -#endif #if 0 - pci_intrdata = pci_conf_read(sc->sc_pcitag, PCI_INTERRUPT_REG); - if (PCI_INTERRUPT_PIN(pci_intrdata) != PCI_INTERRUPT_PIN_NONE) { - sc->sc_intr = pci_map_int(sc->sc_pcitag, PCI_IPL_TTY, - tgaintr, sc); - if (sc->sc_intr == NULL) - printf("%s: WARNING: couldn't map interrupt\n", - sc->sc_dev.dv_xname); - } + /* XXX intr foo? */ #endif if (!wscattach_output(self, console, &sc->sc_dc->dc_ansicons, &tga_acf, @@ -408,35 +438,7 @@ tgaattach(parent, self, aux) } } -int -tgaopen(dev, flag, mode, p) - dev_t dev; - int flag, mode; - struct proc *p; -{ - struct tga_softc *sc; - int unit = TGAUNIT(dev); - - if (unit >= tgacd.cd_ndevs) - return ENXIO; - sc = tgacd.cd_devs[unit]; - if ((sc = tgacd.cd_devs[unit]) == NULL || sc->sc_dc->dc_tgaconf == NULL) - return ENXIO; - - return (0); -} - -int -tgaclose(dev, flag, mode, p) - dev_t dev; - int flag, mode; - struct proc *p; -{ - struct tga_softc *sc = tgacd.cd_devs[TGAUNIT(dev)]; - - return (0); -} - +#if 0 int tgaioctl(dev, cmd, data, flag, p) dev_t dev; @@ -462,6 +464,7 @@ tgammap(dev, offset, nprot) return -1; return alpha_btop(sc->sc_dc->dc_paddr + offset); } +#endif void tga_bell(id) @@ -472,6 +475,43 @@ tga_bell(id) printf("tga_bell: not implemented\n"); } +void +tga_builtin_set_cpos(dc, x, y) + struct tga_devconfig *dc; + int x, y; +{ + + if (x == TGA_CURSOR_OFF || y == TGA_CURSOR_OFF) { + + dc->dc_regs[TGA_REG_VVVR] &= ~0x04; /* XXX */ + wbflush(); + return; + } + + /* + * TGA builtin cursor is 0-based, and position is top-left corner. + */ + dc->dc_regs[TGA_REG_CXYR] = + (x & 0xfff) | ((y & 0xfff) << 12); /* XXX */ + wbflush(); +} + +void +tga_builtin_get_cpos(dc, xp, yp) + struct tga_devconfig *dc; + int *xp, *yp; +{ + tga_reg_t regval; + + if ((dc->dc_regs[TGA_REG_VVVR] & 0x04) == 0) { /* XXX */ + *xp = *yp = TGA_CURSOR_OFF; + return; + } + + regval = dc->dc_regs[TGA_REG_CXYR]; + *xp = regval & 0xfff; /* XXX */ + *yp = (regval >> 12) & 0xfff; /* XXX */ +} /* * Bt485-specific functions. @@ -521,6 +561,7 @@ tga_bt485_set_cpos(dc, x, y) regval &= ~0x03; /* XXX */ regval |= 0x00; /* XXX */ tga_bt485_wr_reg(dc->dc_regs, BT485_REG_COMMAND_2, regval); + return; } /* @@ -531,14 +572,14 @@ tga_bt485_set_cpos(dc, x, y) y += 64; /* XXX CONSTANTS */ - tga_bt485_rd_reg(dc->dc_regs, BT485_REG_CURSOR_X_LOW, - x & 0xff); - tga_bt485_rd_reg(dc->dc_regs, BT485_REG_CURSOR_X_HIGH, - (x >> 8) & 0x0f); - tga_bt485_rd_reg(dc->dc_regs, BT485_REG_CURSOR_Y_LOW, - y & 0xff); - tga_bt485_rd_reg(dc->dc_regs, BT485_REG_CURSOR_Y_HIGH, - (y >> 8) & 0x0f); + tga_bt485_rd_reg(dc->dc_regs, BT485_REG_CURSOR_X_LOW/*, + x & 0xff*/); + tga_bt485_rd_reg(dc->dc_regs, BT485_REG_CURSOR_X_HIGH/*, + (x >> 8) & 0x0f*/); + tga_bt485_rd_reg(dc->dc_regs, BT485_REG_CURSOR_Y_LOW/*, + y & 0xff*/); + tga_bt485_rd_reg(dc->dc_regs, BT485_REG_CURSOR_Y_HIGH/*, + (y >> 8) & 0x0f*/); } void @@ -573,20 +614,27 @@ tga_bt485_get_cpos(dc, xp, yp) } void -tga_console(bus, device, function) - int bus, device, function; +tga_console(pcf, pcfa, pmf, pmfa, ppf, ppfa, bus, device, function) + __const struct pci_conf_fns *pcf; + __const struct pci_mem_fns *pmf; + __const struct pci_pio_fns *ppf; + void *pcfa, *pmfa, *ppfa; + pci_bus_t bus; + pci_device_t device; + pci_function_t function; { struct tga_devconfig *dcp = &tga_console_dc; - tga_getdevconfig(pci_make_tag(bus, device, function), dcp); + tga_getdevconfig(pcf, pcfa, pmf, pmfa, + PCI_MAKE_TAG(bus, device, function), dcp); /* sanity checks */ if (dcp->dc_vaddr == NULL) - panic("tga_console(%d, %d, %d): couldn't map memory space", - bus, device, function); + panic("tga_console(%d, %d): couldn't map memory space", + device, function); if (dcp->dc_tgaconf == NULL) - panic("tga_console(%d, %d, %d): unknown board configuration", - bus, device, function); + panic("tga_console(%d, %d): unknown board configuration", + device, function); wsc_console(&dcp->dc_ansicons, &tga_acf, &dcp->dc_rcons, dcp->dc_rcons.rc_maxrow, dcp->dc_rcons.rc_maxcol, 0, 0); diff --git a/sys/arch/alpha/pci/tgareg.h b/sys/arch/alpha/pci/tgareg.h index 80b37557860..6c335cf9a28 100644 --- a/sys/arch/alpha/pci/tgareg.h +++ b/sys/arch/alpha/pci/tgareg.h @@ -1,4 +1,4 @@ -/* $NetBSD: tgareg.h,v 1.2 1995/08/03 01:17:34 cgd Exp $ */ +/* $NetBSD: tgareg.h,v 1.3 1995/11/23 02:38:28 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -27,6 +27,9 @@ * rights to redistribute these changes. */ +#ifndef _ALPHA_PCI_TGAREG_H_ +#define _ALPHA_PCI_TGAREG_H_ + /* * Device-specific PCI register offsets and contents. */ @@ -152,3 +155,5 @@ typedef int32_t tga_reg_t; #define TGA_REG_SCSR 0x07e /* Command Status */ /* reserved 0x07f */ + +#endif /* _ALPHA_PCI_TGAREG_H_ */ diff --git a/sys/arch/alpha/pci/tgavar.h b/sys/arch/alpha/pci/tgavar.h index 8ce95ddd87b..b1ab195c624 100644 --- a/sys/arch/alpha/pci/tgavar.h +++ b/sys/arch/alpha/pci/tgavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: tgavar.h,v 1.2 1995/08/03 01:17:37 cgd Exp $ */ +/* $NetBSD: tgavar.h,v 1.3 1995/11/23 02:38:31 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -27,6 +27,11 @@ * rights to redistribute these changes. */ +#include <alpha/pci/tgareg.h> +#include <dev/rcons/raster.h> +#include <dev/pseudo/rcons.h> +#include <dev/pseudo/ansicons.h> + struct tga_devconfig; struct tga_ramdac_conf { @@ -42,7 +47,7 @@ struct tga_ramdac_conf { struct tga_conf { char *tgac_name; /* name for this board type */ - struct tga_ramdac_conf + __const struct tga_ramdac_conf *tgac_ramdac; /* the RAMDAC type; see above */ int tgac_phys_depth; /* physical frame buffer depth */ vm_size_t tgac_cspace_size; /* core space size */ @@ -58,12 +63,20 @@ struct tga_conf { }; struct tga_devconfig { - pcitag_t dc_pcitag; /* PCI tag */ + __const struct pci_conf_fns *dc_pcf; + void *dc_pcfa; + __const struct pci_mem_fns *dc_pmf; + void *dc_pmfa; + __const struct pci_pio_fns *dc_ppf; + void *dc_ppfa; + + pci_conftag_t dc_pcitag; /* PCI tag */ + pci_moffset_t dc_pcipaddr; /* PCI phys addr. */ tga_reg_t *dc_regs; /* registers; XXX: need aliases */ int dc_tga_type; /* the device type; see below */ - struct tga_conf *dc_tgaconf; /* device buffer configuration */ + __const struct tga_conf *dc_tgaconf; /* device buffer configuration */ vm_offset_t dc_vaddr; /* memory space virtual base address */ vm_offset_t dc_paddr; /* memory space physical base address */ @@ -96,3 +109,12 @@ struct tga_softc { #define TGA_TYPE_UNKNOWN 7 /* unknown */ #define TGA_CURSOR_OFF -1 /* pass to tgar_cpos to disable */ + +#define DEVICE_IS_TGA(class, id) \ + (PCI_VENDOR(id) == PCI_VENDOR_DEC && \ + PCI_PRODUCT(id) == PCI_PRODUCT_DEC_21030) + +void tga_console __P((__const struct pci_conf_fns *, void *, + __const struct pci_mem_fns *, void *, + __const struct pci_pio_fns *, void *, + pci_bus_t, pci_device_t, pci_function_t)); diff --git a/sys/arch/alpha/pci/wscons.c b/sys/arch/alpha/pci/wscons.c index 8307e1d0d07..fa5a988cf09 100644 --- a/sys/arch/alpha/pci/wscons.c +++ b/sys/arch/alpha/pci/wscons.c @@ -1,4 +1,4 @@ -/* $NetBSD: wscons.c,v 1.2 1995/08/03 01:17:40 cgd Exp $ */ +/* $NetBSD: wscons.c,v 1.3 1995/11/23 02:38:36 cgd Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -39,6 +39,7 @@ #include <dev/cons.h> #include <dev/pseudo/ansicons.h> +#include <alpha/pci/wsconsvar.h> #define NWSC 16 /* XXX XXX XXX */ @@ -105,6 +106,7 @@ wscattach_output(dev, console, acp, acf, acfarg, mrow, mcol, crow, ccol) } wsc_sc[nextowsc].sc_flags |= WSC_OUTPUT; + wsc_sc[nextowsc].sc_tty = ttymalloc(); printf("wsc%d: %s attached as output\n", nextowsc, dev->dv_xname); if (console) @@ -149,9 +151,8 @@ wscopen(dev, flag, mode, p) return ENXIO; if (!sc->sc_tty) - tp = sc->sc_tty = ttymalloc(); - else - tp = sc->sc_tty; + panic("wscopen: no tty!"); + tp = sc->sc_tty; tp->t_oproc = wscstart; tp->t_param = wscparam; diff --git a/sys/arch/alpha/pci/wsconsvar.h b/sys/arch/alpha/pci/wsconsvar.h new file mode 100644 index 00000000000..77347e07faa --- /dev/null +++ b/sys/arch/alpha/pci/wsconsvar.h @@ -0,0 +1,40 @@ +/* $NetBSD: wsconsvar.h,v 1.1 1995/11/23 02:38:39 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 device; +struct ansicons; +struct ansicons_functions; + +int wscattach_output __P((struct device *, int, struct ansicons *, + struct ansicons_functions *, void *, int, int, int, int)); +void wscattach_input __P((struct device *, void *, int (*)(void *), + void (*)(void *, int))); +void wscons_kbdinput __P((char *)); +void wsc_console __P((struct ansicons *, struct ansicons_functions *, + void *, int, int, int, int)); |