Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/hp700/dev Support virtual mode as PCX-U/U+ (and pro...



details:   https://anonhg.NetBSD.org/src/rev/5ac88f366214
branches:  trunk
changeset: 772699:5ac88f366214
user:      skrll <skrll%NetBSD.org@localhost>
date:      Thu Jan 12 23:06:45 2012 +0000

description:
Support virtual mode as PCX-U/U+ (and probably other) CPU based machines
required it. Only PCX-W seemed to work with real mode.

Gratuitous copying of code from astro. Deadlines!

diffstat:

 sys/arch/hp700/dev/uturn.c |  646 ++++++++++++++++++++++++++++++++++++--------
 1 files changed, 530 insertions(+), 116 deletions(-)

diffs (truncated from 826 to 300 lines):

diff -r e4e535a4ef98 -r 5ac88f366214 sys/arch/hp700/dev/uturn.c
--- a/sys/arch/hp700/dev/uturn.c        Thu Jan 12 22:22:10 2012 +0000
+++ b/sys/arch/hp700/dev/uturn.c        Thu Jan 12 23:06:45 2012 +0000
@@ -1,7 +1,52 @@
-/*     $NetBSD: uturn.c,v 1.16 2011/07/01 18:33:09 dyoung Exp $        */
+/*     $NetBSD: uturn.c,v 1.17 2012/01/12 23:06:45 skrll Exp $ */
 
 /*     $OpenBSD: uturn.c,v 1.6 2007/12/29 01:26:14 kettenis Exp $      */
 
+/*-
+ * Copyright (c) 2012, 2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Nick Hudson.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * Copyright (c) 2007 Mark Kettenis
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
 /*
  * Copyright (c) 2004 Michael Shalayeff
  * All rights reserved.
@@ -28,7 +73,13 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/* TODO IOA programming */
+/*
+ * References:
+ * 1. Hardware Cache Coherent Input/Output. Hewlett-Packard Journal, February
+ *    1996.
+ * 2. PA-RISC 1.1 Architecture and Instruction Set Reference Manual,
+ *    Hewlett-Packard, February 1994, Third Edition
+ */
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -37,6 +88,7 @@
 #include <sys/malloc.h>
 #include <sys/extent.h>
 #include <sys/mbuf.h>
+#include <sys/tree.h>
 
 #include <uvm/uvm.h>
 
@@ -46,6 +98,7 @@
 
 #include <hp700/dev/cpudevs.h>
 
+#define UTURNDEBUG
 #ifdef UTURNDEBUG
 
 #define        DPRINTF(s)      do {    \
@@ -101,15 +154,61 @@
        uint32_t        io_io_high;             /* Offset 15 */
 };
 
+
+/* Uturn supports 256 TLB entries */
+#define        UTURN_CHAINID_SHIFT     8
+#define        UTURN_CHAINID_MASK      0xff
+#define        UTURN_TLB_ENTRIES       (1 << UTURN_CHAINID_SHIFT)
+
+#define        UTURN_IOVP_SIZE         PAGE_SIZE
+#define        UTURN_IOVP_SHIFT        PAGE_SHIFT
+#define        UTURN_IOVP_MASK         PAGE_MASK
+
+#define        UTURN_IOVA(iovp, off)   ((iovp) | (off))
+#define        UTURN_IOVP(iova)        ((iova) & UTURN_IOVP_MASK)
+#define        UTURN_IOVA_INDEX(iova)  ((iova) >> UTURN_IOVP_SHIFT)
+
 struct uturn_softc {
        device_t sc_dv;
 
        bus_dma_tag_t sc_dmat;
        struct uturn_regs volatile *sc_regs;
+       uint64_t *sc_pdir;
+       uint32_t sc_chainid_shift;
+
+       char sc_mapname[20];
+       struct extent *sc_map;
 
        struct hppa_bus_dma_tag sc_dmatag;
 };
 
