1 /* $NetBSD: pci_swiz_bus_io_chipdep.c,v 1.32 2001/09/04 05:31:28 thorpej 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  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 /*
41  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
42  * All rights reserved.
43  *
44  * Author: Chris G. Demetriou
45  *
46  * Permission to use, copy, modify and distribute this software and
47  * its documentation is hereby granted, provided that both the copyright
48  * notice and this permission notice appear in all copies of the
49  * software, derivative works or modified versions, and any portions
50  * thereof, and that both notices appear in supporting documentation.
51  *
52  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
53  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
54  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
55  *
56  * Carnegie Mellon requests users of this software to return to
57  *
58  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
59  *  School of Computer Science
60  *  Carnegie Mellon University
61  *  Pittsburgh PA 15213-3890
62  *
63  * any improvements or extensions that they make and grant Carnegie the
64  * rights to redistribute these changes.
65  */
66 
67 /*
68  * Common PCI Chipset "bus I/O" functions, for chipsets which have to
69  * deal with only a single PCI interface chip in a machine.
70  *
71  * uses:
72  *	CHIP		name of the 'chip' it's being compiled for.
73  *	CHIP_IO_BASE	Sparse I/O space base to use.
74  *	CHIP_IO_EX_STORE
75  *			If defined, device-provided static storage area
76  *			for the I/O space extent.  If this is defined,
77  *			CHIP_IO_EX_STORE_SIZE must also be defined.  If
78  *			this is not defined, a static area will be
79  *			declared.
80  *	CHIP_IO_EX_STORE_SIZE
81  *			Size of the device-provided static storage area
82  *			for the I/O memory space extent.
83  */
84 
85 #include <sys/extent.h>
86 
87 #define	__C(A,B)	__CONCAT(A,B)
88 #define	__S(S)		__STRING(S)
89 
90 /* mapping/unmapping */
91 int		__C(CHIP,_io_map) __P((void *, bus_addr_t, bus_size_t, int,
92 		    bus_space_handle_t *, int));
93 void		__C(CHIP,_io_unmap) __P((void *, bus_space_handle_t,
94 		    bus_size_t, int));
95 int		__C(CHIP,_io_subregion) __P((void *, bus_space_handle_t,
96 		    bus_size_t, bus_size_t, bus_space_handle_t *));
97 
98 int		__C(CHIP,_io_translate) __P((void *, bus_addr_t, bus_size_t,
99 		    int, struct alpha_bus_space_translation *));
100 int		__C(CHIP,_io_get_window) __P((void *, int,
101 		    struct alpha_bus_space_translation *));
102 
103 /* allocation/deallocation */
104 int		__C(CHIP,_io_alloc) __P((void *, bus_addr_t, bus_addr_t,
105 		    bus_size_t, bus_size_t, bus_addr_t, int, bus_addr_t *,
106                     bus_space_handle_t *));
107 void		__C(CHIP,_io_free) __P((void *, bus_space_handle_t,
108 		    bus_size_t));
109 
110 /* get kernel virtual address */
111 void *		__C(CHIP,_io_vaddr) __P((void *, bus_space_handle_t));
112 
113 /* mmap for user */
114 paddr_t		__C(CHIP,_io_mmap) __P((void *, bus_addr_t, off_t, int, int));
115 
116 /* barrier */
117 inline void	__C(CHIP,_io_barrier) __P((void *, bus_space_handle_t,
118 		    bus_size_t, bus_size_t, int));
119 
120 /* read (single) */
121 inline u_int8_t	__C(CHIP,_io_read_1) __P((void *, bus_space_handle_t,
122 		    bus_size_t));
123 inline u_int16_t __C(CHIP,_io_read_2) __P((void *, bus_space_handle_t,
124 		    bus_size_t));
125 inline u_int32_t __C(CHIP,_io_read_4) __P((void *, bus_space_handle_t,
126 		    bus_size_t));
127 inline u_int64_t __C(CHIP,_io_read_8) __P((void *, bus_space_handle_t,
128 		    bus_size_t));
129 
130 /* read multiple */
131 void		__C(CHIP,_io_read_multi_1) __P((void *, bus_space_handle_t,
132 		    bus_size_t, u_int8_t *, bus_size_t));
133 void		__C(CHIP,_io_read_multi_2) __P((void *, bus_space_handle_t,
134 		    bus_size_t, u_int16_t *, bus_size_t));
135 void		__C(CHIP,_io_read_multi_4) __P((void *, bus_space_handle_t,
136 		    bus_size_t, u_int32_t *, bus_size_t));
137 void		__C(CHIP,_io_read_multi_8) __P((void *, bus_space_handle_t,
138 		    bus_size_t, u_int64_t *, bus_size_t));
139 
140 /* read region */
141 void		__C(CHIP,_io_read_region_1) __P((void *, bus_space_handle_t,
142 		    bus_size_t, u_int8_t *, bus_size_t));
143 void		__C(CHIP,_io_read_region_2) __P((void *, bus_space_handle_t,
144 		    bus_size_t, u_int16_t *, bus_size_t));
145 void		__C(CHIP,_io_read_region_4) __P((void *, bus_space_handle_t,
146 		    bus_size_t, u_int32_t *, bus_size_t));
147 void		__C(CHIP,_io_read_region_8) __P((void *, bus_space_handle_t,
148 		    bus_size_t, u_int64_t *, bus_size_t));
149 
150 /* write (single) */
151 inline void	__C(CHIP,_io_write_1) __P((void *, bus_space_handle_t,
152 		    bus_size_t, u_int8_t));
153 inline void	__C(CHIP,_io_write_2) __P((void *, bus_space_handle_t,
154 		    bus_size_t, u_int16_t));
155 inline void	__C(CHIP,_io_write_4) __P((void *, bus_space_handle_t,
156 		    bus_size_t, u_int32_t));
157 inline void	__C(CHIP,_io_write_8) __P((void *, bus_space_handle_t,
158 		    bus_size_t, u_int64_t));
159 
160 /* write multiple */
161 void		__C(CHIP,_io_write_multi_1) __P((void *, bus_space_handle_t,
162 		    bus_size_t, const u_int8_t *, bus_size_t));
163 void		__C(CHIP,_io_write_multi_2) __P((void *, bus_space_handle_t,
164 		    bus_size_t, const u_int16_t *, bus_size_t));
165 void		__C(CHIP,_io_write_multi_4) __P((void *, bus_space_handle_t,
166 		    bus_size_t, const u_int32_t *, bus_size_t));
167 void		__C(CHIP,_io_write_multi_8) __P((void *, bus_space_handle_t,
168 		    bus_size_t, const u_int64_t *, bus_size_t));
169 
170 /* write region */
171 void		__C(CHIP,_io_write_region_1) __P((void *, bus_space_handle_t,
172 		    bus_size_t, const u_int8_t *, bus_size_t));
173 void		__C(CHIP,_io_write_region_2) __P((void *, bus_space_handle_t,
174 		    bus_size_t, const u_int16_t *, bus_size_t));
175 void		__C(CHIP,_io_write_region_4) __P((void *, bus_space_handle_t,
176 		    bus_size_t, const u_int32_t *, bus_size_t));
177 void		__C(CHIP,_io_write_region_8) __P((void *, bus_space_handle_t,
178 		    bus_size_t, const u_int64_t *, bus_size_t));
179 
180 /* set multiple */
181 void		__C(CHIP,_io_set_multi_1) __P((void *, bus_space_handle_t,
182 		    bus_size_t, u_int8_t, bus_size_t));
183 void		__C(CHIP,_io_set_multi_2) __P((void *, bus_space_handle_t,
184 		    bus_size_t, u_int16_t, bus_size_t));
185 void		__C(CHIP,_io_set_multi_4) __P((void *, bus_space_handle_t,
186 		    bus_size_t, u_int32_t, bus_size_t));
187 void		__C(CHIP,_io_set_multi_8) __P((void *, bus_space_handle_t,
188 		    bus_size_t, u_int64_t, bus_size_t));
189 
190 /* set region */
191 void		__C(CHIP,_io_set_region_1) __P((void *, bus_space_handle_t,
192 		    bus_size_t, u_int8_t, bus_size_t));
193 void		__C(CHIP,_io_set_region_2) __P((void *, bus_space_handle_t,
194 		    bus_size_t, u_int16_t, bus_size_t));
195 void		__C(CHIP,_io_set_region_4) __P((void *, bus_space_handle_t,
196 		    bus_size_t, u_int32_t, bus_size_t));
197 void		__C(CHIP,_io_set_region_8) __P((void *, bus_space_handle_t,
198 		    bus_size_t, u_int64_t, bus_size_t));
199 
200 /* copy */
201 void		__C(CHIP,_io_copy_region_1) __P((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_2) __P((void *, bus_space_handle_t,
204 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t));
205 void		__C(CHIP,_io_copy_region_4) __P((void *, bus_space_handle_t,
206 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t));
207 void		__C(CHIP,_io_copy_region_8) __P((void *, bus_space_handle_t,
208 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t));
209 
210 #ifndef	CHIP_IO_EX_STORE
211 static long
212     __C(CHIP,_io_ex_storage)[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
213 #define	CHIP_IO_EX_STORE(v)		(__C(CHIP, _io_ex_storage))
214 #define	CHIP_IO_EX_STORE_SIZE(v)	(sizeof __C(CHIP, _io_ex_storage))
215 #endif
216 
217 #ifndef CHIP_ADDR_SHIFT
218 #define	CHIP_ADDR_SHIFT		5
219 #endif
220 
221 #ifndef CHIP_SIZE_SHIFT
222 #define	CHIP_SIZE_SHIFT		3
223 #endif
224 
225 void
226 __C(CHIP,_bus_io_init)(t, v)
227 	bus_space_tag_t t;
228 	void *v;
229 {
230 	struct extent *ex;
231 
232 	/*
233 	 * Initialize the bus space tag.
234 	 */
235 
236 	/* cookie */
237 	t->abs_cookie =		v;
238 
239 	/* mapping/unmapping */
240 	t->abs_map =		__C(CHIP,_io_map);
241 	t->abs_unmap =		__C(CHIP,_io_unmap);
242 	t->abs_subregion =	__C(CHIP,_io_subregion);
243 
244 	t->abs_translate =	__C(CHIP,_io_translate);
245 	t->abs_get_window =	__C(CHIP,_io_get_window);
246 
247 	/* allocation/deallocation */
248 	t->abs_alloc =		__C(CHIP,_io_alloc);
249 	t->abs_free = 		__C(CHIP,_io_free);
250 
251 	/* get kernel virtual address */
252 	t->abs_vaddr =		__C(CHIP,_io_vaddr);
253 
254 	/* mmap for user */
255 	t->abs_mmap =		__C(CHIP,_io_mmap);
256 
257 	/* barrier */
258 	t->abs_barrier =	__C(CHIP,_io_barrier);
259 
260 	/* read (single) */
261 	t->abs_r_1 =		__C(CHIP,_io_read_1);
262 	t->abs_r_2 =		__C(CHIP,_io_read_2);
263 	t->abs_r_4 =		__C(CHIP,_io_read_4);
264 	t->abs_r_8 =		__C(CHIP,_io_read_8);
265 
266 	/* read multiple */
267 	t->abs_rm_1 =		__C(CHIP,_io_read_multi_1);
268 	t->abs_rm_2 =		__C(CHIP,_io_read_multi_2);
269 	t->abs_rm_4 =		__C(CHIP,_io_read_multi_4);
270 	t->abs_rm_8 =		__C(CHIP,_io_read_multi_8);
271 
272 	/* read region */
273 	t->abs_rr_1 =		__C(CHIP,_io_read_region_1);
274 	t->abs_rr_2 =		__C(CHIP,_io_read_region_2);
275 	t->abs_rr_4 =		__C(CHIP,_io_read_region_4);
276 	t->abs_rr_8 =		__C(CHIP,_io_read_region_8);
277 
278 	/* write (single) */
279 	t->abs_w_1 =		__C(CHIP,_io_write_1);
280 	t->abs_w_2 =		__C(CHIP,_io_write_2);
281 	t->abs_w_4 =		__C(CHIP,_io_write_4);
282 	t->abs_w_8 =		__C(CHIP,_io_write_8);
283 
284 	/* write multiple */
285 	t->abs_wm_1 =		__C(CHIP,_io_write_multi_1);
286 	t->abs_wm_2 =		__C(CHIP,_io_write_multi_2);
287 	t->abs_wm_4 =		__C(CHIP,_io_write_multi_4);
288 	t->abs_wm_8 =		__C(CHIP,_io_write_multi_8);
289 
290 	/* write region */
291 	t->abs_wr_1 =		__C(CHIP,_io_write_region_1);
292 	t->abs_wr_2 =		__C(CHIP,_io_write_region_2);
293 	t->abs_wr_4 =		__C(CHIP,_io_write_region_4);
294 	t->abs_wr_8 =		__C(CHIP,_io_write_region_8);
295 
296 	/* set multiple */
297 	t->abs_sm_1 =		__C(CHIP,_io_set_multi_1);
298 	t->abs_sm_2 =		__C(CHIP,_io_set_multi_2);
299 	t->abs_sm_4 =		__C(CHIP,_io_set_multi_4);
300 	t->abs_sm_8 =		__C(CHIP,_io_set_multi_8);
301 
302 	/* set region */
303 	t->abs_sr_1 =		__C(CHIP,_io_set_region_1);
304 	t->abs_sr_2 =		__C(CHIP,_io_set_region_2);
305 	t->abs_sr_4 =		__C(CHIP,_io_set_region_4);
306 	t->abs_sr_8 =		__C(CHIP,_io_set_region_8);
307 
308 	/* copy */
309 	t->abs_c_1 =		__C(CHIP,_io_copy_region_1);
310 	t->abs_c_2 =		__C(CHIP,_io_copy_region_2);
311 	t->abs_c_4 =		__C(CHIP,_io_copy_region_4);
312 	t->abs_c_8 =		__C(CHIP,_io_copy_region_8);
313 
314 	/* XXX WE WANT EXTENT_NOCOALESCE, BUT WE CAN'T USE IT. XXX */
315 	ex = extent_create(__S(__C(CHIP,_bus_io)), 0x0UL, 0xffffffffUL,
316 	    M_DEVBUF, (caddr_t)CHIP_IO_EX_STORE(v), CHIP_IO_EX_STORE_SIZE(v),
317 	    EX_NOWAIT);
318 	extent_alloc_region(ex, 0, 0xffffffffUL, EX_NOWAIT);
319 
320 #ifdef CHIP_IO_W1_BUS_START
321 #ifdef EXTENT_DEBUG
322 	printf("io: freeing from 0x%lx to 0x%lx\n", CHIP_IO_W1_BUS_START(v),
323 	    CHIP_IO_W1_BUS_END(v));
324 #endif
325 	extent_free(ex, CHIP_IO_W1_BUS_START(v),
326 	    CHIP_IO_W1_BUS_END(v) - CHIP_IO_W1_BUS_START(v) + 1, EX_NOWAIT);
327 #endif
328 #ifdef CHIP_IO_W2_BUS_START
329 #ifdef EXTENT_DEBUG
330 	printf("io: freeing from 0x%lx to 0x%lx\n", CHIP_IO_W2_BUS_START(v),
331 	    CHIP_IO_W2_BUS_END(v));
332 #endif
333 	extent_free(ex, CHIP_IO_W2_BUS_START(v),
334 	    CHIP_IO_W2_BUS_END(v) - CHIP_IO_W2_BUS_START(v) + 1, EX_NOWAIT);
335 #endif
336 
337 #ifdef EXTENT_DEBUG
338 	extent_print(ex);
339 #endif
340 	CHIP_IO_EXTENT(v) = ex;
341 }
342 
343 int
344 __C(CHIP,_io_translate)(v, ioaddr, iolen, flags, abst)
345 	void *v;
346 	bus_addr_t ioaddr;
347 	bus_size_t iolen;
348 	int flags;
349 	struct alpha_bus_space_translation *abst;
350 {
351 	bus_addr_t ioend = ioaddr + (iolen - 1);
352 	int linear = flags & BUS_SPACE_MAP_LINEAR;
353 
354 	/*
355 	 * Can't map i/o space linearly.
356 	 */
357 	if (linear)
358 		return (EOPNOTSUPP);
359 
360 #ifdef CHIP_IO_W1_BUS_START
361 	if (ioaddr >= CHIP_IO_W1_BUS_START(v) &&
362 	    ioend <= CHIP_IO_W1_BUS_END(v))
363 		return (__C(CHIP,_io_get_window)(v, 0, abst));
364 #endif
365 
366 #ifdef CHIP_IO_W2_BUS_START
367 	if (ioaddr >= CHIP_IO_W2_BUS_START(v) &&
368 	    ioend <= CHIP_IO_W2_BUS_END(v))
369 		return (__C(CHIP,_io_get_window)(v, 1, abst));
370 #endif
371 
372 #ifdef EXTENT_DEBUG
373 	printf("\n");
374 #ifdef CHIP_IO_W1_BUS_START
375 	printf("%s: window[1]=0x%lx-0x%lx\n",
376 	    __S(__C(CHIP,_io_map)), CHIP_IO_W1_BUS_START(v),
377 	    CHIP_IO_W1_BUS_END(v));
378 #endif
379 #ifdef CHIP_IO_W2_BUS_START
380 	printf("%s: window[2]=0x%lx-0x%lx\n",
381 	    __S(__C(CHIP,_io_map)), CHIP_IO_W2_BUS_START(v),
382 	    CHIP_IO_W2_BUS_END(v));
383 #endif
384 #endif /* EXTENT_DEBUG */
385 	/* No translation. */
386 	return (EINVAL);
387 }
388 
389 int
390 __C(CHIP,_io_get_window)(v, window, abst)
391 	void *v;
392 	int window;
393 	struct alpha_bus_space_translation *abst;
394 {
395 
396 	switch (window) {
397 #ifdef CHIP_IO_W1_BUS_START
398 	case 0:
399 		abst->abst_bus_start = CHIP_IO_W1_BUS_START(v);
400 		abst->abst_bus_end = CHIP_IO_W1_BUS_END(v);
401 		abst->abst_sys_start = CHIP_IO_W1_SYS_START(v);
402 		abst->abst_sys_end = CHIP_IO_W1_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 #ifdef CHIP_IO_W2_BUS_START
410 	case 1:
411 		abst->abst_bus_start = CHIP_IO_W2_BUS_START(v);
412 		abst->abst_bus_end = CHIP_IO_W2_BUS_END(v);
413 		abst->abst_sys_start = CHIP_IO_W2_SYS_START(v);
414 		abst->abst_sys_end = CHIP_IO_W2_SYS_END(v);
415 		abst->abst_addr_shift = CHIP_ADDR_SHIFT;
416 		abst->abst_size_shift = CHIP_SIZE_SHIFT;
417 		abst->abst_flags = 0;
418 		break;
419 #endif
420 
421 	default:
422 		panic(__S(__C(CHIP,_io_get_window)) ": invalid window %d",
423 		    window);
424 	}
425 
426 	return (0);
427 }
428 
429 int
430 __C(CHIP,_io_map)(v, ioaddr, iosize, flags, iohp, acct)
431 	void *v;
432 	bus_addr_t ioaddr;
433 	bus_size_t iosize;
434 	int flags;
435 	bus_space_handle_t *iohp;
436 	int acct;
437 {
438 	struct alpha_bus_space_translation abst;
439 	int error;
440 
441 	/*
442 	 * Get the translation for this address.
443 	 */
444 	error = __C(CHIP,_io_translate)(v, ioaddr, iosize, flags, &abst);
445 	if (error)
446 		return (error);
447 
448 	if (acct == 0)
449 		goto mapit;
450 
451 #ifdef EXTENT_DEBUG
452 	printf("io: allocating 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1);
453 #endif
454         error = extent_alloc_region(CHIP_IO_EXTENT(v), ioaddr, iosize,
455             EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
456 	if (error) {
457 #ifdef EXTENT_DEBUG
458 		printf("io: allocation failed (%d)\n", error);
459 		extent_print(CHIP_IO_EXTENT(v));
460 #endif
461 		return (error);
462 	}
463 
464  mapit:
465 	*iohp = (ALPHA_PHYS_TO_K0SEG(abst.abst_sys_start) >>
466 	    CHIP_ADDR_SHIFT) + (ioaddr - abst.abst_bus_start);
467 
468 	return (0);
469 }
470 
471 void
472 __C(CHIP,_io_unmap)(v, ioh, iosize, acct)
473 	void *v;
474 	bus_space_handle_t ioh;
475 	bus_size_t iosize;
476 	int acct;
477 {
478 	bus_addr_t ioaddr;
479 	int error;
480 
481 	if (acct == 0)
482 		return;
483 
484 #ifdef EXTENT_DEBUG
485 	printf("io: freeing handle 0x%lx for 0x%lx\n", ioh, iosize);
486 #endif
487 
488 	ioh = ALPHA_K0SEG_TO_PHYS(ioh << CHIP_ADDR_SHIFT) >> CHIP_ADDR_SHIFT;
489 
490 #ifdef CHIP_IO_W1_BUS_START
491 	if ((ioh << CHIP_ADDR_SHIFT) >= CHIP_IO_W1_SYS_START(v) &&
492 	    (ioh << CHIP_ADDR_SHIFT) <= CHIP_IO_W1_SYS_END(v)) {
493 		ioaddr = CHIP_IO_W1_BUS_START(v) +
494 		    (ioh - (CHIP_IO_W1_SYS_START(v) >> CHIP_ADDR_SHIFT));
495 	} else
496 #endif
497 #ifdef CHIP_IO_W2_BUS_START
498 	if ((ioh << CHIP_ADDR_SHIFT) >= CHIP_IO_W2_SYS_START(v) &&
499 	    (ioh << CHIP_ADDR_SHIFT) <= CHIP_IO_W2_SYS_END(v)) {
500 		ioaddr = CHIP_IO_W2_BUS_START(v) +
501 		    (ioh - (CHIP_IO_W2_SYS_START(v) >> CHIP_ADDR_SHIFT));
502 	} else
503 #endif
504 	{
505 		printf("\n");
506 #ifdef CHIP_IO_W1_BUS_START
507 		printf("%s: sys window[1]=0x%lx-0x%lx\n",
508 		    __S(__C(CHIP,_io_map)), CHIP_IO_W1_SYS_START(v),
509 		    CHIP_IO_W1_SYS_END(v));
510 #endif
511 #ifdef CHIP_IO_W2_BUS_START
512 		printf("%s: sys window[2]=0x%lx-0x%lx\n",
513 		    __S(__C(CHIP,_io_map)), CHIP_IO_W2_SYS_START(v),
514 		    CHIP_IO_W2_SYS_END(v));
515 #endif
516 		panic("%s: don't know how to unmap %lx",
517 		    __S(__C(CHIP,_io_unmap)), (ioh << CHIP_ADDR_SHIFT));
518 	}
519 
520 #ifdef EXTENT_DEBUG
521 	printf("io: freeing 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1);
522 #endif
523         error = extent_free(CHIP_IO_EXTENT(v), ioaddr, iosize,
524             EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
525 	if (error) {
526 		printf("%s: WARNING: could not unmap 0x%lx-0x%lx (error %d)\n",
527 		   __S(__C(CHIP,_io_unmap)), ioaddr, ioaddr + iosize - 1,
528 		   error);
529 #ifdef EXTENT_DEBUG
530 		extent_print(CHIP_IO_EXTENT(v));
531 #endif
532 	}
533 }
534 
535 int
536 __C(CHIP,_io_subregion)(v, ioh, offset, size, nioh)
537 	void *v;
538 	bus_space_handle_t ioh, *nioh;
539 	bus_size_t offset, size;
540 {
541 
542 	*nioh = ioh + offset;
543 	return (0);
544 }
545 
546 int
547 __C(CHIP,_io_alloc)(v, rstart, rend, size, align, boundary, flags,
548     addrp, bshp)
549 	void *v;
550 	bus_addr_t rstart, rend, *addrp;
551 	bus_size_t size, align, boundary;
552 	int flags;
553 	bus_space_handle_t *bshp;
554 {
555 	struct alpha_bus_space_translation abst;
556 	int linear = flags & BUS_SPACE_MAP_LINEAR;
557 	bus_addr_t ioaddr;
558 	int error;
559 
560 	/*
561 	 * Can't map i/o space linearly.
562 	 */
563 	if (linear)
564 		return (EOPNOTSUPP);
565 
566 	/*
567 	 * Do the requested allocation.
568 	 */
569 #ifdef EXTENT_DEBUG
570 	printf("io: allocating from 0x%lx to 0x%lx\n", rstart, rend);
571 #endif
572 	error = extent_alloc_subregion(CHIP_IO_EXTENT(v), rstart, rend,
573 	    size, align, boundary,
574 	    EX_FAST | EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0),
575 	    &ioaddr);
576 	if (error) {
577 #ifdef EXTENT_DEBUG
578 		printf("io: allocation failed (%d)\n", error);
579 		extent_print(CHIP_IO_EXTENT(v));
580 #endif
581 		return (error);
582 	}
583 
584 #ifdef EXTENT_DEBUG
585 	printf("io: allocated 0x%lx to 0x%lx\n", ioaddr, ioaddr + size - 1);
586 #endif
587 
588 	error = __C(CHIP,_io_translate)(v, ioaddr, size, flags, &abst);
589 	if (error) {
590 		(void) extent_free(CHIP_IO_EXTENT(v), ioaddr, size,
591 		    EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
592 		return (error);
593 	}
594 
595 	*addrp = ioaddr;
596 	*bshp = (ALPHA_PHYS_TO_K0SEG(abst.abst_sys_start) >>
597 	    CHIP_ADDR_SHIFT) + (ioaddr - abst.abst_bus_start);
598 
599 	return (0);
600 }
601 
602 void
603 __C(CHIP,_io_free)(v, bsh, size)
604 	void *v;
605 	bus_space_handle_t bsh;
606 	bus_size_t size;
607 {
608 
609 	/* Unmap does all we need to do. */
610 	__C(CHIP,_io_unmap)(v, bsh, size, 1);
611 }
612 
613 void *
614 __C(CHIP,_io_vaddr)(v, bsh)
615 	void *v;
616 	bus_space_handle_t bsh;
617 {
618 	/*
619 	 * _io_translate() catches BUS_SPACE_MAP_LINEAR,
620 	 * so we shouldn't get here
621 	 */
622 	panic("_io_vaddr");
623 }
624 
625 paddr_t
626 __C(CHIP,_io_mmap)(v, addr, off, prot, flags)
627 	void *v;
628 	bus_addr_t addr;
629 	off_t off;
630 	int prot;
631 	int flags;
632 {
633 
634 	/* Not supported for I/O space. */
635 	return (-1);
636 }
637 
638 inline void
639 __C(CHIP,_io_barrier)(v, h, o, l, f)
640 	void *v;
641 	bus_space_handle_t h;
642 	bus_size_t o, l;
643 	int f;
644 {
645 
646 	if ((f & BUS_SPACE_BARRIER_READ) != 0)
647 		alpha_mb();
648 	else if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
649 		alpha_wmb();
650 }
651 
652 inline u_int8_t
653 __C(CHIP,_io_read_1)(v, ioh, off)
654 	void *v;
655 	bus_space_handle_t ioh;
656 	bus_size_t off;
657 {
658 	register bus_space_handle_t tmpioh;
659 	register u_int32_t *port, val;
660 	register u_int8_t rval;
661 	register int offset;
662 
663 	alpha_mb();
664 
665 	tmpioh = ioh + off;
666 	offset = tmpioh & 3;
667 	port = (u_int32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
668 	    (0 << CHIP_SIZE_SHIFT));
669 	val = *port;
670 	rval = ((val) >> (8 * offset)) & 0xff;
671 
672 	return rval;
673 }
674 
675 inline u_int16_t
676 __C(CHIP,_io_read_2)(v, ioh, off)
677 	void *v;
678 	bus_space_handle_t ioh;
679 	bus_size_t off;
680 {
681 	register bus_space_handle_t tmpioh;
682 	register u_int32_t *port, val;
683 	register u_int16_t rval;
684 	register int offset;
685 
686 	alpha_mb();
687 
688 	tmpioh = ioh + off;
689 	offset = tmpioh & 3;
690 	port = (u_int32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
691 	    (1 << CHIP_SIZE_SHIFT));
692 	val = *port;
693 	rval = ((val) >> (8 * offset)) & 0xffff;
694 
695 	return rval;
696 }
697 
698 inline u_int32_t
699 __C(CHIP,_io_read_4)(v, ioh, off)
700 	void *v;
701 	bus_space_handle_t ioh;
702 	bus_size_t off;
703 {
704 	register bus_space_handle_t tmpioh;
705 	register u_int32_t *port, val;
706 	register u_int32_t rval;
707 	register int offset;
708 
709 	alpha_mb();
710 
711 	tmpioh = ioh + off;
712 	offset = tmpioh & 3;
713 	port = (u_int32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
714 	    (3 << CHIP_SIZE_SHIFT));
715 	val = *port;
716 #if 0
717 	rval = ((val) >> (8 * offset)) & 0xffffffff;
718 #else
719 	rval = val;
720 #endif
721 
722 	return rval;
723 }
724 
725 inline u_int64_t
726 __C(CHIP,_io_read_8)(v, ioh, off)
727 	void *v;
728 	bus_space_handle_t ioh;
729 	bus_size_t off;
730 {
731 
732 	/* XXX XXX XXX */
733 	panic("%s not implemented", __S(__C(CHIP,_io_read_8)));
734 }
735 
736 #define CHIP_io_read_multi_N(BYTES,TYPE)				\
737 void									\
738 __C(__C(CHIP,_io_read_multi_),BYTES)(v, h, o, a, c)			\
739 	void *v;							\
740 	bus_space_handle_t h;						\
741 	bus_size_t o, c;						\
742 	TYPE *a;							\
743 {									\
744 									\
745 	while (c-- > 0) {						\
746 		__C(CHIP,_io_barrier)(v, h, o, sizeof *a,		\
747 		    BUS_SPACE_BARRIER_READ);				\
748 		*a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o);		\
749 	}								\
750 }
751 CHIP_io_read_multi_N(1,u_int8_t)
752 CHIP_io_read_multi_N(2,u_int16_t)
753 CHIP_io_read_multi_N(4,u_int32_t)
754 CHIP_io_read_multi_N(8,u_int64_t)
755 
756 #define CHIP_io_read_region_N(BYTES,TYPE)				\
757 void									\
758 __C(__C(CHIP,_io_read_region_),BYTES)(v, h, o, a, c)			\
759 	void *v;							\
760 	bus_space_handle_t h;						\
761 	bus_size_t o, c;						\
762 	TYPE *a;							\
763 {									\
764 									\
765 	while (c-- > 0) {						\
766 		*a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o);		\
767 		o += sizeof *a;						\
768 	}								\
769 }
770 CHIP_io_read_region_N(1,u_int8_t)
771 CHIP_io_read_region_N(2,u_int16_t)
772 CHIP_io_read_region_N(4,u_int32_t)
773 CHIP_io_read_region_N(8,u_int64_t)
774 
775 inline void
776 __C(CHIP,_io_write_1)(v, ioh, off, val)
777 	void *v;
778 	bus_space_handle_t ioh;
779 	bus_size_t off;
780 	u_int8_t val;
781 {
782 	register bus_space_handle_t tmpioh;
783 	register u_int32_t *port, nval;
784 	register int offset;
785 
786 	tmpioh = ioh + off;
787 	offset = tmpioh & 3;
788         nval = val << (8 * offset);
789         port = (u_int32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
790             (0 << CHIP_SIZE_SHIFT));
791         *port = nval;
792         alpha_mb();
793 }
794 
795 inline void
796 __C(CHIP,_io_write_2)(v, ioh, off, val)
797 	void *v;
798 	bus_space_handle_t ioh;
799 	bus_size_t off;
800 	u_int16_t val;
801 {
802 	register bus_space_handle_t tmpioh;
803 	register u_int32_t *port, nval;
804 	register int offset;
805 
806 	tmpioh = ioh + off;
807 	offset = tmpioh & 3;
808         nval = val << (8 * offset);
809         port = (u_int32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
810             (1 << CHIP_SIZE_SHIFT));
811         *port = nval;
812         alpha_mb();
813 }
814 
815 inline void
816 __C(CHIP,_io_write_4)(v, ioh, off, val)
817 	void *v;
818 	bus_space_handle_t ioh;
819 	bus_size_t off;
820 	u_int32_t val;
821 {
822 	register bus_space_handle_t tmpioh;
823 	register u_int32_t *port, nval;
824 	register int offset;
825 
826 	tmpioh = ioh + off;
827 	offset = tmpioh & 3;
828         nval = val /*<< (8 * offset)*/;
829         port = (u_int32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
830             (3 << CHIP_SIZE_SHIFT));
831         *port = nval;
832         alpha_mb();
833 }
834 
835 inline void
836 __C(CHIP,_io_write_8)(v, ioh, off, val)
837 	void *v;
838 	bus_space_handle_t ioh;
839 	bus_size_t off;
840 	u_int64_t val;
841 {
842 
843 	/* XXX XXX XXX */
844 	panic("%s not implemented", __S(__C(CHIP,_io_write_8)));
845 	alpha_mb();
846 }
847 
848 #define CHIP_io_write_multi_N(BYTES,TYPE)				\
849 void									\
850 __C(__C(CHIP,_io_write_multi_),BYTES)(v, h, o, a, c)			\
851 	void *v;							\
852 	bus_space_handle_t h;						\
853 	bus_size_t o, c;						\
854 	const TYPE *a;							\
855 {									\
856 									\
857 	while (c-- > 0) {						\
858 		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++);		\
859 		__C(CHIP,_io_barrier)(v, h, o, sizeof *a,		\
860 		    BUS_SPACE_BARRIER_WRITE);				\
861 	}								\
862 }
863 CHIP_io_write_multi_N(1,u_int8_t)
864 CHIP_io_write_multi_N(2,u_int16_t)
865 CHIP_io_write_multi_N(4,u_int32_t)
866 CHIP_io_write_multi_N(8,u_int64_t)
867 
868 #define CHIP_io_write_region_N(BYTES,TYPE)				\
869 void									\
870 __C(__C(CHIP,_io_write_region_),BYTES)(v, h, o, a, c)			\
871 	void *v;							\
872 	bus_space_handle_t h;						\
873 	bus_size_t o, c;						\
874 	const TYPE *a;							\
875 {									\
876 									\
877 	while (c-- > 0) {						\
878 		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++);		\
879 		o += sizeof *a;						\
880 	}								\
881 }
882 CHIP_io_write_region_N(1,u_int8_t)
883 CHIP_io_write_region_N(2,u_int16_t)
884 CHIP_io_write_region_N(4,u_int32_t)
885 CHIP_io_write_region_N(8,u_int64_t)
886 
887 #define CHIP_io_set_multi_N(BYTES,TYPE)					\
888 void									\
889 __C(__C(CHIP,_io_set_multi_),BYTES)(v, h, o, val, c)			\
890 	void *v;							\
891 	bus_space_handle_t h;						\
892 	bus_size_t o, c;						\
893 	TYPE val;							\
894 {									\
895 									\
896 	while (c-- > 0) {						\
897 		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, val);		\
898 		__C(CHIP,_io_barrier)(v, h, o, sizeof val,		\
899 		    BUS_SPACE_BARRIER_WRITE);				\
900 	}								\
901 }
902 CHIP_io_set_multi_N(1,u_int8_t)
903 CHIP_io_set_multi_N(2,u_int16_t)
904 CHIP_io_set_multi_N(4,u_int32_t)
905 CHIP_io_set_multi_N(8,u_int64_t)
906 
907 #define CHIP_io_set_region_N(BYTES,TYPE)				\
908 void									\
909 __C(__C(CHIP,_io_set_region_),BYTES)(v, h, o, val, c)			\
910 	void *v;							\
911 	bus_space_handle_t h;						\
912 	bus_size_t o, c;						\
913 	TYPE val;							\
914 {									\
915 									\
916 	while (c-- > 0) {						\
917 		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, val);		\
918 		o += sizeof val;					\
919 	}								\
920 }
921 CHIP_io_set_region_N(1,u_int8_t)
922 CHIP_io_set_region_N(2,u_int16_t)
923 CHIP_io_set_region_N(4,u_int32_t)
924 CHIP_io_set_region_N(8,u_int64_t)
925 
926 #define	CHIP_io_copy_region_N(BYTES)					\
927 void									\
928 __C(__C(CHIP,_io_copy_region_),BYTES)(v, h1, o1, h2, o2, c)		\
929 	void *v;							\
930 	bus_space_handle_t h1, h2;					\
931 	bus_size_t o1, o2, c;						\
932 {									\
933 	bus_size_t o;							\
934 									\
935 	if ((h1 + o1) >= (h2 + o2)) {					\
936 		/* src after dest: copy forward */			\
937 		for (o = 0; c != 0; c--, o += BYTES)			\
938 			__C(__C(CHIP,_io_write_),BYTES)(v, h2, o2 + o,	\
939 			    __C(__C(CHIP,_io_read_),BYTES)(v, h1, o1 + o)); \
940 	} else {							\
941 		/* dest after src: copy backwards */			\
942 		for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES)	\
943 			__C(__C(CHIP,_io_write_),BYTES)(v, h2, o2 + o,	\
944 			    __C(__C(CHIP,_io_read_),BYTES)(v, h1, o1 + o)); \
945 	}								\
946 }
947 CHIP_io_copy_region_N(1)
948 CHIP_io_copy_region_N(2)
949 CHIP_io_copy_region_N(4)
950 CHIP_io_copy_region_N(8)
951