xref: /netbsd-src/sys/arch/alpha/pci/pci_swiz_bus_io_chipdep.c (revision 63aea4bd5b445e491ff0389fe27ec78b3099dba3)
1 /* $NetBSD: pci_swiz_bus_io_chipdep.c,v 1.42 2013/11/04 16:58:33 christos 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.42 2013/11/04 16:58:33 christos 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 */
87 int		__C(CHIP,_io_map)(void *, bus_addr_t, bus_size_t, int,
88 		    bus_space_handle_t *, int);
89 void		__C(CHIP,_io_unmap)(void *, bus_space_handle_t,
90 		    bus_size_t, int);
91 int		__C(CHIP,_io_subregion)(void *, bus_space_handle_t,
92 		    bus_size_t, bus_size_t, bus_space_handle_t *);
93 
94 int		__C(CHIP,_io_translate)(void *, bus_addr_t, bus_size_t,
95 		    int, struct alpha_bus_space_translation *);
96 int		__C(CHIP,_io_get_window)(void *, int,
97 		    struct alpha_bus_space_translation *);
98 
99 /* allocation/deallocation */
100 int		__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 *);
103 void		__C(CHIP,_io_free)(void *, bus_space_handle_t,
104 		    bus_size_t);
105 
106 /* get kernel virtual address */
107 void *		__C(CHIP,_io_vaddr)(void *, bus_space_handle_t);
108 
109 /* mmap for user */
110 paddr_t		__C(CHIP,_io_mmap)(void *, bus_addr_t, off_t, int, int);
111 
112 /* barrier */
113 static inline void	__C(CHIP,_io_barrier)(void *, bus_space_handle_t,
114 		    bus_size_t, bus_size_t, int);
115 
116 /* read (single) */
117 static inline uint8_t	__C(CHIP,_io_read_1)(void *, bus_space_handle_t,
118 		    bus_size_t);
119 static inline uint16_t __C(CHIP,_io_read_2)(void *, bus_space_handle_t,
120 		    bus_size_t);
121 static inline uint32_t __C(CHIP,_io_read_4)(void *, bus_space_handle_t,
122 		    bus_size_t);
123 static inline uint64_t __C(CHIP,_io_read_8)(void *, bus_space_handle_t,
124 		    bus_size_t);
125 
126 /* read multiple */
127 void		__C(CHIP,_io_read_multi_1)(void *, bus_space_handle_t,
128 		    bus_size_t, uint8_t *, bus_size_t);
129 void		__C(CHIP,_io_read_multi_2)(void *, bus_space_handle_t,
130 		    bus_size_t, uint16_t *, bus_size_t);
131 void		__C(CHIP,_io_read_multi_4)(void *, bus_space_handle_t,
132 		    bus_size_t, uint32_t *, bus_size_t);
133 void		__C(CHIP,_io_read_multi_8)(void *, bus_space_handle_t,
134 		    bus_size_t, uint64_t *, bus_size_t);
135 
136 /* read region */
137 void		__C(CHIP,_io_read_region_1)(void *, bus_space_handle_t,
138 		    bus_size_t, uint8_t *, bus_size_t);
139 void		__C(CHIP,_io_read_region_2)(void *, bus_space_handle_t,
140 		    bus_size_t, uint16_t *, bus_size_t);
141 void		__C(CHIP,_io_read_region_4)(void *, bus_space_handle_t,
142 		    bus_size_t, uint32_t *, bus_size_t);
143 void		__C(CHIP,_io_read_region_8)(void *, bus_space_handle_t,
144 		    bus_size_t, uint64_t *, bus_size_t);
145 
146 /* write (single) */
147 static inline void	__C(CHIP,_io_write_1)(void *, bus_space_handle_t,
148 		    bus_size_t, uint8_t);
149 static inline void	__C(CHIP,_io_write_2)(void *, bus_space_handle_t,
150 		    bus_size_t, uint16_t);
151 static inline void	__C(CHIP,_io_write_4)(void *, bus_space_handle_t,
152 		    bus_size_t, uint32_t);
153 static inline void	__C(CHIP,_io_write_8)(void *, bus_space_handle_t,
154 		    bus_size_t, uint64_t);
155 
156 /* write multiple */
157 void		__C(CHIP,_io_write_multi_1)(void *, bus_space_handle_t,
158 		    bus_size_t, const uint8_t *, bus_size_t);
159 void		__C(CHIP,_io_write_multi_2)(void *, bus_space_handle_t,
160 		    bus_size_t, const uint16_t *, bus_size_t);
161 void		__C(CHIP,_io_write_multi_4)(void *, bus_space_handle_t,
162 		    bus_size_t, const uint32_t *, bus_size_t);
163 void		__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 */
167 void		__C(CHIP,_io_write_region_1)(void *, bus_space_handle_t,
168 		    bus_size_t, const uint8_t *, bus_size_t);
169 void		__C(CHIP,_io_write_region_2)(void *, bus_space_handle_t,
170 		    bus_size_t, const uint16_t *, bus_size_t);
171 void		__C(CHIP,_io_write_region_4)(void *, bus_space_handle_t,
172 		    bus_size_t, const uint32_t *, bus_size_t);
173 void		__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 */
177 void		__C(CHIP,_io_set_multi_1)(void *, bus_space_handle_t,
178 		    bus_size_t, uint8_t, bus_size_t);
179 void		__C(CHIP,_io_set_multi_2)(void *, bus_space_handle_t,
180 		    bus_size_t, uint16_t, bus_size_t);
181 void		__C(CHIP,_io_set_multi_4)(void *, bus_space_handle_t,
182 		    bus_size_t, uint32_t, bus_size_t);
183 void		__C(CHIP,_io_set_multi_8)(void *, bus_space_handle_t,
184 		    bus_size_t, uint64_t, bus_size_t);
185 
186 /* set region */
187 void		__C(CHIP,_io_set_region_1)(void *, bus_space_handle_t,
188 		    bus_size_t, uint8_t, bus_size_t);
189 void		__C(CHIP,_io_set_region_2)(void *, bus_space_handle_t,
190 		    bus_size_t, uint16_t, bus_size_t);
191 void		__C(CHIP,_io_set_region_4)(void *, bus_space_handle_t,
192 		    bus_size_t, uint32_t, bus_size_t);
193 void		__C(CHIP,_io_set_region_8)(void *, bus_space_handle_t,
194 		    bus_size_t, uint64_t, bus_size_t);
195 
196 /* copy */
197 void		__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);
199 void		__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);
201 void		__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);
203 void		__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
207 static 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 
221 void
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 
337 int
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 
379 int
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 
417 int
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 
454 void
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 
515 int
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 
524 int
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 
576 void
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 
584 void *
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 
594 paddr_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 
602 static 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 
613 static 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 
633 static 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 
653 static 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 
660 	alpha_mb();
661 
662 	tmpioh = ioh + off;
663 	port = (uint32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
664 	    (3 << CHIP_SIZE_SHIFT));
665 	val = *port;
666 #if 0
667 	int offset = tmpioh & 3;
668 	rval = ((val) >> (8 * offset)) & 0xffffffff;
669 #else
670 	rval = val;
671 #endif
672 
673 	return rval;
674 }
675 
676 static inline uint64_t
677 __C(CHIP,_io_read_8)(void *v, bus_space_handle_t ioh, bus_size_t off)
678 {
679 
680 	/* XXX XXX XXX */
681 	panic("%s not implemented", __S(__C(CHIP,_io_read_8)));
682 }
683 
684 #define CHIP_io_read_multi_N(BYTES,TYPE)				\
685 void									\
686 __C(__C(CHIP,_io_read_multi_),BYTES)(void *v, bus_space_handle_t h, bus_size_t o, TYPE *a, bus_size_t c)			\
687 {									\
688 									\
689 	while (c-- > 0) {						\
690 		__C(CHIP,_io_barrier)(v, h, o, sizeof *a,		\
691 		    BUS_SPACE_BARRIER_READ);				\
692 		*a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o);		\
693 	}								\
694 }
695 CHIP_io_read_multi_N(1,uint8_t)
696 CHIP_io_read_multi_N(2,uint16_t)
697 CHIP_io_read_multi_N(4,uint32_t)
698 CHIP_io_read_multi_N(8,uint64_t)
699 
700 #define CHIP_io_read_region_N(BYTES,TYPE)				\
701 void									\
702 __C(__C(CHIP,_io_read_region_),BYTES)(void *v, bus_space_handle_t h, bus_size_t o, TYPE *a, bus_size_t c)			\
703 {									\
704 									\
705 	while (c-- > 0) {						\
706 		*a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o);		\
707 		o += sizeof *a;						\
708 	}								\
709 }
710 CHIP_io_read_region_N(1,uint8_t)
711 CHIP_io_read_region_N(2,uint16_t)
712 CHIP_io_read_region_N(4,uint32_t)
713 CHIP_io_read_region_N(8,uint64_t)
714 
715 static inline void
716 __C(CHIP,_io_write_1)(void *v, bus_space_handle_t ioh,
717     bus_size_t off, uint8_t val)
718 {
719 	register bus_space_handle_t tmpioh;
720 	register uint32_t *port, nval;
721 	register int offset;
722 
723 	tmpioh = ioh + off;
724 	offset = tmpioh & 3;
725 	nval = val << (8 * offset);
726 	port = (uint32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
727 	    (0 << CHIP_SIZE_SHIFT));
728 	*port = nval;
729 	alpha_mb();
730 }
731 
732 static inline void
733 __C(CHIP,_io_write_2)(void *v, bus_space_handle_t ioh,
734     bus_size_t off, uint16_t val)
735 {
736 	register bus_space_handle_t tmpioh;
737 	register uint32_t *port, nval;
738 	register int offset;
739 
740 	tmpioh = ioh + off;
741 	offset = tmpioh & 3;
742 	nval = val << (8 * offset);
743 	port = (uint32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
744 	    (1 << CHIP_SIZE_SHIFT));
745 	*port = nval;
746 	alpha_mb();
747 }
748 
749 static inline void
750 __C(CHIP,_io_write_4)(void *v, bus_space_handle_t ioh,
751     bus_size_t off, uint32_t val)
752 {
753 	register bus_space_handle_t tmpioh;
754 	register uint32_t *port, nval;
755 
756 	tmpioh = ioh + off;
757 #if 0
758 	register int offset;
759 	offset = tmpioh & 3;
760 #endif
761 	nval = val /*<< (8 * offset)*/;
762 	port = (uint32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
763 	    (3 << CHIP_SIZE_SHIFT));
764 	*port = nval;
765 	alpha_mb();
766 }
767 
768 static inline void
769 __C(CHIP,_io_write_8)(void *v, bus_space_handle_t ioh,
770     bus_size_t off, uint64_t val)
771 {
772 
773 	/* XXX XXX XXX */
774 	panic("%s not implemented", __S(__C(CHIP,_io_write_8)));
775 	alpha_mb();
776 }
777 
778 #define CHIP_io_write_multi_N(BYTES,TYPE)				\
779 void									\
780 __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)			\
781 {									\
782 									\
783 	while (c-- > 0) {						\
784 		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++);		\
785 		__C(CHIP,_io_barrier)(v, h, o, sizeof *a,		\
786 		    BUS_SPACE_BARRIER_WRITE);				\
787 	}								\
788 }
789 CHIP_io_write_multi_N(1,uint8_t)
790 CHIP_io_write_multi_N(2,uint16_t)
791 CHIP_io_write_multi_N(4,uint32_t)
792 CHIP_io_write_multi_N(8,uint64_t)
793 
794 #define CHIP_io_write_region_N(BYTES,TYPE)				\
795 void									\
796 __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)			\
797 {									\
798 									\
799 	while (c-- > 0) {						\
800 		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++);		\
801 		o += sizeof *a;						\
802 	}								\
803 }
804 CHIP_io_write_region_N(1,uint8_t)
805 CHIP_io_write_region_N(2,uint16_t)
806 CHIP_io_write_region_N(4,uint32_t)
807 CHIP_io_write_region_N(8,uint64_t)
808 
809 #define CHIP_io_set_multi_N(BYTES,TYPE)					\
810 void									\
811 __C(__C(CHIP,_io_set_multi_),BYTES)(void *v, bus_space_handle_t h, bus_size_t o, TYPE val, bus_size_t c)			\
812 {									\
813 									\
814 	while (c-- > 0) {						\
815 		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, val);		\
816 		__C(CHIP,_io_barrier)(v, h, o, sizeof val,		\
817 		    BUS_SPACE_BARRIER_WRITE);				\
818 	}								\
819 }
820 CHIP_io_set_multi_N(1,uint8_t)
821 CHIP_io_set_multi_N(2,uint16_t)
822 CHIP_io_set_multi_N(4,uint32_t)
823 CHIP_io_set_multi_N(8,uint64_t)
824 
825 #define CHIP_io_set_region_N(BYTES,TYPE)				\
826 void									\
827 __C(__C(CHIP,_io_set_region_),BYTES)(void *v, bus_space_handle_t h, bus_size_t o, TYPE val, bus_size_t c)			\
828 {									\
829 									\
830 	while (c-- > 0) {						\
831 		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, val);		\
832 		o += sizeof val;					\
833 	}								\
834 }
835 CHIP_io_set_region_N(1,uint8_t)
836 CHIP_io_set_region_N(2,uint16_t)
837 CHIP_io_set_region_N(4,uint32_t)
838 CHIP_io_set_region_N(8,uint64_t)
839 
840 #define	CHIP_io_copy_region_N(BYTES)					\
841 void									\
842 __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)		\
843 {									\
844 	bus_size_t o;							\
845 									\
846 	if ((h1 + o1) >= (h2 + o2)) {					\
847 		/* src after dest: copy forward */			\
848 		for (o = 0; c != 0; c--, o += BYTES)			\
849 			__C(__C(CHIP,_io_write_),BYTES)(v, h2, o2 + o,	\
850 			    __C(__C(CHIP,_io_read_),BYTES)(v, h1, o1 + o)); \
851 	} else {							\
852 		/* dest after src: copy backwards */			\
853 		for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES)	\
854 			__C(__C(CHIP,_io_write_),BYTES)(v, h2, o2 + o,	\
855 			    __C(__C(CHIP,_io_read_),BYTES)(v, h1, o1 + o)); \
856 	}								\
857 }
858 CHIP_io_copy_region_N(1)
859 CHIP_io_copy_region_N(2)
860 CHIP_io_copy_region_N(4)
861 CHIP_io_copy_region_N(8)
862