1/* $NetBSD: bus_space.c,v 1.19 2011/02/12 04:52:28 tsutsui Exp $ */ 2 3/*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * Implementation of bus_space mapping for the hp300. 34 */ 35 36#include <sys/cdefs.h> 37__KERNEL_RCSID(0, "$NetBSD: bus_space.c,v 1.19 2011/02/12 04:52:28 tsutsui Exp $"); 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/extent.h> 42 43#include <machine/autoconf.h> 44#include <machine/bus.h> 45 46#include <uvm/uvm_extern.h> 47 48extern int *nofault; 49 50/* ARGSUSED */ 51int 52bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags, 53 bus_space_handle_t *bshp) 54{ 55 vaddr_t kva; 56 vsize_t offset; 57 int error; 58 59 if (t->bustype == HP300_BUS_SPACE_INTIO) { 60 /* 61 * Intio space is direct-mapped in pmap_bootstrap(); just 62 * do the translation. 63 */ 64 *bshp = (bus_space_handle_t)IIOV(INTIOBASE + bpa); 65 return 0; 66 } 67 68 if (t->bustype != HP300_BUS_SPACE_DIO && 69 t->bustype != HP300_BUS_SPACE_SGC) 70 panic("%s: bad space tag", __func__); 71 72 /* 73 * Allocate virtual address space from the extio extent map. 74 */ 75 offset = m68k_page_offset(bpa); 76 size = m68k_round_page(offset + size); 77 error = extent_alloc(extio_ex, size, PAGE_SIZE, 0, 78 EX_FAST | EX_NOWAIT | (extio_ex_malloc_safe ? EX_MALLOCOK : 0), 79 &kva); 80 if (error) 81 return error; 82 83 /* 84 * Map the range. The range is always cache-inhibited on the hp300. 85 */ 86 physaccess((void *)kva, (void *)bpa, size, PG_RW|PG_CI); 87 88 /* 89 * All done. 90 */ 91 *bshp = (bus_space_handle_t)(kva + offset); 92 return 0; 93} 94 95/* ARGSUSED */ 96int 97bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend, 98 bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags, 99 bus_addr_t *bpap, bus_space_handle_t *bshp) 100{ 101 102 /* 103 * Not meaningful on any currently-supported hp300 bus. 104 */ 105 return EINVAL; 106} 107 108/* ARGSUSED */ 109void 110bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) 111{ 112 113 /* 114 * Not meaningful on any currently-supported hp300 bus. 115 */ 116 panic("%s: shouldn't be here", __func__); 117} 118 119void 120bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size) 121{ 122 vaddr_t kva; 123 vsize_t offset; 124 125 if (t->bustype == HP300_BUS_SPACE_INTIO) { 126 /* 127 * Intio space is direct-mapped in pmap_bootstrap(); nothing 128 * to do 129 */ 130 return; 131 } 132 133 if (t->bustype != HP300_BUS_SPACE_DIO && 134 t->bustype != HP300_BUS_SPACE_SGC) 135 panic("%s: bad space tag", __func__); 136 137 kva = m68k_trunc_page(bsh); 138 offset = m68k_page_offset(bsh); 139 size = m68k_round_page(offset + size); 140 141#ifdef DIAGNOSTIC 142 if (bsh < (vaddr_t)extiobase || 143 bsh >= ((vaddr_t)extiobase + ptoa(EIOMAPSIZE))) 144 panic("%s: bad bus space handle", __func__); 145#endif 146 147 /* 148 * Unmap the range. 149 */ 150 physunaccess((void *)kva, size); 151 152 /* 153 * Free it from the extio extent map. 154 */ 155 if (extent_free(extio_ex, kva, size, 156 EX_NOWAIT | (extio_ex_malloc_safe ? EX_MALLOCOK : 0))) 157 printf("%s: kva 0x%lx size 0x%lx: " 158 "can't free region\n", __func__, (u_long)bsh, size); 159} 160 161/* ARGSUSED */ 162int 163bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh, 164 bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp) 165{ 166 167 *nbshp = bsh + offset; 168 return 0; 169} 170 171/* ARGSUSED */ 172int 173hp300_bus_space_probe(bus_space_tag_t t, bus_space_handle_t bsh, 174 bus_size_t offset, int sz) 175{ 176 label_t faultbuf; 177 int i; 178 179 nofault = (int *)&faultbuf; 180 if (setjmp((label_t *)nofault)) { 181 nofault = NULL; 182 return 0; 183 } 184 185 switch (sz) { 186 case 1: 187 i = bus_space_read_1(t, bsh, offset); 188 break; 189 190 case 2: 191 i = bus_space_read_2(t, bsh, offset); 192 break; 193 194 case 4: 195 i = bus_space_read_4(t, bsh, offset); 196 break; 197 198 default: 199 panic("%s: unupported data size %d", __func__, sz); 200 /* NOTREACHED */ 201 } 202 203 nofault = NULL; 204 return 1; 205} 206