1 /* $NetBSD: pci_bwx_bus_io_chipdep.c,v 1.24 2023/12/06 01:46:34 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998, 2000 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 of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1995, 1996 Carnegie-Mellon University. 35 * All rights reserved. 36 * 37 * Author: Chris G. Demetriou 38 * 39 * Permission to use, copy, modify and distribute this software and 40 * its documentation is hereby granted, provided that both the copyright 41 * notice and this permission notice appear in all copies of the 42 * software, derivative works or modified versions, and any portions 43 * thereof, and that both notices appear in supporting documentation. 44 * 45 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 46 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 47 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 48 * 49 * Carnegie Mellon requests users of this software to return to 50 * 51 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU 52 * School of Computer Science 53 * Carnegie Mellon University 54 * Pittsburgh PA 15213-3890 55 * 56 * any improvements or extensions that they make and grant Carnegie the 57 * rights to redistribute these changes. 58 */ 59 60 /* 61 * Common PCI Chipset "bus I/O" functions, for chipsets which have to 62 * deal with only a single PCI interface chip in a machine. 63 * 64 * uses: 65 * CHIP name of the 'chip' it's being compiled for. 66 * CHIP_IO_BASE I/O space base to use. 67 * CHIP_IO_ARENA_STORE 68 * If defined, device-provided static storage area 69 * for the I/O space arena. If this is defined, 70 * CHIP_IO_BTAG_STORE and CHIP_IO_BTAG_COUNT must 71 * also be defined. If this is not defined, a 72 * static area will be declared. 73 * CHIP_IO_BTAG_STORE 74 * Device-provided static storage area for the 75 * I/O space arena's boundary tags. Ignored 76 * unless CHIP_IO_ARENA_STORE is defined. 77 * CHIP_IO_BTAG_COUNT 78 * The number of device-provided static I/O 79 * space boundary tags. Ignored unless 80 * CHIP_IO_ARENA_STORE is defined. 81 */ 82 83 #include <sys/cdefs.h> 84 __KERNEL_RCSID(1, "$NetBSD: pci_bwx_bus_io_chipdep.c,v 1.24 2023/12/06 01:46:34 thorpej Exp $"); 85 86 #include <sys/vmem_impl.h> 87 88 #include <machine/bwx.h> 89 90 #define __C(A,B) __CONCAT(A,B) 91 #define __S(S) __STRING(S) 92 93 /* mapping/unmapping */ 94 static int __C(CHIP,_io_map)(void *, bus_addr_t, bus_size_t, int, 95 bus_space_handle_t *, int); 96 static void __C(CHIP,_io_unmap)(void *, bus_space_handle_t, 97 bus_size_t, int); 98 static int __C(CHIP,_io_subregion)(void *, bus_space_handle_t, 99 bus_size_t, bus_size_t, bus_space_handle_t *); 100 101 static int __C(CHIP,_io_translate)(void *, bus_addr_t, bus_size_t, 102 int, struct alpha_bus_space_translation *); 103 static int __C(CHIP,_io_get_window)(void *, int, 104 struct alpha_bus_space_translation *); 105 106 /* allocation/deallocation */ 107 static int __C(CHIP,_io_alloc)(void *, bus_addr_t, bus_addr_t, 108 bus_size_t, bus_size_t, bus_addr_t, int, bus_addr_t *, 109 bus_space_handle_t *); 110 static void __C(CHIP,_io_free)(void *, bus_space_handle_t, 111 bus_size_t); 112 113 /* get kernel virtual address */ 114 static void * __C(CHIP,_io_vaddr)(void *, bus_space_handle_t); 115 116 /* mmap for user */ 117 static paddr_t __C(CHIP,_io_mmap)(void *, bus_addr_t, off_t, int, int); 118 119 /* barrier */ 120 static inline void __C(CHIP,_io_barrier)(void *, bus_space_handle_t, 121 bus_size_t, bus_size_t, int); 122 123 /* read (single) */ 124 static inline uint8_t __C(CHIP,_io_read_1)(void *, bus_space_handle_t, 125 bus_size_t); 126 static inline uint16_t __C(CHIP,_io_read_2)(void *, bus_space_handle_t, 127 bus_size_t); 128 static inline uint32_t __C(CHIP,_io_read_4)(void *, bus_space_handle_t, 129 bus_size_t); 130 static inline uint64_t __C(CHIP,_io_read_8)(void *, bus_space_handle_t, 131 bus_size_t); 132 133 /* read multiple */ 134 static void __C(CHIP,_io_read_multi_1)(void *, bus_space_handle_t, 135 bus_size_t, uint8_t *, bus_size_t); 136 static void __C(CHIP,_io_read_multi_2)(void *, bus_space_handle_t, 137 bus_size_t, uint16_t *, bus_size_t); 138 static void __C(CHIP,_io_read_multi_4)(void *, bus_space_handle_t, 139 bus_size_t, uint32_t *, bus_size_t); 140 static void __C(CHIP,_io_read_multi_8)(void *, bus_space_handle_t, 141 bus_size_t, uint64_t *, bus_size_t); 142 143 /* read region */ 144 static void __C(CHIP,_io_read_region_1)(void *, bus_space_handle_t, 145 bus_size_t, uint8_t *, bus_size_t); 146 static void __C(CHIP,_io_read_region_2)(void *, bus_space_handle_t, 147 bus_size_t, uint16_t *, bus_size_t); 148 static void __C(CHIP,_io_read_region_4)(void *, bus_space_handle_t, 149 bus_size_t, uint32_t *, bus_size_t); 150 static void __C(CHIP,_io_read_region_8)(void *, bus_space_handle_t, 151 bus_size_t, uint64_t *, bus_size_t); 152 153 /* write (single) */ 154 static inline void __C(CHIP,_io_write_1)(void *, bus_space_handle_t, 155 bus_size_t, uint8_t); 156 static inline void __C(CHIP,_io_write_2)(void *, bus_space_handle_t, 157 bus_size_t, uint16_t); 158 static inline void __C(CHIP,_io_write_4)(void *, bus_space_handle_t, 159 bus_size_t, uint32_t); 160 static inline void __C(CHIP,_io_write_8)(void *, bus_space_handle_t, 161 bus_size_t, uint64_t); 162 163 /* write multiple */ 164 static void __C(CHIP,_io_write_multi_1)(void *, bus_space_handle_t, 165 bus_size_t, const uint8_t *, bus_size_t); 166 static void __C(CHIP,_io_write_multi_2)(void *, bus_space_handle_t, 167 bus_size_t, const uint16_t *, bus_size_t); 168 static void __C(CHIP,_io_write_multi_4)(void *, bus_space_handle_t, 169 bus_size_t, const uint32_t *, bus_size_t); 170 static void __C(CHIP,_io_write_multi_8)(void *, bus_space_handle_t, 171 bus_size_t, const uint64_t *, bus_size_t); 172 173 /* write region */ 174 static void __C(CHIP,_io_write_region_1)(void *, bus_space_handle_t, 175 bus_size_t, const uint8_t *, bus_size_t); 176 static void __C(CHIP,_io_write_region_2)(void *, bus_space_handle_t, 177 bus_size_t, const uint16_t *, bus_size_t); 178 static void __C(CHIP,_io_write_region_4)(void *, bus_space_handle_t, 179 bus_size_t, const uint32_t *, bus_size_t); 180 static void __C(CHIP,_io_write_region_8)(void *, bus_space_handle_t, 181 bus_size_t, const uint64_t *, bus_size_t); 182 183 /* set multiple */ 184 static void __C(CHIP,_io_set_multi_1)(void *, bus_space_handle_t, 185 bus_size_t, uint8_t, bus_size_t); 186 static void __C(CHIP,_io_set_multi_2)(void *, bus_space_handle_t, 187 bus_size_t, uint16_t, bus_size_t); 188 static void __C(CHIP,_io_set_multi_4)(void *, bus_space_handle_t, 189 bus_size_t, uint32_t, bus_size_t); 190 static void __C(CHIP,_io_set_multi_8)(void *, bus_space_handle_t, 191 bus_size_t, uint64_t, bus_size_t); 192 193 /* set region */ 194 static void __C(CHIP,_io_set_region_1)(void *, bus_space_handle_t, 195 bus_size_t, uint8_t, bus_size_t); 196 static void __C(CHIP,_io_set_region_2)(void *, bus_space_handle_t, 197 bus_size_t, uint16_t, bus_size_t); 198 static void __C(CHIP,_io_set_region_4)(void *, bus_space_handle_t, 199 bus_size_t, uint32_t, bus_size_t); 200 static void __C(CHIP,_io_set_region_8)(void *, bus_space_handle_t, 201 bus_size_t, uint64_t, bus_size_t); 202 203 /* copy */ 204 static void __C(CHIP,_io_copy_region_1)(void *, bus_space_handle_t, 205 bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 206 static void __C(CHIP,_io_copy_region_2)(void *, bus_space_handle_t, 207 bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 208 static void __C(CHIP,_io_copy_region_4)(void *, bus_space_handle_t, 209 bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 210 static void __C(CHIP,_io_copy_region_8)(void *, bus_space_handle_t, 211 bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t); 212 213 #ifndef CHIP_IO_ARENA_STORE 214 #define CHIP_IO_BTAG_COUNT(v) VMEM_EST_BTCOUNT(1, 8) 215 #define CHIP_IO_BTAG_STORE(v) __C(CHIP,_io_btag_store) 216 #define CHIP_IO_ARENA_STORE(v) (&(__C(CHIP,_io_arena_store))) 217 218 static struct vmem __C(CHIP,_io_arena_store); 219 static struct vmem_btag __C(CHIP,_io_btag_store)[CHIP_IO_BTAG_COUNT(xxx)]; 220 #endif /* CHIP_IO_ARENA_STORE */ 221 222 void 223 __C(CHIP,_bus_io_init)( 224 bus_space_tag_t t, 225 void *v) 226 { 227 vmem_t *vm; 228 int error __diagused; 229 230 /* 231 * Initialize the bus space tag. 232 */ 233 234 /* cookie */ 235 t->abs_cookie = v; 236 237 /* mapping/unmapping */ 238 t->abs_map = __C(CHIP,_io_map); 239 t->abs_unmap = __C(CHIP,_io_unmap); 240 t->abs_subregion = __C(CHIP,_io_subregion); 241 242 t->abs_translate = __C(CHIP,_io_translate); 243 t->abs_get_window = __C(CHIP,_io_get_window); 244 245 /* allocation/deallocation */ 246 t->abs_alloc = __C(CHIP,_io_alloc); 247 t->abs_free = __C(CHIP,_io_free); 248 249 /* get kernel virtual address */ 250 t->abs_vaddr = __C(CHIP,_io_vaddr); 251 252 /* mmap for user */ 253 t->abs_mmap = __C(CHIP,_io_mmap); 254 255 /* barrier */ 256 t->abs_barrier = __C(CHIP,_io_barrier); 257 258 /* read (single) */ 259 t->abs_r_1 = __C(CHIP,_io_read_1); 260 t->abs_r_2 = __C(CHIP,_io_read_2); 261 t->abs_r_4 = __C(CHIP,_io_read_4); 262 t->abs_r_8 = __C(CHIP,_io_read_8); 263 264 /* read multiple */ 265 t->abs_rm_1 = __C(CHIP,_io_read_multi_1); 266 t->abs_rm_2 = __C(CHIP,_io_read_multi_2); 267 t->abs_rm_4 = __C(CHIP,_io_read_multi_4); 268 t->abs_rm_8 = __C(CHIP,_io_read_multi_8); 269 270 /* read region */ 271 t->abs_rr_1 = __C(CHIP,_io_read_region_1); 272 t->abs_rr_2 = __C(CHIP,_io_read_region_2); 273 t->abs_rr_4 = __C(CHIP,_io_read_region_4); 274 t->abs_rr_8 = __C(CHIP,_io_read_region_8); 275 276 /* write (single) */ 277 t->abs_w_1 = __C(CHIP,_io_write_1); 278 t->abs_w_2 = __C(CHIP,_io_write_2); 279 t->abs_w_4 = __C(CHIP,_io_write_4); 280 t->abs_w_8 = __C(CHIP,_io_write_8); 281 282 /* write multiple */ 283 t->abs_wm_1 = __C(CHIP,_io_write_multi_1); 284 t->abs_wm_2 = __C(CHIP,_io_write_multi_2); 285 t->abs_wm_4 = __C(CHIP,_io_write_multi_4); 286 t->abs_wm_8 = __C(CHIP,_io_write_multi_8); 287 288 /* write region */ 289 t->abs_wr_1 = __C(CHIP,_io_write_region_1); 290 t->abs_wr_2 = __C(CHIP,_io_write_region_2); 291 t->abs_wr_4 = __C(CHIP,_io_write_region_4); 292 t->abs_wr_8 = __C(CHIP,_io_write_region_8); 293 294 /* set multiple */ 295 t->abs_sm_1 = __C(CHIP,_io_set_multi_1); 296 t->abs_sm_2 = __C(CHIP,_io_set_multi_2); 297 t->abs_sm_4 = __C(CHIP,_io_set_multi_4); 298 t->abs_sm_8 = __C(CHIP,_io_set_multi_8); 299 300 /* set region */ 301 t->abs_sr_1 = __C(CHIP,_io_set_region_1); 302 t->abs_sr_2 = __C(CHIP,_io_set_region_2); 303 t->abs_sr_4 = __C(CHIP,_io_set_region_4); 304 t->abs_sr_8 = __C(CHIP,_io_set_region_8); 305 306 /* copy */ 307 t->abs_c_1 = __C(CHIP,_io_copy_region_1); 308 t->abs_c_2 = __C(CHIP,_io_copy_region_2); 309 t->abs_c_4 = __C(CHIP,_io_copy_region_4); 310 t->abs_c_8 = __C(CHIP,_io_copy_region_8); 311 312 vm = vmem_init(CHIP_IO_ARENA_STORE(v), 313 __S(__C(CHIP,_bus_io)), /* name */ 314 0, /* addr */ 315 0, /* size */ 316 1, /* quantum */ 317 NULL, /* importfn */ 318 NULL, /* releasefn */ 319 NULL, /* source */ 320 0, /* qcache_max */ 321 VM_NOSLEEP | VM_PRIVTAGS, 322 IPL_NONE); 323 KASSERT(vm != NULL); 324 325 vmem_add_bts(vm, CHIP_IO_BTAG_STORE(v), CHIP_IO_BTAG_COUNT(v)); 326 error = vmem_add(vm, 0, 0x100000000UL, VM_NOSLEEP); 327 KASSERT(error == 0); 328 329 CHIP_IO_ARENA(v) = vm; 330 } 331 332 static int 333 __C(CHIP,_io_translate)( 334 void *v, 335 bus_addr_t ioaddr, 336 bus_size_t iolen, 337 int flags, 338 struct alpha_bus_space_translation *abst) 339 { 340 int linear = flags & BUS_SPACE_MAP_LINEAR; 341 342 /* 343 * Can't map i/o space linearly. 344 */ 345 if (linear) 346 return (EOPNOTSUPP); 347 348 return (__C(CHIP,_io_get_window)(v, 0, abst)); 349 } 350 351 static int 352 __C(CHIP,_io_get_window)( 353 void *v, 354 int window, 355 struct alpha_bus_space_translation *abst) 356 { 357 358 switch (window) { 359 case 0: 360 abst->abst_bus_start = 0; 361 abst->abst_bus_end = 0xffffffffUL; 362 abst->abst_sys_start = CHIP_IO_SYS_START(v); 363 abst->abst_sys_end = CHIP_IO_SYS_START(v) + abst->abst_bus_end; 364 abst->abst_addr_shift = 0; 365 abst->abst_size_shift = 0; 366 abst->abst_flags = ABST_DENSE|ABST_BWX; 367 break; 368 369 default: 370 panic(__S(__C(CHIP,_io_get_window)) ": invalid window %d", 371 window); 372 } 373 374 return (0); 375 } 376 377 static int 378 __C(CHIP,_io_map)( 379 void *v, 380 bus_addr_t ioaddr, 381 bus_size_t iosize, 382 int flags, 383 bus_space_handle_t *iohp, 384 int acct) 385 { 386 struct alpha_bus_space_translation abst; 387 int error; 388 389 /* 390 * Get the translation for this address. 391 */ 392 error = __C(CHIP,_io_translate)(v, ioaddr, iosize, flags, &abst); 393 if (error) 394 return (error); 395 396 if (acct == 0) 397 goto mapit; 398 399 #ifdef EXTENT_DEBUG 400 printf("io: allocating 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1); 401 #endif 402 error = vmem_xalloc_addr(CHIP_IO_ARENA(v), ioaddr, iosize, VM_NOSLEEP); 403 if (error) { 404 #ifdef EXTENT_DEBUG 405 printf("io: allocation failed (%d)\n", error); 406 /* vmem_print(CHIP_IO_ARENA(v)); XXX */ 407 #endif 408 return (error); 409 } 410 411 mapit: 412 *iohp = ALPHA_PHYS_TO_K0SEG(abst.abst_sys_start + ioaddr); 413 414 return (0); 415 } 416 417 static void 418 __C(CHIP,_io_unmap)( 419 void *v, 420 bus_space_handle_t ioh, 421 bus_size_t iosize, 422 int acct) 423 { 424 bus_addr_t ioaddr; 425 426 if (acct == 0) 427 return; 428 429 #ifdef EXTENT_DEBUG 430 printf("io: freeing handle 0x%lx for 0x%lx\n", ioh, iosize); 431 #endif 432 433 ioaddr = ioh - ALPHA_PHYS_TO_K0SEG(CHIP_IO_SYS_START(v)); 434 435 #ifdef EXTENT_DEBUG 436 printf("io: freeing 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1); 437 #endif 438 vmem_xfree(CHIP_IO_ARENA(v), ioaddr, iosize); 439 } 440 441 static int 442 __C(CHIP,_io_subregion)( 443 void *v, 444 bus_space_handle_t ioh, 445 bus_size_t offset, 446 bus_size_t size, 447 bus_space_handle_t *nioh) 448 { 449 450 *nioh = ioh + offset; 451 return (0); 452 } 453 454 static int 455 __C(CHIP,_io_alloc)( 456 void *v, 457 bus_addr_t rstart, 458 bus_addr_t rend, 459 bus_size_t size, 460 bus_size_t align, 461 bus_size_t boundary, 462 int flags, 463 bus_addr_t *addrp, 464 bus_space_handle_t *bshp) 465 { 466 struct alpha_bus_space_translation abst; 467 int linear = flags & BUS_SPACE_MAP_LINEAR; 468 vmem_addr_t ioaddr; 469 int error; 470 471 /* 472 * Can't map i/o space linearly. 473 */ 474 if (linear) 475 return (EOPNOTSUPP); 476 477 /* 478 * Do the requested allocation. 479 */ 480 #ifdef EXTENT_DEBUG 481 printf("io: allocating from 0x%lx to 0x%lx\n", rstart, rend); 482 #endif 483 error = vmem_xalloc(CHIP_IO_ARENA(v), size, 484 align, /* align */ 485 0, /* phase */ 486 boundary, /* nocross */ 487 rstart, /* minaddr */ 488 rend, /* maxaddr */ 489 VM_BESTFIT | VM_NOSLEEP, 490 &ioaddr); 491 if (error) { 492 #ifdef EXTENT_DEBUG 493 printf("io: allocation failed (%d)\n", error); 494 /* vmem_print(CHIP_IO_ARENA(v)); XXX */ 495 #endif 496 return (error); 497 } 498 499 #ifdef EXTENT_DEBUG 500 printf("io: allocated 0x%lx to 0x%lx\n", ioaddr, ioaddr + size - 1); 501 #endif 502 503 error = __C(CHIP,_io_translate)(v, ioaddr, size, flags, &abst); 504 if (error) { 505 vmem_xfree(CHIP_IO_ARENA(v), ioaddr, size); 506 return (error); 507 } 508 509 *addrp = ioaddr; 510 *bshp = ALPHA_PHYS_TO_K0SEG(abst.abst_sys_start + ioaddr); 511 512 return (0); 513 } 514 515 static void 516 __C(CHIP,_io_free)( 517 void *v, 518 bus_space_handle_t bsh, 519 bus_size_t size) 520 { 521 522 /* Unmap does all we need to do. */ 523 __C(CHIP,_io_unmap)(v, bsh, size, 1); 524 } 525 526 static void * 527 __C(CHIP,_io_vaddr)( 528 void *v, 529 bus_space_handle_t bsh) 530 { 531 /* 532 * _io_translate() catches BUS_SPACE_MAP_LINEAR, 533 * so we shouldn't get here 534 */ 535 panic("_io_vaddr"); 536 } 537 538 static paddr_t 539 __C(CHIP,_io_mmap)( 540 void *v, 541 bus_addr_t addr, 542 off_t off, 543 int prot, 544 int flags) 545 { 546 547 /* Not supported for I/O space. */ 548 return (-1); 549 } 550 551 static inline void 552 __C(CHIP,_io_barrier)( 553 void *v, 554 bus_space_handle_t h, 555 bus_size_t o, 556 bus_size_t l, 557 int f) 558 { 559 560 if ((f & BUS_SPACE_BARRIER_READ) != 0) 561 alpha_mb(); 562 else if ((f & BUS_SPACE_BARRIER_WRITE) != 0) 563 alpha_wmb(); 564 } 565 566 static inline uint8_t 567 __C(CHIP,_io_read_1)( 568 void *v, 569 bus_space_handle_t ioh, 570 bus_size_t off) 571 { 572 bus_addr_t addr; 573 574 addr = ioh + off; 575 alpha_mb(); 576 return (alpha_ldbu((uint8_t *)addr)); 577 } 578 579 static inline uint16_t 580 __C(CHIP,_io_read_2)( 581 void *v, 582 bus_space_handle_t ioh, 583 bus_size_t off) 584 { 585 bus_addr_t addr; 586 587 addr = ioh + off; 588 #ifdef DIAGNOSTIC 589 if (addr & 1) 590 panic(__S(__C(CHIP,_io_read_2)) ": addr 0x%lx not aligned", 591 addr); 592 #endif 593 alpha_mb(); 594 return (alpha_ldwu((uint16_t *)addr)); 595 } 596 597 static inline uint32_t 598 __C(CHIP,_io_read_4)( 599 void *v, 600 bus_space_handle_t ioh, 601 bus_size_t off) 602 { 603 bus_addr_t addr; 604 605 addr = ioh + off; 606 #ifdef DIAGNOSTIC 607 if (addr & 3) 608 panic(__S(__C(CHIP,_io_read_4)) ": addr 0x%lx not aligned", 609 addr); 610 #endif 611 alpha_mb(); 612 return (*(uint32_t *)addr); 613 } 614 615 static inline uint64_t 616 __C(CHIP,_io_read_8)( 617 void *v, 618 bus_space_handle_t ioh, 619 bus_size_t off) 620 { 621 622 /* XXX XXX XXX */ 623 panic("%s not implemented", __S(__C(CHIP,_io_read_8))); 624 } 625 626 #define CHIP_io_read_multi_N(BYTES,TYPE) \ 627 static void \ 628 __C(__C(CHIP,_io_read_multi_),BYTES)( \ 629 void *v, \ 630 bus_space_handle_t h, \ 631 bus_size_t o, \ 632 TYPE *a, \ 633 bus_size_t c) \ 634 { \ 635 \ 636 while (c-- > 0) { \ 637 __C(CHIP,_io_barrier)(v, h, o, sizeof *a, \ 638 BUS_SPACE_BARRIER_READ); \ 639 *a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o); \ 640 } \ 641 } 642 CHIP_io_read_multi_N(1,uint8_t) 643 CHIP_io_read_multi_N(2,uint16_t) 644 CHIP_io_read_multi_N(4,uint32_t) 645 CHIP_io_read_multi_N(8,uint64_t) 646 647 #define CHIP_io_read_region_N(BYTES,TYPE) \ 648 static void \ 649 __C(__C(CHIP,_io_read_region_),BYTES)( \ 650 void *v, \ 651 bus_space_handle_t h, \ 652 bus_size_t o, \ 653 TYPE *a, \ 654 bus_size_t c) \ 655 { \ 656 \ 657 while (c-- > 0) { \ 658 *a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o); \ 659 o += sizeof *a; \ 660 } \ 661 } 662 CHIP_io_read_region_N(1,uint8_t) 663 CHIP_io_read_region_N(2,uint16_t) 664 CHIP_io_read_region_N(4,uint32_t) 665 CHIP_io_read_region_N(8,uint64_t) 666 667 static inline void 668 __C(CHIP,_io_write_1)( 669 void *v, 670 bus_space_handle_t ioh, 671 bus_size_t off, 672 uint8_t val) 673 { 674 bus_addr_t addr; 675 676 addr = ioh + off; 677 alpha_stb((uint8_t *)addr, val); 678 alpha_mb(); 679 } 680 681 static inline void 682 __C(CHIP,_io_write_2)( 683 void *v, 684 bus_space_handle_t ioh, 685 bus_size_t off, 686 uint16_t val) 687 { 688 bus_addr_t addr; 689 690 addr = ioh + off; 691 #ifdef DIAGNOSTIC 692 if (addr & 1) 693 panic(__S(__C(CHIP,_io_write_2)) ": addr 0x%lx not aligned", 694 addr); 695 #endif 696 alpha_stw((uint16_t *)addr, val); 697 alpha_mb(); 698 } 699 700 static inline void 701 __C(CHIP,_io_write_4)( 702 void *v, 703 bus_space_handle_t ioh, 704 bus_size_t off, 705 uint32_t val) 706 { 707 bus_addr_t addr; 708 709 addr = ioh + off; 710 #ifdef DIAGNOSTIC 711 if (addr & 3) 712 panic(__S(__C(CHIP,_io_write_4)) ": addr 0x%lx not aligned", 713 addr); 714 #endif 715 *(uint32_t *)addr = val; 716 alpha_mb(); 717 } 718 719 static inline void 720 __C(CHIP,_io_write_8)( 721 void *v, 722 bus_space_handle_t ioh, 723 bus_size_t off, 724 uint64_t val) 725 { 726 727 /* XXX XXX XXX */ 728 panic("%s not implemented", __S(__C(CHIP,_io_write_8))); 729 alpha_mb(); 730 } 731 732 #define CHIP_io_write_multi_N(BYTES,TYPE) \ 733 static void \ 734 __C(__C(CHIP,_io_write_multi_),BYTES)( \ 735 void *v, \ 736 bus_space_handle_t h, \ 737 bus_size_t o, \ 738 const TYPE *a, \ 739 bus_size_t c) \ 740 { \ 741 \ 742 while (c-- > 0) { \ 743 __C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++); \ 744 __C(CHIP,_io_barrier)(v, h, o, sizeof *a, \ 745 BUS_SPACE_BARRIER_WRITE); \ 746 } \ 747 } 748 CHIP_io_write_multi_N(1,uint8_t) 749 CHIP_io_write_multi_N(2,uint16_t) 750 CHIP_io_write_multi_N(4,uint32_t) 751 CHIP_io_write_multi_N(8,uint64_t) 752 753 #define CHIP_io_write_region_N(BYTES,TYPE) \ 754 static void \ 755 __C(__C(CHIP,_io_write_region_),BYTES)( \ 756 void *v, \ 757 bus_space_handle_t h, \ 758 bus_size_t o, \ 759 const TYPE *a, \ 760 bus_size_t c) \ 761 { \ 762 \ 763 while (c-- > 0) { \ 764 __C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++); \ 765 o += sizeof *a; \ 766 } \ 767 } 768 CHIP_io_write_region_N(1,uint8_t) 769 CHIP_io_write_region_N(2,uint16_t) 770 CHIP_io_write_region_N(4,uint32_t) 771 CHIP_io_write_region_N(8,uint64_t) 772 773 #define CHIP_io_set_multi_N(BYTES,TYPE) \ 774 static void \ 775 __C(__C(CHIP,_io_set_multi_),BYTES)( \ 776 void *v, \ 777 bus_space_handle_t h, \ 778 bus_size_t o, \ 779 TYPE val, \ 780 bus_size_t c) \ 781 { \ 782 \ 783 while (c-- > 0) { \ 784 __C(__C(CHIP,_io_write_),BYTES)(v, h, o, val); \ 785 __C(CHIP,_io_barrier)(v, h, o, sizeof val, \ 786 BUS_SPACE_BARRIER_WRITE); \ 787 } \ 788 } 789 CHIP_io_set_multi_N(1,uint8_t) 790 CHIP_io_set_multi_N(2,uint16_t) 791 CHIP_io_set_multi_N(4,uint32_t) 792 CHIP_io_set_multi_N(8,uint64_t) 793 794 #define CHIP_io_set_region_N(BYTES,TYPE) \ 795 static void \ 796 __C(__C(CHIP,_io_set_region_),BYTES)( \ 797 void *v, \ 798 bus_space_handle_t h, \ 799 bus_size_t o, \ 800 TYPE val, \ 801 bus_size_t c) \ 802 { \ 803 \ 804 while (c-- > 0) { \ 805 __C(__C(CHIP,_io_write_),BYTES)(v, h, o, val); \ 806 o += sizeof val; \ 807 } \ 808 } 809 CHIP_io_set_region_N(1,uint8_t) 810 CHIP_io_set_region_N(2,uint16_t) 811 CHIP_io_set_region_N(4,uint32_t) 812 CHIP_io_set_region_N(8,uint64_t) 813 814 #define CHIP_io_copy_region_N(BYTES) \ 815 static void \ 816 __C(__C(CHIP,_io_copy_region_),BYTES)( \ 817 void *v, \ 818 bus_space_handle_t h1, \ 819 bus_size_t o1, \ 820 bus_space_handle_t h2, \ 821 bus_size_t o2, \ 822 bus_size_t c) \ 823 { \ 824 bus_size_t o; \ 825 \ 826 if ((h1 + o1) >= (h2 + o2)) { \ 827 /* src after dest: copy forward */ \ 828 for (o = 0; c != 0; c--, o += BYTES) { \ 829 __C(__C(CHIP,_io_write_),BYTES)(v, h2, o2 + o, \ 830 __C(__C(CHIP,_io_read_),BYTES)(v, h1, o1 + o)); \ 831 } \ 832 } else { \ 833 /* dest after src: copy backwards */ \ 834 for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES) { \ 835 __C(__C(CHIP,_io_write_),BYTES)(v, h2, o2 + o, \ 836 __C(__C(CHIP,_io_read_),BYTES)(v, h1, o1 + o)); \ 837 } \ 838 } \ 839 } 840 CHIP_io_copy_region_N(1) 841 CHIP_io_copy_region_N(2) 842 CHIP_io_copy_region_N(4) 843 CHIP_io_copy_region_N(8) 844