1 /* $NetBSD: jensenio_bus_intio.c,v 1.2 2008/04/28 20:23:11 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 1999 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 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 33 34 __KERNEL_RCSID(0, "$NetBSD: jensenio_bus_intio.c,v 1.2 2008/04/28 20:23:11 martin Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/malloc.h> 39 #include <sys/device.h> 40 #include <sys/extent.h> 41 42 #include <machine/bus.h> 43 44 #include <dev/eisa/eisavar.h> 45 46 #include <dev/isa/isavar.h> 47 48 #include <alpha/jensenio/jensenioreg.h> 49 #include <alpha/jensenio/jenseniovar.h> 50 51 /* mapping/unmapping */ 52 int jensenio_intio_map(void *, bus_addr_t, bus_size_t, int, 53 bus_space_handle_t *, int); 54 void jensenio_intio_unmap(void *, bus_space_handle_t, 55 bus_size_t, int); 56 int jensenio_intio_subregion(void *, bus_space_handle_t, 57 bus_size_t, bus_size_t, bus_space_handle_t *); 58 59 /* allocation/deallocation */ 60 /* Not supported for Internal space */ 61 62 /* barrier */ 63 inline void jensenio_intio_barrier(void *, bus_space_handle_t, 64 bus_size_t, bus_size_t, int); 65 66 /* read (single) */ 67 inline u_int8_t jensenio_intio_read_1(void *, bus_space_handle_t, bus_size_t); 68 69 /* read multiple */ 70 void jensenio_intio_read_multi_1(void *, bus_space_handle_t, 71 bus_size_t, u_int8_t *, bus_size_t); 72 73 /* read region */ 74 /* Not supported for Internal space */ 75 76 /* write (single) */ 77 inline void jensenio_intio_write_1(void *, bus_space_handle_t, 78 bus_size_t, u_int8_t); 79 80 /* write multiple */ 81 void jensenio_intio_write_multi_1(void *, bus_space_handle_t, 82 bus_size_t, const u_int8_t *, bus_size_t); 83 84 /* write region */ 85 /* Not supported for Internal space */ 86 87 /* set multiple */ 88 void jensenio_intio_set_multi_1(void *, bus_space_handle_t, 89 bus_size_t, u_int8_t, bus_size_t); 90 91 /* set region */ 92 /* Not supported for Internal space */ 93 94 /* copy */ 95 /* Not supported for Internal space */ 96 97 void 98 jensenio_bus_intio_init(bus_space_tag_t t, void *v) 99 { 100 101 /* 102 * Initialize the bus space tag. 103 */ 104 105 memset(t, 0, sizeof(*t)); 106 107 /* cookie */ 108 t->abs_cookie = v; 109 110 /* mapping/unmapping */ 111 t->abs_map = jensenio_intio_map; 112 t->abs_unmap = jensenio_intio_unmap; 113 t->abs_subregion = jensenio_intio_subregion; 114 115 /* barrier */ 116 t->abs_barrier = jensenio_intio_barrier; 117 118 /* read (single) */ 119 t->abs_r_1 = jensenio_intio_read_1; 120 121 /* read multiple */ 122 t->abs_rm_1 = jensenio_intio_read_multi_1; 123 124 /* write (single) */ 125 t->abs_w_1 = jensenio_intio_write_1; 126 127 /* write multiple */ 128 t->abs_wm_1 = jensenio_intio_write_multi_1; 129 130 /* set multiple */ 131 t->abs_sm_1 = jensenio_intio_set_multi_1; 132 133 /* 134 * Extent map is already set up. 135 */ 136 } 137 138 int 139 jensenio_intio_map(void *v, bus_addr_t ioaddr, bus_size_t iosize, int flags, 140 bus_space_handle_t *iohp, int acct) 141 { 142 struct jensenio_config *jcp = v; 143 int linear = flags & BUS_SPACE_MAP_LINEAR; 144 int error; 145 146 /* 147 * Can't map i/o space linearly. 148 */ 149 if (linear) 150 return (EOPNOTSUPP); 151 152 if (acct) { 153 #ifdef EXTENT_DEBUG 154 printf("intio: allocating 0x%lx to 0x%lx\n", ioaddr, 155 ioaddr + iosize - 1); 156 #endif 157 error = extent_alloc_region(jcp->jc_io_ex, ioaddr, iosize, 158 EX_NOWAIT | (jcp->jc_mallocsafe ? EX_MALLOCOK : 0)); 159 if (error) { 160 #ifdef EXTENT_DEBUG 161 printf("intio: allocation failed (%d)\n", error); 162 extent_print(jcp->jc_io_ex); 163 #endif 164 return (error); 165 } 166 } 167 168 *iohp = ALPHA_PHYS_TO_K0SEG((ioaddr << 9) + JENSEN_VL82C106); 169 return (0); 170 } 171 172 void 173 jensenio_intio_unmap(void *v, bus_space_handle_t ioh, bus_size_t iosize, 174 int acct) 175 { 176 struct jensenio_config *jcp = v; 177 bus_addr_t ioaddr; 178 int error; 179 180 if (acct == 0) 181 return; 182 183 #ifdef EXTENT_DEBUG 184 printf("intio: freeing handle 0x%lx for 0x%lx\n", ioh, iosize); 185 #endif 186 187 ioh = ALPHA_K0SEG_TO_PHYS(ioh); 188 189 ioaddr = (ioh - JENSEN_VL82C106) >> 9; 190 191 #ifdef EXTENT_DEBUG 192 printf("intio: freeing 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1); 193 #endif 194 error = extent_free(jcp->jc_io_ex, ioaddr, iosize, 195 EX_NOWAIT | (jcp->jc_mallocsafe ? EX_MALLOCOK : 0)); 196 if (error) { 197 printf("WARNING: could not unmap 0x%lx-0x%lx (error %d)\n", 198 ioaddr, ioaddr + iosize - 1, error); 199 #ifdef EXTENT_DEBUG 200 extent_print(jcp->jc_io_ex); 201 #endif 202 } 203 } 204 205 int 206 jensenio_intio_subregion(void *v, bus_space_handle_t ioh, bus_size_t offset, 207 bus_size_t size, bus_space_handle_t *nioh) 208 { 209 210 *nioh = ioh + (offset << 9); 211 return (0); 212 } 213 214 inline void 215 jensenio_intio_barrier(void *v, bus_space_handle_t h, bus_size_t o, 216 bus_size_t l, int f) 217 { 218 219 if ((f & BUS_SPACE_BARRIER_READ) != 0) 220 alpha_mb(); 221 else if ((f & BUS_SPACE_BARRIER_WRITE) != 0) 222 alpha_wmb(); 223 } 224 225 inline u_int8_t 226 jensenio_intio_read_1(void *v, bus_space_handle_t ioh, bus_size_t off) 227 { 228 register u_int32_t *port; 229 230 alpha_mb(); 231 232 port = (u_int32_t *)(ioh + (off << 9)); 233 return (*port & 0xff); 234 } 235 236 void 237 jensenio_intio_read_multi_1(void *v, bus_space_handle_t h, bus_size_t o, 238 u_int8_t *a, bus_size_t c) 239 { 240 241 while (c-- > 0) { 242 jensenio_intio_barrier(v, h, o, sizeof *a, 243 BUS_SPACE_BARRIER_READ); 244 *a++ = jensenio_intio_read_1(v, h, o); 245 } 246 } 247 248 inline void 249 jensenio_intio_write_1(void *v, bus_space_handle_t ioh, bus_size_t off, 250 u_int8_t val) 251 { 252 register u_int32_t *port; 253 254 port = (u_int32_t *)(ioh + (off << 9)); 255 *port = val; 256 alpha_mb(); 257 } 258 259 void 260 jensenio_intio_write_multi_1(void *v, bus_space_handle_t h, bus_size_t o, 261 const u_int8_t *a, bus_size_t c) 262 { 263 264 while (c-- > 0) { 265 jensenio_intio_write_1(v, h, o, *a++); 266 jensenio_intio_barrier(v, h, o, sizeof *a, 267 BUS_SPACE_BARRIER_WRITE); 268 } 269 } 270 271 void 272 jensenio_intio_set_multi_1(void *v, bus_space_handle_t h, bus_size_t o, 273 u_int8_t val, bus_size_t c) 274 { 275 276 while (c-- > 0) { 277 jensenio_intio_write_1(v, h, o, val); 278 jensenio_intio_barrier(v, h, o, sizeof val, 279 BUS_SPACE_BARRIER_WRITE); 280 } 281 } 282