1 /* $NetBSD: a12c_bus_mem.c,v 1.6 2009/03/14 14:45:53 dsl Exp $ */
3 /* [Notice revision 2.0]
4 * Copyright (c) 1997 Avalon Computer Systems, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright and
13 * author notice, this list of conditions, and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of Avalon Computer Systems, Inc. nor the names of
18 * its contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 * 4. This copyright will be assigned to The NetBSD Foundation on
21 * 1/1/2000 unless these terms (including possibly the assignment
22 * date) are updated in writing by Avalon prior to the latest specified
25 * THIS SOFTWARE IS PROVIDED BY AVALON COMPUTER SYSTEMS, INC. AND CONTRIBUTORS
26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
38 #include "opt_avalon_a12.h" /* Config options headers */
39 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/device.h>
43 #include <machine/bus.h>
44 #include <alpha/pci/a12creg.h>
45 #include <alpha/pci/a12cvar.h>
47 #define A12C_BUS_MEM() /* Generate ctags(1) key */
49 __KERNEL_RCSID(0, "$NetBSD: a12c_bus_mem.c,v 1.6 2009/03/14 14:45:53 dsl Exp $");
52 void pci_a12c_mem_barrier(void *, bus_space_handle_t
,
53 bus_size_t
, bus_size_t
, int);
55 /* Memory read (single) */
56 u_int8_t
pci_a12c_mem_read_1(void *, bus_space_handle_t
,
58 u_int16_t
pci_a12c_mem_read_2(void *, bus_space_handle_t
,
60 u_int32_t
pci_a12c_mem_read_4(void *, bus_space_handle_t
,
62 u_int64_t
pci_a12c_mem_read_8(void *, bus_space_handle_t
,
65 /* Memory read multiple */
66 void pci_a12c_mem_read_multi_1(void *, bus_space_handle_t
,
67 bus_size_t
, u_int8_t
*, bus_size_t
);
68 void pci_a12c_mem_read_multi_2(void *, bus_space_handle_t
,
69 bus_size_t
, u_int16_t
*, bus_size_t
);
70 void pci_a12c_mem_read_multi_4(void *, bus_space_handle_t
,
71 bus_size_t
, u_int32_t
*, bus_size_t
);
72 void pci_a12c_mem_read_multi_8(void *, bus_space_handle_t
,
73 bus_size_t
, u_int64_t
*, bus_size_t
);
75 /* Memory read region */
76 void pci_a12c_mem_read_region_1(void *, bus_space_handle_t
,
77 bus_size_t
, u_int8_t
*, bus_size_t
);
78 void pci_a12c_mem_read_region_2(void *, bus_space_handle_t
,
79 bus_size_t
, u_int16_t
*, bus_size_t
);
80 void pci_a12c_mem_read_region_4(void *, bus_space_handle_t
,
81 bus_size_t
, u_int32_t
*, bus_size_t
);
82 void pci_a12c_mem_read_region_8(void *, bus_space_handle_t
,
83 bus_size_t
, u_int64_t
*, bus_size_t
);
85 /* Memory write (single) */
86 void pci_a12c_mem_write_1(void *, bus_space_handle_t
,
87 bus_size_t
, u_int8_t
);
88 void pci_a12c_mem_write_2(void *, bus_space_handle_t
,
89 bus_size_t
, u_int16_t
);
90 void pci_a12c_mem_write_4(void *, bus_space_handle_t
,
91 bus_size_t
, u_int32_t
);
92 void pci_a12c_mem_write_8(void *, bus_space_handle_t
,
93 bus_size_t
, u_int64_t
);
95 /* Memory write multiple */
96 void pci_a12c_mem_write_multi_1(void *, bus_space_handle_t
,
97 bus_size_t
, const u_int8_t
*, bus_size_t
);
98 void pci_a12c_mem_write_multi_2(void *, bus_space_handle_t
,
99 bus_size_t
, const u_int16_t
*, bus_size_t
);
100 void pci_a12c_mem_write_multi_4(void *, bus_space_handle_t
,
101 bus_size_t
, const u_int32_t
*, bus_size_t
);
102 void pci_a12c_mem_write_multi_8(void *, bus_space_handle_t
,
103 bus_size_t
, const u_int64_t
*, bus_size_t
);
105 /* Memory write region */
106 void pci_a12c_mem_write_region_1(void *, bus_space_handle_t
,
107 bus_size_t
, const u_int8_t
*, bus_size_t
);
108 void pci_a12c_mem_write_region_2(void *, bus_space_handle_t
,
109 bus_size_t
, const u_int16_t
*, bus_size_t
);
110 void pci_a12c_mem_write_region_4(void *, bus_space_handle_t
,
111 bus_size_t
, const u_int32_t
*, bus_size_t
);
112 void pci_a12c_mem_write_region_8(void *, bus_space_handle_t
,
113 bus_size_t
, const u_int64_t
*, bus_size_t
);
115 /* Memory set multiple */
116 void pci_a12c_mem_set_multi_1(void *, bus_space_handle_t
,
117 bus_size_t
, u_int8_t
, bus_size_t
);
118 void pci_a12c_mem_set_multi_2(void *, bus_space_handle_t
,
119 bus_size_t
, u_int16_t
, bus_size_t
);
120 void pci_a12c_mem_set_multi_4(void *, bus_space_handle_t
,
121 bus_size_t
, u_int32_t
, bus_size_t
);
122 void pci_a12c_mem_set_multi_8(void *, bus_space_handle_t
,
123 bus_size_t
, u_int64_t
, bus_size_t
);
125 /* Memory set region */
126 void pci_a12c_mem_set_region_1(void *, bus_space_handle_t
,
127 bus_size_t
, u_int8_t
, bus_size_t
);
128 void pci_a12c_mem_set_region_2(void *, bus_space_handle_t
,
129 bus_size_t
, u_int16_t
, bus_size_t
);
130 void pci_a12c_mem_set_region_4(void *, bus_space_handle_t
,
131 bus_size_t
, u_int32_t
, bus_size_t
);
132 void pci_a12c_mem_set_region_8(void *, bus_space_handle_t
,
133 bus_size_t
, u_int64_t
, bus_size_t
);
136 void pci_a12c_mem_copy_region_1(void *, bus_space_handle_t
,
137 bus_size_t
, bus_space_handle_t
, bus_size_t
, bus_size_t
);
138 void pci_a12c_mem_copy_region_2(void *, bus_space_handle_t
,
139 bus_size_t
, bus_space_handle_t
, bus_size_t
, bus_size_t
);
140 void pci_a12c_mem_copy_region_4(void *, bus_space_handle_t
,
141 bus_size_t
, bus_space_handle_t
, bus_size_t
, bus_size_t
);
142 void pci_a12c_mem_copy_region_8(void *, bus_space_handle_t
,
143 bus_size_t
, bus_space_handle_t
, bus_size_t
, bus_size_t
);
145 #define __S(S) __STRING(S)
147 /* mapping/unmapping */
148 int pci_a12c_mem_map(void *, bus_addr_t
, bus_size_t
, int,
149 bus_space_handle_t
*, int);
150 void pci_a12c_mem_unmap(void *, bus_space_handle_t
,
152 int pci_a12c_mem_subregion(void *, bus_space_handle_t
,
153 bus_size_t
, bus_size_t
, bus_space_handle_t
*);
155 /* allocation/deallocation */
156 int pci_a12c_mem_alloc(void *, bus_addr_t
, bus_addr_t
,
157 bus_size_t
, bus_size_t
, bus_addr_t
, int, bus_addr_t
*,
158 bus_space_handle_t
*);
159 void pci_a12c_mem_free(void *, bus_space_handle_t
,
162 /* get kernel virtual address*/
163 void *pci_a12c_mem_vaddr(void *, bus_space_handle_t
);
165 static struct alpha_bus_space pci_a12c_mem_space
= {
169 /* mapping/unmapping */
172 pci_a12c_mem_subregion
,
174 /* allocation/deallocation */
178 /* get kernel virtual address */
182 pci_a12c_mem_barrier
,
191 pci_a12c_mem_read_multi_1
,
192 pci_a12c_mem_read_multi_2
,
193 pci_a12c_mem_read_multi_4
,
194 pci_a12c_mem_read_multi_8
,
197 pci_a12c_mem_read_region_1
,
198 pci_a12c_mem_read_region_2
,
199 pci_a12c_mem_read_region_4
,
200 pci_a12c_mem_read_region_8
,
203 pci_a12c_mem_write_1
,
204 pci_a12c_mem_write_2
,
205 pci_a12c_mem_write_4
,
206 pci_a12c_mem_write_8
,
209 pci_a12c_mem_write_multi_1
,
210 pci_a12c_mem_write_multi_2
,
211 pci_a12c_mem_write_multi_4
,
212 pci_a12c_mem_write_multi_8
,
215 pci_a12c_mem_write_region_1
,
216 pci_a12c_mem_write_region_2
,
217 pci_a12c_mem_write_region_4
,
218 pci_a12c_mem_write_region_8
,
221 pci_a12c_mem_set_multi_1
,
222 pci_a12c_mem_set_multi_2
,
223 pci_a12c_mem_set_multi_4
,
224 pci_a12c_mem_set_multi_8
,
227 pci_a12c_mem_set_region_1
,
228 pci_a12c_mem_set_region_2
,
229 pci_a12c_mem_set_region_4
,
230 pci_a12c_mem_set_region_8
,
233 pci_a12c_mem_copy_region_1
,
234 pci_a12c_mem_copy_region_2
,
235 pci_a12c_mem_copy_region_4
,
236 pci_a12c_mem_copy_region_8
,
240 a12c_bus_mem_init(void *v
)
244 t
= &pci_a12c_mem_space
;
250 pci_a12c_mem_map(void *v
, bus_addr_t memaddr
, bus_size_t memsize
, int flags
, bus_space_handle_t
*memhp
, int acct
)
252 if(flags
& BUS_SPACE_MAP_LINEAR
)
253 printf("warning, linear a12 pci map requested\n");
254 if(memaddr
>= 1L<<28 || memaddr
<0)
261 pci_a12c_mem_unmap(void *v
, bus_space_handle_t memh
, bus_size_t memsize
, int acct
)
266 pci_a12c_mem_subregion(void *v
, bus_space_handle_t memh
, bus_size_t offset
, bus_size_t size
, bus_space_handle_t
*nmemh
)
268 *nmemh
= memh
+ offset
;
273 pci_a12c_mem_alloc(v
, rstart
, rend
, size
, align
, boundary
, flags
,
276 bus_addr_t rstart
, rend
, *addrp
;
277 bus_size_t size
, align
, boundary
;
279 bus_space_handle_t
*bshp
;
285 pci_a12c_mem_free(void *v
, bus_space_handle_t bsh
, bus_size_t size
)
290 pci_a12c_mem_vaddr(void *v
, bus_space_handle_t bsh
)
292 /* not supported (could panic() if pci_a12c_mem_map() caught it) */
297 pci_a12c_mem_barrier(void *v
, bus_space_handle_t h
, bus_size_t o
, bus_size_t l
, int f
)
299 /* optimize for wmb-only case but fall back to the more general mb */
301 if (f
== BUS_SPACE_BARRIER_WRITE
)
306 * Don't worry about calling small subroutines on the alpha. In the
307 * time it takes to do a PCI bus target transfer, the 21164-400 can execute
308 * 160 cycles, and up to 320 integer instructions.
311 setup_target_transfer(bus_space_handle_t memh
, bus_size_t off
)
313 register u_int64_t addr
,t
;
317 t
= REGVAL(A12_OMR
) & ~A12_OMR_PCIAddr2
;
319 t
|= A12_OMR_PCIAddr2
;
322 return (void *)ALPHA_PHYS_TO_K0SEG(A12_PCITarget
| (addr
& ~4L));
325 #define TARGET_EA(t,memh,off) ((t *)setup_target_transfer((memh),(off)))
327 #define TARGET_READ(n,t) \
330 __CONCAT(pci_a12c_mem_read_,n)(void *v, \
331 bus_space_handle_t memh, \
334 return *TARGET_EA(t,memh,off); \
337 TARGET_READ(1, u_int8_t
)
338 TARGET_READ(2, u_int16_t
)
339 TARGET_READ(4, u_int32_t
)
340 TARGET_READ(8, u_int64_t
)
342 #define pci_a12c_mem_read_multi_N(BYTES,TYPE) \
344 __CONCAT(pci_a12c_mem_read_multi_,BYTES)(v, h, o, a, c) \
346 bus_space_handle_t h; \
353 *a++ = __CONCAT(pci_a12c_mem_read_,BYTES)(v, h, o); \
357 pci_a12c_mem_read_multi_N(1,u_int8_t
)
358 pci_a12c_mem_read_multi_N(2,u_int16_t
)
359 pci_a12c_mem_read_multi_N(4,u_int32_t
)
360 pci_a12c_mem_read_multi_N(8,u_int64_t
)
363 * In this case, we _really_ don't want all those barriers that the
364 * bus_space_read's once did, and that we have carried over into
365 * the A12 version. Perhaps we need a gratuitous barrier-on mode.
366 * The only reason to have the bus_space_r/w functions do barriers is
367 * to make up for call sites that incorrectly omit the bus_space_barrier
371 #define pci_a12c_mem_read_region_N(BYTES,TYPE) \
373 __CONCAT(pci_a12c_mem_read_region_,BYTES)(v, h, o, a, c) \
375 bus_space_handle_t h; \
381 *a++ = __CONCAT(pci_a12c_mem_read_,BYTES)(v, h, o); \
385 pci_a12c_mem_read_region_N(1,u_int8_t
)
386 pci_a12c_mem_read_region_N(2,u_int16_t
)
387 pci_a12c_mem_read_region_N(4,u_int32_t
)
388 pci_a12c_mem_read_region_N(8,u_int64_t
)
390 #define TARGET_WRITE(n,t) \
392 __CONCAT(pci_a12c_mem_write_,n)(v, memh, off, val) \
394 bus_space_handle_t memh; \
399 *TARGET_EA(t,memh,off) = val; \
403 TARGET_WRITE(1,u_int8_t
)
404 TARGET_WRITE(2,u_int16_t
)
405 TARGET_WRITE(4,u_int32_t
)
406 TARGET_WRITE(8,u_int64_t
)
408 #define pci_a12c_mem_write_multi_N(BYTES,TYPE) \
410 __CONCAT(pci_a12c_mem_write_multi_,BYTES)(v, h, o, a, c) \
412 bus_space_handle_t h; \
418 __CONCAT(pci_a12c_mem_write_,BYTES)(v, h, o, *a++); \
423 pci_a12c_mem_write_multi_N(1,u_int8_t
)
424 pci_a12c_mem_write_multi_N(2,u_int16_t
)
425 pci_a12c_mem_write_multi_N(4,u_int32_t
)
426 pci_a12c_mem_write_multi_N(8,u_int64_t
)
428 #define pci_a12c_mem_write_region_N(BYTES,TYPE) \
430 __CONCAT(pci_a12c_mem_write_region_,BYTES)(v, h, o, a, c) \
432 bus_space_handle_t h; \
438 __CONCAT(pci_a12c_mem_write_,BYTES)(v, h, o, *a++); \
443 pci_a12c_mem_write_region_N(1,u_int8_t
)
444 pci_a12c_mem_write_region_N(2,u_int16_t
)
445 pci_a12c_mem_write_region_N(4,u_int32_t
)
446 pci_a12c_mem_write_region_N(8,u_int64_t
)
448 #define pci_a12c_mem_set_multi_N(BYTES,TYPE) \
450 __CONCAT(pci_a12c_mem_set_multi_,BYTES)(v, h, o, val, c) \
452 bus_space_handle_t h; \
458 __CONCAT(pci_a12c_mem_write_,BYTES)(v, h, o, val); \
463 pci_a12c_mem_set_multi_N(1,u_int8_t
)
464 pci_a12c_mem_set_multi_N(2,u_int16_t
)
465 pci_a12c_mem_set_multi_N(4,u_int32_t
)
466 pci_a12c_mem_set_multi_N(8,u_int64_t
)
468 #define pci_a12c_mem_set_region_N(BYTES,TYPE) \
470 __CONCAT(pci_a12c_mem_set_region_,BYTES)(v, h, o, val, c) \
472 bus_space_handle_t h; \
478 __CONCAT(pci_a12c_mem_write_,BYTES)(v, h, o, val); \
483 pci_a12c_mem_set_region_N(1,u_int8_t
)
484 pci_a12c_mem_set_region_N(2,u_int16_t
)
485 pci_a12c_mem_set_region_N(4,u_int32_t
)
486 pci_a12c_mem_set_region_N(8,u_int64_t
)
488 #define pci_a12c_mem_copy_region_N(BYTES) \
490 __CONCAT(pci_a12c_mem_copy_region_,BYTES)(v, h1, o1, h2, o2, c) \
492 bus_space_handle_t h1, h2; \
493 bus_size_t o1, o2, c; \
497 if ((h1 >> 63) != 0 && (h2 >> 63) != 0) { \
498 memmove((void *)(h2 + o2), (void *)(h1 + o1), c * BYTES); \
502 if (h1 + o1 >= h2 + o2) \
503 /* src after dest: copy forward */ \
504 for (o = 0; c > 0; c--, o += BYTES) \
505 __CONCAT(pci_a12c_mem_write_,BYTES)(v, h2, o2 + o, \
506 __CONCAT(pci_a12c_mem_read_,BYTES)(v, h1, o1 + o)); \
508 /* dest after src: copy backwards */ \
509 for (o = (c - 1) * BYTES; c > 0; c--, o -= BYTES) \
510 __CONCAT(pci_a12c_mem_write_,BYTES)(v, h2, o2 + o, \
511 __CONCAT(pci_a12c_mem_read_,BYTES)(v, h1, o1 + o)); \
513 pci_a12c_mem_copy_region_N(1)
514 pci_a12c_mem_copy_region_N(2)
515 pci_a12c_mem_copy_region_N(4)
516 pci_a12c_mem_copy_region_N(8)