1 /* $FreeBSD: releng/6.0/sys/pc98/pc98/busiosubr.c 139825 2005-01-07 02:29:27Z imp $ */
2 /* $NecBSD: busiosubr.c,v 1.30.4.4 1999/08/28 02:25:35 honda Exp $ */
3 /* $NetBSD$ */
4
5 /*-
6 * [NetBSD for NEC PC-98 series]
7 * Copyright (c) 1996, 1997, 1998
8 * NetBSD/pc98 porting staff. All rights reserved.
9 *
10 * [Ported for FreeBSD]
11 * Copyright (c) 2001
12 * TAKAHASHI Yoshihiro. All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. The name of the author may not be used to endorse or promote products
23 * derived from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 /*
39 * Copyright (c) 1997, 1998
40 * Naofumi HONDA. All rights reserved.
41 */
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
47 #include <machine/bus.h>
48
49 static MALLOC_DEFINE(M_BUSSPACEHANDLE, "busspacehandle", "Bus space handle");
50
51 _BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int8_t,1)
52 _BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int16_t,2)
53 _BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int32_t,4)
54 _BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int8_t,1)
55 _BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int16_t,2)
56 _BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int32_t,4)
57
58 _BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int8_t,1)
59 _BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int16_t,2)
60 _BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int32_t,4)
61 _BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int8_t,1)
62 _BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int16_t,2)
63 _BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int32_t,4)
64
65 struct bus_space_tag SBUS_io_space_tag = {
66 BUS_SPACE_IO,
67
68 /* direct bus access methods */
69 {
70 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int8_t,1),
71 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int16_t,2),
72 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int32_t,4),
73 },
74
75 /* relocate bus access methods */
76 {
77 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int8_t,1),
78 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int16_t,2),
79 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int32_t,4),
80 }
81 };
82
83 struct bus_space_tag SBUS_mem_space_tag = {
84 BUS_SPACE_MEM,
85
86 /* direct bus access methods */
87 {
88 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int8_t,1),
89 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int16_t,2),
90 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int32_t,4),
91 },
92
93 /* relocate bus access methods */
94 {
95 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int8_t,1),
96 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int16_t,2),
97 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int32_t,4),
98 }
99 };
100
101
102 #include "opt_mecia.h"
103 #ifdef DEV_MECIA
104
105 _BUS_SPACE_CALL_FUNCS_PROTO(NEPC_DA_io,u_int16_t,2)
106 _BUS_SPACE_CALL_FUNCS_PROTO(NEPC_DA_io,u_int32_t,4)
107
108 _BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int16_t,2)
109 _BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int32_t,4)
110
111 struct bus_space_tag NEPC_io_space_tag = {
112 BUS_SPACE_IO,
113
114 /* direct bus access methods */
115 {
116 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int8_t,1),
117 _BUS_SPACE_CALL_FUNCS_TAB(NEPC_DA_io,u_int16_t,2),
118 _BUS_SPACE_CALL_FUNCS_TAB(NEPC_DA_io,u_int32_t,4),
119 },
120
121 /* relocate bus access methods */
122 {
123 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int8_t,1),
124 _BUS_SPACE_CALL_FUNCS_TAB(NEPC_RA_io,u_int16_t,2),
125 _BUS_SPACE_CALL_FUNCS_TAB(NEPC_RA_io,u_int32_t,4),
126 }
127 };
128
129 struct bus_space_tag NEPC_mem_space_tag = {
130 BUS_SPACE_MEM,
131
132 /* direct bus access methods */
133 {
134 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int8_t,1),
135 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int16_t,2),
136 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int32_t,4),
137 },
138
139 /* relocate bus access methods */
140 {
141 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int8_t,1),
142 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int16_t,2),
143 _BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int32_t,4),
144 }
145 };
146
147 #endif /* DEV_MECIA */
148
149 /*************************************************************************
150 * map init
151 *************************************************************************/
152 static __inline void
153 bus_space_iat_init(bus_space_handle_t bsh)
154 {
155 int i;
156
157 for (i = 0; i < bsh->bsh_maxiatsz; i++)
158 bsh->bsh_iat[i] = bsh->bsh_base + i;
159 }
160
161 /*************************************************************************
162 * handle allocation
163 *************************************************************************/
164 int
165 i386_bus_space_handle_alloc(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size,
166 bus_space_handle_t *bshp)
167 {
168 bus_space_handle_t bsh;
169
170 bsh = (bus_space_handle_t) malloc(sizeof (*bsh), M_BUSSPACEHANDLE,
171 M_NOWAIT | M_ZERO);
172 if (bsh == NULL)
173 return ENOMEM;
174
175 bsh->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE;
176 bsh->bsh_iatsz = 0;
177 bsh->bsh_base = bpa;
178 bsh->bsh_sz = size;
179 bsh->bsh_res = NULL;
180 bsh->bsh_ressz = 0;
181 bus_space_iat_init(bsh);
182
183 bsh->bsh_bam = t->bs_da; /* default: direct access */
184
185 *bshp = bsh;
186 return 0;
187 }
188
189 void
190 i386_bus_space_handle_free(bus_space_tag_t t, bus_space_handle_t bsh,
191 size_t size)
192 {
193
194 free(bsh, M_BUSSPACEHANDLE);
195 }
196
197 /*************************************************************************
198 * map
199 *************************************************************************/
200 int
201 i386_memio_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags,
202 bus_space_handle_t *bshp)
203 {
204
205 return i386_bus_space_handle_alloc(t, bpa, size, bshp);
206 }
207
208 void
209 i386_memio_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
210 {
211
212 i386_bus_space_handle_free(t, bsh, bsh->bsh_sz);
213 }
214
215 void
216 i386_memio_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
217 {
218
219 /* i386_memio_unmap() does all that we need to do. */
220 i386_memio_unmap(t, bsh, bsh->bsh_sz);
221 }
222
223 int
224 i386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh,
225 bus_size_t offset, bus_size_t size,
226 bus_space_handle_t *tbshp)
227 {
228 int i, error = 0;
229 bus_space_handle_t bsh;
230 bus_addr_t pbase;
231
232 pbase = pbsh->bsh_base + offset;
233 switch (t->bs_tag) {
234 case BUS_SPACE_IO:
235 if (pbsh->bsh_iatsz > 0) {
236 if (offset >= pbsh->bsh_iatsz ||
237 offset + size > pbsh->bsh_iatsz)
238 return EINVAL;
239 pbase = pbsh->bsh_base;
240 }
241 break;
242
243 case BUS_SPACE_MEM:
244 if (pbsh->bsh_iatsz > 0)
245 return EINVAL;
246 if (offset > pbsh->bsh_sz || offset + size > pbsh->bsh_sz)
247 return EINVAL;
248 break;
249
250 default:
251 panic("i386_memio_subregion: bad bus space tag");
252 break;
253 }
254
255 error = i386_bus_space_handle_alloc(t, pbase, size, &bsh);
256 if (error != 0)
257 return error;
258
259 switch (t->bs_tag) {
260 case BUS_SPACE_IO:
261 if (pbsh->bsh_iatsz > 0) {
262 for (i = 0; i < size; i ++)
263 bsh->bsh_iat[i] = pbsh->bsh_iat[i + offset];
264 bsh->bsh_iatsz = size;
265 } else if (pbsh->bsh_base > bsh->bsh_base ||
266 pbsh->bsh_base + pbsh->bsh_sz <
267 bsh->bsh_base + bsh->bsh_sz) {
268 i386_bus_space_handle_free(t, bsh, size);
269 return EINVAL;
270 }
271 break;
272
273 case BUS_SPACE_MEM:
274 break;
275 }
276
277 if (pbsh->bsh_iatsz > 0)
278 bsh->bsh_bam = t->bs_ra; /* relocate access */
279 *tbshp = bsh;
280 return error;
281 }
Cache object: d88987247575a055c5aa7a294030585b
|