xref: /netbsd-src/sys/arch/luna68k/dev/xp.c (revision 4b552d31e19902d717589952b1ae158ab04f16fa)
1 /* $NetBSD: xp.c,v 1.8 2023/01/15 05:08:33 tsutsui Exp $ */
2 
3 /*-
4  * Copyright (c) 2016 Izumi Tsutsui.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 /*
28  * LUNA's Hitachi HD647180 "XP" I/O processor driver
29  */
30 
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: xp.c,v 1.8 2023/01/15 05:08:33 tsutsui Exp $");
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/conf.h>
37 #include <sys/device.h>
38 #include <sys/fcntl.h>
39 #include <sys/ioctl.h>
40 #include <sys/kmem.h>
41 #include <sys/mman.h>
42 #include <sys/errno.h>
43 
44 #include <uvm/uvm_extern.h>
45 
46 #include <machine/autoconf.h>
47 #include <machine/board.h>
48 #include <machine/xpio.h>
49 
50 #include <luna68k/dev/xpbusvar.h>
51 
52 #include "ioconf.h"
53 #include "xplx/xplxdefs.h"
54 
55 struct xp_softc {
56 	device_t	sc_dev;
57 
58 	vaddr_t		sc_shm_base;
59 	vsize_t		sc_shm_size;
60 	vaddr_t		sc_tas;
61 
62 	bool		sc_isopen;
63 	int		sc_flags;
64 };
65 
66 static int xp_match(device_t, cfdata_t, void *);
67 static void xp_attach(device_t, device_t, void *);
68 
69 static dev_type_open(xp_open);
70 static dev_type_close(xp_close);
71 static dev_type_read(xp_read);
72 static dev_type_write(xp_write);
73 static dev_type_ioctl(xp_ioctl);
74 static dev_type_mmap(xp_mmap);
75 
76 const struct cdevsw xp_cdevsw = {
77 	.d_open     = xp_open,
78 	.d_close    = xp_close,
79 	.d_read     = xp_read,
80 	.d_write    = xp_write,
81 	.d_ioctl    = xp_ioctl,
82 	.d_stop     = nostop,
83 	.d_tty      = notty,
84 	.d_poll     = nopoll,
85 	.d_mmap     = xp_mmap,
86 	.d_kqfilter = nokqfilter,
87 	.d_discard  = nodiscard,
88 	.d_flag     = 0
89 };
90 
91 CFATTACH_DECL_NEW(xp, sizeof(struct xp_softc),
92     xp_match, xp_attach, NULL, NULL);
93 
94 /* #define XP_DEBUG */
95 
96 #ifdef XP_DEBUG
97 #define XP_DEBUG_ALL	0xff
98 uint32_t xp_debug = 0;
99 #define DPRINTF(x, y)	if (xp_debug & (x)) printf y
100 #else
101 #define DPRINTF(x, y)	/* nothing */
102 #endif
103 
104 static bool xp_matched;
105 
106 static int
xp_match(device_t parent,cfdata_t cf,void * aux)107 xp_match(device_t parent, cfdata_t cf, void *aux)
108 {
109 	struct xpbus_attach_args *xa = aux;
110 
111 	/* only one XP processor */
112 	if (xp_matched)
113 		return 0;
114 
115 	if (strcmp(xa->xa_name, xp_cd.cd_name))
116 		return 0;
117 
118 	xp_matched = true;
119 	return 1;
120 }
121 
122 static void
xp_attach(device_t parent,device_t self,void * aux)123 xp_attach(device_t parent, device_t self, void *aux)
124 {
125 	struct xp_softc *sc = device_private(self);
126 
127 	sc->sc_dev = self;
128 
129 	aprint_normal(": HD647180X I/O processor\n");
130 
131 	sc->sc_shm_base = XP_SHM_BASE;
132 	sc->sc_shm_size = XP_SHM_SIZE;
133 	sc->sc_tas      = XP_TAS_ADDR;
134 }
135 
136 static int
xp_open(dev_t dev,int flags,int devtype,struct lwp * l)137 xp_open(dev_t dev, int flags, int devtype, struct lwp *l)
138 {
139 	struct xp_softc *sc;
140 	int unit;
141 	u_int a;
142 
143 	DPRINTF(XP_DEBUG_ALL, ("%s\n", __func__));
144 
145 	unit = minor(dev);
146 	sc = device_lookup_private(&xp_cd, unit);
147 	if (sc == NULL)
148 		return ENXIO;
149 	if (sc->sc_isopen)
150 		return EBUSY;
151 
152 	if ((flags & FWRITE) != 0) {
153 		/* exclusive if write */
154 		a = xp_acquire(DEVID_XPBUS, XP_ACQ_EXCL);
155 		if (a == 0)
156 			return EBUSY;
157 		if (a != (1 << DEVID_XPBUS)) {
158 			xp_release(DEVID_XPBUS);
159 			return EBUSY;
160 		}
161 	} else {
162 		a = xp_acquire(DEVID_XPBUS, 0);
163 		if (a == 0)
164 			return EBUSY;
165 	}
166 
167 	sc->sc_isopen = true;
168 	sc->sc_flags = flags;
169 
170 	return 0;
171 }
172 
173 static int
xp_close(dev_t dev,int flags,int mode,struct lwp * l)174 xp_close(dev_t dev, int flags, int mode, struct lwp *l)
175 {
176 	struct xp_softc *sc;
177 	int unit;
178 
179 	DPRINTF(XP_DEBUG_ALL, ("%s\n", __func__));
180 
181 	unit = minor(dev);
182 	sc = device_lookup_private(&xp_cd, unit);
183 
184 	xp_release(DEVID_XPBUS);
185 
186 	sc->sc_isopen = false;
187 
188 	return 0;
189 }
190 
191 static int
xp_ioctl(dev_t dev,u_long cmd,void * addr,int flags,struct lwp * l)192 xp_ioctl(dev_t dev, u_long cmd, void *addr, int flags, struct lwp *l)
193 {
194 	struct xp_softc *sc;
195 	int unit, error;
196 	struct xp_download *downld;
197 	uint8_t *loadbuf;
198 	size_t loadsize;
199 
200 	DPRINTF(XP_DEBUG_ALL, ("%s\n", __func__));
201 
202 	unit = minor(dev);
203 	sc = device_lookup_private(&xp_cd, unit);
204 
205 	switch (cmd) {
206 	case XPIOCDOWNLD:
207 		if ((sc->sc_flags & FWRITE) == 0) {
208 			return EACCES;
209 		}
210 		downld = addr;
211 		loadsize = downld->size;
212 		if (loadsize == 0 || loadsize > sc->sc_shm_size) {
213 			return EINVAL;
214 		}
215 
216 		loadbuf = kmem_alloc(loadsize, KM_SLEEP);
217 		error = copyin(downld->data, loadbuf, loadsize);
218 		if (error == 0) {
219 			xp_set_shm_dirty();
220 			xp_cpu_reset_hold();
221 			delay(100);
222 			memcpy((void *)sc->sc_shm_base, loadbuf, loadsize);
223 			delay(100);
224 			xp_cpu_reset_release();
225 		} else {
226 			DPRINTF(XP_DEBUG_ALL, ("%s: ioctl failed (err =  %d)\n",
227 			    __func__, error));
228 		}
229 
230 		kmem_free(loadbuf, loadsize);
231 		return error;
232 
233 	default:
234 		return ENOTTY;
235 	}
236 
237 	panic("%s: cmd (%ld) is not handled", device_xname(sc->sc_dev), cmd);
238 }
239 
240 static paddr_t
xp_mmap(dev_t dev,off_t offset,int prot)241 xp_mmap(dev_t dev, off_t offset, int prot)
242 {
243 	struct xp_softc *sc;
244 	int unit;
245 	paddr_t pa;
246 
247 	pa = -1;
248 
249 	unit = minor(dev);
250 	sc = device_lookup_private(&xp_cd, unit);
251 
252 	if (offset >= 0 &&
253 	    offset < sc->sc_shm_size) {
254 		pa = m68k_btop(m68k_trunc_page(sc->sc_shm_base) + offset);
255 	}
256 
257 	if ((prot & PROT_WRITE) != 0)
258 		xp_set_shm_dirty();
259 
260 	return pa;
261 }
262 
263 static int
xp_read(dev_t dev,struct uio * uio,int flags)264 xp_read(dev_t dev, struct uio *uio, int flags)
265 {
266 
267 	return ENODEV;
268 }
269 
270 static int
xp_write(dev_t dev,struct uio * uio,int flags)271 xp_write(dev_t dev, struct uio *uio, int flags)
272 {
273 
274 	return ENODEV;
275 }
276