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