xref: /netbsd-src/sys/arch/alpha/pci/pci_bwx_bus_io_chipdep.c (revision 6b54fdb24ad88ed15360450b84084a49b81ab71b)
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