busiosubr.c revision 120375
1240135Skib/* $FreeBSD: head/sys/pc98/pc98/busiosubr.c 120375 2003-09-23 08:22:34Z nyan $ */
2257491Skib/*	$NecBSD: busiosubr.c,v 1.30.4.4 1999/08/28 02:25:35 honda Exp $	*/
3254147Sobrien/*	$NetBSD$	*/
4240135Skib
5240135Skib/*
6240135Skib * [NetBSD for NEC PC-98 series]
7257491Skib *  Copyright (c) 1996, 1997, 1998
8257491Skib *	NetBSD/pc98 porting staff. All rights reserved.
9257491Skib *
10240135Skib * [Ported for FreeBSD]
11240135Skib *  Copyright (c) 2001
12240135Skib *	TAKAHASHI Yoshihiro. All rights reserved.
13240135Skib *
14240135Skib *  Redistribution and use in source and binary forms, with or without
15240135Skib *  modification, are permitted provided that the following conditions
16240135Skib *  are met:
17240135Skib *  1. Redistributions of source code must retain the above copyright
18240135Skib *     notice, this list of conditions and the following disclaimer.
19240135Skib *  2. Redistributions in binary form must reproduce the above copyright
20240135Skib *     notice, this list of conditions and the following disclaimer in the
21240135Skib *     documentation and/or other materials provided with the distribution.
22240135Skib *  3. The name of the author may not be used to endorse or promote products
23240135Skib *     derived from this software without specific prior written permission.
24240135Skib *
25240135Skib * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26240135Skib * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27240135Skib * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28240135Skib * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
29240135Skib * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30240135Skib * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31240135Skib * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32240135Skib * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33240135Skib * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34240135Skib * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35240135Skib * POSSIBILITY OF SUCH DAMAGE.
36240135Skib */
37254147Sobrien
38240135Skib/*
39256381Smarkm * Copyright (c) 1997, 1998
40254147Sobrien *	Naofumi HONDA.  All rights reserved.
41256381Smarkm */
42240135Skib
43240135Skib#include <sys/param.h>
44254147Sobrien#include <sys/systm.h>
45254147Sobrien#include <sys/kernel.h>
46254147Sobrien#include <sys/malloc.h>
47254147Sobrien#include <machine/bus.h>
48256381Smarkm
49256381Smarkmstatic MALLOC_DEFINE(M_BUSSPACEHANDLE, "busspacehandle", "Bus space handle");
50256381Smarkm
51256381Smarkm_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int8_t,1)
52254147Sobrien_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int16_t,2)
53240135Skib_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int32_t,4)
54240135Skib_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int8_t,1)
55240135Skib_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int16_t,2)
56240135Skib_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int32_t,4)
57240135Skib
58256381Smarkm_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int8_t,1)
59268519Sdelphij_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int16_t,2)
60256381Smarkm_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int32_t,4)
61256381Smarkm_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int8_t,1)
62240135Skib_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int16_t,2)
63240135Skib_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int32_t,4)
64240135Skib
65257491Skibstruct bus_space_tag SBUS_io_space_tag = {
66240135Skib	BUS_SPACE_IO,
67240135Skib
68257491Skib	/* direct bus access methods */
69257491Skib	{
70240135Skib		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int8_t,1),
71257491Skib		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int16_t,2),
72240135Skib		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int32_t,4),
73257491Skib	},
74257491Skib
75257491Skib	/* relocate bus access methods */
76257491Skib	{
77257491Skib		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int8_t,1),
78257491Skib		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int16_t,2),
79257491Skib		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int32_t,4),
80257491Skib	}
81257491Skib};
82257491Skib
83257491Skibstruct bus_space_tag SBUS_mem_space_tag = {
84240135Skib	BUS_SPACE_MEM,
85240135Skib
86240135Skib	/* direct bus access methods */
87240135Skib	{
88240135Skib		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int8_t,1),
89240135Skib		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int16_t,2),
90240135Skib		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int32_t,4),
91240135Skib	},
92257491Skib
93257491Skib	/* relocate bus access methods */
94240135Skib	{
95257491Skib		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int8_t,1),
96257491Skib		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int16_t,2),
97257491Skib		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int32_t,4),
98240135Skib	}
99240135Skib};
100240135Skib
101240135Skib
102240135Skib#include "opt_mecia.h"
103254147Sobrien#ifdef DEV_MECIA
104254147Sobrien
105254147Sobrien_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_DA_io,u_int16_t,2)
106256381Smarkm_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_DA_io,u_int32_t,4)
107254147Sobrien
108254147Sobrien_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int16_t,2)
109254147Sobrien_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int32_t,4)
110256381Smarkm
111256381Smarkmstruct bus_space_tag NEPC_io_space_tag = {
112256381Smarkm	BUS_SPACE_IO,
113254147Sobrien
114254147Sobrien	/* direct bus access methods */
115240135Skib	{
116256381Smarkm		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int8_t,1),
117254147Sobrien		_BUS_SPACE_CALL_FUNCS_TAB(NEPC_DA_io,u_int16_t,2),
118256381Smarkm		_BUS_SPACE_CALL_FUNCS_TAB(NEPC_DA_io,u_int32_t,4),
119256381Smarkm	},
120256381Smarkm
121256381Smarkm	/* relocate bus access methods */
122256381Smarkm	{
123256381Smarkm		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int8_t,1),
124256381Smarkm		_BUS_SPACE_CALL_FUNCS_TAB(NEPC_RA_io,u_int16_t,2),
125256381Smarkm		_BUS_SPACE_CALL_FUNCS_TAB(NEPC_RA_io,u_int32_t,4),
126256381Smarkm	}
127256381Smarkm};
128256381Smarkm
129256381Smarkmstruct bus_space_tag NEPC_mem_space_tag = {
130256381Smarkm	BUS_SPACE_MEM,
131256381Smarkm
132254147Sobrien	/* direct bus access methods */
133254147Sobrien	{
134256381Smarkm		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int8_t,1),
135254147Sobrien		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int16_t,2),
136254147Sobrien		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int32_t,4),
137256381Smarkm	},
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 *************************************************************************/
152static __inline void
153bus_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 *************************************************************************/
164int
165i386_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
189void
190i386_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 *************************************************************************/
200int
201i386_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
208void
209i386_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
215void
216i386_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
223int
224i386_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}
282