1/* $NetBSD: pci_bwx_bus_io_chipdep.c,v 1.20 2012/01/27 18:52:49 para 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_EX_STORE
68 *			If defined, device-provided static storage area
69 *			for the I/O space extent.  If this is defined,
70 *			CHIP_IO_EX_STORE_SIZE must also be defined.  If
71 *			this is not defined, a static area will be
72 *			declared.
73 *	CHIP_IO_EX_STORE_SIZE
74 *			Size of the device-provided static storage area
75 *			for the I/O memory space extent.
76 */
77
78#include <sys/cdefs.h>
79__KERNEL_RCSID(1, "$NetBSD: pci_bwx_bus_io_chipdep.c,v 1.20 2012/01/27 18:52:49 para Exp $");
80
81#include <sys/extent.h>
82
83#include <machine/bwx.h>
84
85#define	__C(A,B)	__CONCAT(A,B)
86#define	__S(S)		__STRING(S)
87
88/* mapping/unmapping */
89int		__C(CHIP,_io_map)(void *, bus_addr_t, bus_size_t, int,
90		    bus_space_handle_t *, int);
91void		__C(CHIP,_io_unmap)(void *, bus_space_handle_t,
92		    bus_size_t, int);
93int		__C(CHIP,_io_subregion)(void *, bus_space_handle_t,
94		    bus_size_t, bus_size_t, bus_space_handle_t *);
95
96int		__C(CHIP,_io_translate)(void *, bus_addr_t, bus_size_t,
97		    int, struct alpha_bus_space_translation *);
98int		__C(CHIP,_io_get_window)(void *, int,
99		    struct alpha_bus_space_translation *);
100
101/* allocation/deallocation */
102int		__C(CHIP,_io_alloc)(void *, bus_addr_t, bus_addr_t,
103		    bus_size_t, bus_size_t, bus_addr_t, int, bus_addr_t *,
104	            bus_space_handle_t *);
105void		__C(CHIP,_io_free)(void *, bus_space_handle_t,
106		    bus_size_t);
107
108/* get kernel virtual address */
109void *		__C(CHIP,_io_vaddr)(void *, bus_space_handle_t);
110
111/* mmap for user */
112paddr_t		__C(CHIP,_io_mmap)(void *, bus_addr_t, off_t, int, int);
113
114/* barrier */
115static inline void	__C(CHIP,_io_barrier)(void *, bus_space_handle_t,
116		    bus_size_t, bus_size_t, int);
117
118/* read (single) */
119static inline uint8_t	__C(CHIP,_io_read_1)(void *, bus_space_handle_t,
120		    bus_size_t);
121static inline uint16_t __C(CHIP,_io_read_2)(void *, bus_space_handle_t,
122		    bus_size_t);
123static inline uint32_t __C(CHIP,_io_read_4)(void *, bus_space_handle_t,
124		    bus_size_t);
125static inline uint64_t __C(CHIP,_io_read_8)(void *, bus_space_handle_t,
126		    bus_size_t);
127
128/* read multiple */
129void		__C(CHIP,_io_read_multi_1)(void *, bus_space_handle_t,
130		    bus_size_t, uint8_t *, bus_size_t);
131void		__C(CHIP,_io_read_multi_2)(void *, bus_space_handle_t,
132		    bus_size_t, uint16_t *, bus_size_t);
133void		__C(CHIP,_io_read_multi_4)(void *, bus_space_handle_t,
134		    bus_size_t, uint32_t *, bus_size_t);
135void		__C(CHIP,_io_read_multi_8)(void *, bus_space_handle_t,
136		    bus_size_t, uint64_t *, bus_size_t);
137
138/* read region */
139void		__C(CHIP,_io_read_region_1)(void *, bus_space_handle_t,
140		    bus_size_t, uint8_t *, bus_size_t);
141void		__C(CHIP,_io_read_region_2)(void *, bus_space_handle_t,
142		    bus_size_t, uint16_t *, bus_size_t);
143void		__C(CHIP,_io_read_region_4)(void *, bus_space_handle_t,
144		    bus_size_t, uint32_t *, bus_size_t);
145void		__C(CHIP,_io_read_region_8)(void *, bus_space_handle_t,
146		    bus_size_t, uint64_t *, bus_size_t);
147
148/* write (single) */
149static inline void	__C(CHIP,_io_write_1)(void *, bus_space_handle_t,
150		    bus_size_t, uint8_t);
151static inline void	__C(CHIP,_io_write_2)(void *, bus_space_handle_t,
152		    bus_size_t, uint16_t);
153static inline void	__C(CHIP,_io_write_4)(void *, bus_space_handle_t,
154		    bus_size_t, uint32_t);
155static inline void	__C(CHIP,_io_write_8)(void *, bus_space_handle_t,
156		    bus_size_t, uint64_t);
157
158/* write multiple */
159void		__C(CHIP,_io_write_multi_1)(void *, bus_space_handle_t,
160		    bus_size_t, const uint8_t *, bus_size_t);
161void		__C(CHIP,_io_write_multi_2)(void *, bus_space_handle_t,
162		    bus_size_t, const uint16_t *, bus_size_t);
163void		__C(CHIP,_io_write_multi_4)(void *, bus_space_handle_t,
164		    bus_size_t, const uint32_t *, bus_size_t);
165void		__C(CHIP,_io_write_multi_8)(void *, bus_space_handle_t,
166		    bus_size_t, const uint64_t *, bus_size_t);
167
168/* write region */
169void		__C(CHIP,_io_write_region_1)(void *, bus_space_handle_t,
170		    bus_size_t, const uint8_t *, bus_size_t);
171void		__C(CHIP,_io_write_region_2)(void *, bus_space_handle_t,
172		    bus_size_t, const uint16_t *, bus_size_t);
173void		__C(CHIP,_io_write_region_4)(void *, bus_space_handle_t,
174		    bus_size_t, const uint32_t *, bus_size_t);
175void		__C(CHIP,_io_write_region_8)(void *, bus_space_handle_t,
176		    bus_size_t, const uint64_t *, bus_size_t);
177
178/* set multiple */
179void		__C(CHIP,_io_set_multi_1)(void *, bus_space_handle_t,
180		    bus_size_t, uint8_t, bus_size_t);
181void		__C(CHIP,_io_set_multi_2)(void *, bus_space_handle_t,
182		    bus_size_t, uint16_t, bus_size_t);
183void		__C(CHIP,_io_set_multi_4)(void *, bus_space_handle_t,
184		    bus_size_t, uint32_t, bus_size_t);
185void		__C(CHIP,_io_set_multi_8)(void *, bus_space_handle_t,
186		    bus_size_t, uint64_t, bus_size_t);
187
188/* set region */
189void		__C(CHIP,_io_set_region_1)(void *, bus_space_handle_t,
190		    bus_size_t, uint8_t, bus_size_t);
191void		__C(CHIP,_io_set_region_2)(void *, bus_space_handle_t,
192		    bus_size_t, uint16_t, bus_size_t);
193void		__C(CHIP,_io_set_region_4)(void *, bus_space_handle_t,
194		    bus_size_t, uint32_t, bus_size_t);
195void		__C(CHIP,_io_set_region_8)(void *, bus_space_handle_t,
196		    bus_size_t, uint64_t, bus_size_t);
197
198/* copy */
199void		__C(CHIP,_io_copy_region_1)(void *, bus_space_handle_t,
200		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
201void		__C(CHIP,_io_copy_region_2)(void *, bus_space_handle_t,
202		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
203void		__C(CHIP,_io_copy_region_4)(void *, bus_space_handle_t,
204		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
205void		__C(CHIP,_io_copy_region_8)(void *, bus_space_handle_t,
206		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
207
208#ifndef	CHIP_IO_EX_STORE
209static long
210    __C(CHIP,_io_ex_storage)[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
211#define	CHIP_IO_EX_STORE(v)		(__C(CHIP, _io_ex_storage))
212#define	CHIP_IO_EX_STORE_SIZE(v)	(sizeof __C(CHIP, _io_ex_storage))
213#endif
214
215void
216__C(CHIP,_bus_io_init)(
217	bus_space_tag_t t,
218	void *v)
219{
220	struct extent *ex;
221
222	/*
223	 * Initialize the bus space tag.
224	 */
225
226	/* cookie */
227	t->abs_cookie =		v;
228
229	/* mapping/unmapping */
230	t->abs_map =		__C(CHIP,_io_map);
231	t->abs_unmap =		__C(CHIP,_io_unmap);
232	t->abs_subregion =	__C(CHIP,_io_subregion);
233
234	t->abs_translate =	__C(CHIP,_io_translate);
235	t->abs_get_window =	__C(CHIP,_io_get_window);
236
237	/* allocation/deallocation */
238	t->abs_alloc =		__C(CHIP,_io_alloc);
239	t->abs_free = 		__C(CHIP,_io_free);
240
241	/* get kernel virtual address */
242	t->abs_vaddr =		__C(CHIP,_io_vaddr);
243
244	/* mmap for user */
245	t->abs_mmap =		__C(CHIP,_io_mmap);
246
247	/* barrier */
248	t->abs_barrier =	__C(CHIP,_io_barrier);
249
250	/* read (single) */
251	t->abs_r_1 =		__C(CHIP,_io_read_1);
252	t->abs_r_2 =		__C(CHIP,_io_read_2);
253	t->abs_r_4 =		__C(CHIP,_io_read_4);
254	t->abs_r_8 =		__C(CHIP,_io_read_8);
255
256	/* read multiple */
257	t->abs_rm_1 =		__C(CHIP,_io_read_multi_1);
258	t->abs_rm_2 =		__C(CHIP,_io_read_multi_2);
259	t->abs_rm_4 =		__C(CHIP,_io_read_multi_4);
260	t->abs_rm_8 =		__C(CHIP,_io_read_multi_8);
261
262	/* read region */
263	t->abs_rr_1 =		__C(CHIP,_io_read_region_1);
264	t->abs_rr_2 =		__C(CHIP,_io_read_region_2);
265	t->abs_rr_4 =		__C(CHIP,_io_read_region_4);
266	t->abs_rr_8 =		__C(CHIP,_io_read_region_8);
267
268	/* write (single) */
269	t->abs_w_1 =		__C(CHIP,_io_write_1);
270	t->abs_w_2 =		__C(CHIP,_io_write_2);
271	t->abs_w_4 =		__C(CHIP,_io_write_4);
272	t->abs_w_8 =		__C(CHIP,_io_write_8);
273
274	/* write multiple */
275	t->abs_wm_1 =		__C(CHIP,_io_write_multi_1);
276	t->abs_wm_2 =		__C(CHIP,_io_write_multi_2);
277	t->abs_wm_4 =		__C(CHIP,_io_write_multi_4);
278	t->abs_wm_8 =		__C(CHIP,_io_write_multi_8);
279
280	/* write region */
281	t->abs_wr_1 =		__C(CHIP,_io_write_region_1);
282	t->abs_wr_2 =		__C(CHIP,_io_write_region_2);
283	t->abs_wr_4 =		__C(CHIP,_io_write_region_4);
284	t->abs_wr_8 =		__C(CHIP,_io_write_region_8);
285
286	/* set multiple */
287	t->abs_sm_1 =		__C(CHIP,_io_set_multi_1);
288	t->abs_sm_2 =		__C(CHIP,_io_set_multi_2);
289	t->abs_sm_4 =		__C(CHIP,_io_set_multi_4);
290	t->abs_sm_8 =		__C(CHIP,_io_set_multi_8);
291
292	/* set region */
293	t->abs_sr_1 =		__C(CHIP,_io_set_region_1);
294	t->abs_sr_2 =		__C(CHIP,_io_set_region_2);
295	t->abs_sr_4 =		__C(CHIP,_io_set_region_4);
296	t->abs_sr_8 =		__C(CHIP,_io_set_region_8);
297
298	/* copy */
299	t->abs_c_1 =		__C(CHIP,_io_copy_region_1);
300	t->abs_c_2 =		__C(CHIP,_io_copy_region_2);
301	t->abs_c_4 =		__C(CHIP,_io_copy_region_4);
302	t->abs_c_8 =		__C(CHIP,_io_copy_region_8);
303
304	ex = extent_create(__S(__C(CHIP,_bus_io)), 0x0UL, 0xffffffffUL,
305	    (void *)CHIP_IO_EX_STORE(v), CHIP_IO_EX_STORE_SIZE(v),
306	    EX_NOWAIT|EX_NOCOALESCE);
307
308	CHIP_IO_EXTENT(v) = ex;
309}
310
311int
312__C(CHIP,_io_translate)(
313	void *v,
314	bus_addr_t ioaddr,
315	bus_size_t iolen,
316	int flags,
317	struct alpha_bus_space_translation *abst)
318{
319	int linear = flags & BUS_SPACE_MAP_LINEAR;
320
321	/*
322	 * Can't map i/o space linearly.
323	 */
324	if (linear)
325		return (EOPNOTSUPP);
326
327	return (__C(CHIP,_io_get_window)(v, 0, abst));
328}
329
330int
331__C(CHIP,_io_get_window)(
332	void *v,
333	int window,
334	struct alpha_bus_space_translation *abst)
335{
336
337	switch (window) {
338	case 0:
339		abst->abst_bus_start = 0;
340		abst->abst_bus_end = 0xffffffffUL;
341		abst->abst_sys_start = CHIP_IO_SYS_START(v);
342		abst->abst_sys_end = CHIP_IO_SYS_START(v) + abst->abst_bus_end;
343		abst->abst_addr_shift = 0;
344		abst->abst_size_shift = 0;
345		abst->abst_flags = ABST_DENSE|ABST_BWX;
346		break;
347
348	default:
349		panic(__S(__C(CHIP,_io_get_window)) ": invalid window %d",
350		    window);
351	}
352
353	return (0);
354}
355
356int
357__C(CHIP,_io_map)(
358	void *v,
359	bus_addr_t ioaddr,
360	bus_size_t iosize,
361	int flags,
362	bus_space_handle_t *iohp,
363	int acct)
364{
365	struct alpha_bus_space_translation abst;
366	int error;
367
368	/*
369	 * Get the translation for this address.
370	 */
371	error = __C(CHIP,_io_translate)(v, ioaddr, iosize, flags, &abst);
372	if (error)
373		return (error);
374
375	if (acct == 0)
376		goto mapit;
377
378#ifdef EXTENT_DEBUG
379	printf("io: allocating 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1);
380#endif
381	error = extent_alloc_region(CHIP_IO_EXTENT(v), ioaddr, iosize,
382	    EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
383	if (error) {
384#ifdef EXTENT_DEBUG
385		printf("io: allocation failed (%d)\n", error);
386		extent_print(CHIP_IO_EXTENT(v));
387#endif
388		return (error);
389	}
390
391 mapit:
392	*iohp = ALPHA_PHYS_TO_K0SEG(abst.abst_sys_start + ioaddr);
393
394	return (0);
395}
396
397void
398__C(CHIP,_io_unmap)(
399	void *v,
400	bus_space_handle_t ioh,
401	bus_size_t iosize,
402	int acct)
403{
404	bus_addr_t ioaddr;
405	int error;
406
407	if (acct == 0)
408		return;
409
410#ifdef EXTENT_DEBUG
411	printf("io: freeing handle 0x%lx for 0x%lx\n", ioh, iosize);
412#endif
413
414	ioaddr = ioh - ALPHA_PHYS_TO_K0SEG(CHIP_IO_SYS_START(v));
415
416#ifdef EXTENT_DEBUG
417	printf("io: freeing 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1);
418#endif
419	error = extent_free(CHIP_IO_EXTENT(v), ioaddr, iosize,
420	    EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
421	if (error) {
422		printf("%s: WARNING: could not unmap 0x%lx-0x%lx (error %d)\n",
423		   __S(__C(CHIP,_io_unmap)), ioaddr, ioaddr + iosize - 1,
424		   error);
425#ifdef EXTENT_DEBUG
426		extent_print(CHIP_IO_EXTENT(v));
427#endif
428	}
429}
430
431int
432__C(CHIP,_io_subregion)(
433	void *v,
434	bus_space_handle_t ioh,
435	bus_size_t offset,
436	bus_size_t size,
437	bus_space_handle_t *nioh)
438{
439
440	*nioh = ioh + offset;
441	return (0);
442}
443
444int
445__C(CHIP,_io_alloc)(
446	void *v,
447	bus_addr_t rstart,
448	bus_addr_t rend,
449	bus_size_t size,
450	bus_size_t align,
451	bus_size_t boundary,
452	int flags,
453	bus_addr_t *addrp,
454	bus_space_handle_t *bshp)
455{
456	struct alpha_bus_space_translation abst;
457	int linear = flags & BUS_SPACE_MAP_LINEAR;
458	bus_addr_t ioaddr;
459	int error;
460
461	/*
462	 * Can't map i/o space linearly.
463	 */
464	if (linear)
465		return (EOPNOTSUPP);
466
467	/*
468	 * Do the requested allocation.
469	 */
470#ifdef EXTENT_DEBUG
471	printf("io: allocating from 0x%lx to 0x%lx\n", rstart, rend);
472#endif
473	error = extent_alloc_subregion(CHIP_IO_EXTENT(v), rstart, rend,
474	    size, align, boundary,
475	    EX_FAST | EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0),
476	    &ioaddr);
477	if (error) {
478#ifdef EXTENT_DEBUG
479		printf("io: allocation failed (%d)\n", error);
480		extent_print(CHIP_IO_EXTENT(v));
481#endif
482		return (error);
483	}
484
485#ifdef EXTENT_DEBUG
486	printf("io: allocated 0x%lx to 0x%lx\n", ioaddr, ioaddr + size - 1);
487#endif
488
489	error = __C(CHIP,_io_translate)(v, ioaddr, size, flags, &abst);
490	if (error) {
491		(void) extent_free(CHIP_IO_EXTENT(v), ioaddr, size,
492		    EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
493		return (error);
494	}
495
496	*addrp = ioaddr;
497	*bshp = ALPHA_PHYS_TO_K0SEG(abst.abst_sys_start + ioaddr);
498
499	return (0);
500}
501
502void
503__C(CHIP,_io_free)(
504	void *v,
505	bus_space_handle_t bsh,
506	bus_size_t size)
507{
508
509	/* Unmap does all we need to do. */
510	__C(CHIP,_io_unmap)(v, bsh, size, 1);
511}
512
513void *
514__C(CHIP,_io_vaddr)(
515	void *v,
516	bus_space_handle_t bsh)
517{
518	/*
519	 * _io_translate() catches BUS_SPACE_MAP_LINEAR,
520	 * so we shouldn't get here
521	 */
522	panic("_io_vaddr");
523}
524
525paddr_t
526__C(CHIP,_io_mmap)(
527	void *v,
528	bus_addr_t addr,
529	off_t off,
530	int prot,
531	int flags)
532{
533
534	/* Not supported for I/O space. */
535	return (-1);
536}
537
538static inline void
539__C(CHIP,_io_barrier)(
540	void *v,
541	bus_space_handle_t h,
542	bus_size_t o,
543	bus_size_t l,
544	int f)
545{
546
547	if ((f & BUS_SPACE_BARRIER_READ) != 0)
548		alpha_mb();
549	else if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
550		alpha_wmb();
551}
552
553static inline uint8_t
554__C(CHIP,_io_read_1)(
555	void *v,
556	bus_space_handle_t ioh,
557	bus_size_t off)
558{
559	bus_addr_t addr;
560
561	addr = ioh + off;
562	alpha_mb();
563	return (alpha_ldbu((uint8_t *)addr));
564}
565
566static inline uint16_t
567__C(CHIP,_io_read_2)(
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#ifdef DIAGNOSTIC
576	if (addr & 1)
577		panic(__S(__C(CHIP,_io_read_2)) ": addr 0x%lx not aligned",
578		    addr);
579#endif
580	alpha_mb();
581	return (alpha_ldwu((uint16_t *)addr));
582}
583
584static inline uint32_t
585__C(CHIP,_io_read_4)(
586	void *v,
587	bus_space_handle_t ioh,
588	bus_size_t off)
589{
590	bus_addr_t addr;
591
592	addr = ioh + off;
593#ifdef DIAGNOSTIC
594	if (addr & 3)
595		panic(__S(__C(CHIP,_io_read_4)) ": addr 0x%lx not aligned",
596		    addr);
597#endif
598	alpha_mb();
599	return (*(uint32_t *)addr);
600}
601
602static inline uint64_t
603__C(CHIP,_io_read_8)(
604	void *v,
605	bus_space_handle_t ioh,
606	bus_size_t off)
607{
608
609	/* XXX XXX XXX */
610	panic("%s not implemented", __S(__C(CHIP,_io_read_8)));
611}
612
613#define CHIP_io_read_multi_N(BYTES,TYPE)				\
614void									\
615__C(__C(CHIP,_io_read_multi_),BYTES)(					\
616	void *v,							\
617	bus_space_handle_t h,						\
618	bus_size_t o,							\
619	TYPE *a,							\
620	bus_size_t c)							\
621{									\
622									\
623	while (c-- > 0) {						\
624		__C(CHIP,_io_barrier)(v, h, o, sizeof *a,		\
625		    BUS_SPACE_BARRIER_READ);				\
626		*a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o);		\
627	}								\
628}
629CHIP_io_read_multi_N(1,uint8_t)
630CHIP_io_read_multi_N(2,uint16_t)
631CHIP_io_read_multi_N(4,uint32_t)
632CHIP_io_read_multi_N(8,uint64_t)
633
634#define CHIP_io_read_region_N(BYTES,TYPE)				\
635void									\
636__C(__C(CHIP,_io_read_region_),BYTES)(					\
637	void *v,							\
638	bus_space_handle_t h,						\
639	bus_size_t o,							\
640	TYPE *a,							\
641	bus_size_t c)							\
642{									\
643									\
644	while (c-- > 0) {						\
645		*a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o);		\
646		o += sizeof *a;						\
647	}								\
648}
649CHIP_io_read_region_N(1,uint8_t)
650CHIP_io_read_region_N(2,uint16_t)
651CHIP_io_read_region_N(4,uint32_t)
652CHIP_io_read_region_N(8,uint64_t)
653
654static inline void
655__C(CHIP,_io_write_1)(
656	void *v,
657	bus_space_handle_t ioh,
658	bus_size_t off,
659	uint8_t val)
660{
661	bus_addr_t addr;
662
663	addr = ioh + off;
664	alpha_stb((uint8_t *)addr, val);
665	alpha_mb();
666}
667
668static inline void
669__C(CHIP,_io_write_2)(
670	void *v,
671	bus_space_handle_t ioh,
672	bus_size_t off,
673	uint16_t val)
674{
675	bus_addr_t addr;
676
677	addr = ioh + off;
678#ifdef DIAGNOSTIC
679	if (addr & 1)
680		panic(__S(__C(CHIP,_io_write_2)) ": addr 0x%lx not aligned",
681		    addr);
682#endif
683	alpha_stw((uint16_t *)addr, val);
684	alpha_mb();
685}
686
687static inline void
688__C(CHIP,_io_write_4)(
689	void *v,
690	bus_space_handle_t ioh,
691	bus_size_t off,
692	uint32_t val)
693{
694	bus_addr_t addr;
695
696	addr = ioh + off;
697#ifdef DIAGNOSTIC
698	if (addr & 3)
699		panic(__S(__C(CHIP,_io_write_4)) ": addr 0x%lx not aligned",
700		    addr);
701#endif
702	*(uint32_t *)addr = val;
703	alpha_mb();
704}
705
706static inline void
707__C(CHIP,_io_write_8)(
708	void *v,
709	bus_space_handle_t ioh,
710	bus_size_t off,
711	uint64_t val)
712{
713
714	/* XXX XXX XXX */
715	panic("%s not implemented", __S(__C(CHIP,_io_write_8)));
716	alpha_mb();
717}
718
719#define CHIP_io_write_multi_N(BYTES,TYPE)				\
720void									\
721__C(__C(CHIP,_io_write_multi_),BYTES)(					\
722	void *v,							\
723	bus_space_handle_t h,						\
724	bus_size_t o,							\
725	const TYPE *a,							\
726	bus_size_t c)							\
727{									\
728									\
729	while (c-- > 0) {						\
730		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++);		\
731		__C(CHIP,_io_barrier)(v, h, o, sizeof *a,		\
732		    BUS_SPACE_BARRIER_WRITE);				\
733	}								\
734}
735CHIP_io_write_multi_N(1,uint8_t)
736CHIP_io_write_multi_N(2,uint16_t)
737CHIP_io_write_multi_N(4,uint32_t)
738CHIP_io_write_multi_N(8,uint64_t)
739
740#define CHIP_io_write_region_N(BYTES,TYPE)				\
741void									\
742__C(__C(CHIP,_io_write_region_),BYTES)(					\
743	void *v,							\
744	bus_space_handle_t h,						\
745	bus_size_t o,							\
746	const TYPE *a,							\
747	bus_size_t c)							\
748{									\
749									\
750	while (c-- > 0) {						\
751		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++);		\
752		o += sizeof *a;						\
753	}								\
754}
755CHIP_io_write_region_N(1,uint8_t)
756CHIP_io_write_region_N(2,uint16_t)
757CHIP_io_write_region_N(4,uint32_t)
758CHIP_io_write_region_N(8,uint64_t)
759
760#define CHIP_io_set_multi_N(BYTES,TYPE)					\
761void									\
762__C(__C(CHIP,_io_set_multi_),BYTES)(					\
763	void *v,							\
764	bus_space_handle_t h,						\
765	bus_size_t o,							\
766	TYPE val,							\
767	bus_size_t c)							\
768{									\
769									\
770	while (c-- > 0) {						\
771		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, val);		\
772		__C(CHIP,_io_barrier)(v, h, o, sizeof val,		\
773		    BUS_SPACE_BARRIER_WRITE);				\
774	}								\
775}
776CHIP_io_set_multi_N(1,uint8_t)
777CHIP_io_set_multi_N(2,uint16_t)
778CHIP_io_set_multi_N(4,uint32_t)
779CHIP_io_set_multi_N(8,uint64_t)
780
781#define CHIP_io_set_region_N(BYTES,TYPE)				\
782void									\
783__C(__C(CHIP,_io_set_region_),BYTES)(					\
784	void *v,							\
785	bus_space_handle_t h,						\
786	bus_size_t o,							\
787	TYPE val,							\
788	bus_size_t c)							\
789{									\
790									\
791	while (c-- > 0) {						\
792		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, val);		\
793		o += sizeof val;					\
794	}								\
795}
796CHIP_io_set_region_N(1,uint8_t)
797CHIP_io_set_region_N(2,uint16_t)
798CHIP_io_set_region_N(4,uint32_t)
799CHIP_io_set_region_N(8,uint64_t)
800
801#define	CHIP_io_copy_region_N(BYTES)					\
802void									\
803__C(__C(CHIP,_io_copy_region_),BYTES)(					\
804	void *v,							\
805	bus_space_handle_t h1,						\
806	bus_size_t o1,							\
807	bus_space_handle_t h2,						\
808	bus_size_t o2,							\
809	bus_size_t c)							\
810{									\
811	bus_size_t o;							\
812									\
813	if ((h1 + o1) >= (h2 + o2)) {					\
814		/* src after dest: copy forward */			\
815		for (o = 0; c != 0; c--, o += BYTES) {			\
816			__C(__C(CHIP,_io_write_),BYTES)(v, h2, o2 + o,	\
817			    __C(__C(CHIP,_io_read_),BYTES)(v, h1, o1 + o)); \
818		}							\
819	} else {							\
820		/* dest after src: copy backwards */			\
821		for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES) {	\
822			__C(__C(CHIP,_io_write_),BYTES)(v, h2, o2 + o,	\
823			    __C(__C(CHIP,_io_read_),BYTES)(v, h1, o1 + o)); \
824		}							\
825	}								\
826}
827CHIP_io_copy_region_N(1)
828CHIP_io_copy_region_N(2)
829CHIP_io_copy_region_N(4)
830CHIP_io_copy_region_N(8)
831