1/* $OpenBSD: pci_bwx_bus_io_chipdep.c,v 1.9 2009/12/25 20:52:34 miod Exp $ */
2/* $NetBSD: pcs_bus_io_common.c,v 1.14 1996/12/02 22:19:35 cgd Exp $ */
3
4/*
5 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
6 * All rights reserved.
7 *
8 * Author: Chris G. Demetriou
9 *
10 * Permission to use, copy, modify and distribute this software and
11 * its documentation is hereby granted, provided that both the copyright
12 * notice and this permission notice appear in all copies of the
13 * software, derivative works or modified versions, and any portions
14 * thereof, and that both notices appear in supporting documentation.
15 *
16 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
18 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 *
20 * Carnegie Mellon requests users of this software to return to
21 *
22 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
23 *  School of Computer Science
24 *  Carnegie Mellon University
25 *  Pittsburgh PA 15213-3890
26 *
27 * any improvements or extensions that they make and grant Carnegie the
28 * rights to redistribute these changes.
29 */
30
31/*
32 * Common PCI Chipset "bus I/O" functions, for chipsets which have to
33 * deal with only a single PCI interface chip in a machine.
34 *
35 * uses:
36 *	CHIP		name of the 'chip' it's being compiled for.
37 *	CHIP_IO_BASE	Sparse I/O space base to use.
38 */
39
40#include <sys/extent.h>
41
42#include <machine/bwx.h>
43
44#define	__C(A,B)	__CONCAT(A,B)
45#define	__S(S)		__STRING(S)
46
47#ifndef	CHIP_EXTENT_NAME
48#define	CHIP_EXTENT_NAME(v)	__S(__C(CHIP,_bus_io))
49#endif
50
51#ifndef	CHIP_EXTENT_STORAGE
52#define CHIP_EXTENT_STORAGE(v)	__C(CHIP,_io_ex_storage)
53static long
54    __C(CHIP,_io_ex_storage)[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
55#endif
56
57/* mapping/unmapping */
58int		__C(CHIP,_io_map)(void *, bus_addr_t, bus_size_t, int,
59		    bus_space_handle_t *);
60void		__C(CHIP,_io_unmap)(void *, bus_space_handle_t,
61		    bus_size_t);
62int		__C(CHIP,_io_subregion)(void *, bus_space_handle_t,
63		    bus_size_t, bus_size_t, bus_space_handle_t *);
64
65/* allocation/deallocation */
66int		__C(CHIP,_io_alloc)(void *, bus_addr_t, bus_addr_t,
67		    bus_size_t, bus_size_t, bus_addr_t, int, bus_addr_t *,
68                    bus_space_handle_t *);
69void		__C(CHIP,_io_free)(void *, bus_space_handle_t,
70		    bus_size_t);
71
72/* get kernel virtual address */
73void *		__C(CHIP,_io_vaddr)(void *, bus_space_handle_t);
74
75/* barrier */
76inline void	__C(CHIP,_io_barrier)(void *, bus_space_handle_t,
77		    bus_size_t, bus_size_t, int);
78
79/* read (single) */
80inline u_int8_t	__C(CHIP,_io_read_1)(void *, bus_space_handle_t,
81		    bus_size_t);
82inline u_int16_t __C(CHIP,_io_read_2)(void *, bus_space_handle_t,
83		    bus_size_t);
84inline u_int32_t __C(CHIP,_io_read_4)(void *, bus_space_handle_t,
85		    bus_size_t);
86inline u_int64_t __C(CHIP,_io_read_8)(void *, bus_space_handle_t,
87		    bus_size_t);
88
89/* read multiple */
90void		__C(CHIP,_io_read_multi_1)(void *, bus_space_handle_t,
91		    bus_size_t, u_int8_t *, bus_size_t);
92void		__C(CHIP,_io_read_multi_2)(void *, bus_space_handle_t,
93		    bus_size_t, u_int16_t *, bus_size_t);
94void		__C(CHIP,_io_read_multi_4)(void *, bus_space_handle_t,
95		    bus_size_t, u_int32_t *, bus_size_t);
96void		__C(CHIP,_io_read_multi_8)(void *, bus_space_handle_t,
97		    bus_size_t, u_int64_t *, bus_size_t);
98
99/* read region */
100void		__C(CHIP,_io_read_region_1)(void *, bus_space_handle_t,
101		    bus_size_t, u_int8_t *, bus_size_t);
102void		__C(CHIP,_io_read_region_2)(void *, bus_space_handle_t,
103		    bus_size_t, u_int16_t *, bus_size_t);
104void		__C(CHIP,_io_read_region_4)(void *, bus_space_handle_t,
105		    bus_size_t, u_int32_t *, bus_size_t);
106void		__C(CHIP,_io_read_region_8)(void *, bus_space_handle_t,
107		    bus_size_t, u_int64_t *, bus_size_t);
108
109/* write (single) */
110inline void	__C(CHIP,_io_write_1)(void *, bus_space_handle_t,
111		    bus_size_t, u_int8_t);
112inline void	__C(CHIP,_io_write_2)(void *, bus_space_handle_t,
113		    bus_size_t, u_int16_t);
114inline void	__C(CHIP,_io_write_4)(void *, bus_space_handle_t,
115		    bus_size_t, u_int32_t);
116inline void	__C(CHIP,_io_write_8)(void *, bus_space_handle_t,
117		    bus_size_t, u_int64_t);
118
119/* write multiple */
120void		__C(CHIP,_io_write_multi_1)(void *, bus_space_handle_t,
121		    bus_size_t, const u_int8_t *, bus_size_t);
122void		__C(CHIP,_io_write_multi_2)(void *, bus_space_handle_t,
123		    bus_size_t, const u_int16_t *, bus_size_t);
124void		__C(CHIP,_io_write_multi_4)(void *, bus_space_handle_t,
125		    bus_size_t, const u_int32_t *, bus_size_t);
126void		__C(CHIP,_io_write_multi_8)(void *, bus_space_handle_t,
127		    bus_size_t, const u_int64_t *, bus_size_t);
128
129/* write region */
130void		__C(CHIP,_io_write_region_1)(void *, bus_space_handle_t,
131		    bus_size_t, const u_int8_t *, bus_size_t);
132void		__C(CHIP,_io_write_region_2)(void *, bus_space_handle_t,
133		    bus_size_t, const u_int16_t *, bus_size_t);
134void		__C(CHIP,_io_write_region_4)(void *, bus_space_handle_t,
135		    bus_size_t, const u_int32_t *, bus_size_t);
136void		__C(CHIP,_io_write_region_8)(void *, bus_space_handle_t,
137		    bus_size_t, const u_int64_t *, bus_size_t);
138
139/* set multiple */
140void		__C(CHIP,_io_set_multi_1)(void *, bus_space_handle_t,
141		    bus_size_t, u_int8_t, bus_size_t);
142void		__C(CHIP,_io_set_multi_2)(void *, bus_space_handle_t,
143		    bus_size_t, u_int16_t, bus_size_t);
144void		__C(CHIP,_io_set_multi_4)(void *, bus_space_handle_t,
145		    bus_size_t, u_int32_t, bus_size_t);
146void		__C(CHIP,_io_set_multi_8)(void *, bus_space_handle_t,
147		    bus_size_t, u_int64_t, bus_size_t);
148
149/* set region */
150void		__C(CHIP,_io_set_region_1)(void *, bus_space_handle_t,
151		    bus_size_t, u_int8_t, bus_size_t);
152void		__C(CHIP,_io_set_region_2)(void *, bus_space_handle_t,
153		    bus_size_t, u_int16_t, bus_size_t);
154void		__C(CHIP,_io_set_region_4)(void *, bus_space_handle_t,
155		    bus_size_t, u_int32_t, bus_size_t);
156void		__C(CHIP,_io_set_region_8)(void *, bus_space_handle_t,
157		    bus_size_t, u_int64_t, bus_size_t);
158
159/* copy */
160void		__C(CHIP,_io_copy_1)(void *, bus_space_handle_t,
161		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
162void		__C(CHIP,_io_copy_2)(void *, bus_space_handle_t,
163		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
164void		__C(CHIP,_io_copy_4)(void *, bus_space_handle_t,
165		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
166void		__C(CHIP,_io_copy_8)(void *, bus_space_handle_t,
167		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
168
169/* read multiple raw */
170void		__C(CHIP,_io_read_raw_multi_2)(void *, bus_space_handle_t,
171		    bus_size_t, u_int8_t *, bus_size_t);
172void		__C(CHIP,_io_read_raw_multi_4)(void *, bus_space_handle_t,
173		    bus_size_t, u_int8_t *, bus_size_t);
174void		__C(CHIP,_io_read_raw_multi_8)(void *, bus_space_handle_t,
175		    bus_size_t, u_int8_t *, bus_size_t);
176
177/* write multiple raw */
178void		__C(CHIP,_io_write_raw_multi_2)(void *,
179		    bus_space_handle_t, bus_size_t, const u_int8_t *,
180		    bus_size_t);
181void		__C(CHIP,_io_write_raw_multi_4)(void *,
182		    bus_space_handle_t, bus_size_t, const u_int8_t *,
183		    bus_size_t);
184void		__C(CHIP,_io_write_raw_multi_8)(void *,
185		    bus_space_handle_t, bus_size_t, const u_int8_t *,
186		    bus_size_t);
187
188void
189__C(CHIP,_bus_io_init)(t, v)
190	bus_space_tag_t t;
191	void *v;
192{
193	struct extent *ex;
194
195	/*
196	 * Initialize the bus space tag.
197	 */
198
199	/* cookie */
200	t->abs_cookie =		v;
201
202	/* mapping/unmapping */
203	t->abs_map =		__C(CHIP,_io_map);
204	t->abs_unmap =		__C(CHIP,_io_unmap);
205	t->abs_subregion =	__C(CHIP,_io_subregion);
206
207	/* allocation/deallocation */
208	t->abs_alloc =		__C(CHIP,_io_alloc);
209	t->abs_free = 		__C(CHIP,_io_free);
210
211	/* get kernel virtual address */
212	t->abs_vaddr =		__C(CHIP,_io_vaddr);
213
214	/* barrier */
215	t->abs_barrier =	__C(CHIP,_io_barrier);
216
217	/* read (single) */
218	t->abs_r_1 =		__C(CHIP,_io_read_1);
219	t->abs_r_2 =		__C(CHIP,_io_read_2);
220	t->abs_r_4 =		__C(CHIP,_io_read_4);
221	t->abs_r_8 =		__C(CHIP,_io_read_8);
222
223	/* read multiple */
224	t->abs_rm_1 =		__C(CHIP,_io_read_multi_1);
225	t->abs_rm_2 =		__C(CHIP,_io_read_multi_2);
226	t->abs_rm_4 =		__C(CHIP,_io_read_multi_4);
227	t->abs_rm_8 =		__C(CHIP,_io_read_multi_8);
228
229	/* read region */
230	t->abs_rr_1 =		__C(CHIP,_io_read_region_1);
231	t->abs_rr_2 =		__C(CHIP,_io_read_region_2);
232	t->abs_rr_4 =		__C(CHIP,_io_read_region_4);
233	t->abs_rr_8 =		__C(CHIP,_io_read_region_8);
234
235	/* write (single) */
236	t->abs_w_1 =		__C(CHIP,_io_write_1);
237	t->abs_w_2 =		__C(CHIP,_io_write_2);
238	t->abs_w_4 =		__C(CHIP,_io_write_4);
239	t->abs_w_8 =		__C(CHIP,_io_write_8);
240
241	/* write multiple */
242	t->abs_wm_1 =		__C(CHIP,_io_write_multi_1);
243	t->abs_wm_2 =		__C(CHIP,_io_write_multi_2);
244	t->abs_wm_4 =		__C(CHIP,_io_write_multi_4);
245	t->abs_wm_8 =		__C(CHIP,_io_write_multi_8);
246
247	/* write region */
248	t->abs_wr_1 =		__C(CHIP,_io_write_region_1);
249	t->abs_wr_2 =		__C(CHIP,_io_write_region_2);
250	t->abs_wr_4 =		__C(CHIP,_io_write_region_4);
251	t->abs_wr_8 =		__C(CHIP,_io_write_region_8);
252
253	/* set multiple */
254	t->abs_sm_1 =		__C(CHIP,_io_set_multi_1);
255	t->abs_sm_2 =		__C(CHIP,_io_set_multi_2);
256	t->abs_sm_4 =		__C(CHIP,_io_set_multi_4);
257	t->abs_sm_8 =		__C(CHIP,_io_set_multi_8);
258
259	/* set region */
260	t->abs_sr_1 =		__C(CHIP,_io_set_region_1);
261	t->abs_sr_2 =		__C(CHIP,_io_set_region_2);
262	t->abs_sr_4 =		__C(CHIP,_io_set_region_4);
263	t->abs_sr_8 =		__C(CHIP,_io_set_region_8);
264
265	/* copy */
266	t->abs_c_1 =		__C(CHIP,_io_copy_1);
267	t->abs_c_2 =		__C(CHIP,_io_copy_2);
268	t->abs_c_4 =		__C(CHIP,_io_copy_4);
269	t->abs_c_8 =		__C(CHIP,_io_copy_8);
270
271	/* read multiple raw */
272	t->abs_rrm_2 =		__C(CHIP,_io_read_raw_multi_2);
273	t->abs_rrm_4 =		__C(CHIP,_io_read_raw_multi_4);
274	t->abs_rrm_8 =		__C(CHIP,_io_read_raw_multi_8);
275
276	/* write multiple raw*/
277	t->abs_wrm_2 =		__C(CHIP,_io_write_raw_multi_2);
278	t->abs_wrm_4 =		__C(CHIP,_io_write_raw_multi_4);
279	t->abs_wrm_8 =		__C(CHIP,_io_write_raw_multi_8);
280
281	ex = extent_create(CHIP_EXTENT_NAME(v), 0x0UL, 0xffffffffUL,
282	    M_DEVBUF, (caddr_t)CHIP_EXTENT_STORAGE(v),
283	    sizeof(CHIP_EXTENT_STORAGE(v)), EX_NOWAIT|EX_NOCOALESCE);
284
285	CHIP_IO_EXTENT(v) = ex;
286}
287
288int
289__C(CHIP,_io_map)(v, ioaddr, iosize, flags, iohp)
290	void *v;
291	bus_addr_t ioaddr;
292	bus_size_t iosize;
293	int flags;
294	bus_space_handle_t *iohp;
295{
296	int error;
297
298	/*
299	 * Can't map i/o space linearly.
300	 */
301	if (flags & BUS_SPACE_MAP_LINEAR)
302		return (EOPNOTSUPP);
303
304#ifdef EXTENT_DEBUG
305	printf("io: allocating 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1);
306#endif
307        error = extent_alloc_region(CHIP_IO_EXTENT(v), ioaddr, iosize,
308            EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
309	if (error) {
310#ifdef EXTENT_DEBUG
311		printf("io: allocation failed (%d)\n", error);
312		extent_print(CHIP_IO_EXTENT(v));
313#endif
314		return (error);
315	}
316
317	*iohp = ALPHA_PHYS_TO_K0SEG(CHIP_IO_SYS_START(v)) + ioaddr;
318
319	return (0);
320}
321
322void
323__C(CHIP,_io_unmap)(v, ioh, iosize)
324	void *v;
325	bus_space_handle_t ioh;
326	bus_size_t iosize;
327{
328	bus_addr_t ioaddr;
329	int error;
330
331#ifdef EXTENT_DEBUG
332	printf("io: freeing handle 0x%lx for 0x%lx\n", ioh, iosize);
333#endif
334
335	ioaddr = ioh - ALPHA_PHYS_TO_K0SEG(CHIP_IO_SYS_START(v));
336
337#ifdef EXTENT_DEBUG
338	printf("io: freeing 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1);
339#endif
340        error = extent_free(CHIP_IO_EXTENT(v), ioaddr, iosize,
341            EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
342	if (error) {
343		printf("%s: WARNING: could not unmap 0x%lx-0x%lx (error %d)\n",
344		   __S(__C(CHIP,_io_unmap)), ioaddr, ioaddr + iosize - 1,
345		   error);
346#ifdef EXTENT_DEBUG
347		extent_print(CHIP_IO_EXTENT(v));
348#endif
349	}
350}
351
352int
353__C(CHIP,_io_subregion)(v, ioh, offset, size, nioh)
354	void *v;
355	bus_space_handle_t ioh, *nioh;
356	bus_size_t offset, size;
357{
358
359	*nioh = ioh + offset;
360	return (0);
361}
362
363int
364__C(CHIP,_io_alloc)(v, rstart, rend, size, align, boundary, flags,
365    addrp, bshp)
366	void *v;
367	bus_addr_t rstart, rend, *addrp;
368	bus_size_t size, align, boundary;
369	int flags;
370	bus_space_handle_t *bshp;
371{
372
373	/* XXX XXX XXX XXX XXX XXX */
374	panic("%s not implemented", __S(__C(CHIP,_io_alloc)));
375}
376
377void
378__C(CHIP,_io_free)(v, bsh, size)
379	void *v;
380	bus_space_handle_t bsh;
381	bus_size_t size;
382{
383
384	/* XXX XXX XXX XXX XXX XXX */
385	panic("%s not implemented", __S(__C(CHIP,_io_free)));
386}
387
388void *
389__C(CHIP,_io_vaddr)(v, bsh)
390	void *v;
391	bus_space_handle_t bsh;
392{
393	/*
394	 * _io_map() catches BUS_SPACE_MAP_LINEAR,
395	 * so we shouldn't get here
396	 */
397	panic("_io_vaddr");
398}
399
400inline void
401__C(CHIP,_io_barrier)(v, h, o, l, f)
402	void *v;
403	bus_space_handle_t h;
404	bus_size_t o, l;
405	int f;
406{
407
408	if ((f & BUS_SPACE_BARRIER_READ) != 0)
409		alpha_mb();
410	else if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
411		alpha_wmb();
412}
413
414inline u_int8_t
415__C(CHIP,_io_read_1)(v, ioh, off)
416	void *v;
417	bus_space_handle_t ioh;
418	bus_size_t off;
419{
420	bus_addr_t addr;
421
422	addr = ioh + off;
423	alpha_mb();
424	return (alpha_ldbu((u_int8_t *)addr));
425}
426
427inline u_int16_t
428__C(CHIP,_io_read_2)(v, ioh, off)
429	void *v;
430	bus_space_handle_t ioh;
431	bus_size_t off;
432{
433	bus_addr_t addr;
434
435	addr = ioh + off;
436#ifdef DIAGNOSTIC
437	if (addr & 1)
438		panic(__S(__C(CHIP,_io_read_2)) ": addr 0x%lx not aligned",
439		    addr);
440#endif
441	alpha_mb();
442	return (alpha_ldwu((u_int16_t *)addr));
443}
444
445inline u_int32_t
446__C(CHIP,_io_read_4)(v, ioh, off)
447	void *v;
448	bus_space_handle_t ioh;
449	bus_size_t off;
450{
451	bus_addr_t addr;
452
453	addr = ioh + off;
454#ifdef DIAGNOSTIC
455	if (addr & 3)
456		panic(__S(__C(CHIP,_io_read_4)) ": addr 0x%lx not aligned",
457		    addr);
458#endif
459	alpha_mb();
460	return (*(u_int32_t *)addr);
461}
462
463inline u_int64_t
464__C(CHIP,_io_read_8)(v, ioh, off)
465	void *v;
466	bus_space_handle_t ioh;
467	bus_size_t off;
468{
469
470	/* XXX XXX XXX */
471	panic("%s not implemented", __S(__C(CHIP,_io_read_8)));
472}
473
474#define CHIP_io_read_multi_N(BYTES,TYPE)				\
475void									\
476__C(__C(CHIP,_io_read_multi_),BYTES)(v, h, o, a, c)			\
477	void *v;							\
478	bus_space_handle_t h;						\
479	bus_size_t o, c;						\
480	TYPE *a;							\
481{									\
482									\
483	while (c-- > 0) {						\
484		__C(CHIP,_io_barrier)(v, h, o, sizeof *a,		\
485		    BUS_SPACE_BARRIER_READ);				\
486		*a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o);		\
487	}								\
488}
489CHIP_io_read_multi_N(1,u_int8_t)
490CHIP_io_read_multi_N(2,u_int16_t)
491CHIP_io_read_multi_N(4,u_int32_t)
492CHIP_io_read_multi_N(8,u_int64_t)
493
494#define CHIP_io_read_region_N(BYTES,TYPE)				\
495void									\
496__C(__C(CHIP,_io_read_region_),BYTES)(v, h, o, a, c)			\
497	void *v;							\
498	bus_space_handle_t h;						\
499	bus_size_t o, c;						\
500	TYPE *a;							\
501{									\
502									\
503	while (c-- > 0) {						\
504		*a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o);		\
505		o += sizeof *a;						\
506	}								\
507}
508CHIP_io_read_region_N(1,u_int8_t)
509CHIP_io_read_region_N(2,u_int16_t)
510CHIP_io_read_region_N(4,u_int32_t)
511CHIP_io_read_region_N(8,u_int64_t)
512
513inline void
514__C(CHIP,_io_write_1)(v, ioh, off, val)
515	void *v;
516	bus_space_handle_t ioh;
517	bus_size_t off;
518	u_int8_t val;
519{
520	bus_addr_t addr;
521
522	addr = ioh + off;
523	alpha_stb((u_int8_t *)addr, val);
524        alpha_mb();
525}
526
527inline void
528__C(CHIP,_io_write_2)(v, ioh, off, val)
529	void *v;
530	bus_space_handle_t ioh;
531	bus_size_t off;
532	u_int16_t val;
533{
534	bus_addr_t addr;
535
536	addr = ioh + off;
537#ifdef DIAGNOSTIC
538	if (addr & 1)
539		panic(__S(__C(CHIP,_io_write_2)) ": addr 0x%lx not aligned",
540		    addr);
541#endif
542	alpha_stw((u_int16_t *)addr, val);
543	alpha_mb();
544}
545
546inline void
547__C(CHIP,_io_write_4)(v, ioh, off, val)
548	void *v;
549	bus_space_handle_t ioh;
550	bus_size_t off;
551	u_int32_t val;
552{
553	bus_addr_t addr;
554
555	addr = ioh + off;
556#ifdef DIAGNOSTIC
557	if (addr & 3)
558		panic(__S(__C(CHIP,_io_write_4)) ": addr 0x%lx not aligned",
559		    addr);
560#endif
561	*(u_int32_t *)addr = val;
562	alpha_mb();
563}
564
565inline void
566__C(CHIP,_io_write_8)(v, ioh, off, val)
567	void *v;
568	bus_space_handle_t ioh;
569	bus_size_t off;
570	u_int64_t val;
571{
572
573	/* XXX XXX XXX */
574	panic("%s not implemented", __S(__C(CHIP,_io_write_8)));
575	alpha_mb();
576}
577
578#define CHIP_io_write_multi_N(BYTES,TYPE)				\
579void									\
580__C(__C(CHIP,_io_write_multi_),BYTES)(v, h, o, a, c)			\
581	void *v;							\
582	bus_space_handle_t h;						\
583	bus_size_t o, c;						\
584	const TYPE *a;							\
585{									\
586									\
587	while (c-- > 0) {						\
588		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++);		\
589		__C(CHIP,_io_barrier)(v, h, o, sizeof *a,		\
590		    BUS_SPACE_BARRIER_WRITE);				\
591	}								\
592}
593CHIP_io_write_multi_N(1,u_int8_t)
594CHIP_io_write_multi_N(2,u_int16_t)
595CHIP_io_write_multi_N(4,u_int32_t)
596CHIP_io_write_multi_N(8,u_int64_t)
597
598#define CHIP_io_write_region_N(BYTES,TYPE)				\
599void									\
600__C(__C(CHIP,_io_write_region_),BYTES)(v, h, o, a, c)			\
601	void *v;							\
602	bus_space_handle_t h;						\
603	bus_size_t o, c;						\
604	const TYPE *a;							\
605{									\
606									\
607	while (c-- > 0) {						\
608		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++);		\
609		o += sizeof *a;						\
610	}								\
611}
612CHIP_io_write_region_N(1,u_int8_t)
613CHIP_io_write_region_N(2,u_int16_t)
614CHIP_io_write_region_N(4,u_int32_t)
615CHIP_io_write_region_N(8,u_int64_t)
616
617#define CHIP_io_set_multi_N(BYTES,TYPE)					\
618void									\
619__C(__C(CHIP,_io_set_multi_),BYTES)(v, h, o, val, c)			\
620	void *v;							\
621	bus_space_handle_t h;						\
622	bus_size_t o, c;						\
623	TYPE val;							\
624{									\
625									\
626	while (c-- > 0) {						\
627		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, val);		\
628		__C(CHIP,_io_barrier)(v, h, o, sizeof val,		\
629		    BUS_SPACE_BARRIER_WRITE);				\
630	}								\
631}
632CHIP_io_set_multi_N(1,u_int8_t)
633CHIP_io_set_multi_N(2,u_int16_t)
634CHIP_io_set_multi_N(4,u_int32_t)
635CHIP_io_set_multi_N(8,u_int64_t)
636
637#define CHIP_io_set_region_N(BYTES,TYPE)				\
638void									\
639__C(__C(CHIP,_io_set_region_),BYTES)(v, h, o, val, c)			\
640	void *v;							\
641	bus_space_handle_t h;						\
642	bus_size_t o, c;						\
643	TYPE val;							\
644{									\
645									\
646	while (c-- > 0) {						\
647		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, val);		\
648		o += sizeof val;					\
649	}								\
650}
651CHIP_io_set_region_N(1,u_int8_t)
652CHIP_io_set_region_N(2,u_int16_t)
653CHIP_io_set_region_N(4,u_int32_t)
654CHIP_io_set_region_N(8,u_int64_t)
655
656#define	CHIP_io_copy_N(BYTES)						\
657void									\
658__C(__C(CHIP,_io_copy_),BYTES)(v, h1, o1, h2, o2, c)			\
659	void *v;							\
660	bus_space_handle_t h1, h2;					\
661	bus_size_t o1, o2, c;						\
662{									\
663	bus_size_t i, o;						\
664									\
665	for (i = 0, o = 0; i < c; i++, o += BYTES)			\
666		__C(__C(CHIP,_io_write_),BYTES)(v, h2, o2 + o,		\
667		    __C(__C(CHIP,_io_read_),BYTES)(v, h1, o1 + o));	\
668}
669CHIP_io_copy_N(1)
670CHIP_io_copy_N(2)
671CHIP_io_copy_N(4)
672CHIP_io_copy_N(8)
673
674#define CHIP_io_read_raw_multi_N(BYTES,TYPE)				\
675void									\
676__C(__C(CHIP,_io_read_raw_multi_),BYTES)(v, h, o, a, c)			\
677	void *v;							\
678	bus_space_handle_t h;						\
679	bus_size_t o, c;						\
680	u_int8_t *a;							\
681{									\
682	TYPE temp;							\
683	int i;								\
684									\
685	while (c > 0) {							\
686		__C(CHIP,_io_barrier)(v, h, o, BYTES,			\
687		    BUS_SPACE_BARRIER_READ);				\
688		temp = __C(__C(CHIP,_io_read_),BYTES)(v, h, o);		\
689		i = MIN(c, BYTES);					\
690		c -= i;							\
691		while (i--) {						\
692			*a++ = temp & 0xff;				\
693			temp >>= 8;					\
694		}							\
695	}								\
696}
697CHIP_io_read_raw_multi_N(2,u_int16_t)
698CHIP_io_read_raw_multi_N(4,u_int32_t)
699CHIP_io_read_raw_multi_N(8,u_int64_t)
700
701#define CHIP_io_write_raw_multi_N(BYTES,TYPE)				\
702void									\
703__C(__C(CHIP,_io_write_raw_multi_),BYTES)(v, h, o, a, c)		\
704	void *v;							\
705	bus_space_handle_t h;						\
706	bus_size_t o, c;						\
707	const u_int8_t *a;						\
708{									\
709	TYPE temp;							\
710	int i;								\
711									\
712	while (c > 0) {							\
713		temp = 0;						\
714		for (i = BYTES - 1; i >= 0; i--) {			\
715			temp <<= 8;					\
716			if (i < c)					\
717				temp |= *(a + i);			\
718		}							\
719		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, temp);		\
720		__C(CHIP,_io_barrier)(v, h, o, BYTES,			\
721		    BUS_SPACE_BARRIER_WRITE);				\
722		i = MIN(c, BYTES); 					\
723		c -= i;							\
724		a += i;							\
725	}								\
726}
727CHIP_io_write_raw_multi_N(2,u_int16_t)
728CHIP_io_write_raw_multi_N(4,u_int32_t)
729CHIP_io_write_raw_multi_N(8,u_int64_t)
730