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