1130803Smarcel/* $NetBSD: jensenio_bus_intio.c,v 1.7 2023/12/04 00:32:10 thorpej Exp $ */
2130803Smarcel
3130803Smarcel/*-
4130803Smarcel * Copyright (c) 1999 The NetBSD Foundation, Inc.
5130803Smarcel * All rights reserved.
6130803Smarcel *
7130803Smarcel * This code is derived from software contributed to The NetBSD Foundation
8130803Smarcel * by Jason R. Thorpe.
9130803Smarcel *
10130803Smarcel * Redistribution and use in source and binary forms, with or without
11130803Smarcel * modification, are permitted provided that the following conditions
12130803Smarcel * are met:
13130803Smarcel * 1. Redistributions of source code must retain the above copyright
14130803Smarcel *    notice, this list of conditions and the following disclaimer.
15130803Smarcel * 2. Redistributions in binary form must reproduce the above copyright
16130803Smarcel *    notice, this list of conditions and the following disclaimer in the
17130803Smarcel *    documentation and/or other materials provided with the distribution.
18130803Smarcel *
19130803Smarcel * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20130803Smarcel * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21130803Smarcel * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22130803Smarcel * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23130803Smarcel * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24130803Smarcel * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25130803Smarcel * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26130803Smarcel * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27130803Smarcel * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28130803Smarcel * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29130803Smarcel * POSSIBILITY OF SUCH DAMAGE.
30130803Smarcel */
31130803Smarcel
32130803Smarcel#include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
33130803Smarcel
34130803Smarcel__KERNEL_RCSID(0, "$NetBSD: jensenio_bus_intio.c,v 1.7 2023/12/04 00:32:10 thorpej Exp $");
35130803Smarcel
36130803Smarcel#include <sys/param.h>
37130803Smarcel#include <sys/systm.h>
38130803Smarcel#include <sys/device.h>
39130803Smarcel#include <sys/vmem.h>
40130803Smarcel
41130803Smarcel#include <sys/bus.h>
42130803Smarcel
43130803Smarcel#include <dev/eisa/eisavar.h>
44130803Smarcel
45130803Smarcel#include <dev/isa/isavar.h>
46130803Smarcel
47130803Smarcel#include <alpha/jensenio/jensenioreg.h>
48130803Smarcel#include <alpha/jensenio/jenseniovar.h>
49130803Smarcel
50130803Smarcel/* mapping/unmapping */
51130803Smarcelint		jensenio_intio_map(void *, bus_addr_t, bus_size_t, int,
52130803Smarcel		    bus_space_handle_t *, int);
53130803Smarcelvoid		jensenio_intio_unmap(void *, bus_space_handle_t,
54130803Smarcel		    bus_size_t, int);
55130803Smarcelint		jensenio_intio_subregion(void *, bus_space_handle_t,
56130803Smarcel		    bus_size_t, bus_size_t, bus_space_handle_t *);
57130803Smarcel
58130803Smarcel/* allocation/deallocation */
59130803Smarcel	/* Not supported for Internal space */
60130803Smarcel
61130803Smarcel/* barrier */
62130803Smarcelstatic inline void	jensenio_intio_barrier(void *, bus_space_handle_t,
63130803Smarcel		    bus_size_t, bus_size_t, int);
64130803Smarcel
65130803Smarcel/* read (single) */
66130803Smarcelstatic inline uint8_t	jensenio_intio_read_1(void *, bus_space_handle_t, bus_size_t);
67130803Smarcel
68130803Smarcel/* read multiple */
69130803Smarcelvoid		jensenio_intio_read_multi_1(void *, bus_space_handle_t,
70130803Smarcel		    bus_size_t, uint8_t *, bus_size_t);
71130803Smarcel
72130803Smarcel/* read region */
73130803Smarcel	/* Not supported for Internal space */
74130803Smarcel
75130803Smarcel/* write (single) */
76130803Smarcelstatic inline void	jensenio_intio_write_1(void *, bus_space_handle_t,
77130803Smarcel		    bus_size_t, uint8_t);
78130803Smarcel
79130803Smarcel/* write multiple */
80130803Smarcelvoid		jensenio_intio_write_multi_1(void *, bus_space_handle_t,
81130803Smarcel		    bus_size_t, const uint8_t *, bus_size_t);
82130803Smarcel
83130803Smarcel/* write region */
84130803Smarcel	/* Not supported for Internal space */
85130803Smarcel
86130803Smarcel/* set multiple */
87130803Smarcelvoid		jensenio_intio_set_multi_1(void *, bus_space_handle_t,
88130803Smarcel		    bus_size_t, uint8_t, bus_size_t);
89130803Smarcel
90130803Smarcel/* set region */
91130803Smarcel	/* Not supported for Internal space */
92130803Smarcel
93130803Smarcel/* copy */
94130803Smarcel	/* Not supported for Internal space */
95130803Smarcel
96130803Smarcelvoid
97130803Smarceljensenio_bus_intio_init(bus_space_tag_t t, void *v)
98130803Smarcel{
99130803Smarcel
100130803Smarcel	/*
101130803Smarcel	 * Initialize the bus space tag.
102130803Smarcel	 */
103130803Smarcel
104130803Smarcel	memset(t, 0, sizeof(*t));
105130803Smarcel
106130803Smarcel	/* cookie */
107130803Smarcel	t->abs_cookie =		v;
108130803Smarcel
109130803Smarcel	/* mapping/unmapping */
110130803Smarcel	t->abs_map =		jensenio_intio_map;
111130803Smarcel	t->abs_unmap =		jensenio_intio_unmap;
112130803Smarcel	t->abs_subregion =	jensenio_intio_subregion;
113130803Smarcel
114130803Smarcel	/* barrier */
115130803Smarcel	t->abs_barrier =	jensenio_intio_barrier;
116130803Smarcel
117130803Smarcel	/* read (single) */
118130803Smarcel	t->abs_r_1 =		jensenio_intio_read_1;
119130803Smarcel
120130803Smarcel	/* read multiple */
121130803Smarcel	t->abs_rm_1 =		jensenio_intio_read_multi_1;
122130803Smarcel
123130803Smarcel	/* write (single) */
124130803Smarcel	t->abs_w_1 =		jensenio_intio_write_1;
125130803Smarcel
126130803Smarcel	/* write multiple */
127130803Smarcel	t->abs_wm_1 =		jensenio_intio_write_multi_1;
128130803Smarcel
129130803Smarcel	/* set multiple */
130130803Smarcel	t->abs_sm_1 =		jensenio_intio_set_multi_1;
131130803Smarcel
132130803Smarcel	/*
133130803Smarcel	 * Extent map is already set up.
134130803Smarcel	 */
135130803Smarcel}
136130803Smarcel
137130803Smarcelint
138130803Smarceljensenio_intio_map(void *v, bus_addr_t ioaddr, bus_size_t iosize, int flags,
139130803Smarcel    bus_space_handle_t *iohp, int acct)
140130803Smarcel{
141130803Smarcel	struct jensenio_config *jcp = v;
142130803Smarcel	int linear = flags & BUS_SPACE_MAP_LINEAR;
143130803Smarcel	int error;
144130803Smarcel
145130803Smarcel	/*
146130803Smarcel	 * Can't map i/o space linearly.
147130803Smarcel	 */
148130803Smarcel	if (linear)
149130803Smarcel		return (EOPNOTSUPP);
150130803Smarcel
151130803Smarcel	if (acct) {
152130803Smarcel#ifdef EXTENT_DEBUG
153130803Smarcel		printf("intio: allocating 0x%lx to 0x%lx\n", ioaddr,
154130803Smarcel		    ioaddr + iosize - 1);
155130803Smarcel#endif
156130803Smarcel		error = vmem_xalloc_addr(jcp->jc_io_arena, ioaddr, iosize,
157130803Smarcel		    VM_NOSLEEP);
158130803Smarcel		if (error) {
159130803Smarcel#ifdef EXTENT_DEBUG
160130803Smarcel			printf("intio: allocation failed (%d)\n", error);
161130803Smarcel			/* vmem_print(jcp->jc_io_arena);	XXX */
162130803Smarcel#endif
163130803Smarcel			return (error);
164130803Smarcel		}
165130803Smarcel	}
166130803Smarcel
167130803Smarcel	*iohp = ALPHA_PHYS_TO_K0SEG((ioaddr << 9) + JENSEN_VL82C106);
168130803Smarcel	return (0);
169130803Smarcel}
170130803Smarcel
171130803Smarcelvoid
172130803Smarceljensenio_intio_unmap(void *v, bus_space_handle_t ioh, bus_size_t iosize,
173130803Smarcel    int acct)
174130803Smarcel{
175130803Smarcel	struct jensenio_config *jcp = v;
176130803Smarcel	bus_addr_t ioaddr;
177130803Smarcel
178130803Smarcel	if (acct == 0)
179130803Smarcel		return;
180130803Smarcel
181130803Smarcel#ifdef EXTENT_DEBUG
182130803Smarcel	printf("intio: freeing handle 0x%lx for 0x%lx\n", ioh, iosize);
183130803Smarcel#endif
184130803Smarcel
185130803Smarcel	ioh = ALPHA_K0SEG_TO_PHYS(ioh);
186130803Smarcel
187130803Smarcel	ioaddr = (ioh - JENSEN_VL82C106) >> 9;
188130803Smarcel
189130803Smarcel#ifdef EXTENT_DEBUG
190130803Smarcel	printf("intio: freeing 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1);
191130803Smarcel#endif
192130803Smarcel	vmem_xfree(jcp->jc_io_arena, ioaddr, iosize);
193130803Smarcel}
194130803Smarcel
195130803Smarcelint
196130803Smarceljensenio_intio_subregion(void *v, bus_space_handle_t ioh, bus_size_t offset,
197130803Smarcel    bus_size_t size, bus_space_handle_t *nioh)
198130803Smarcel{
199130803Smarcel
200130803Smarcel	*nioh = ioh + (offset << 9);
201130803Smarcel	return (0);
202130803Smarcel}
203130803Smarcel
204130803Smarcelstatic inline void
205130803Smarceljensenio_intio_barrier(void *v, bus_space_handle_t h, bus_size_t o,
206130803Smarcel    bus_size_t l, int f)
207130803Smarcel{
208130803Smarcel
209130803Smarcel	if ((f & BUS_SPACE_BARRIER_READ) != 0)
210130803Smarcel		alpha_mb();
211130803Smarcel	else if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
212130803Smarcel		alpha_wmb();
213130803Smarcel}
214130803Smarcel
215130803Smarcelstatic inline uint8_t
216130803Smarceljensenio_intio_read_1(void *v, bus_space_handle_t ioh, bus_size_t off)
217130803Smarcel{
218130803Smarcel	register uint32_t *port;
219130803Smarcel
220130803Smarcel	alpha_mb();
221130803Smarcel
222130803Smarcel	port = (uint32_t *)(ioh + (off << 9));
223130803Smarcel	return (*port & 0xff);
224130803Smarcel}
225130803Smarcel
226130803Smarcelvoid
227130803Smarceljensenio_intio_read_multi_1(void *v, bus_space_handle_t h, bus_size_t o,
228130803Smarcel    uint8_t *a, bus_size_t c)
229130803Smarcel{
230130803Smarcel
231130803Smarcel	while (c-- > 0) {
232130803Smarcel		jensenio_intio_barrier(v, h, o, sizeof *a,
233130803Smarcel		    BUS_SPACE_BARRIER_READ);
234130803Smarcel		*a++ = jensenio_intio_read_1(v, h, o);
235130803Smarcel	}
236130803Smarcel}
237130803Smarcel
238130803Smarcelstatic inline void
239130803Smarceljensenio_intio_write_1(void *v, bus_space_handle_t ioh, bus_size_t off,
240130803Smarcel    uint8_t val)
241130803Smarcel{
242130803Smarcel	register uint32_t *port;
243130803Smarcel
244130803Smarcel	port = (uint32_t *)(ioh + (off << 9));
245130803Smarcel	*port = val;
246130803Smarcel	alpha_mb();
247130803Smarcel}
248130803Smarcel
249130803Smarcelvoid
250130803Smarceljensenio_intio_write_multi_1(void *v, bus_space_handle_t h, bus_size_t o,
251130803Smarcel    const uint8_t *a, bus_size_t c)
252130803Smarcel{
253130803Smarcel
254130803Smarcel	while (c-- > 0) {
255130803Smarcel		jensenio_intio_write_1(v, h, o, *a++);
256130803Smarcel		jensenio_intio_barrier(v, h, o, sizeof *a,
257130803Smarcel		    BUS_SPACE_BARRIER_WRITE);
258130803Smarcel	}
259130803Smarcel}
260130803Smarcel
261130803Smarcelvoid
262130803Smarceljensenio_intio_set_multi_1(void *v, bus_space_handle_t h, bus_size_t o,
263130803Smarcel    uint8_t val, bus_size_t c)
264130803Smarcel{
265130803Smarcel
266130803Smarcel	while (c-- > 0) {
267130803Smarcel		jensenio_intio_write_1(v, h, o, val);
268130803Smarcel		jensenio_intio_barrier(v, h, o, sizeof val,
269130803Smarcel		    BUS_SPACE_BARRIER_WRITE);
270130803Smarcel	}
271130803Smarcel}
272130803Smarcel