]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/pc98/pc98/busiosubr.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.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_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 }