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