diff options
author | Jason Wright <jason@cvs.openbsd.org> | 2001-02-16 05:17:33 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 2001-02-16 05:17:33 +0000 |
commit | 980314a4de8d2809d8c120d23e1068ab3c802c08 (patch) | |
tree | 3f4175d2d7c2addd3e7ded206175adfa7a3fb26b /sys/arch/alpha/pci | |
parent | ac2d01d1f83c16a093a5c03c1211c2585d4e5435 (diff) |
bring in netbsd bus_dma stuff for lca and apecs busses
Diffstat (limited to 'sys/arch/alpha/pci')
-rw-r--r-- | sys/arch/alpha/pci/apecs.c | 40 | ||||
-rw-r--r-- | sys/arch/alpha/pci/apecs_dma.c | 392 | ||||
-rw-r--r-- | sys/arch/alpha/pci/apecsreg.h | 20 | ||||
-rw-r--r-- | sys/arch/alpha/pci/apecsvar.h | 9 | ||||
-rw-r--r-- | sys/arch/alpha/pci/lca.c | 72 | ||||
-rw-r--r-- | sys/arch/alpha/pci/lca_dma.c | 396 | ||||
-rw-r--r-- | sys/arch/alpha/pci/lcareg.h | 37 | ||||
-rw-r--r-- | sys/arch/alpha/pci/lcavar.h | 9 |
8 files changed, 881 insertions, 94 deletions
diff --git a/sys/arch/alpha/pci/apecs.c b/sys/arch/alpha/pci/apecs.c index fb3fdaa0459..e33608f6165 100644 --- a/sys/arch/alpha/pci/apecs.c +++ b/sys/arch/alpha/pci/apecs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: apecs.c,v 1.9 2000/11/08 16:01:16 art Exp $ */ +/* $OpenBSD: apecs.c,v 1.10 2001/02/16 05:17:31 jason Exp $ */ /* $NetBSD: apecs.c,v 1.16 1996/12/05 01:39:34 cgd Exp $ */ /* @@ -45,15 +45,11 @@ #include <dev/pci/pcivar.h> #include <alpha/pci/apecsreg.h> #include <alpha/pci/apecsvar.h> -#if defined(DEC_2100_A50) +#ifdef DEC_2100_A50 #include <alpha/pci/pci_2100_a50.h> #endif -#ifdef __BROKEN_INDIRECT_CONFIG int apecsmatch __P((struct device *, void *, void *)); -#else -int apecsmatch __P((struct device *, struct cfdata *, void *)); -#endif void apecsattach __P((struct device *, struct device *, void *)); struct cfattach apecs_ca = { @@ -73,11 +69,7 @@ struct apecs_config apecs_configuration; int apecsmatch(parent, match, aux) struct device *parent; -#ifdef __BROKEN_INDIRECT_CONFIG void *match; -#else - struct cfdata *match; -#endif void *aux; { struct mainbus_attach_args *ma = aux; @@ -110,11 +102,6 @@ apecs_init(acp, mallocsafe) acp->ac_haxr1 = REGVAL(EPIC_HAXR1); acp->ac_haxr2 = REGVAL(EPIC_HAXR2); - /* - * Can't set up SGMAP data here; can be called before malloc(). - * XXX THIS COMMENT NO LONGER MAKES SENSE. - */ - if (!acp->ac_initted) { /* don't do these twice since they set up extents */ acp->ac_iot = apecs_bus_io_init(acp); @@ -124,19 +111,6 @@ apecs_init(acp, mallocsafe) apecs_pci_init(&acp->ac_pc, acp); - /* Turn off DMA window enables in PCI Base Reg 1. */ - REGVAL(EPIC_PCI_BASE_1) = 0; - alpha_mb(); - - /* XXX SGMAP? */ - - /* XXX XXX BEGIN XXX XXX */ - { /* XXX */ - extern vm_offset_t alpha_XXX_dmamap_or; /* XXX */ - alpha_XXX_dmamap_or = 0x40000000; /* XXX */ - } /* XXX */ - /* XXX XXX END XXX XXX */ - acp->ac_initted = 1; } @@ -159,7 +133,7 @@ apecsattach(parent, self, aux) acp = sc->sc_acp = &apecs_configuration; apecs_init(acp, 1); - /* XXX SGMAP FOO */ + apecs_dma_init(acp); printf(": DECchip %s Core Logic chipset\n", acp->ac_memwidth == 128 ? "21072" : "21071"); @@ -173,7 +147,7 @@ apecsattach(parent, self, aux) printf("WARNING: 21071-DA NOT PASS2... NO BETS...\n"); switch (hwrpb->rpb_type) { -#if defined(DEC_2100_A50) +#ifdef DEC_2100_A50 case ST_DEC_2100_A50: pci_2100_a50_pickintr(acp); break; @@ -186,8 +160,14 @@ apecsattach(parent, self, aux) pba.pba_busname = "pci"; pba.pba_iot = acp->ac_iot; pba.pba_memt = acp->ac_memt; + pba.pba_dmat = + alphabus_dma_get_tag(&acp->ac_dmat_direct, ALPHA_BUS_PCI); pba.pba_pc = &acp->ac_pc; pba.pba_bus = 0; +#ifdef notyet + pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED | + PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY; +#endif config_found(self, &pba, apecsprint); } diff --git a/sys/arch/alpha/pci/apecs_dma.c b/sys/arch/alpha/pci/apecs_dma.c new file mode 100644 index 00000000000..341de0c80b5 --- /dev/null +++ b/sys/arch/alpha/pci/apecs_dma.c @@ -0,0 +1,392 @@ +/* $OpenBSD: apecs_dma.c,v 1.1 2001/02/16 05:17:31 jason Exp $ */ +/* $NetBSD: apecs_dma.c,v 1.13 2000/06/29 08:58:45 mrg Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 FOUNDATION OR CONTRIBUTORS + * 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. + */ + +/* + * XXX - We should define this before including bus.h, but since other stuff + * pulls in bus.h we must do this here. + */ +#define _ALPHA_BUS_DMA_PRIVATE + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/malloc.h> + +#include <vm/vm.h> +#include <uvm/uvm_extern.h> + +#include <machine/bus.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <alpha/pci/apecsreg.h> +#include <alpha/pci/apecsvar.h> + +bus_dma_tag_t apecs_dma_get_tag __P((bus_dma_tag_t, alpha_bus_t)); + +int apecs_bus_dmamap_create_sgmap __P((bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *)); + +void apecs_bus_dmamap_destroy_sgmap __P((bus_dma_tag_t, bus_dmamap_t)); + +int apecs_bus_dmamap_load_sgmap __P((bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int)); + +int apecs_bus_dmamap_load_mbuf_sgmap __P((bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int)); + +int apecs_bus_dmamap_load_uio_sgmap __P((bus_dma_tag_t, bus_dmamap_t, + struct uio *, int)); + +int apecs_bus_dmamap_load_raw_sgmap __P((bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int)); + +void apecs_bus_dmamap_unload_sgmap __P((bus_dma_tag_t, bus_dmamap_t)); + +/* + * Direct-mapped window: 1G at 1G + */ +#define APECS_DIRECT_MAPPED_BASE (1*1024*1024*1024) +#define APECS_DIRECT_MAPPED_SIZE (1*1024*1024*1024) + +/* + * SGMAP window: 8M at 8M + */ +#define APECS_SGMAP_MAPPED_BASE (8*1024*1024) +#define APECS_SGMAP_MAPPED_SIZE (8*1024*1024) + +/* + * Macro to flush APECS scatter/gather TLB. + */ +#define APECS_TLB_INVALIDATE() \ +do { \ + alpha_mb(); \ + REGVAL(EPIC_TBIA) = 0; \ + alpha_mb(); \ +} while (0) + +void +apecs_dma_init(acp) + struct apecs_config *acp; +{ + bus_addr_t tbase; + bus_dma_tag_t t; + + /* + * Initialize the DMA tag used for direct-mapped DMA. + */ + t = &acp->ac_dmat_direct; + t->_cookie = acp; + t->_wbase = APECS_DIRECT_MAPPED_BASE; + t->_wsize = APECS_DIRECT_MAPPED_SIZE; + t->_next_window = NULL; + t->_boundary = 0; + t->_sgmap = NULL; + t->_get_tag = apecs_dma_get_tag; + t->_dmamap_create = _bus_dmamap_create; + t->_dmamap_destroy = _bus_dmamap_destroy; + t->_dmamap_load = _bus_dmamap_load_direct; + t->_dmamap_load_mbuf = _bus_dmamap_load_mbuf_direct; + t->_dmamap_load_uio = _bus_dmamap_load_uio_direct; + t->_dmamap_load_raw = _bus_dmamap_load_raw_direct; + t->_dmamap_unload = _bus_dmamap_unload; + t->_dmamap_sync = _bus_dmamap_sync; + + t->_dmamem_alloc = _bus_dmamem_alloc; + t->_dmamem_free = _bus_dmamem_free; + t->_dmamem_map = _bus_dmamem_map; + t->_dmamem_unmap = _bus_dmamem_unmap; + t->_dmamem_mmap = _bus_dmamem_mmap; + + /* + * Initialize the DMA tag used for sgmap-mapped DMA. + */ + t = &acp->ac_dmat_sgmap; + t->_cookie = acp; + t->_wbase = APECS_SGMAP_MAPPED_BASE; + t->_wsize = APECS_SGMAP_MAPPED_SIZE; + t->_next_window = NULL; + t->_boundary = 0; + t->_sgmap = &acp->ac_sgmap; + t->_get_tag = apecs_dma_get_tag; + t->_dmamap_create = apecs_bus_dmamap_create_sgmap; + t->_dmamap_destroy = apecs_bus_dmamap_destroy_sgmap; + t->_dmamap_load = apecs_bus_dmamap_load_sgmap; + t->_dmamap_load_mbuf = apecs_bus_dmamap_load_mbuf_sgmap; + t->_dmamap_load_uio = apecs_bus_dmamap_load_uio_sgmap; + t->_dmamap_load_raw = apecs_bus_dmamap_load_raw_sgmap; + t->_dmamap_unload = apecs_bus_dmamap_unload_sgmap; + t->_dmamap_sync = _bus_dmamap_sync; + + t->_dmamem_alloc = _bus_dmamem_alloc; + t->_dmamem_free = _bus_dmamem_free; + t->_dmamem_map = _bus_dmamem_map; + t->_dmamem_unmap = _bus_dmamem_unmap; + t->_dmamem_mmap = _bus_dmamem_mmap; + + /* + * The firmware has set up window 2 as a 1G direct-mapped DMA + * window beginning at 1G. We leave it alone. Disable + * window 1. + */ + REGVAL(EPIC_PCI_BASE_1) = 0; + alpha_mb(); + + /* + * Initialize the SGMAP. + */ + alpha_sgmap_init(t, &acp->ac_sgmap, "apecs_sgmap", + APECS_SGMAP_MAPPED_BASE, 0, APECS_SGMAP_MAPPED_SIZE, + sizeof(u_int64_t), NULL, 0); + + /* + * Set up window 1 as an 8MB SGMAP-mapped window + * starting at 8MB. + */ + REGVAL(EPIC_PCI_BASE_1) = APECS_SGMAP_MAPPED_BASE | + EPIC_PCI_BASE_SGEN | EPIC_PCI_BASE_WENB; + alpha_mb(); + + REGVAL(EPIC_PCI_MASK_1) = EPIC_PCI_MASK_8M; + alpha_mb(); + + tbase = acp->ac_sgmap.aps_ptpa >> EPIC_TBASE_SHIFT; + if ((tbase & EPIC_TBASE_T_BASE) != tbase) + panic("apecs_dma_init: bad page table address"); + REGVAL(EPIC_TBASE_1) = tbase; + alpha_mb(); + + APECS_TLB_INVALIDATE(); + + /* XXX XXX BEGIN XXX XXX */ + { /* XXX */ + extern paddr_t alpha_XXX_dmamap_or; /* XXX */ + alpha_XXX_dmamap_or = APECS_DIRECT_MAPPED_BASE; /* XXX */ + } /* XXX */ + /* XXX XXX END XXX XXX */ +} + +/* + * Return the bus dma tag to be used for the specified bus type. + * INTERNAL USE ONLY! + */ +bus_dma_tag_t +apecs_dma_get_tag(t, bustype) + bus_dma_tag_t t; + alpha_bus_t bustype; +{ + struct apecs_config *acp = t->_cookie; + + switch (bustype) { + case ALPHA_BUS_PCI: + case ALPHA_BUS_EISA: + /* + * Systems with an APECS can only support 1G + * of memory, so we use the direct-mapped window + * on busses that have 32-bit DMA. + */ + return (&acp->ac_dmat_direct); + + case ALPHA_BUS_ISA: + /* + * ISA doesn't have enough address bits to use + * the direct-mapped DMA window, so we must use + * SGMAPs. + */ + return (&acp->ac_dmat_sgmap); + + default: + panic("apecs_dma_get_tag: shouldn't be here, really..."); + } +} + +/* + * Load an APECS SGMAP-mapped DMA map with a linear buffer. + */ +int +apecs_bus_dmamap_load_sgmap(t, map, buf, buflen, p, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + void *buf; + bus_size_t buflen; + struct proc *p; + int flags; +{ + int error; + + error = pci_sgmap_pte64_load(t, map, buf, buflen, p, flags, + t->_sgmap); + if (error == 0) + APECS_TLB_INVALIDATE(); + + return (error); +} + +/* + * Load an APECS SGMAP-mapped DMA map with an mbuf chain. + */ +int +apecs_bus_dmamap_load_mbuf_sgmap(t, map, m, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + struct mbuf *m; + int flags; +{ + int error; + + error = pci_sgmap_pte64_load_mbuf(t, map, m, flags, t->_sgmap); + if (error == 0) + APECS_TLB_INVALIDATE(); + + return (error); +} + +/* + * Load an APECS SGMAP-mapped DMA map with a uio. + */ +int +apecs_bus_dmamap_load_uio_sgmap(t, map, uio, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + struct uio *uio; + int flags; +{ + int error; + + error = pci_sgmap_pte64_load_uio(t, map, uio, flags, t->_sgmap); + if (error == 0) + APECS_TLB_INVALIDATE(); + + return (error); +} + +/* + * Load an APECS SGMAP-mapped DMA map with raw memory. + */ +int +apecs_bus_dmamap_load_raw_sgmap(t, map, segs, nsegs, size, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + bus_dma_segment_t *segs; + int nsegs; + bus_size_t size; + int flags; +{ + int error; + + error = pci_sgmap_pte64_load_raw(t, map, segs, nsegs, size, flags, + t->_sgmap); + if (error == 0) + APECS_TLB_INVALIDATE(); + + return (error); +} + +/* + * Unload an APECS DMA map. + */ +void +apecs_bus_dmamap_unload_sgmap(t, map) + bus_dma_tag_t t; + bus_dmamap_t map; +{ + + /* + * Invalidate any SGMAP page table entries used by this + * mapping. + */ + pci_sgmap_pte64_unload(t, map, t->_sgmap); + APECS_TLB_INVALIDATE(); + + /* + * Do the generic bits of the unload. + */ + _bus_dmamap_unload(t, map); +} + +/* + * Create a APECS SGMAP-mapped DMA map. + */ +int +apecs_bus_dmamap_create_sgmap(t, size, nsegments, maxsegsz, boundary, + flags, dmamp) + bus_dma_tag_t t; + bus_size_t size; + int nsegments; + bus_size_t maxsegsz; + bus_size_t boundary; + int flags; + bus_dmamap_t *dmamp; +{ + bus_dmamap_t map; + int error; + + error = _bus_dmamap_create(t, size, nsegments, maxsegsz, + boundary, flags, dmamp); + if (error) + return (error); + + map = *dmamp; + + if (flags & BUS_DMA_ALLOCNOW) { + error = alpha_sgmap_alloc(map, round_page(size), + t->_sgmap, flags); + if (error) + apecs_bus_dmamap_destroy_sgmap(t, map); + } + + return (error); +} + +/* + * Destroy a APECS SGMAP-mapped DMA map. + */ +void +apecs_bus_dmamap_destroy_sgmap(t, map) + bus_dma_tag_t t; + bus_dmamap_t map; +{ + + if (map->_dm_flags & DMAMAP_HAS_SGMAP) + alpha_sgmap_free(map, t->_sgmap); + + _bus_dmamap_destroy(t, map); +} diff --git a/sys/arch/alpha/pci/apecsreg.h b/sys/arch/alpha/pci/apecsreg.h index 169faaf6cf1..aa920ea5064 100644 --- a/sys/arch/alpha/pci/apecsreg.h +++ b/sys/arch/alpha/pci/apecsreg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: apecsreg.h,v 1.4 1996/10/30 22:39:51 niklas Exp $ */ -/* $NetBSD: apecsreg.h,v 1.4 1996/07/09 00:54:34 cgd Exp $ */ +/* $OpenBSD: apecsreg.h,v 1.5 2001/02/16 05:17:31 jason Exp $ */ +/* $NetBSD: apecsreg.h,v 1.5.2.2 1997/06/06 20:26:53 thorpej Exp $ */ /* * Copyright (c) 1995 Carnegie-Mellon University. @@ -261,6 +261,7 @@ #define EPIC_TBASE_2 (EPIC_BASE + 0x00e0) /* Trans. Base 2 */ #define EPIC_TBASE_RSVD 0x000001ff #define EPIC_TBASE_T_BASE 0xfffffe00 +#define EPIC_TBASE_SHIFT 1 #define EPIC_PCI_BASE_1 (EPIC_BASE + 0x0100) /* PCI Base 1 */ #define EPIC_PCI_BASE_2 (EPIC_BASE + 0x0120) /* PCI Base 2 */ @@ -270,9 +271,22 @@ #define EPIC_PCI_BASE_PCI_BASE 0xfff00000 #define EPIC_PCI_MASK_1 (EPIC_BASE + 0x0140) /* PCI Mask 1 */ -#define EPIC_PCI_MASK_2 (EPIC_BASE + 0x0160) /* PCI Maxk 2 */ +#define EPIC_PCI_MASK_2 (EPIC_BASE + 0x0160) /* PCI Mask 2 */ #define EPIC_PCI_MASK_RSVD 0x000fffff #define EPIC_PCI_MASK_PCI_MASK 0xfff00000 +#define EPIC_PCI_MASK_1M 0x00000000 +#define EPIC_PCI_MASK_2M 0x00100000 +#define EPIC_PCI_MASK_4M 0x00300000 +#define EPIC_PCI_MASK_8M 0x00700000 +#define EPIC_PCI_MASK_16M 0x00f00000 +#define EPIC_PCI_MASK_32M 0x01f00000 +#define EPIC_PCI_MASK_64M 0x03f00000 +#define EPIC_PCI_MASK_128M 0x07f00000 +#define EPIC_PCI_MASK_256M 0x0ff00000 +#define EPIC_PCI_MASK_512M 0x1ff00000 +#define EPIC_PCI_MASK_1G 0x3ff00000 +#define EPIC_PCI_MASK_2G 0x7ff00000 +#define EPIC_PCI_MASK_4G 0xfff00000 #define EPIC_HAXR0 (EPIC_BASE + 0x0180) /* Host Addr Extn 0 */ diff --git a/sys/arch/alpha/pci/apecsvar.h b/sys/arch/alpha/pci/apecsvar.h index a9653702ee5..ee55b21ec4c 100644 --- a/sys/arch/alpha/pci/apecsvar.h +++ b/sys/arch/alpha/pci/apecsvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: apecsvar.h,v 1.6 1997/01/24 19:57:35 niklas Exp $ */ +/* $OpenBSD: apecsvar.h,v 1.7 2001/02/16 05:17:31 jason Exp $ */ /* $NetBSD: apecsvar.h,v 1.5 1996/11/25 03:49:36 cgd Exp $ */ /* @@ -30,6 +30,7 @@ #include <dev/isa/isavar.h> #include <dev/pci/pcivar.h> +#include <alpha/pci/pci_sgmap_pte64.h> /* * An APECS chipset's configuration. @@ -47,6 +48,11 @@ struct apecs_config { bus_space_tag_t ac_iot, ac_memt; struct alpha_pci_chipset ac_pc; + struct alpha_bus_dma_tag ac_dmat_direct; + struct alpha_bus_dma_tag ac_dmat_sgmap; + + struct alpha_sgmap ac_sgmap; + u_int32_t ac_haxr1, ac_haxr2; struct extent *ac_io_ex, *ac_d_mem_ex, *ac_s_mem_ex; @@ -61,6 +67,7 @@ struct apecs_softc { void apecs_init __P((struct apecs_config *, int)); void apecs_pci_init __P((pci_chipset_tag_t, void *)); +void apecs_dma_init __P((struct apecs_config *)); bus_space_tag_t apecs_bus_io_init __P((void *)); bus_space_tag_t apecs_bus_mem_init __P((void *)); diff --git a/sys/arch/alpha/pci/lca.c b/sys/arch/alpha/pci/lca.c index a4ccb4473b8..3ff240cb90c 100644 --- a/sys/arch/alpha/pci/lca.c +++ b/sys/arch/alpha/pci/lca.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lca.c,v 1.8 2000/11/08 16:01:19 art Exp $ */ +/* $OpenBSD: lca.c,v 1.9 2001/02/16 05:17:31 jason Exp $ */ /* $NetBSD: lca.c,v 1.14 1996/12/05 01:39:35 cgd Exp $ */ /* @@ -45,15 +45,11 @@ #include <dev/pci/pcivar.h> #include <alpha/pci/lcareg.h> #include <alpha/pci/lcavar.h> -#if defined(DEC_AXPPCI_33) +#ifdef DEC_AXPPCI_33 #include <alpha/pci/pci_axppci_33.h> #endif -#ifdef __BROKEN_INDIRECT_CONFIG int lcamatch __P((struct device *, void *, void *)); -#else -int lcamatch __P((struct device *, struct cfdata *, void *)); -#endif void lcaattach __P((struct device *, struct device *, void *)); struct cfattach lca_ca = { @@ -73,11 +69,7 @@ struct lca_config lca_configuration; int lcamatch(parent, match, aux) struct device *parent; -#ifdef __BROKEN_INDIRECT_CONFIG void *match; -#else - struct cfdata *match; -#endif void *aux; { struct mainbus_attach_args *ma = aux; @@ -102,10 +94,6 @@ lca_init(lcp, mallocsafe) { /* - * Can't set up SGMAP data here; can be called before malloc(). - */ - - /* * The LCA HAE register is WRITE-ONLY, so we can't tell where * the second sparse window is actually mapped. Therefore, * we have to guess where it is. This seems to be the normal @@ -145,49 +133,11 @@ lca_init(lcp, mallocsafe) * * IOC_CONF set to ZERO. */ - 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; */ - alpha_mb(); - - /* XXX XXX BEGIN XXX XXX */ - { /* XXX */ - extern vm_offset_t alpha_XXX_dmamap_or; /* XXX */ - alpha_XXX_dmamap_or = 0x40000000; /* XXX */ - } /* XXX */ - /* XXX XXX END XXX XXX */ + REGVAL64(LCA_IOC_CONF) = 0; lcp->lc_initted = 1; } -#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; - alpha_mb(); - - /* 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; - alpha_mb(); -} -#endif - void lcaattach(parent, self, aux) struct device *parent, *self; @@ -203,19 +153,19 @@ lcaattach(parent, self, aux) /* * set up the chipset's info; done once at console init time - * (maybe), but doesn't hurt to do twice. + * (maybe), but we must do it twice to take care of things + * that need to use memory allocation. */ lcp = sc->sc_lcp = &lca_configuration; lca_init(lcp, 1); -#ifdef notdef - lca_init_sgmap(lcp); -#endif /* XXX print chipset information */ printf("\n"); + lca_dma_init(lcp); + switch (hwrpb->rpb_type) { -#if defined(DEC_AXPPCI_33) +#ifdef DEC_AXPPCI_33 case ST_DEC_AXPPCI_33: pci_axppci_33_pickintr(lcp); break; @@ -228,8 +178,14 @@ lcaattach(parent, self, aux) pba.pba_busname = "pci"; pba.pba_iot = lcp->lc_iot; pba.pba_memt = lcp->lc_memt; + pba.pba_dmat = alphabus_dma_get_tag(&lcp->lc_dmat_direct, + ALPHA_BUS_PCI); pba.pba_pc = &lcp->lc_pc; pba.pba_bus = 0; +#ifdef notyet + pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED | + PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | PCI_FLAGS_MWI_OKAY; +#endif config_found(self, &pba, lcaprint); } diff --git a/sys/arch/alpha/pci/lca_dma.c b/sys/arch/alpha/pci/lca_dma.c new file mode 100644 index 00000000000..080204f2dbd --- /dev/null +++ b/sys/arch/alpha/pci/lca_dma.c @@ -0,0 +1,396 @@ +/* $OpenBSD: lca_dma.c,v 1.1 2001/02/16 05:17:31 jason Exp $ */ +/* $NetBSD: lca_dma.c,v 1.13 2000/06/29 08:58:47 mrg Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 FOUNDATION OR CONTRIBUTORS + * 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. + */ + +/* + * XXX - We should define this before including bus.h, but since other stuff + * pulls in bus.h we must do this here. + */ +#define _ALPHA_BUS_DMA_PRIVATE + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/malloc.h> + +#include <vm/vm.h> +#include <uvm/uvm_extern.h> + +#include <machine/bus.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <alpha/pci/lcareg.h> +#include <alpha/pci/lcavar.h> + +bus_dma_tag_t lca_dma_get_tag __P((bus_dma_tag_t, alpha_bus_t)); + +int lca_bus_dmamap_create_sgmap __P((bus_dma_tag_t, bus_size_t, int, + bus_size_t, bus_size_t, int, bus_dmamap_t *)); + +void lca_bus_dmamap_destroy_sgmap __P((bus_dma_tag_t, bus_dmamap_t)); + +int lca_bus_dmamap_load_sgmap __P((bus_dma_tag_t, bus_dmamap_t, void *, + bus_size_t, struct proc *, int)); + +int lca_bus_dmamap_load_mbuf_sgmap __P((bus_dma_tag_t, bus_dmamap_t, + struct mbuf *, int)); + +int lca_bus_dmamap_load_uio_sgmap __P((bus_dma_tag_t, bus_dmamap_t, + struct uio *, int)); + +int lca_bus_dmamap_load_raw_sgmap __P((bus_dma_tag_t, bus_dmamap_t, + bus_dma_segment_t *, int, bus_size_t, int)); + +void lca_bus_dmamap_unload_sgmap __P((bus_dma_tag_t, bus_dmamap_t)); + +/* + * Direct-mapped window: 1G at 1G + */ +#define LCA_DIRECT_MAPPED_BASE (1*1024*1024*1024) +#define LCA_DIRECT_MAPPED_SIZE (1*1024*1024*1024) + +/* + * SGMAP window: 8M at 8M + */ +#define LCA_SGMAP_MAPPED_BASE (8*1024*1024) +#define LCA_SGMAP_MAPPED_SIZE (8*1024*1024) + +/* + * Macro to flush LCA scatter/gather TLB. + */ +#define LCA_TLB_INVALIDATE() \ +do { \ + alpha_mb(); \ + REGVAL64(LCA_IOC_TBIA) = 0; \ + alpha_mb(); \ +} while (0) + +void +lca_dma_init(lcp) + struct lca_config *lcp; +{ + bus_dma_tag_t t; + + /* + * Initialize the DMA tag used for direct-mapped DMA. + */ + t = &lcp->lc_dmat_direct; + t->_cookie = lcp; + t->_wbase = LCA_DIRECT_MAPPED_BASE; + t->_wsize = LCA_DIRECT_MAPPED_SIZE; + t->_next_window = NULL; + t->_boundary = 0; + t->_sgmap = NULL; + t->_get_tag = lca_dma_get_tag; + t->_dmamap_create = _bus_dmamap_create; + t->_dmamap_destroy = _bus_dmamap_destroy; + t->_dmamap_load = _bus_dmamap_load_direct; + t->_dmamap_load_mbuf = _bus_dmamap_load_mbuf_direct; + t->_dmamap_load_uio = _bus_dmamap_load_uio_direct; + t->_dmamap_load_raw = _bus_dmamap_load_raw_direct; + t->_dmamap_unload = _bus_dmamap_unload; + t->_dmamap_sync = _bus_dmamap_sync; + + t->_dmamem_alloc = _bus_dmamem_alloc; + t->_dmamem_free = _bus_dmamem_free; + t->_dmamem_map = _bus_dmamem_map; + t->_dmamem_unmap = _bus_dmamem_unmap; + t->_dmamem_mmap = _bus_dmamem_mmap; + + /* + * Initialize the DMA tag used for sgmap-mapped DMA. + */ + t = &lcp->lc_dmat_sgmap; + t->_cookie = lcp; + t->_wbase = LCA_SGMAP_MAPPED_BASE; + t->_wsize = LCA_SGMAP_MAPPED_SIZE; + t->_next_window = NULL; + t->_boundary = 0; + t->_sgmap = &lcp->lc_sgmap; + t->_get_tag = lca_dma_get_tag; + t->_dmamap_create = lca_bus_dmamap_create_sgmap; + + t->_dmamap_destroy = lca_bus_dmamap_destroy_sgmap; + t->_dmamap_load = lca_bus_dmamap_load_sgmap; + t->_dmamap_load_mbuf = lca_bus_dmamap_load_mbuf_sgmap; + t->_dmamap_load_uio = lca_bus_dmamap_load_uio_sgmap; + t->_dmamap_load_raw = lca_bus_dmamap_load_raw_sgmap; + t->_dmamap_unload = lca_bus_dmamap_unload_sgmap; + t->_dmamap_sync = _bus_dmamap_sync; + + t->_dmamem_alloc = _bus_dmamem_alloc; + t->_dmamem_free = _bus_dmamem_free; + t->_dmamem_map = _bus_dmamem_map; + t->_dmamem_unmap = _bus_dmamem_unmap; + t->_dmamem_mmap = _bus_dmamem_mmap; + + /* + * The firmware has set up window 1 as a 1G direct-mapped DMA + * window beginning at 1G. We leave it alone. Disable + * window 0. + */ + REGVAL64(LCA_IOC_W_BASE0) = 0; + alpha_mb(); + + /* + * Initialize the SGMAP. + */ + alpha_sgmap_init(t, &lcp->lc_sgmap, "lca_sgmap", + LCA_SGMAP_MAPPED_BASE, 0, LCA_SGMAP_MAPPED_SIZE, + sizeof(u_int64_t), NULL, 0); + + /* + * Set up window 0 as an 8MB SGMAP-mapped window + * starting at 8MB. + */ + REGVAL64(LCA_IOC_W_BASE0) = LCA_SGMAP_MAPPED_BASE | + IOC_W_BASE_SG | IOC_W_BASE_WEN; + alpha_mb(); + + REGVAL64(LCA_IOC_W_MASK0) = IOC_W_MASK_8M; + alpha_mb(); + + if ((lcp->lc_sgmap.aps_ptpa & IOC_W_T_BASE) != + lcp->lc_sgmap.aps_ptpa) + panic("lca_dma_init: bad page table address"); + REGVAL64(LCA_IOC_W_T_BASE0) = lcp->lc_sgmap.aps_ptpa; + alpha_mb(); + + /* Enble the scatter/gather TLB. */ + REGVAL64(LCA_IOC_TB_ENA) = IOC_TB_ENA_TEN; + alpha_mb(); + + LCA_TLB_INVALIDATE(); + + /* XXX XXX BEGIN XXX XXX */ + { /* XXX */ + extern paddr_t alpha_XXX_dmamap_or; /* XXX */ + alpha_XXX_dmamap_or = LCA_DIRECT_MAPPED_BASE; /* XXX */ + } /* XXX */ + /* XXX XXX END XXX XXX */ +} + +/* + * Return the bus dma tag to be used for the specified bus type. + * INTERNAL USE ONLY! + */ +bus_dma_tag_t +lca_dma_get_tag(t, bustype) + bus_dma_tag_t t; + alpha_bus_t bustype; +{ + struct lca_config *lcp = t->_cookie; + + switch (bustype) { + case ALPHA_BUS_PCI: + case ALPHA_BUS_EISA: + /* + * Systems with an LCA can only support 1G + * of memory, so we use the direct-mapped window + * on busses that have 32-bit DMA. + */ + return (&lcp->lc_dmat_direct); + + case ALPHA_BUS_ISA: + /* + * ISA doesn't have enough address bits to use + * the direct-mapped DMA window, so we must use + * SGMAPs. + */ + return (&lcp->lc_dmat_sgmap); + + default: + panic("lca_dma_get_tag: shouldn't be here, really..."); + } +} + +/* + * Load an LCA SGMAP-mapped DMA map with a linear buffer. + */ +int +lca_bus_dmamap_load_sgmap(t, map, buf, buflen, p, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + void *buf; + bus_size_t buflen; + struct proc *p; + int flags; +{ + int error; + + error = pci_sgmap_pte64_load(t, map, buf, buflen, p, flags, + t->_sgmap); + if (error == 0) + LCA_TLB_INVALIDATE(); + + return (error); +} + +/* + * Load an LCA SGMAP-mapped DMA map with an mbuf chain. + */ +int +lca_bus_dmamap_load_mbuf_sgmap(t, map, m, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + struct mbuf *m; + int flags; +{ + int error; + + error = pci_sgmap_pte64_load_mbuf(t, map, m, flags, t->_sgmap); + if (error == 0) + LCA_TLB_INVALIDATE(); + + return (error); +} + +/* + * Load an LCA SGMAP-mapped DMA map with a uio. + */ +int +lca_bus_dmamap_load_uio_sgmap(t, map, uio, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + struct uio *uio; + int flags; +{ + int error; + + error = pci_sgmap_pte64_load_uio(t, map, uio, flags, t->_sgmap); + if (error == 0) + LCA_TLB_INVALIDATE(); + + return (error); +} + +/* + * Load an LCA SGMAP-mapped DMA map with raw memory. + */ +int +lca_bus_dmamap_load_raw_sgmap(t, map, segs, nsegs, size, flags) + bus_dma_tag_t t; + bus_dmamap_t map; + bus_dma_segment_t *segs; + int nsegs; + bus_size_t size; + int flags; +{ + int error; + + error = pci_sgmap_pte64_load_raw(t, map, segs, nsegs, size, flags, + t->_sgmap); + if (error == 0) + LCA_TLB_INVALIDATE(); + + return (error); +} + +/* + * Unload an LCA DMA map. + */ +void +lca_bus_dmamap_unload_sgmap(t, map) + bus_dma_tag_t t; + bus_dmamap_t map; +{ + + /* + * Invalidate any SGMAP page table entries used by this + * mapping. + */ + pci_sgmap_pte64_unload(t, map, t->_sgmap); + LCA_TLB_INVALIDATE(); + + /* + * Do the generic bits of the unload. + */ + _bus_dmamap_unload(t, map); +} + +/* + * Create a LCA SGMAP-mapped DMA map. + */ +int +lca_bus_dmamap_create_sgmap(t, size, nsegments, maxsegsz, boundary, + flags, dmamp) + bus_dma_tag_t t; + bus_size_t size; + int nsegments; + bus_size_t maxsegsz; + bus_size_t boundary; + int flags; + bus_dmamap_t *dmamp; +{ + bus_dmamap_t map; + int error; + + error = _bus_dmamap_create(t, size, nsegments, maxsegsz, + boundary, flags, dmamp); + if (error) + return (error); + + map = *dmamp; + + if (flags & BUS_DMA_ALLOCNOW) { + error = alpha_sgmap_alloc(map, round_page(size), + t->_sgmap, flags); + if (error) + lca_bus_dmamap_destroy_sgmap(t, map); + } + + return (error); +} + +/* + * Destroy a LCA SGMAP-mapped DMA map. + */ +void +lca_bus_dmamap_destroy_sgmap(t, map) + bus_dma_tag_t t; + bus_dmamap_t map; +{ + + if (map->_dm_flags & DMAMAP_HAS_SGMAP) + alpha_sgmap_free(map, t->_sgmap); + + _bus_dmamap_destroy(t, map); +} diff --git a/sys/arch/alpha/pci/lcareg.h b/sys/arch/alpha/pci/lcareg.h index d8fc88d3f46..ef74361a430 100644 --- a/sys/arch/alpha/pci/lcareg.h +++ b/sys/arch/alpha/pci/lcareg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: lcareg.h,v 1.5 1997/01/24 19:57:45 niklas Exp $ */ +/* $OpenBSD: lcareg.h,v 1.6 2001/02/16 05:17:32 jason Exp $ */ /* $NetBSD: lcareg.h,v 1.4 1996/11/23 06:41:00 cgd Exp $ */ /* @@ -49,8 +49,23 @@ #define IOC_HAE_RSVSD 0xffffffff07ffffffUL #define LCA_IOC_CONF (LCA_IOC_BASE + 0x020) /* Configuration Cycle Type */ + #define LCA_IOC_STAT0 (LCA_IOC_BASE + 0x040) /* Status 0 */ +#define IOC_STAT0_CMD 0x000000000000000fUL /* PCI command mask */ +#define IOC_STAT0_ERR 0x0000000000000010UL /* IOC error indicator R/W1C */ +#define IOC_STAT0_LOST 0x0000000000000020UL /* IOC lose error info R/W1C */ +#define IOC_STAT0_THIT 0x0000000000000040UL /* test hit */ +#define IOC_STAT0_TREF 0x0000000000000080UL /* test reference */ +#define IOC_STAT0_CODE 0x0000000000000700UL /* code mask */ +#define IOC_STAT0_CODESHIFT 8 +#define IOC_STAT0_P_NBR 0x00000000ffffe000UL /* page number mask */ + #define LCA_IOC_STAT1 (LCA_IOC_BASE + 0x060) /* Status 1 */ +#define IOC_STAT1_ADDR 0x00000000ffffffffUL /* PCI address mask */ + +#define LCA_IOC_TBIA (LCA_IOC_BASE + 0x080) /* TLB Invalidate All */ +#define LCA_IOC_TB_ENA (LCA_IOC_BASE + 0x0a0) /* TLB Enable */ +#define IOC_TB_ENA_TEN 0x0000000000000080UL #define LCA_IOC_W_BASE0 (LCA_IOC_BASE + 0x100) /* Window Base */ #define LCA_IOC_W_MASK0 (LCA_IOC_BASE + 0x140) /* Window Mask */ @@ -59,3 +74,23 @@ #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 */ + +#define IOC_W_BASE_W_BASE 0x00000000fff00000UL /* Window base value */ +#define IOC_W_BASE_SG 0x0000000100000000UL /* Window uses SGMAPs */ +#define IOC_W_BASE_WEN 0x0000000200000000UL /* Window enable */ + +#define IOC_W_MASK_1M 0x0000000000000000UL /* 1MB window */ +#define IOC_W_MASK_2M 0x0000000000100000UL /* 2MB window */ +#define IOC_W_MASK_4M 0x0000000000300000UL /* 4MB window */ +#define IOC_W_MASK_8M 0x0000000000700000UL /* 8MB window */ +#define IOC_W_MASK_16M 0x0000000000f00000UL /* 16MB window */ +#define IOC_W_MASK_32M 0x0000000001f00000UL /* 32MB window */ +#define IOC_W_MASK_64M 0x0000000003f00000UL /* 64MB window */ +#define IOC_W_MASK_128M 0x0000000007f00000UL /* 128M window */ +#define IOC_W_MASK_256M 0x000000000ff00000UL /* 256M window */ +#define IOC_W_MASK_512M 0x000000001ff00000UL /* 512M window */ +#define IOC_W_MASK_1G 0x000000003ff00000UL /* 1GB window */ +#define IOC_W_MASK_2G 0x000000007ff00000UL /* 2GB window */ +#define IOC_W_MASK_4G 0x00000000fff00000UL /* 4GB window */ + +#define IOC_W_T_BASE 0x00000000fffffc00UL /* page table base */ diff --git a/sys/arch/alpha/pci/lcavar.h b/sys/arch/alpha/pci/lcavar.h index 597e783eb34..6b40ff3234f 100644 --- a/sys/arch/alpha/pci/lcavar.h +++ b/sys/arch/alpha/pci/lcavar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: lcavar.h,v 1.6 1997/01/24 19:57:46 niklas Exp $ */ +/* $OpenBSD: lcavar.h,v 1.7 2001/02/16 05:17:32 jason Exp $ */ /* $NetBSD: lcavar.h,v 1.5 1996/11/25 03:49:38 cgd Exp $ */ /* @@ -30,6 +30,7 @@ #include <dev/isa/isavar.h> #include <dev/pci/pcivar.h> +#include <alpha/pci/pci_sgmap_pte64.h> /* * LCA chipset's configuration. @@ -43,6 +44,11 @@ struct lca_config { bus_space_tag_t lc_iot, lc_memt; struct alpha_pci_chipset lc_pc; + struct alpha_bus_dma_tag lc_dmat_direct; + struct alpha_bus_dma_tag lc_dmat_sgmap; + + struct alpha_sgmap lc_sgmap; + bus_addr_t lc_s_mem_w2_masked_base; struct extent *lc_io_ex, *lc_d_mem_ex, *lc_s_mem_ex; @@ -57,6 +63,7 @@ struct lca_softc { void lca_init __P((struct lca_config *, int)); void lca_pci_init __P((pci_chipset_tag_t, void *)); +void lca_dma_init __P((struct lca_config *)); bus_space_tag_t lca_bus_io_init __P((void *)); bus_space_tag_t lca_bus_mem_init __P((void *)); |