1 /* $NetBSD: isa_io.c,v 1.13 2023/12/20 13:55:18 thorpej Exp $ */ 2 3 /* 4 * Copyright 1997 5 * Digital Equipment Corporation. All rights reserved. 6 * 7 * This software is furnished under license and may be used and 8 * copied only in accordance with the following terms and conditions. 9 * Subject to these conditions, you may download, copy, install, 10 * use, modify and distribute this software in source and/or binary 11 * form. No title or ownership is transferred hereby. 12 * 13 * 1) Any source code used, modified or distributed must reproduce 14 * and retain this copyright notice and list of conditions as 15 * they appear in the source file. 16 * 17 * 2) No right is granted to use any trade name, trademark, or logo of 18 * Digital Equipment Corporation. Neither the "Digital Equipment 19 * Corporation" name nor any trademark or logo of Digital Equipment 20 * Corporation may be used to endorse or promote products derived 21 * from this software without the prior written permission of 22 * Digital Equipment Corporation. 23 * 24 * 3) This software is provided "AS-IS" and any express or implied 25 * warranties, including but not limited to, any implied warranties 26 * of merchantability, fitness for a particular purpose, or 27 * non-infringement are disclaimed. In no event shall DIGITAL be 28 * liable for any damages whatsoever, and in particular, DIGITAL 29 * shall not be liable for special, indirect, consequential, or 30 * incidental damages or damages for lost profits, loss of 31 * revenue or loss of use, whether such damages arise in contract, 32 * negligence, tort, under statute, in equity, at law or otherwise, 33 * even if advised of the possibility of such damage. 34 */ 35 36 /* 37 * bus_space I/O functions for isa 38 */ 39 40 #include <sys/cdefs.h> 41 __KERNEL_RCSID(0, "$NetBSD: isa_io.c,v 1.13 2023/12/20 13:55:18 thorpej Exp $"); 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/vmem_impl.h> 46 #include <sys/bus.h> 47 #include <machine/pio.h> 48 #include <machine/isa_machdep.h> 49 50 /* Proto types for all the bus_space structure functions */ 51 52 bs_protos(isa); 53 bs_protos(bs_notimpl); 54 55 /* 56 * Declare the isa bus space tags 57 * The IO and MEM structs are identical, except for the cookies, 58 * which contain the address space bases. 59 */ 60 61 /* 62 * NOTE: ASSEMBLY LANGUAGE RELIES ON THE COOKIE -- THE FIRST MEMBER OF 63 * THIS STRUCTURE -- TO BE THE VIRTUAL ADDRESS OF 16 BIT ISA/IO! 64 */ 65 struct bus_space isa_io_bs_tag = { 66 /* cookie */ 67 .bs_cookie = NULL, /* initialized below */ 68 69 /* mapping/unmapping */ 70 .bs_map = isa_bs_map, 71 .bs_unmap = isa_bs_unmap, 72 .bs_subregion = isa_bs_subregion, 73 74 /* allocation/deallocation */ 75 .bs_alloc = isa_bs_alloc, 76 .bs_free = isa_bs_free, 77 78 /* get kernel virtual address */ 79 .bs_vaddr = isa_bs_vaddr, 80 81 /* mmap bus space for userland */ 82 .bs_mmap = bs_notimpl_bs_mmap, /* XXX possible even? XXX */ 83 84 /* barrier */ 85 .bs_barrier = isa_bs_barrier, 86 87 /* read (single) */ 88 .bs_r_1 = isa_bs_r_1, 89 .bs_r_2 = isa_bs_r_2, 90 .bs_r_4 = isa_bs_r_4, 91 .bs_r_8 = bs_notimpl_bs_r_8, 92 93 /* read multiple */ 94 .bs_rm_1 = isa_bs_rm_1, 95 .bs_rm_2 = isa_bs_rm_2, 96 .bs_rm_4 = isa_bs_rm_4, 97 .bs_rm_8 = bs_notimpl_bs_rm_8, 98 99 /* read region */ 100 .bs_rr_1 = isa_bs_rr_1, 101 .bs_rr_2 = isa_bs_rr_2, 102 .bs_rr_4 = isa_bs_rr_4, 103 .bs_rr_8 = bs_notimpl_bs_rr_8, 104 105 /* write (single) */ 106 .bs_w_1 = isa_bs_w_1, 107 .bs_w_2 = isa_bs_w_2, 108 .bs_w_4 = isa_bs_w_4, 109 .bs_w_8 = bs_notimpl_bs_w_8, 110 111 /* write multiple */ 112 .bs_wm_1 = isa_bs_wm_1, 113 .bs_wm_2 = isa_bs_wm_2, 114 .bs_wm_4 = isa_bs_wm_4, 115 .bs_wm_8 = bs_notimpl_bs_wm_8, 116 117 /* write region */ 118 .bs_wr_1 = isa_bs_wr_1, 119 .bs_wr_2 = isa_bs_wr_2, 120 .bs_wr_4 = isa_bs_wr_4, 121 .bs_wr_8 = bs_notimpl_bs_wr_8, 122 123 /* set multiple */ 124 .bs_sm_1 = bs_notimpl_bs_sm_1, 125 .bs_sm_2 = bs_notimpl_bs_sm_2, 126 .bs_sm_4 = bs_notimpl_bs_sm_4, 127 .bs_sm_8 = bs_notimpl_bs_sm_8, 128 129 /* set region */ 130 .bs_sr_1 = bs_notimpl_bs_sr_1, 131 .bs_sr_2 = isa_bs_sr_2, 132 .bs_sr_4 = bs_notimpl_bs_sr_4, 133 .bs_sr_8 = bs_notimpl_bs_sr_8, 134 135 /* copy */ 136 .bs_c_1 = bs_notimpl_bs_c_1, 137 .bs_c_2 = bs_notimpl_bs_c_2, 138 .bs_c_4 = bs_notimpl_bs_c_4, 139 .bs_c_8 = bs_notimpl_bs_c_8, 140 }; 141 142 /* 143 * NOTE: ASSEMBLY LANGUAGE RELIES ON THE COOKIE -- THE FIRST MEMBER OF 144 * THIS STRUCTURE -- TO BE THE VIRTUAL ADDRESS OF ISA/MEMORY! 145 */ 146 struct bus_space isa_mem_bs_tag = { 147 /* cookie */ 148 .bs_cookie = NULL, /* initialized below */ 149 150 /* mapping/unmapping */ 151 .bs_map = isa_bs_map, 152 .bs_unmap = isa_bs_unmap, 153 .bs_subregion = isa_bs_subregion, 154 155 /* allocation/deallocation */ 156 .bs_alloc = isa_bs_alloc, 157 .bs_free = isa_bs_free, 158 159 /* get kernel virtual address */ 160 .bs_vaddr = isa_bs_vaddr, 161 162 /* mmap bus space for userland */ 163 .bs_mmap = bs_notimpl_bs_mmap, /* XXX open for now ... XXX */ 164 165 /* barrier */ 166 .bs_barrier = isa_bs_barrier, 167 168 /* read (single) */ 169 .bs_r_1 = isa_bs_r_1, 170 .bs_r_2 = isa_bs_r_2, 171 .bs_r_4 = isa_bs_r_4, 172 .bs_r_8 = bs_notimpl_bs_r_8, 173 174 /* read multiple */ 175 .bs_rm_1 = isa_bs_rm_1, 176 .bs_rm_2 = isa_bs_rm_2, 177 .bs_rm_4 = isa_bs_rm_4, 178 .bs_rm_8 = bs_notimpl_bs_rm_8, 179 180 /* read region */ 181 .bs_rr_1 = isa_bs_rr_1, 182 .bs_rr_2 = isa_bs_rr_2, 183 .bs_rr_4 = isa_bs_rr_4, 184 .bs_rr_8 = bs_notimpl_bs_rr_8, 185 186 /* write (single) */ 187 .bs_w_1 = isa_bs_w_1, 188 .bs_w_2 = isa_bs_w_2, 189 .bs_w_4 = isa_bs_w_4, 190 .bs_w_8 = bs_notimpl_bs_w_8, 191 192 /* write multiple */ 193 .bs_wm_1 = isa_bs_wm_1, 194 .bs_wm_2 = isa_bs_wm_2, 195 .bs_wm_4 = isa_bs_wm_4, 196 .bs_wm_8 = bs_notimpl_bs_wm_8, 197 198 /* write region */ 199 .bs_wr_1 = isa_bs_wr_1, 200 .bs_wr_2 = isa_bs_wr_2, 201 .bs_wr_4 = isa_bs_wr_4, 202 .bs_wr_8 = bs_notimpl_bs_wr_8, 203 204 /* set multiple */ 205 .bs_sm_1 = bs_notimpl_bs_sm_1, 206 .bs_sm_2 = bs_notimpl_bs_sm_2, 207 .bs_sm_4 = bs_notimpl_bs_sm_4, 208 .bs_sm_8 = bs_notimpl_bs_sm_8, 209 210 /* set region */ 211 .bs_sr_1 = bs_notimpl_bs_sr_1, 212 .bs_sr_2 = isa_bs_sr_2, 213 .bs_sr_4 = bs_notimpl_bs_sr_4, 214 .bs_sr_8 = bs_notimpl_bs_sr_8, 215 216 /* copy */ 217 .bs_c_1 = bs_notimpl_bs_c_1, 218 .bs_c_2 = bs_notimpl_bs_c_2, 219 .bs_c_4 = bs_notimpl_bs_c_4, 220 .bs_c_8 = bs_notimpl_bs_c_8, 221 }; 222 223 #define ISAIO_BTAG_COUNT VMEM_EST_BTCOUNT(1, 8) 224 #define ISAMEM_BTAG_COUNT VMEM_EST_BTCOUNT(1, 8) 225 226 static struct vmem isaio_arena_store; 227 static struct vmem isamem_arena_store; 228 static struct vmem_btag isaio_btag_store[ISAIO_BTAG_COUNT]; 229 static struct vmem_btag isamem_btag_store[ISAMEM_BTAG_COUNT]; 230 static vmem_t *isaio_arena; 231 static vmem_t *isamem_arena; 232 233 /* bus space functions */ 234 235 void 236 isa_io_init(vaddr_t isa_io_addr, vaddr_t isa_mem_addr) 237 { 238 int error __diagused; 239 240 isa_io_bs_tag.bs_cookie = (void *)isa_io_addr; 241 isa_mem_bs_tag.bs_cookie = (void *)isa_mem_addr; 242 243 isaio_arena = vmem_init(&isaio_arena_store, 244 "isaio", 245 0, /* addr */ 246 0, /* size */ 247 1, /* quantum */ 248 NULL, /* importfn */ 249 NULL, /* releasefn */ 250 NULL, /* source */ 251 0, /* qcache_max */ 252 VM_NOSLEEP | VM_PRIVTAGS, 253 IPL_NONE); 254 KASSERT(isaio_arena != NULL); 255 256 vmem_add_bts(isaio_arena, isaio_btag_store, ISAIO_BTAG_COUNT); 257 error = vmem_add(isaio_arena, 0x0, 0x10000, VM_NOSLEEP); 258 KASSERT(error == 0); 259 260 isamem_arena = vmem_init(&isamem_arena_store, 261 "isamem", 262 0, /* addr */ 263 0, /* size */ 264 1, /* quantum */ 265 NULL, /* importfn */ 266 NULL, /* releasefn */ 267 NULL, /* source */ 268 0, /* qcache_max */ 269 VM_NOSLEEP | VM_PRIVTAGS, 270 IPL_NONE); 271 KASSERT(isamem_arena != NULL); 272 273 vmem_add_bts(isamem_arena, isamem_btag_store, ISAMEM_BTAG_COUNT); 274 error = vmem_add(isamem_arena, 0x0, 0x100000, VM_NOSLEEP); 275 KASSERT(error == 0); 276 } 277 278 /* 279 * break the abstraction: sometimes, other parts of the system 280 * (e.g. X servers) need to map ISA space directly. use these 281 * functions sparingly! 282 */ 283 vaddr_t 284 isa_io_data_vaddr(void) 285 { 286 return (vaddr_t)isa_io_bs_tag.bs_cookie; 287 } 288 289 vaddr_t 290 isa_mem_data_vaddr(void) 291 { 292 return (vaddr_t)isa_mem_bs_tag.bs_cookie; 293 } 294 295 int 296 isa_bs_map(void *t, bus_addr_t bpa, bus_size_t size, int cacheable, bus_space_handle_t *bshp) 297 { 298 vmem_t *vm; 299 int err; 300 301 if (t == isa_io_bs_tag.bs_cookie) 302 vm = isaio_arena; 303 else 304 vm = isamem_arena; 305 306 err = vmem_xalloc_addr(vm, bpa, size, VM_NOSLEEP); 307 if (err) 308 return err; 309 310 *bshp = bpa + (bus_addr_t)t; 311 return(0); 312 } 313 314 void 315 isa_bs_unmap(void *t, bus_space_handle_t bsh, bus_size_t size) 316 { 317 isa_bs_free(t, bsh, size); 318 } 319 320 int 321 isa_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp) 322 { 323 *nbshp = bsh + offset; 324 return(0); 325 } 326 327 int 328 isa_bs_alloc( 329 void *t, 330 bus_addr_t rstart, 331 bus_addr_t rend, 332 bus_size_t size, 333 bus_size_t alignment, 334 bus_size_t boundary, 335 int cacheable, 336 bus_addr_t *bpap, 337 bus_space_handle_t *bshp) 338 { 339 vmem_t *vm; 340 vmem_addr_t bpa; 341 int err; 342 343 if (t == isa_io_bs_tag.bs_cookie) 344 vm = isaio_arena; 345 else 346 vm = isamem_arena; 347 348 err = vmem_xalloc(vm, size, 349 alignment, /* align */ 350 0, /* phase */ 351 boundary, /* nocross */ 352 rstart, /* minaddr */ 353 rend, /* maxaddr */ 354 VM_BESTFIT | VM_NOSLEEP, 355 &bpa); 356 if (err) 357 return err; 358 359 *bshp = *bpap = bpa + (bus_addr_t)t; 360 return 0; 361 } 362 363 void 364 isa_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size) 365 { 366 vmem_t *vm; 367 368 if (t == isa_io_bs_tag.bs_cookie) 369 vm = isaio_arena; 370 else 371 vm = isamem_arena; 372 373 vmem_xfree(vm, bsh - (bus_addr_t)t, size); 374 } 375 376 void * 377 isa_bs_vaddr(void *t, bus_space_handle_t bsh) 378 { 379 380 return ((void *)bsh); 381 } 382 383 void 384 isa_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset, bus_size_t len, int flags) 385 { 386 /* just return */ 387 } 388