1*3e6e9bd4Stsutsui /* $NetBSD: bus_subr.c,v 1.33 2013/09/06 17:43:19 tsutsui Exp $ */
2201c1f17Sgwr
3201c1f17Sgwr /*-
4201c1f17Sgwr * Copyright (c) 1996 The NetBSD Foundation, Inc.
5201c1f17Sgwr * All rights reserved.
6201c1f17Sgwr *
7201c1f17Sgwr * This code is derived from software contributed to The NetBSD Foundation
8201c1f17Sgwr * by Adam Glass and Gordon W. Ross.
9201c1f17Sgwr *
10201c1f17Sgwr * Redistribution and use in source and binary forms, with or without
11201c1f17Sgwr * modification, are permitted provided that the following conditions
12201c1f17Sgwr * are met:
13201c1f17Sgwr * 1. Redistributions of source code must retain the above copyright
14201c1f17Sgwr * notice, this list of conditions and the following disclaimer.
15201c1f17Sgwr * 2. Redistributions in binary form must reproduce the above copyright
16201c1f17Sgwr * notice, this list of conditions and the following disclaimer in the
17201c1f17Sgwr * documentation and/or other materials provided with the distribution.
18201c1f17Sgwr *
19201c1f17Sgwr * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20201c1f17Sgwr * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21201c1f17Sgwr * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22201c1f17Sgwr * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23201c1f17Sgwr * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24201c1f17Sgwr * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25201c1f17Sgwr * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26201c1f17Sgwr * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27201c1f17Sgwr * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28201c1f17Sgwr * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29201c1f17Sgwr * POSSIBILITY OF SUCH DAMAGE.
30201c1f17Sgwr */
31201c1f17Sgwr
32201c1f17Sgwr /*
335193e1e3Sgwr * bus_xxx support functions, Sun3X-specific part.
345193e1e3Sgwr * The common stuff is in autoconf.c
35201c1f17Sgwr */
36201c1f17Sgwr
37ed517291Slukem #include <sys/cdefs.h>
38*3e6e9bd4Stsutsui __KERNEL_RCSID(0, "$NetBSD: bus_subr.c,v 1.33 2013/09/06 17:43:19 tsutsui Exp $");
39ed517291Slukem
40201c1f17Sgwr #include <sys/param.h>
41201c1f17Sgwr #include <sys/systm.h>
42201c1f17Sgwr #include <sys/device.h>
43201c1f17Sgwr
441b01ec09Sgwr #include <uvm/uvm_extern.h>
451b01ec09Sgwr
46201c1f17Sgwr #include <machine/autoconf.h>
47201c1f17Sgwr #include <machine/cpu.h>
48201c1f17Sgwr #include <machine/mon.h>
49eff2e270Sgwr #include <machine/pmap.h>
50eff2e270Sgwr #include <machine/pte.h>
51eff2e270Sgwr
52eff2e270Sgwr #include <sun3/sun3/machdep.h>
53eff2e270Sgwr #include <sun3/sun3x/vme.h>
54201c1f17Sgwr
55201c1f17Sgwr label_t *nofault;
56201c1f17Sgwr
573f6f86d8Sjeremy /* These are defined in pmap.c */
58573961b5Stsutsui extern vaddr_t tmp_vpages[];
593f6f86d8Sjeremy extern int tmp_vpages_inuse;
60201c1f17Sgwr
61eff2e270Sgwr static const struct {
62eff2e270Sgwr long base;
63eff2e270Sgwr long mask;
64eff2e270Sgwr } bus_info[BUS__NTYPES] = {
65eff2e270Sgwr { /* OBIO */ 0, ~0 },
66eff2e270Sgwr { /* OBMEM */ 0, ~0 },
67eff2e270Sgwr /* VME A16 */
68eff2e270Sgwr { VME16D16_BASE, VME16_MASK },
69eff2e270Sgwr { VME16D32_BASE, VME16_MASK },
70eff2e270Sgwr /* VME A24 */
71eff2e270Sgwr { VME24D16_BASE, VME24_MASK },
72eff2e270Sgwr { VME24D32_BASE, VME24_MASK },
73eff2e270Sgwr /* VME A32 */
74eff2e270Sgwr { VME32D16_BASE, VME32_MASK },
75eff2e270Sgwr { VME32D32_BASE, VME32_MASK },
76eff2e270Sgwr };
77201c1f17Sgwr
78201c1f17Sgwr /*
795193e1e3Sgwr * Create a temporary, one-page mapping for a device.
805193e1e3Sgwr * This is used by some device probe routines that
815193e1e3Sgwr * need to do peek/write/read tricks.
82201c1f17Sgwr */
835193e1e3Sgwr void *
bus_tmapin(int bustype,int pa)8410b1a7beSchs bus_tmapin(int bustype, int pa)
85201c1f17Sgwr {
86573961b5Stsutsui vaddr_t pgva;
87d74e1744Sgwr int off, s;
88201c1f17Sgwr
89eff2e270Sgwr if ((bustype < 0) || (bustype >= BUS__NTYPES))
905193e1e3Sgwr panic("bus_tmapin: bustype");
91eff2e270Sgwr
92a5b83941Sgwr off = pa & PGOFSET;
93a5b83941Sgwr pa -= off;
945193e1e3Sgwr
955193e1e3Sgwr pa &= bus_info[bustype].mask;
965193e1e3Sgwr pa |= bus_info[bustype].base;
97a5b83941Sgwr pa |= PMAP_NC;
98201c1f17Sgwr
99a3ec356dSthorpej s = splvm();
1003f6f86d8Sjeremy if (tmp_vpages_inuse)
1015193e1e3Sgwr panic("bus_tmapin: tmp_vpages_inuse");
1023f6f86d8Sjeremy tmp_vpages_inuse++;
103b53e0d4fSjeremy
104a5b83941Sgwr pgva = tmp_vpages[1];
1059480c51bScegger pmap_kenter_pa(pgva, pa, VM_PROT_READ | VM_PROT_WRITE, 0);
1060e7661f0Schris pmap_update(pmap_kernel());
1075193e1e3Sgwr splx(s);
108201c1f17Sgwr
1095193e1e3Sgwr return ((void *)(pgva + off));
110201c1f17Sgwr }
111201c1f17Sgwr
11210b1a7beSchs void
bus_tmapout(void * vp)11310b1a7beSchs bus_tmapout(void *vp)
1145193e1e3Sgwr {
115573961b5Stsutsui vaddr_t pgva;
1165193e1e3Sgwr int s;
1175193e1e3Sgwr
1185193e1e3Sgwr pgva = m68k_trunc_page(vp);
1195193e1e3Sgwr if (pgva != tmp_vpages[1])
1205193e1e3Sgwr return;
1215193e1e3Sgwr
122a3ec356dSthorpej s = splvm();
1233b9d5835Sthorpej pmap_kremove(pgva, PAGE_SIZE);
1240e7661f0Schris pmap_update(pmap_kernel());
1253f6f86d8Sjeremy --tmp_vpages_inuse;
126b53e0d4fSjeremy splx(s);
127201c1f17Sgwr }
128201c1f17Sgwr
1295193e1e3Sgwr /*
1305193e1e3Sgwr * Make a permanent mapping for a device.
1315193e1e3Sgwr */
132201c1f17Sgwr void *
bus_mapin(int bustype,int pa,int sz)13310b1a7beSchs bus_mapin(int bustype, int pa, int sz)
134201c1f17Sgwr {
135573961b5Stsutsui vaddr_t va;
136a5b83941Sgwr int off;
137201c1f17Sgwr
138eff2e270Sgwr if ((bustype < 0) || (bustype >= BUS__NTYPES))
139a5b83941Sgwr panic("bus_mapin: bustype");
140201c1f17Sgwr
141a5b83941Sgwr off = pa & PGOFSET;
142a5b83941Sgwr pa -= off;
143201c1f17Sgwr sz += off;
144a5b83941Sgwr sz = m68k_round_page(sz);
145201c1f17Sgwr
1465193e1e3Sgwr /* Borrow PROM mappings if we can. */
1475193e1e3Sgwr if (bustype == BUS_OBIO) {
148c207dcd8Stsutsui if (find_prom_map(pa, PMAP_OBIO, sz, &va) == 0)
1495193e1e3Sgwr goto done;
1505193e1e3Sgwr }
1515193e1e3Sgwr
1525193e1e3Sgwr pa &= bus_info[bustype].mask;
1535193e1e3Sgwr pa |= bus_info[bustype].base;
154a5b83941Sgwr pa |= PMAP_NC; /* non-cached */
155201c1f17Sgwr
156201c1f17Sgwr /* Get some kernel virtual address space. */
1576b2d8b66Syamt va = uvm_km_alloc(kernel_map, sz, 0, UVM_KMF_VAONLY | UVM_KMF_WAITVA);
158201c1f17Sgwr if (va == 0)
159201c1f17Sgwr panic("bus_mapin");
160201c1f17Sgwr
161201c1f17Sgwr /* Map it to the specified bus. */
1625193e1e3Sgwr pmap_map(va, pa, pa + sz, VM_PROT_ALL);
163201c1f17Sgwr
1645193e1e3Sgwr done:
1655193e1e3Sgwr return ((void*)(va + off));
166201c1f17Sgwr }
167201c1f17Sgwr
1685193e1e3Sgwr void
bus_mapout(void * ptr,int sz)16910b1a7beSchs bus_mapout(void *ptr, int sz)
170eb841680Sgwr {
171573961b5Stsutsui vaddr_t va;
1725193e1e3Sgwr int off;
173eb841680Sgwr
174573961b5Stsutsui va = (vaddr_t)ptr;
175eff2e270Sgwr
1765193e1e3Sgwr /* If it was a PROM mapping, do NOT free it! */
1775193e1e3Sgwr if ((va >= SUN3X_MONSTART) && (va < SUN3X_MONEND))
1785193e1e3Sgwr return;
179eb841680Sgwr
1805193e1e3Sgwr off = va & PGOFSET;
1815193e1e3Sgwr va -= off;
1825193e1e3Sgwr sz += off;
1835193e1e3Sgwr sz = m68k_round_page(sz);
184201c1f17Sgwr
1858e1de5f3Stsutsui pmap_remove(pmap_kernel(), va, va + sz);
1868e1de5f3Stsutsui pmap_update(pmap_kernel());
1876b2d8b66Syamt uvm_km_free(kernel_map, va, sz, UVM_KMF_VAONLY);
188201c1f17Sgwr }
189