+/*
+ * per-map IOVA page table
+ */
+struct uturn_page_entry {
+       SPLAY_ENTRY(uturn_page_entry) upe_node;
+       paddr_t upe_pa;
+       vaddr_t upe_va;
+       bus_addr_t upe_iova;
+};
+
+struct uturn_page_map {
+       SPLAY_HEAD(uturn_page_tree, uturn_page_entry) upm_tree;
+       int upm_maxpage;        /* Size of allocated page map */
+       int upm_pagecnt;        /* Number of entries in use */
+       struct uturn_page_entry upm_map[1];
+};
+
+/*
+ * per-map UTURN state
+ */
+struct uturn_map_state {
+       struct uturn_softc *ums_sc;
+       bus_addr_t ums_iovastart;
+       bus_size_t ums_iovasize;
+       struct uturn_page_map ums_map;  /* map must be last (array at end) */
+};
+
 int    uturnmatch(device_t, cfdata_t, void *);
 void   uturnattach(device_t, device_t, void *);
 static device_t uturn_callback(device_t, struct confargs *);
@@ -137,6 +236,18 @@
 void uturn_dmamem_unmap(void *, void *, size_t);
 paddr_t uturn_dmamem_mmap(void *, bus_dma_segment_t *, int, off_t, int, int);
 
+static void uturn_iommu_enter(struct uturn_softc *, bus_addr_t, pa_space_t,
+    vaddr_t, paddr_t);
+static void uturn_iommu_remove(struct uturn_softc *, bus_addr_t, bus_size_t);
+
+struct uturn_map_state *uturn_iomap_create(int);
+void   uturn_iomap_destroy(struct uturn_map_state *);
+int    uturn_iomap_insert_page(struct uturn_map_state *, vaddr_t, paddr_t);
+bus_addr_t uturn_iomap_translate(struct uturn_map_state *, paddr_t);
+void   uturn_iomap_clear_pages(struct uturn_map_state *);
+
+static int uturn_iomap_load_map(struct uturn_softc *, bus_dmamap_t, int);
+
 const struct hppa_bus_dma_tag uturn_dmat = {
        NULL,
        uturn_dmamap_create, uturn_dmamap_destroy,
@@ -172,6 +283,11 @@
        struct uturn_softc *sc = device_private(self);
        bus_space_handle_t ioh;
        volatile struct uturn_regs *r;
+       struct pglist pglist;
+       int iova_bits;
+       vaddr_t va;
+       psize_t size;
+       int i;
 
        if (bus_space_map(ca->ca_iot, ca->ca_hpa, IOMOD_HPASIZE, 0, &ioh)) {
                aprint_error(": can't map IO space\n");
@@ -189,7 +305,59 @@
            ca->ca_type.iodc_revision < 0x10 ? "U2" : "UTurn",
            ca->ca_type.iodc_revision & 0xf);
 
-       r->io_control = UTURN_REAL_MODE;
+       /*
+        * Setup the iommu.
+        */
+
+       /* XXX 28 bits gives us 256Mb of iova space */
+       /* Calculate based on %age of RAM */
+       iova_bits = 28;
+
+       /*
+        * size is # of pdir entries (64bits) in bytes.  1 entry per IOVA
+        * page.
+        */
+       size = (1 << (iova_bits - UTURN_IOVP_SHIFT)) * sizeof(uint64_t);
+
+       /*
+        * Chainid is the upper most bits of an IOVP used to determine which
+        * TLB entry an IOVP will use.
+        */
+       sc->sc_chainid_shift = iova_bits - UTURN_CHAINID_SHIFT;
+
+       /*
+        * Allocate memory for I/O pagetables.  They need to be physically
+        * contiguous.
+        */
+
+       if (uvm_pglistalloc(size, 0, -1, PAGE_SIZE, 0, &pglist, 1, 0) != 0)
+               panic("%s: no memory", __func__);
+
+       va = (vaddr_t)VM_PAGE_TO_PHYS(TAILQ_FIRST(&pglist));
+       sc->sc_pdir = (int64_t *)va;
+
+       memset(sc->sc_pdir, 0, size);
+
+       r->io_chain_id_mask = UTURN_CHAINID_MASK << sc->sc_chainid_shift;
+       r->io_pdir_base = VM_PAGE_TO_PHYS(TAILQ_FIRST(&pglist));
+
+       r->io_tlb_entry_m = 0;
+       r->io_tlb_entry_l = 0;
+
+       /* for (i = UTURN_TLB_ENTRIES; i != 0; i--) { */
+       for (i = 0; i < UTURN_TLB_ENTRIES; i++) {
+               r->io_command =
+                   UTURN_CMD_TLB_DIRECT_WRITE | (i << sc->sc_chainid_shift);
+       }
+       /*
+        * Go to "Virtual Mode"
+        */
+       r->io_control = UTURN_VIRTUAL_MODE;
+
+       snprintf(sc->sc_mapname, sizeof(sc->sc_mapname), "%s_map",
+           device_xname(sc->sc_dv));
+       sc->sc_map = extent_create(sc->sc_mapname, 0, (1 << iova_bits),
+           M_DEVBUF, 0, 0, EX_NOWAIT);
 
        sc->sc_dmatag = uturn_dmat;
        sc->sc_dmatag._cookie = sc;
@@ -205,7 +373,6 @@
        nca.ca_dmatag = &sc->sc_dmatag;
        nca.ca_nmodules = MAXMODBUS - 1;
        pdc_scanbus(self, &nca, uturn_callback);
-
 }
 
 static device_t
