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@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 */ 94static int __C(CHIP,_io_map)(void *, bus_addr_t, bus_size_t, int, 95 bus_space_handle_t *, int); 96static void __C(CHIP,_io_unmap)(void *, bus_space_handle_t, 97 bus_size_t, int); 98static int __C(CHIP,_io_subregion)(void *, bus_space_handle_t, 99 bus_size_t, bus_size_t, bus_space_handle_t *); 100 101static int __C(CHIP,_io_translate)(void *, bus_addr_t, bus_size_t, 102 int, struct alpha_bus_space_translation *); 103static int __C(CHIP,_io_get_window)(void *, int, 104 struct alpha_bus_space_translation *); 105 106/* allocation/deallocation */ 107static 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 *); 110static void __C(CHIP,_io_free)(void *, bus_space_handle_t, 111 bus_size_t); 112 113/* get kernel virtual address */ 114static void * __C(CHIP,_io_vaddr)(void *, bus_space_handle_t); 115 116/* mmap for user */ 117static paddr_t __C(CHIP,_io_mmap)(void *, bus_addr_t, off_t, int, int); 118 119/* barrier */ 120static inline void __C(CHIP,_io_barrier)(void *, bus_space_handle_t, 121 bus_size_t, bus_size_t, int); 122 123/* read (single) */ 124static inline uint8_t __C(CHIP,_io_read_1)(void *, bus_space_handle_t, 125 bus_size_t); 126static inline uint16_t __C(CHIP,_io_read_2)(void *, bus_space_handle_t, 127 bus_size_t); 128static inline uint32_t __C(CHIP,_io_read_4)(void *, bus_space_handle_t, 129 bus_size_t); 130static inline uint64_t __C(CHIP,_io_read_8)(void *, bus_space_handle_t, 131 bus_size_t); 132 133/* read multiple */ 134static void __C(CHIP,_io_read_multi_1)(void *, bus_space_handle_t, 135 bus_size_t, uint8_t *, bus_size_t); 136static void __C(CHIP,_io_read_multi_2)(void *, bus_space_handle_t, 137 bus_size_t, uint16_t *, bus_size_t); 138static void __C(CHIP,_io_read_multi_4)(void *, bus_space_handle_t, 139 bus_size_t, uint32_t *, bus_size_t); 140static 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 */ 144static void __C(CHIP,_io_read_region_1)(void *, bus_space_handle_t, 145 bus_size_t, uint8_t *, bus_size_t); 146static void __C(CHIP,_io_read_region_2)(void *, bus_space_handle_t, 147 bus_size_t, uint16_t *, bus_size_t); 148static void __C(CHIP,_io_read_region_4)(void *, bus_space_handle_t, 149 bus_size_t, uint32_t *, bus_size_t); 150static 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) */ 154static inline void __C(CHIP,_io_write_1)(void *, bus_space_handle_t, 155 bus_size_t, uint8_t); 156static inline void __C(CHIP,_io_write_2)(void *, bus_space_handle_t, 157 bus_size_t, uint16_t); 158static inline void __C(CHIP,_io_write_4)(void *, bus_space_handle_t, 159 bus_size_t, uint32_t); 160static inline void __C(CHIP,_io_write_8)(void *, bus_space_handle_t, 161 bus_size_t, uint64_t); 162 163/* write multiple */ 164static void __C(CHIP,_io_write_multi_1)(void *, bus_space_handle_t, 165 bus_size_t, const uint8_t *, bus_size_t); 166static void __C(CHIP,_io_write_multi_2)(void *, bus_space_handle_t, 167 bus_size_t, const uint16_t *, bus_size_t); 168static void __C(CHIP,_io_write_multi_4)(void *, bus_space_handle_t, 169 bus_size_t, const uint32_t *, bus_size_t); 170static 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 */ 174static void __C(CHIP,_io_write_region_1)(void *, bus_space_handle_t, 175 bus_size_t, const uint8_t *, bus_size_t); 176static void __C(CHIP,_io_write_region_2)(void *, bus_space_handle_t, 177 bus_size_t, const uint16_t *, bus_size_t); 178static void __C(CHIP,_io_write_region_4)(void *, bus_space_handle_t, 179 bus_size_t, const uint32_t *, bus_size_t); 180static 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 */ 184static void __C(CHIP,_io_set_multi_1)(void *, bus_space_handle_t, 185 bus_size_t, uint8_t, bus_size_t); 186static void __C(CHIP,_io_set_multi_2)(void *, bus_space_handle_t, 187 bus_size_t, uint16_t, bus_size_t); 188static void __C(CHIP,_io_set_multi_4)(void *, bus_space_handle_t, 189 bus_size_t, uint32_t, bus_size_t); 190static 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 */ 194static void __C(CHIP,_io_set_region_1)(void *, bus_space_handle_t, 195 bus_size_t, uint8_t, bus_size_t); 196static void __C(CHIP,_io_set_region_2)(void *, bus_space_handle_t, 197 bus_size_t, uint16_t, bus_size_t); 198static void __C(CHIP,_io_set_region_4)(void *, bus_space_handle_t, 199 bus_size_t, uint32_t, bus_size_t); 200static void __C(CHIP,_io_set_region_8)(void *, bus_space_handle_t, 201 bus_size_t, uint64_t, bus_size_t); 202 203/* copy */ 204static 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); 206static 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); 208static 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); 210static 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 218static struct vmem __C(CHIP,_io_arena_store); 219static struct vmem_btag __C(CHIP,_io_btag_store)[CHIP_IO_BTAG_COUNT(xxx)]; 220#endif /* CHIP_IO_ARENA_STORE */ 221 222void 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 332static 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 351static 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 377static 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 417static 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 441static 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 454static 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 515static 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 526static 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 538static 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 551static 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 566static 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 579static 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 597static 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 615static 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) \ 627static 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} 642CHIP_io_read_multi_N(1,uint8_t) 643CHIP_io_read_multi_N(2,uint16_t) 644CHIP_io_read_multi_N(4,uint32_t) 645CHIP_io_read_multi_N(8,uint64_t) 646 647#define CHIP_io_read_region_N(BYTES,TYPE) \ 648static 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} 662CHIP_io_read_region_N(1,uint8_t) 663CHIP_io_read_region_N(2,uint16_t) 664CHIP_io_read_region_N(4,uint32_t) 665CHIP_io_read_region_N(8,uint64_t) 666 667static 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 681static 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 700static 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 719static 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) \ 733static 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} 748CHIP_io_write_multi_N(1,uint8_t) 749CHIP_io_write_multi_N(2,uint16_t) 750CHIP_io_write_multi_N(4,uint32_t) 751CHIP_io_write_multi_N(8,uint64_t) 752 753#define CHIP_io_write_region_N(BYTES,TYPE) \ 754static 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} 768CHIP_io_write_region_N(1,uint8_t) 769CHIP_io_write_region_N(2,uint16_t) 770CHIP_io_write_region_N(4,uint32_t) 771CHIP_io_write_region_N(8,uint64_t) 772 773#define CHIP_io_set_multi_N(BYTES,TYPE) \ 774static 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} 789CHIP_io_set_multi_N(1,uint8_t) 790CHIP_io_set_multi_N(2,uint16_t) 791CHIP_io_set_multi_N(4,uint32_t) 792CHIP_io_set_multi_N(8,uint64_t) 793 794#define CHIP_io_set_region_N(BYTES,TYPE) \ 795static 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} 809CHIP_io_set_region_N(1,uint8_t) 810CHIP_io_set_region_N(2,uint16_t) 811CHIP_io_set_region_N(4,uint32_t) 812CHIP_io_set_region_N(8,uint64_t) 813 814#define CHIP_io_copy_region_N(BYTES) \ 815static 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} 840CHIP_io_copy_region_N(1) 841CHIP_io_copy_region_N(2) 842CHIP_io_copy_region_N(4) 843CHIP_io_copy_region_N(8) 844