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 */
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
__C(CHIP,_bus_io_init)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
__C(CHIP,_io_translate)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
__C(CHIP,_io_get_window)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
__C(CHIP,_io_map)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
__C(CHIP,_io_unmap)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
__C(CHIP,_io_subregion)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
__C(CHIP,_io_alloc)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
__C(CHIP,_io_free)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 *
__C(CHIP,_io_vaddr)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
__C(CHIP,_io_mmap)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
__C(CHIP,_io_barrier)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
__C(CHIP,_io_read_1)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
__C(CHIP,_io_read_2)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
__C(CHIP,_io_read_4)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
__C(CHIP,_io_read_8)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
__C(CHIP,_io_write_1)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
__C(CHIP,_io_write_2)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
__C(CHIP,_io_write_4)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
__C(CHIP,_io_write_8)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