@@ -216,20 +383,134 @@
            mbsubmatch);
 }
 
+/*
+ * PDIR entry format (HP bit number)
+ *
+ * +-------+----------------+----------------------------------------------+
+ * |0     3|4             15|16                                          31|
+ * | PPN   | Virtual Index  |         Physical Page Number (PPN)           |
+ * | [0:3] |    [0:11]      |                 [4:19]                       |
+ * +-------+----------------+----------------------------------------------+
+ * 
+ * +-----------------------+-----------------------------------------------+
+ * |0           19|20    24|   25   |       |       |      |  30   |   31  |
+ * |     PPN      |  Rsvd  | PH     |Update | Rsvd  |Lock  | Safe  | Valid |
+ * |    [20:39    |        | Enable |Enable |       |Enable| DMA   |       |
+ * +-----------------------+-----------------------------------------------+
+ *
+ */
+
+#define UTURN_PENTRY_PREFETCH  0x40
+#define UTURN_PENTRY_UPDATE    0x20
+#define UTURN_PENTRY_LOCK      0x04    /* eisa devices only */
+#define UTURN_PENTRY_SAFEDMA   0x02    /* use safe dma - for subcacheline */
+#define UTURN_PENTRY_VALID     0x01
+
+static void
+uturn_iommu_enter(struct uturn_softc *sc, bus_addr_t iova, pa_space_t sp,
+    vaddr_t va, paddr_t pa)
+{
+       uint64_t pdir_entry;
+       uint64_t *pdirp;
+       uint32_t ci; /* coherent index */
+
+       pdirp = &sc->sc_pdir[UTURN_IOVA_INDEX(iova)];
+
+       DPRINTF(("%s: iova %lx pdir %p pdirp %p pa %lx", __func__, iova,
+           sc->sc_pdir, pdirp, pa));
+
+       ci = lci(HPPA_SID_KERNEL, va);
+
+       /* setup hints, etc */
+       pdir_entry = (UTURN_PENTRY_LOCK | UTURN_PENTRY_SAFEDMA |
+            UTURN_PENTRY_VALID);
+
+       /*
+        * bottom 36 bits of pa map directly into entry to form PPN[4:39]
+        * leaving last 12 bits for hints, etc.
+        */



Home | Main Index | Thread Index | Old Index