]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/pc98/pc98/busiosubr.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / pc98 / pc98 / busiosubr.c
1 /* $FreeBSD$ */
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_TAG_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_TAG_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_TAG_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_TAG_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_map_load(bus_space_tag_t t, bus_space_handle_t bsh,
225                     bus_size_t size, bus_space_iat_t iat, u_int flags __unused)
226 {
227         int i;
228
229         if (size > bsh->bsh_maxiatsz) {
230                 printf("i386_memio_map_load: map size too large\n");
231                 return EINVAL;
232         }
233
234         for (i = 0; i < bsh->bsh_maxiatsz; i++) {
235                 if (i < size)
236                         bsh->bsh_iat[i] = iat[i];
237                 else
238                         bsh->bsh_iat[i] = 0;
239                 bsh->bsh_iat[i] += bsh->bsh_base;
240         }
241
242         bsh->bsh_iatsz = size;
243         bsh->bsh_bam = t->bs_ra;        /* relocate access */
244
245         return 0;
246 }
247
248 int
249 i386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh,
250                      bus_size_t offset, bus_size_t size,
251                      bus_space_handle_t *tbshp)
252 {
253         int i, error = 0;
254         bus_space_handle_t bsh;
255         bus_addr_t pbase;
256
257         pbase = pbsh->bsh_base + offset;
258         switch (t->bs_tag) {
259         case BUS_SPACE_TAG_IO:
260                 if (pbsh->bsh_iatsz > 0) {
261                         if (offset >= pbsh->bsh_iatsz || 
262                             offset + size > pbsh->bsh_iatsz)
263                                 return EINVAL;
264                         pbase = pbsh->bsh_base;
265                 }
266                 break;
267
268         case BUS_SPACE_TAG_MEM:
269                 if (pbsh->bsh_iatsz > 0)
270                         return EINVAL;
271                 if (offset > pbsh->bsh_sz || offset + size > pbsh->bsh_sz)
272                         return EINVAL;
273                 break;
274
275         default:
276                 panic("i386_memio_subregion: bad bus space tag");
277                 break;
278         }
279
280         error = i386_bus_space_handle_alloc(t, pbase, size, &bsh);
281         if (error != 0)
282                 return error;
283
284         switch (t->bs_tag) {
285         case BUS_SPACE_TAG_IO:
286                 if (pbsh->bsh_iatsz > 0) {
287                         for (i = 0; i < size; i ++)
288                                 bsh->bsh_iat[i] = pbsh->bsh_iat[i + offset];
289                         bsh->bsh_iatsz = size;
290                 } else if (pbsh->bsh_base > bsh->bsh_base ||
291                          pbsh->bsh_base + pbsh->bsh_sz <
292                          bsh->bsh_base + bsh->bsh_sz) {
293                         i386_bus_space_handle_free(t, bsh, size);
294                         return EINVAL;
295                 }
296                 break;
297
298         case BUS_SPACE_TAG_MEM:
299                 break;
300         }
301
302         if (pbsh->bsh_iatsz > 0)
303                 bsh->bsh_bam = t->bs_ra;        /* relocate access */
304         *tbshp = bsh;
305         return error;
306 }
307
308 int
309 i386_memio_compare(bus_space_tag_t t1, bus_space_handle_t bsh1,
310                    bus_space_tag_t t2, bus_space_handle_t bsh2)
311 {
312         int i;
313
314         if (t1->bs_tag != t2->bs_tag)
315                 return (1);
316         if (bsh1->bsh_base != bsh2->bsh_base)
317                 return (1);
318         if (bsh1->bsh_sz != bsh2->bsh_sz)
319                 return (1);
320         if (bsh1->bsh_bam.bs_read_1 != bsh2->bsh_bam.bs_read_1) /* XXX */
321                 return (1);
322
323         if (bsh1->bsh_iatsz != bsh2->bsh_iatsz)
324                 return (1);
325         for (i = 0; i < bsh1->bsh_iatsz; i++) {
326                 if (bsh1->bsh_iat[i] != bsh2->bsh_iat[i])
327                         return (1);
328         }
329
330         return (0);
331 }