1 /* $NetBSD: bus_space.c,v 1.5 2002/09/27 15:35:41 provos Exp $ */ 2 /* NetBSD: bus_machdep.c,v 1.1 2000/01/26 18:48:00 drochner Exp */ 3 4 /*- 5 * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace 10 * Simulation Facility, NASA Ames Research Center. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the NetBSD 23 * Foundation, Inc. and its contributors. 24 * 4. Neither the name of The NetBSD Foundation nor the names of its 25 * contributors may be used to endorse or promote products derived 26 * from this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 * POSSIBILITY OF SUCH DAMAGE. 39 */ 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/malloc.h> 44 #include <sys/extent.h> 45 46 #include <uvm/uvm_extern.h> 47 48 #include <machine/bus.h> 49 50 void 51 arc_bus_space_init(bst, name, paddr, vaddr, start, size) 52 bus_space_tag_t bst; 53 const char *name; 54 paddr_t paddr; 55 vaddr_t vaddr; 56 bus_addr_t start; 57 bus_size_t size; 58 { 59 bst->bs_name = name; 60 bst->bs_extent = NULL; 61 bst->bs_start = start; 62 bst->bs_size = size; 63 bst->bs_pbase = paddr; 64 bst->bs_vbase = vaddr; 65 bst->bs_compose_handle = arc_bus_space_compose_handle; 66 bst->bs_dispose_handle = arc_bus_space_dispose_handle; 67 bst->bs_paddr = arc_bus_space_paddr; 68 bst->bs_map = arc_bus_space_map; 69 bst->bs_unmap = arc_bus_space_unmap; 70 bst->bs_subregion = arc_bus_space_subregion; 71 bst->bs_mmap = arc_bus_space_mmap; 72 bst->bs_alloc = arc_bus_space_alloc; 73 bst->bs_free = arc_bus_space_free; 74 bst->bs_aux = NULL; 75 bst->bs_stride_1 = 0; 76 bst->bs_stride_2 = 0; 77 bst->bs_stride_4 = 0; 78 bst->bs_stride_8 = 0; 79 } 80 81 void 82 arc_bus_space_init_extent(bst, storage, storagesize) 83 bus_space_tag_t bst; 84 caddr_t storage; 85 size_t storagesize; 86 { 87 bst->bs_extent = extent_create(bst->bs_name, 88 bst->bs_start, bst->bs_start + bst->bs_size, M_DEVBUF, 89 storage, storagesize, EX_NOWAIT); 90 if (bst->bs_extent == NULL) 91 panic("arc_bus_space_init_extent: cannot create extent map %s", 92 bst->bs_name); 93 } 94 95 void 96 arc_bus_space_set_aligned_stride(bst, alignment_shift) 97 bus_space_tag_t bst; 98 unsigned int alignment_shift; /* log2(alignment) */ 99 { 100 bst->bs_stride_1 = alignment_shift; 101 if (alignment_shift > 0) 102 --alignment_shift; 103 bst->bs_stride_2 = alignment_shift; 104 if (alignment_shift > 0) 105 --alignment_shift; 106 bst->bs_stride_4 = alignment_shift; 107 if (alignment_shift > 0) 108 --alignment_shift; 109 bst->bs_stride_8 = alignment_shift; 110 } 111 112 static int malloc_safe = 0; 113 114 void 115 arc_bus_space_malloc_set_safe() 116 { 117 malloc_safe = EX_MALLOCOK; 118 } 119 120 int 121 arc_bus_space_extent_malloc_flag() 122 { 123 return (malloc_safe); 124 } 125 126 int 127 arc_bus_space_compose_handle(bst, addr, size, flags, bshp) 128 bus_space_tag_t bst; 129 bus_addr_t addr; 130 bus_size_t size; 131 int flags; 132 bus_space_handle_t *bshp; 133 { 134 bus_space_handle_t bsh = bst->bs_vbase + (addr - bst->bs_start); 135 136 /* 137 * Since all buses can be linearly mappable, we don't have to check 138 * BUS_SPACE_MAP_LINEAR and BUS_SPACE_MAP_PREFETCHABLE. 139 */ 140 if ((flags & BUS_SPACE_MAP_CACHEABLE) == 0) { 141 *bshp = bsh; 142 return (0); 143 } 144 if (bsh < MIPS_KSEG1_START) /* KUSEG or KSEG0 */ 145 panic("arc_bus_space_compose_handle: bad address 0x%x", bsh); 146 if (bsh < MIPS_KSEG2_START) { /* KSEG1 */ 147 *bshp = MIPS_PHYS_TO_KSEG0(MIPS_KSEG1_TO_PHYS(bsh)); 148 return (0); 149 } 150 /* 151 * KSEG2: 152 * Do not make the page cacheable in this case, since: 153 * - the page which this bus_space belongs might include 154 * other bus_spaces. 155 * or 156 * - this bus might be mapped by wired TLB, in that case, 157 * we cannot manupulate cacheable attribute with page granularity. 158 */ 159 #ifdef DIAGNOSTIC 160 printf("arc_bus_space_compose_handle: ignore cacheable 0x%x\n", bsh); 161 #endif 162 *bshp = bsh; 163 return (0); 164 } 165 166 int 167 arc_bus_space_dispose_handle(bst, bsh, size) 168 bus_space_tag_t bst; 169 bus_space_handle_t bsh; 170 bus_size_t size; 171 { 172 return (0); 173 } 174 175 int 176 arc_bus_space_paddr(bst, bsh, pap) 177 bus_space_tag_t bst; 178 bus_space_handle_t bsh; 179 paddr_t *pap; 180 { 181 if (bsh < MIPS_KSEG0_START) /* KUSEG */ 182 panic("arc_bus_space_paddr(0x%qx): bad address", 183 (unsigned long long) bsh); 184 else if (bsh < MIPS_KSEG1_START) /* KSEG0 */ 185 *pap = MIPS_KSEG0_TO_PHYS(bsh); 186 else if (bsh < MIPS_KSEG2_START) /* KSEG1 */ 187 *pap = MIPS_KSEG1_TO_PHYS(bsh); 188 else { /* KSEG2 */ 189 /* 190 * Since this region may be mapped by wired TLB, 191 * kvtophys() is not always available. 192 */ 193 *pap = bst->bs_pbase + (bsh - bst->bs_vbase); 194 } 195 return (0); 196 } 197 198 int 199 arc_bus_space_map(bst, addr, size, flags, bshp) 200 bus_space_tag_t bst; 201 bus_addr_t addr; 202 bus_size_t size; 203 int flags; 204 bus_space_handle_t *bshp; 205 { 206 int err; 207 208 if (addr < bst->bs_start || addr + size > bst->bs_start + bst->bs_size) 209 return (EINVAL); 210 211 if (bst->bs_extent != NULL) { 212 err = extent_alloc_region(bst->bs_extent, addr, size, 213 EX_NOWAIT | malloc_safe); 214 if (err) 215 return (err); 216 } 217 218 return (bus_space_compose_handle(bst, addr, size, flags, bshp)); 219 } 220 221 void 222 arc_bus_space_unmap(bst, bsh, size) 223 bus_space_tag_t bst; 224 bus_space_handle_t bsh; 225 bus_size_t size; 226 { 227 if (bst->bs_extent != NULL) { 228 paddr_t pa; 229 bus_addr_t addr; 230 int err; 231 232 /* bus_space_paddr() becomes unavailable after unmapping */ 233 err = bus_space_paddr(bst, bsh, &pa); 234 if (err) 235 panic("arc_bus_space_unmap: %s va 0x%qx: error %d", 236 bst->bs_name, (unsigned long long) bsh, err); 237 addr = (bus_size_t)(pa - bst->bs_pbase) + bst->bs_start; 238 extent_free(bst->bs_extent, addr, size, 239 EX_NOWAIT | malloc_safe); 240 } 241 bus_space_dispose_handle(bst, bsh, size); 242 } 243 244 int 245 arc_bus_space_subregion(bst, bsh, offset, size, nbshp) 246 bus_space_tag_t bst; 247 bus_space_handle_t bsh; 248 bus_size_t offset; 249 bus_size_t size; 250 bus_space_handle_t *nbshp; 251 { 252 *nbshp = bsh + offset; 253 return (0); 254 } 255 256 paddr_t 257 arc_bus_space_mmap(bst, addr, off, prot, flags) 258 bus_space_tag_t bst; 259 bus_addr_t addr; 260 off_t off; 261 int prot; 262 int flags; 263 { 264 265 /* 266 * XXX We do not disallow mmap'ing of EISA/PCI I/O space here, 267 * XXX which we should be doing. 268 */ 269 270 if (addr < bst->bs_start || 271 (addr + off) >= (bst->bs_start + bst->bs_size)) 272 return (-1); 273 274 return (mips_btop(bst->bs_pbase + (addr - bst->bs_start) + off)); 275 } 276 277 int 278 arc_bus_space_alloc(bst, start, end, size, align, boundary, flags, addrp, bshp) 279 bus_space_tag_t bst; 280 bus_addr_t start; 281 bus_addr_t end; 282 bus_size_t size; 283 bus_size_t align; 284 bus_size_t boundary; 285 int flags; 286 bus_addr_t *addrp; 287 bus_space_handle_t *bshp; 288 { 289 u_long addr; 290 int err; 291 292 if (bst->bs_extent == NULL) 293 panic("arc_bus_space_alloc: extent map %s not available", 294 bst->bs_name); 295 296 if (start < bst->bs_start || 297 start + size > bst->bs_start + bst->bs_size) 298 return (EINVAL); 299 300 err = extent_alloc_subregion(bst->bs_extent, start, end, size, 301 align, boundary, EX_FAST | EX_NOWAIT | malloc_safe, &addr); 302 if (err) 303 return (err); 304 305 *addrp = addr; 306 return (bus_space_compose_handle(bst, addr, size, flags, bshp)); 307 } 308