pci_swiz_bus_io_chipdep.c revision 1.10 1 /* $NetBSD: pci_swiz_bus_io_chipdep.c,v 1.10 1996/11/25 03:37:23 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
5 * All rights reserved.
6 *
7 * Author: Chris G. Demetriou
8 *
9 * Permission to use, copy, modify and distribute this software and
10 * its documentation is hereby granted, provided that both the copyright
11 * notice and this permission notice appear in all copies of the
12 * software, derivative works or modified versions, and any portions
13 * thereof, and that both notices appear in supporting documentation.
14 *
15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 *
19 * Carnegie Mellon requests users of this software to return to
20 *
21 * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
22 * School of Computer Science
23 * Carnegie Mellon University
24 * Pittsburgh PA 15213-3890
25 *
26 * any improvements or extensions that they make and grant Carnegie the
27 * rights to redistribute these changes.
28 */
29
30 /*
31 * Common PCI Chipset "bus I/O" functions, for chipsets which have to
32 * deal with only a single PCI interface chip in a machine.
33 *
34 * uses:
35 * CHIP name of the 'chip' it's being compiled for.
36 * CHIP_IO_BASE Sparse I/O space base to use.
37 */
38
39 #include <sys/extent.h>
40
41 #define __C(A,B) __CONCAT(A,B)
42 #define __S(S) __STRING(S)
43
44 /* mapping/unmapping */
45 int __C(CHIP,_io_map) __P((void *, bus_addr_t, bus_size_t, int,
46 bus_space_handle_t *));
47 void __C(CHIP,_io_unmap) __P((void *, bus_space_handle_t,
48 bus_size_t));
49 int __C(CHIP,_io_subregion) __P((void *, bus_space_handle_t,
50 bus_size_t, bus_size_t, bus_space_handle_t *));
51
52 /* allocation/deallocation */
53 int __C(CHIP,_io_alloc) __P((void *, bus_addr_t, bus_addr_t,
54 bus_size_t, bus_size_t, bus_addr_t, int, bus_addr_t *,
55 bus_space_handle_t *));
56 void __C(CHIP,_io_free) __P((void *, bus_space_handle_t,
57 bus_size_t));
58
59 /* read (single) */
60 u_int8_t __C(CHIP,_io_read_1) __P((void *, bus_space_handle_t,
61 bus_size_t));
62 u_int16_t __C(CHIP,_io_read_2) __P((void *, bus_space_handle_t,
63 bus_size_t));
64 u_int32_t __C(CHIP,_io_read_4) __P((void *, bus_space_handle_t,
65 bus_size_t));
66 u_int64_t __C(CHIP,_io_read_8) __P((void *, bus_space_handle_t,
67 bus_size_t));
68
69 /* read multiple */
70 void __C(CHIP,_io_read_multi_1) __P((void *, bus_space_handle_t,
71 bus_size_t, u_int8_t *, bus_size_t));
72 void __C(CHIP,_io_read_multi_2) __P((void *, bus_space_handle_t,
73 bus_size_t, u_int16_t *, bus_size_t));
74 void __C(CHIP,_io_read_multi_4) __P((void *, bus_space_handle_t,
75 bus_size_t, u_int32_t *, bus_size_t));
76 void __C(CHIP,_io_read_multi_8) __P((void *, bus_space_handle_t,
77 bus_size_t, u_int64_t *, bus_size_t));
78
79 /* read region */
80 void __C(CHIP,_io_read_region_1) __P((void *, bus_space_handle_t,
81 bus_size_t, u_int8_t *, bus_size_t));
82 void __C(CHIP,_io_read_region_2) __P((void *, bus_space_handle_t,
83 bus_size_t, u_int16_t *, bus_size_t));
84 void __C(CHIP,_io_read_region_4) __P((void *, bus_space_handle_t,
85 bus_size_t, u_int32_t *, bus_size_t));
86 void __C(CHIP,_io_read_region_8) __P((void *, bus_space_handle_t,
87 bus_size_t, u_int64_t *, bus_size_t));
88
89 /* write (single) */
90 void __C(CHIP,_io_write_1) __P((void *, bus_space_handle_t,
91 bus_size_t, u_int8_t));
92 void __C(CHIP,_io_write_2) __P((void *, bus_space_handle_t,
93 bus_size_t, u_int16_t));
94 void __C(CHIP,_io_write_4) __P((void *, bus_space_handle_t,
95 bus_size_t, u_int32_t));
96 void __C(CHIP,_io_write_8) __P((void *, bus_space_handle_t,
97 bus_size_t, u_int64_t));
98
99 /* write multiple */
100 void __C(CHIP,_io_write_multi_1) __P((void *, bus_space_handle_t,
101 bus_size_t, const u_int8_t *, bus_size_t));
102 void __C(CHIP,_io_write_multi_2) __P((void *, bus_space_handle_t,
103 bus_size_t, const u_int16_t *, bus_size_t));
104 void __C(CHIP,_io_write_multi_4) __P((void *, bus_space_handle_t,
105 bus_size_t, const u_int32_t *, bus_size_t));
106 void __C(CHIP,_io_write_multi_8) __P((void *, bus_space_handle_t,
107 bus_size_t, const u_int64_t *, bus_size_t));
108
109 /* write region */
110 void __C(CHIP,_io_write_region_1) __P((void *, bus_space_handle_t,
111 bus_size_t, const u_int8_t *, bus_size_t));
112 void __C(CHIP,_io_write_region_2) __P((void *, bus_space_handle_t,
113 bus_size_t, const u_int16_t *, bus_size_t));
114 void __C(CHIP,_io_write_region_4) __P((void *, bus_space_handle_t,
115 bus_size_t, const u_int32_t *, bus_size_t));
116 void __C(CHIP,_io_write_region_8) __P((void *, bus_space_handle_t,
117 bus_size_t, const u_int64_t *, bus_size_t));
118
119 /* barrier */
120 void __C(CHIP,_io_barrier) __P((void *, bus_space_handle_t,
121 bus_size_t, bus_size_t, int));
122
123 static long
124 __C(CHIP,_io_ex_storage)[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
125
126 static struct alpha_bus_space __C(CHIP,_io_space) = {
127 /* cookie */
128 NULL,
129
130 /* mapping/unmapping */
131 __C(CHIP,_io_map),
132 __C(CHIP,_io_unmap),
133 __C(CHIP,_io_subregion),
134
135 /* allocation/deallocation */
136 __C(CHIP,_io_alloc),
137 __C(CHIP,_io_free),
138
139 /* read (single) */
140 __C(CHIP,_io_read_1),
141 __C(CHIP,_io_read_2),
142 __C(CHIP,_io_read_4),
143 __C(CHIP,_io_read_8),
144
145 /* read multi */
146 __C(CHIP,_io_read_multi_1),
147 __C(CHIP,_io_read_multi_2),
148 __C(CHIP,_io_read_multi_4),
149 __C(CHIP,_io_read_multi_8),
150
151 /* read region */
152 __C(CHIP,_io_read_region_1),
153 __C(CHIP,_io_read_region_2),
154 __C(CHIP,_io_read_region_4),
155 __C(CHIP,_io_read_region_8),
156
157 /* write (single) */
158 __C(CHIP,_io_write_1),
159 __C(CHIP,_io_write_2),
160 __C(CHIP,_io_write_4),
161 __C(CHIP,_io_write_8),
162
163 /* write multi */
164 __C(CHIP,_io_write_multi_1),
165 __C(CHIP,_io_write_multi_2),
166 __C(CHIP,_io_write_multi_4),
167 __C(CHIP,_io_write_multi_8),
168
169 /* write region */
170 __C(CHIP,_io_write_region_1),
171 __C(CHIP,_io_write_region_2),
172 __C(CHIP,_io_write_region_4),
173 __C(CHIP,_io_write_region_8),
174
175 /* set multi */
176 /* XXX IMPLEMENT */
177
178 /* set region */
179 /* XXX IMPLEMENT */
180
181 /* copy */
182 /* XXX IMPLEMENT */
183
184 /* barrier */
185 __C(CHIP,_io_barrier),
186 };
187
188 bus_space_tag_t
189 __C(CHIP,_bus_io_init)(v)
190 void *v;
191 {
192 bus_space_tag_t t = &__C(CHIP,_io_space);
193 struct extent *ex;
194
195 t->abs_cookie = v;
196
197 /* XXX WE WANT EXTENT_NOCOALESCE, BUT WE CAN'T USE IT. XXX */
198 ex = extent_create(__S(__C(CHIP,_bus_io)), 0x0UL, 0xffffffffUL,
199 M_DEVBUF, (caddr_t)__C(CHIP,_io_ex_storage),
200 sizeof(__C(CHIP,_io_ex_storage)), EX_NOWAIT);
201 extent_alloc_region(ex, 0, 0xffffffffUL, EX_NOWAIT);
202
203 #ifdef CHIP_IO_W1_BUS_START
204 #ifdef EXTENT_DEBUG
205 printf("io: freeing from 0x%lx to 0x%lx\n", CHIP_IO_W1_BUS_START(v),
206 CHIP_IO_W1_BUS_END(v));
207 #endif
208 extent_free(ex, CHIP_IO_W1_BUS_START(v),
209 CHIP_IO_W1_BUS_END(v) - CHIP_IO_W1_BUS_START(v) + 1, EX_NOWAIT);
210 #endif
211 #ifdef CHIP_IO_W2_BUS_START
212 #ifdef EXTENT_DEBUG
213 printf("io: freeing from 0x%lx to 0x%lx\n", CHIP_IO_W2_BUS_START(v),
214 CHIP_IO_W2_BUS_END(v));
215 #endif
216 extent_free(ex, CHIP_IO_W2_BUS_START(v),
217 CHIP_IO_W2_BUS_END(v) - CHIP_IO_W2_BUS_START(v) + 1, EX_NOWAIT);
218 #endif
219
220 #ifdef EXTENT_DEBUG
221 extent_print(ex);
222 #endif
223 CHIP_IO_EXTENT(v) = ex;
224
225 return (t);
226 }
227
228 int
229 __C(CHIP,_io_map)(v, ioaddr, iosize, cacheable, iohp)
230 void *v;
231 bus_addr_t ioaddr;
232 bus_size_t iosize;
233 int cacheable;
234 bus_space_handle_t *iohp;
235 {
236 int error;
237
238 #ifdef EXTENT_DEBUG
239 printf("io: allocating 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1);
240 #endif
241 error = extent_alloc_region(CHIP_IO_EXTENT(v), ioaddr, iosize,
242 EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
243 if (error) {
244 #ifdef EXTENT_DEBUG
245 printf("io: allocation failed (%d)\n", error);
246 extent_print(CHIP_IO_EXTENT(v));
247 #endif
248 return (error);
249 }
250
251 #ifdef CHIP_IO_W1_BUS_START
252 if (ioaddr >= CHIP_IO_W1_BUS_START(v) &&
253 ioaddr <= CHIP_IO_W1_BUS_END(v)) {
254 *iohp = (ALPHA_PHYS_TO_K0SEG(CHIP_IO_W1_SYS_START(v)) >> 5) +
255 (ioaddr - CHIP_IO_W1_BUS_START(v));
256 } else
257 #endif
258 #ifdef CHIP_IO_W2_BUS_START
259 if (ioaddr >= CHIP_IO_W2_BUS_START(v) &&
260 ioaddr <= CHIP_IO_W2_BUS_END(v)) {
261 *iohp = (ALPHA_PHYS_TO_K0SEG(CHIP_IO_W2_SYS_START(v)) >> 5) +
262 (ioaddr - CHIP_IO_W2_BUS_START(v));
263 } else
264 #endif
265 {
266 printf("\n");
267 #ifdef CHIP_IO_W1_BUS_START
268 printf("%s: window[1]=0x%lx-0x%lx\n",
269 __S(__C(CHIP,_io_map)), CHIP_IO_W1_BUS_START(v),
270 CHIP_IO_W1_BUS_END(v));
271 #endif
272 #ifdef CHIP_IO_W2_BUS_START
273 printf("%s: window[2]=0x%lx-0x%lx\n",
274 __S(__C(CHIP,_io_map)), CHIP_IO_W2_BUS_START(v),
275 CHIP_IO_W2_BUS_END(v));
276 #endif
277 panic("%s: don't know how to map %lx",
278 __S(__C(CHIP,_io_map)), ioaddr);
279 }
280
281 return (0);
282 }
283
284 void
285 __C(CHIP,_io_unmap)(v, ioh, iosize)
286 void *v;
287 bus_space_handle_t ioh;
288 bus_size_t iosize;
289 {
290 bus_addr_t ioaddr;
291 int error;
292
293 #ifdef EXTENT_DEBUG
294 printf("io: freeing handle 0x%lx for 0x%lx\n", ioh, iosize);
295 #endif
296
297 ioh = ALPHA_K0SEG_TO_PHYS(ioh << 5) >> 5;
298
299 #ifdef CHIP_IO_W1_BUS_START
300 if ((ioh << 5) >= CHIP_IO_W1_SYS_START(v) &&
301 (ioh << 5) <= CHIP_IO_W1_SYS_END(v)) {
302 ioaddr = CHIP_IO_W1_BUS_START(v) +
303 (ioh - (CHIP_IO_W1_SYS_START(v) >> 5));
304 } else
305 #endif
306 #ifdef CHIP_IO_W2_BUS_START
307 if ((ioh << 5) >= CHIP_IO_W2_SYS_START(v) &&
308 (ioh << 5) <= CHIP_IO_W2_SYS_END(v)) {
309 ioaddr = CHIP_IO_W2_BUS_START(v) +
310 (ioh - (CHIP_IO_W2_SYS_START(v) >> 5));
311 } else
312 #endif
313 {
314 printf("\n");
315 #ifdef CHIP_IO_W1_BUS_START
316 printf("%s: sys window[1]=0x%lx-0x%lx\n",
317 __S(__C(CHIP,_io_map)), CHIP_IO_W1_SYS_START(v),
318 CHIP_IO_W1_SYS_END(v));
319 #endif
320 #ifdef CHIP_IO_W2_BUS_START
321 printf("%s: sys window[2]=0x%lx-0x%lx\n",
322 __S(__C(CHIP,_io_map)), CHIP_IO_W2_SYS_START(v),
323 CHIP_IO_W2_SYS_END(v));
324 #endif
325 panic("%s: don't know how to unmap %lx",
326 __S(__C(CHIP,_io_unmap)), (ioh << 5));
327 }
328
329 #ifdef EXTENT_DEBUG
330 printf("io: freeing 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1);
331 #endif
332 error = extent_free(CHIP_IO_EXTENT(v), ioaddr, iosize,
333 EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
334 if (error) {
335 printf("%s: WARNING: could not unmap 0x%lx-0x%lx (error %d)\n",
336 __S(__C(CHIP,_io_unmap)), ioaddr, ioaddr + iosize - 1,
337 error);
338 #ifdef EXTENT_DEBUG
339 extent_print(CHIP_IO_EXTENT(v));
340 #endif
341 }
342 }
343
344 int
345 __C(CHIP,_io_subregion)(v, ioh, offset, size, nioh)
346 void *v;
347 bus_space_handle_t ioh, *nioh;
348 bus_size_t offset, size;
349 {
350
351 *nioh = ioh + offset;
352 return (0);
353 }
354
355 int
356 __C(CHIP,_io_alloc)(v, rstart, rend, size, align, boundary, cacheable,
357 addrp, bshp)
358 void *v;
359 bus_addr_t rstart, rend, *addrp;
360 bus_size_t size, align, boundary;
361 int cacheable;
362 bus_space_handle_t *bshp;
363 {
364
365 /* XXX XXX XXX XXX XXX XXX */
366 panic("%s not implemented", __S(__C(CHIP,_io_alloc)));
367 }
368
369 void
370 __C(CHIP,_io_free)(v, bsh, size)
371 void *v;
372 bus_space_handle_t bsh;
373 bus_size_t size;
374 {
375
376 /* XXX XXX XXX XXX XXX XXX */
377 panic("%s not implemented", __S(__C(CHIP,_io_free)));
378 }
379
380 u_int8_t
381 __C(CHIP,_io_read_1)(v, ioh, off)
382 void *v;
383 bus_space_handle_t ioh;
384 bus_size_t off;
385 {
386 register bus_space_handle_t tmpioh;
387 register u_int32_t *port, val;
388 register u_int8_t rval;
389 register int offset;
390
391 alpha_mb();
392
393 tmpioh = ioh + off;
394 offset = tmpioh & 3;
395 port = (u_int32_t *)((tmpioh << 5) | (0 << 3));
396 val = *port;
397 rval = ((val) >> (8 * offset)) & 0xff;
398
399 return rval;
400 }
401
402 u_int16_t
403 __C(CHIP,_io_read_2)(v, ioh, off)
404 void *v;
405 bus_space_handle_t ioh;
406 bus_size_t off;
407 {
408 register bus_space_handle_t tmpioh;
409 register u_int32_t *port, val;
410 register u_int16_t rval;
411 register int offset;
412
413 alpha_mb();
414
415 tmpioh = ioh + off;
416 offset = tmpioh & 3;
417 port = (u_int32_t *)((tmpioh << 5) | (1 << 3));
418 val = *port;
419 rval = ((val) >> (8 * offset)) & 0xffff;
420
421 return rval;
422 }
423
424 u_int32_t
425 __C(CHIP,_io_read_4)(v, ioh, off)
426 void *v;
427 bus_space_handle_t ioh;
428 bus_size_t off;
429 {
430 register bus_space_handle_t tmpioh;
431 register u_int32_t *port, val;
432 register u_int32_t rval;
433 register int offset;
434
435 alpha_mb();
436
437 tmpioh = ioh + off;
438 offset = tmpioh & 3;
439 port = (u_int32_t *)((tmpioh << 5) | (3 << 3));
440 val = *port;
441 #if 0
442 rval = ((val) >> (8 * offset)) & 0xffffffff;
443 #else
444 rval = val;
445 #endif
446
447 return rval;
448 }
449
450 u_int64_t
451 __C(CHIP,_io_read_8)(v, ioh, off)
452 void *v;
453 bus_space_handle_t ioh;
454 bus_size_t off;
455 {
456
457 /* XXX XXX XXX */
458 panic("%s not implemented", __S(__C(CHIP,_io_read_8)));
459 }
460
461 #define CHIP_io_read_multi_N(BYTES,TYPE) \
462 void \
463 __C(__C(CHIP,_io_read_multi_),BYTES)(v, h, o, a, c) \
464 void *v; \
465 bus_space_handle_t h; \
466 bus_size_t o, c; \
467 TYPE *a; \
468 { \
469 \
470 while (c-- > 0) { \
471 __C(CHIP,_io_barrier)(v, h, o, sizeof *a, \
472 BUS_BARRIER_READ); \
473 *a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o); \
474 } \
475 }
476 CHIP_io_read_multi_N(1,u_int8_t)
477 CHIP_io_read_multi_N(2,u_int16_t)
478 CHIP_io_read_multi_N(4,u_int32_t)
479 CHIP_io_read_multi_N(8,u_int64_t)
480
481 #define CHIP_io_read_region_N(BYTES,TYPE) \
482 void \
483 __C(__C(CHIP,_io_read_region_),BYTES)(v, h, o, a, c) \
484 void *v; \
485 bus_space_handle_t h; \
486 bus_size_t o, c; \
487 TYPE *a; \
488 { \
489 \
490 while (c-- > 0) { \
491 *a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o); \
492 o += sizeof *a; \
493 } \
494 }
495 CHIP_io_read_region_N(1,u_int8_t)
496 CHIP_io_read_region_N(2,u_int16_t)
497 CHIP_io_read_region_N(4,u_int32_t)
498 CHIP_io_read_region_N(8,u_int64_t)
499
500 void
501 __C(CHIP,_io_write_1)(v, ioh, off, val)
502 void *v;
503 bus_space_handle_t ioh;
504 bus_size_t off;
505 u_int8_t val;
506 {
507 register bus_space_handle_t tmpioh;
508 register u_int32_t *port, nval;
509 register int offset;
510
511 tmpioh = ioh + off;
512 offset = tmpioh & 3;
513 nval = val << (8 * offset);
514 port = (u_int32_t *)((tmpioh << 5) | (0 << 3));
515 *port = nval;
516 alpha_mb();
517 }
518
519 void
520 __C(CHIP,_io_write_2)(v, ioh, off, val)
521 void *v;
522 bus_space_handle_t ioh;
523 bus_size_t off;
524 u_int16_t val;
525 {
526 register bus_space_handle_t tmpioh;
527 register u_int32_t *port, nval;
528 register int offset;
529
530 tmpioh = ioh + off;
531 offset = tmpioh & 3;
532 nval = val << (8 * offset);
533 port = (u_int32_t *)((tmpioh << 5) | (1 << 3));
534 *port = nval;
535 alpha_mb();
536 }
537
538 void
539 __C(CHIP,_io_write_4)(v, ioh, off, val)
540 void *v;
541 bus_space_handle_t ioh;
542 bus_size_t off;
543 u_int32_t val;
544 {
545 register bus_space_handle_t tmpioh;
546 register u_int32_t *port, nval;
547 register int offset;
548
549 tmpioh = ioh + off;
550 offset = tmpioh & 3;
551 nval = val /*<< (8 * offset)*/;
552 port = (u_int32_t *)((tmpioh << 5) | (3 << 3));
553 *port = nval;
554 alpha_mb();
555 }
556
557 void
558 __C(CHIP,_io_write_8)(v, ioh, off, val)
559 void *v;
560 bus_space_handle_t ioh;
561 bus_size_t off;
562 u_int64_t val;
563 {
564
565 /* XXX XXX XXX */
566 panic("%s not implemented", __S(__C(CHIP,_io_write_8)));
567 alpha_mb();
568 }
569
570 #define CHIP_io_write_multi_N(BYTES,TYPE) \
571 void \
572 __C(__C(CHIP,_io_write_multi_),BYTES)(v, h, o, a, c) \
573 void *v; \
574 bus_space_handle_t h; \
575 bus_size_t o, c; \
576 const TYPE *a; \
577 { \
578 \
579 while (c-- > 0) { \
580 __C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++); \
581 __C(CHIP,_io_barrier)(v, h, o, sizeof *a, \
582 BUS_BARRIER_WRITE); \
583 } \
584 }
585 CHIP_io_write_multi_N(1,u_int8_t)
586 CHIP_io_write_multi_N(2,u_int16_t)
587 CHIP_io_write_multi_N(4,u_int32_t)
588 CHIP_io_write_multi_N(8,u_int64_t)
589
590 #define CHIP_io_write_region_N(BYTES,TYPE) \
591 void \
592 __C(__C(CHIP,_io_write_region_),BYTES)(v, h, o, a, c) \
593 void *v; \
594 bus_space_handle_t h; \
595 bus_size_t o, c; \
596 const TYPE *a; \
597 { \
598 \
599 while (c-- > 0) { \
600 __C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++); \
601 o += sizeof *a; \
602 } \
603 }
604 CHIP_io_write_region_N(1,u_int8_t)
605 CHIP_io_write_region_N(2,u_int16_t)
606 CHIP_io_write_region_N(4,u_int32_t)
607 CHIP_io_write_region_N(8,u_int64_t)
608
609 void
610 __C(CHIP,_io_barrier)(v, h, o, l, f)
611 void *v;
612 bus_space_handle_t h;
613 bus_size_t o, l;
614 int f;
615 {
616
617 if ((f & BUS_BARRIER_READ) != 0)
618 alpha_mb();
619 else if ((f & BUS_BARRIER_WRITE) != 0)
620 alpha_wmb();
621 }
622