184615Snyan/* $FreeBSD$ */
284615Snyan/*	$NecBSD: busiosubr.c,v 1.30.4.4 1999/08/28 02:25:35 honda Exp $	*/
384615Snyan/*	$NetBSD$	*/
484615Snyan
5139825Simp/*-
684615Snyan * [NetBSD for NEC PC-98 series]
784615Snyan *  Copyright (c) 1996, 1997, 1998
884615Snyan *	NetBSD/pc98 porting staff. All rights reserved.
984615Snyan *
1084615Snyan * [Ported for FreeBSD]
1184615Snyan *  Copyright (c) 2001
1284615Snyan *	TAKAHASHI Yoshihiro. All rights reserved.
1384615Snyan *
1484615Snyan *  Redistribution and use in source and binary forms, with or without
1584615Snyan *  modification, are permitted provided that the following conditions
1684615Snyan *  are met:
1784615Snyan *  1. Redistributions of source code must retain the above copyright
1884615Snyan *     notice, this list of conditions and the following disclaimer.
1984615Snyan *  2. Redistributions in binary form must reproduce the above copyright
2084615Snyan *     notice, this list of conditions and the following disclaimer in the
2184615Snyan *     documentation and/or other materials provided with the distribution.
2284615Snyan *  3. The name of the author may not be used to endorse or promote products
2384615Snyan *     derived from this software without specific prior written permission.
2484615Snyan *
2584615Snyan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2684615Snyan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2784615Snyan * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2884615Snyan * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2984615Snyan * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
3084615Snyan * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
3184615Snyan * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3284615Snyan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3384615Snyan * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
3484615Snyan * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3584615Snyan * POSSIBILITY OF SUCH DAMAGE.
3684615Snyan */
3784615Snyan
3884615Snyan/*
3984615Snyan * Copyright (c) 1997, 1998
4084615Snyan *	Naofumi HONDA.  All rights reserved.
4184615Snyan */
4284615Snyan
4384615Snyan#include <sys/param.h>
4484615Snyan#include <sys/systm.h>
4584615Snyan#include <sys/kernel.h>
4690762Snyan#include <sys/malloc.h>
4784615Snyan#include <machine/bus.h>
4884615Snyan
4990762Snyanstatic MALLOC_DEFINE(M_BUSSPACEHANDLE, "busspacehandle", "Bus space handle");
5090762Snyan
5184615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int8_t,1)
5284615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int16_t,2)
5384615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int32_t,4)
5484615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int8_t,1)
5584615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int16_t,2)
5684615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_mem,u_int32_t,4)
5784615Snyan
5884615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int8_t,1)
5984615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int16_t,2)
6084615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_io,u_int32_t,4)
6184615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int8_t,1)
6284615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int16_t,2)
6384615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_RA_mem,u_int32_t,4)
6484615Snyan
6584615Snyanstruct bus_space_tag SBUS_io_space_tag = {
66214584Snyan	BUS_SPACE_TAG_IO,
6784615Snyan
6884615Snyan	/* direct bus access methods */
6984615Snyan	{
7084615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int8_t,1),
7184615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int16_t,2),
7284615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int32_t,4),
7384615Snyan	},
7484615Snyan
7584615Snyan	/* relocate bus access methods */
7684615Snyan	{
7784615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int8_t,1),
7884615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int16_t,2),
7984615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int32_t,4),
8084615Snyan	}
8184615Snyan};
8284615Snyan
8384615Snyanstruct bus_space_tag SBUS_mem_space_tag = {
84214584Snyan	BUS_SPACE_TAG_MEM,
8584615Snyan
8684615Snyan	/* direct bus access methods */
8784615Snyan	{
8884615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int8_t,1),
8984615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int16_t,2),
9084615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int32_t,4),
9184615Snyan	},
9284615Snyan
9384615Snyan	/* relocate bus access methods */
9484615Snyan	{
9584615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int8_t,1),
9684615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int16_t,2),
9784615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int32_t,4),
9884615Snyan	}
9984615Snyan};
10084615Snyan
10184615Snyan
10284615Snyan#include "opt_mecia.h"
10384615Snyan#ifdef DEV_MECIA
10484615Snyan
10584615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_DA_io,u_int16_t,2)
10684615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_DA_io,u_int32_t,4)
10784615Snyan
10884615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int16_t,2)
10984615Snyan_BUS_SPACE_CALL_FUNCS_PROTO(NEPC_RA_io,u_int32_t,4)
11084615Snyan
11184615Snyanstruct bus_space_tag NEPC_io_space_tag = {
112214584Snyan	BUS_SPACE_TAG_IO,
11384615Snyan
11484615Snyan	/* direct bus access methods */
11584615Snyan	{
11684615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_io,u_int8_t,1),
11784615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(NEPC_DA_io,u_int16_t,2),
11884615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(NEPC_DA_io,u_int32_t,4),
11984615Snyan	},
12084615Snyan
12184615Snyan	/* relocate bus access methods */
12284615Snyan	{
12384615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_io,u_int8_t,1),
12484615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(NEPC_RA_io,u_int16_t,2),
12584615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(NEPC_RA_io,u_int32_t,4),
12684615Snyan	}
12784615Snyan};
12884615Snyan
12984615Snyanstruct bus_space_tag NEPC_mem_space_tag = {
130214584Snyan	BUS_SPACE_TAG_MEM,
13184615Snyan
13284615Snyan	/* direct bus access methods */
13384615Snyan	{
13484615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int8_t,1),
13584615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int16_t,2),
13684615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_DA_mem,u_int32_t,4),
13784615Snyan	},
13884615Snyan
13984615Snyan	/* relocate bus access methods */
14084615Snyan	{
14184615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int8_t,1),
14284615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int16_t,2),
14384615Snyan		_BUS_SPACE_CALL_FUNCS_TAB(SBUS_RA_mem,u_int32_t,4),
14484615Snyan	}
14584615Snyan};
14684615Snyan
14784615Snyan#endif /* DEV_MECIA */
14890762Snyan
14990762Snyan/*************************************************************************
15090762Snyan * map init
15190762Snyan *************************************************************************/
15290762Snyanstatic __inline void
15390762Snyanbus_space_iat_init(bus_space_handle_t bsh)
15490762Snyan{
15590762Snyan	int i;
15690762Snyan
15790762Snyan	for (i = 0; i < bsh->bsh_maxiatsz; i++)
15890762Snyan		bsh->bsh_iat[i] = bsh->bsh_base + i;
15990762Snyan}
16090762Snyan
16190762Snyan/*************************************************************************
16290762Snyan * handle allocation
16390762Snyan *************************************************************************/
16490762Snyanint
16590762Snyani386_bus_space_handle_alloc(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size,
16690762Snyan			    bus_space_handle_t *bshp)
16790762Snyan{
16890762Snyan	bus_space_handle_t bsh;
16990762Snyan
17090762Snyan	bsh = (bus_space_handle_t) malloc(sizeof (*bsh), M_BUSSPACEHANDLE,
17190762Snyan					  M_NOWAIT | M_ZERO);
17290762Snyan	if (bsh == NULL)
17390762Snyan		return ENOMEM;
17490762Snyan
17590762Snyan	bsh->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE;
17690762Snyan	bsh->bsh_iatsz = 0;
17790762Snyan	bsh->bsh_base = bpa;
17890762Snyan	bsh->bsh_sz = size;
17990762Snyan	bsh->bsh_res = NULL;
18090762Snyan	bsh->bsh_ressz = 0;
18190762Snyan	bus_space_iat_init(bsh);
18290762Snyan
18390762Snyan	bsh->bsh_bam = t->bs_da;		/* default: direct access */
18490762Snyan
18590762Snyan	*bshp = bsh;
18690762Snyan	return 0;
18790762Snyan}
18890762Snyan
18990762Snyanvoid
19090762Snyani386_bus_space_handle_free(bus_space_tag_t t, bus_space_handle_t bsh,
19190762Snyan			   size_t size)
19290762Snyan{
19390762Snyan
19490762Snyan	free(bsh, M_BUSSPACEHANDLE);
19590762Snyan}
19690762Snyan
19790762Snyan/*************************************************************************
19890762Snyan * map
19990762Snyan *************************************************************************/
200120375Snyanint
201120375Snyani386_memio_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags,
202120375Snyan	       bus_space_handle_t *bshp)
203120375Snyan{
204120375Snyan
205120375Snyan	return i386_bus_space_handle_alloc(t, bpa, size, bshp);
206120375Snyan}
207120375Snyan
20890850Snyanvoid
20990850Snyani386_memio_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
21090850Snyan{
21190850Snyan
21290850Snyan	i386_bus_space_handle_free(t, bsh, bsh->bsh_sz);
21390850Snyan}
21490850Snyan
21590850Snyanvoid
21690850Snyani386_memio_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
21790850Snyan{
21890850Snyan
21990850Snyan	/* i386_memio_unmap() does all that we need to do. */
22090850Snyan	i386_memio_unmap(t, bsh, bsh->bsh_sz);
22190850Snyan}
22290850Snyan
22390762Snyanint
224182836Snyani386_memio_map_load(bus_space_tag_t t, bus_space_handle_t bsh,
225182836Snyan		    bus_size_t size, bus_space_iat_t iat, u_int flags __unused)
226182836Snyan{
227182836Snyan	int i;
228182836Snyan
229182836Snyan	if (size > bsh->bsh_maxiatsz) {
230182836Snyan		printf("i386_memio_map_load: map size too large\n");
231182836Snyan		return EINVAL;
232182836Snyan	}
233182836Snyan
234182836Snyan	for (i = 0; i < bsh->bsh_maxiatsz; i++) {
235182836Snyan		if (i < size)
236182836Snyan			bsh->bsh_iat[i] = iat[i];
237182836Snyan		else
238182836Snyan			bsh->bsh_iat[i] = 0;
239182836Snyan		bsh->bsh_iat[i] += bsh->bsh_base;
240182836Snyan	}
241182836Snyan
242182836Snyan	bsh->bsh_iatsz = size;
243182836Snyan	bsh->bsh_bam = t->bs_ra;	/* relocate access */
244182836Snyan
245182836Snyan	return 0;
246182836Snyan}
247182836Snyan
248182836Snyanint
24990762Snyani386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh,
25090762Snyan		     bus_size_t offset, bus_size_t size,
25190762Snyan		     bus_space_handle_t *tbshp)
25290762Snyan{
25390762Snyan	int i, error = 0;
25490762Snyan	bus_space_handle_t bsh;
25590762Snyan	bus_addr_t pbase;
25690762Snyan
25790762Snyan	pbase = pbsh->bsh_base + offset;
25890762Snyan	switch (t->bs_tag) {
259214584Snyan	case BUS_SPACE_TAG_IO:
26090762Snyan		if (pbsh->bsh_iatsz > 0) {
26190762Snyan			if (offset >= pbsh->bsh_iatsz ||
26290762Snyan			    offset + size > pbsh->bsh_iatsz)
26390762Snyan				return EINVAL;
26490762Snyan			pbase = pbsh->bsh_base;
26590762Snyan		}
26690762Snyan		break;
26790762Snyan
268214584Snyan	case BUS_SPACE_TAG_MEM:
26990762Snyan		if (pbsh->bsh_iatsz > 0)
27090762Snyan			return EINVAL;
27190762Snyan		if (offset > pbsh->bsh_sz || offset + size > pbsh->bsh_sz)
27290762Snyan			return EINVAL;
27390762Snyan		break;
27490762Snyan
27590762Snyan	default:
27690762Snyan		panic("i386_memio_subregion: bad bus space tag");
27790762Snyan		break;
27890762Snyan	}
27990762Snyan
28090762Snyan	error = i386_bus_space_handle_alloc(t, pbase, size, &bsh);
28190762Snyan	if (error != 0)
28290762Snyan		return error;
28390762Snyan
28490762Snyan	switch (t->bs_tag) {
285214584Snyan	case BUS_SPACE_TAG_IO:
28690762Snyan		if (pbsh->bsh_iatsz > 0) {
28790762Snyan			for (i = 0; i < size; i ++)
28890762Snyan				bsh->bsh_iat[i] = pbsh->bsh_iat[i + offset];
28990762Snyan			bsh->bsh_iatsz = size;
29090762Snyan		} else if (pbsh->bsh_base > bsh->bsh_base ||
29190762Snyan		         pbsh->bsh_base + pbsh->bsh_sz <
29290762Snyan		         bsh->bsh_base + bsh->bsh_sz) {
29390762Snyan			i386_bus_space_handle_free(t, bsh, size);
29490762Snyan			return EINVAL;
29590762Snyan		}
29690762Snyan		break;
29790762Snyan
298214584Snyan	case BUS_SPACE_TAG_MEM:
29990762Snyan		break;
30090762Snyan	}
30190762Snyan
30290762Snyan	if (pbsh->bsh_iatsz > 0)
30390762Snyan		bsh->bsh_bam = t->bs_ra;	/* relocate access */
30490762Snyan	*tbshp = bsh;
30590762Snyan	return error;
30690762Snyan}
307180303Snyan
308180303Snyanint
309180303Snyani386_memio_compare(bus_space_tag_t t1, bus_space_handle_t bsh1,
310180303Snyan		   bus_space_tag_t t2, bus_space_handle_t bsh2)
311180303Snyan{
312180303Snyan	int i;
313180303Snyan
314180303Snyan	if (t1->bs_tag != t2->bs_tag)
315180303Snyan		return (1);
316180303Snyan	if (bsh1->bsh_base != bsh2->bsh_base)
317180303Snyan		return (1);
318180303Snyan	if (bsh1->bsh_sz != bsh2->bsh_sz)
319180303Snyan		return (1);
320180303Snyan	if (bsh1->bsh_bam.bs_read_1 != bsh2->bsh_bam.bs_read_1)	/* XXX */
321180303Snyan		return (1);
322180303Snyan
323180303Snyan	if (bsh1->bsh_iatsz != bsh2->bsh_iatsz)
324180303Snyan		return (1);
325180303Snyan	for (i = 0; i < bsh1->bsh_iatsz; i++) {
326180303Snyan		if (bsh1->bsh_iat[i] != bsh2->bsh_iat[i])
327180303Snyan			return (1);
328180303Snyan	}
329180303Snyan
330180303Snyan	return (0);
331180303Snyan}
332