1 /* $OpenBSD: xp.c,v 1.3 2017/09/08 05:36:52 deraadt Exp $ */ 2 /* $NetBSD: xp.c,v 1.1 2016/12/03 17:38:02 tsutsui Exp $ */ 3 4 /*- 5 * Copyright (c) 2016 Izumi Tsutsui. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* 29 * LUNA's Hitachi HD647180 "XP" I/O processor driver 30 */ 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/conf.h> 35 #include <sys/device.h> 36 #include <sys/ioctl.h> 37 #include <sys/malloc.h> 38 #include <sys/errno.h> 39 40 #include <uvm/uvm_extern.h> 41 42 #include <machine/autoconf.h> 43 #include <machine/board.h> 44 #include <machine/xpio.h> 45 46 #define XP_SHM_BASE TRI_PORT_RAM 47 #define XP_SHM_SIZE 0x00010000 /* 64KB for XP; rest 64KB for lance */ 48 #define XP_TAS_ADDR OBIO_TAS 49 50 struct xp_softc { 51 struct device sc_dev; 52 53 vaddr_t sc_shm_base; 54 vsize_t sc_shm_size; 55 vaddr_t sc_tas; 56 57 bool sc_isopen; 58 }; 59 60 static int xp_match(struct device *, void *, void *); 61 static void xp_attach(struct device *, struct device *, void *); 62 63 const struct cfattach xp_ca = { 64 sizeof (struct xp_softc), xp_match, xp_attach 65 }; 66 67 struct cfdriver xp_cd = { 68 NULL, "xp", DV_DULL 69 }; 70 71 /* #define XP_DEBUG */ 72 73 #ifdef XP_DEBUG 74 #define XP_DEBUG_ALL 0xff 75 uint32_t xp_debug = 0; 76 #define DPRINTF(x, y) if (xp_debug & (x)) printf y 77 #else 78 #define DPRINTF(x, y) /* nothing */ 79 #endif 80 81 static bool xp_matched; 82 83 /* 84 * PIO 0 port C is connected to XP's reset line 85 * 86 * XXX: PIO port functions should be shared with machdep.c for DIP SWs 87 */ 88 #define PIO_ADDR OBIO_PIO0_BASE 89 #define PORT_A (0 * 4) 90 #define PORT_B (1 * 4) 91 #define PORT_C (2 * 4) 92 #define CTRL (3 * 4) 93 94 /* PIO0 Port C bit definition */ 95 #define XP_INT1_REQ 0 /* INTR B */ 96 /* unused */ /* IBF B */ 97 #define XP_INT1_ENA 2 /* INTE B */ 98 #define XP_INT5_REQ 3 /* INTR A */ 99 #define XP_INT5_ENA 4 /* INTE A */ 100 /* unused */ /* IBF A */ 101 #define PARITY 6 /* PC6 output to enable parity error */ 102 #define XP_RESET 7 /* PC7 output to reset HD647180 XP */ 103 104 /* Port control for PC6 and PC7 */ 105 #define ON 1 106 #define OFF 0 107 108 static uint8_t put_pio0c(uint8_t bit, uint8_t set) 109 { 110 volatile uint8_t * const pio0 = (uint8_t *)PIO_ADDR; 111 112 pio0[CTRL] = (bit << 1) | (set & 0x01); 113 114 return pio0[PORT_C]; 115 } 116 117 static int 118 xp_match(struct device *parent, void *cf, void *aux) 119 { 120 struct mainbus_attach_args *maa = aux; 121 122 /* only one XP processor */ 123 if (xp_matched) 124 return 0; 125 126 if (strcmp(maa->ma_name, xp_cd.cd_name)) 127 return 0; 128 129 if (maa->ma_addr != XP_SHM_BASE) 130 return 0; 131 132 xp_matched = true; 133 return 1; 134 } 135 136 static void 137 xp_attach(struct device *parent, struct device *self, void *aux) 138 { 139 struct xp_softc *sc = (void *)self; 140 141 printf(": HD647180X I/O processor\n"); 142 143 sc->sc_shm_base = XP_SHM_BASE; 144 sc->sc_shm_size = XP_SHM_SIZE; 145 sc->sc_tas = XP_TAS_ADDR; 146 } 147 148 int 149 xpopen(dev_t dev, int flags, int mode, struct proc *p) 150 { 151 struct xp_softc *sc; 152 int unit; 153 154 DPRINTF(XP_DEBUG_ALL, ("%s\n", __func__)); 155 156 unit = minor(dev); 157 if (unit >= xp_cd.cd_ndevs) 158 return ENXIO; 159 sc = xp_cd.cd_devs[unit]; 160 if (sc == NULL) 161 return ENXIO; 162 if (sc->sc_isopen) 163 return EBUSY; 164 165 sc->sc_isopen = true; 166 167 return 0; 168 } 169 170 int 171 xpclose(dev_t dev, int flags, int mode, struct proc *p) 172 { 173 struct xp_softc *sc; 174 int unit; 175 176 DPRINTF(XP_DEBUG_ALL, ("%s\n", __func__)); 177 178 unit = minor(dev); 179 if (unit >= xp_cd.cd_ndevs) 180 return ENXIO; 181 sc = xp_cd.cd_devs[unit]; 182 sc->sc_isopen = false; 183 184 return 0; 185 } 186 187 int 188 xpioctl(dev_t dev, u_long cmd, void *addr, int flags, struct proc *p) 189 { 190 struct xp_softc *sc; 191 int unit, error; 192 struct xp_download *downld; 193 uint8_t *loadbuf; 194 size_t loadsize; 195 196 DPRINTF(XP_DEBUG_ALL, ("%s\n", __func__)); 197 198 unit = minor(dev); 199 if (unit >= xp_cd.cd_ndevs) 200 return ENXIO; 201 sc = xp_cd.cd_devs[unit]; 202 203 switch (cmd) { 204 case XPIOCDOWNLD: 205 downld = addr; 206 loadsize = downld->size; 207 if (loadsize == 0 || loadsize > sc->sc_shm_size) { 208 return EINVAL; 209 } 210 211 loadbuf = malloc(loadsize, M_DEVBUF, M_WAITOK); 212 if (loadbuf == NULL) { 213 return ENOMEM; 214 } 215 error = copyin(downld->data, loadbuf, loadsize); 216 if (error == 0) { 217 put_pio0c(XP_RESET, ON); 218 delay(100); 219 memcpy((void *)sc->sc_shm_base, loadbuf, loadsize); 220 delay(100); 221 put_pio0c(XP_RESET, OFF); 222 } else { 223 DPRINTF(XP_DEBUG_ALL, ("%s: ioctl failed (err = %d)\n", 224 __func__, error)); 225 } 226 227 free(loadbuf, M_DEVBUF, loadsize); 228 return error; 229 230 default: 231 return ENOTTY; 232 } 233 } 234 235 paddr_t 236 xpmmap(dev_t dev, off_t offset, int prot) 237 { 238 struct xp_softc *sc; 239 int unit; 240 paddr_t pa; 241 242 pa = -1; 243 244 unit = minor(dev); 245 sc = xp_cd.cd_devs[unit]; 246 247 if (offset >= 0 && 248 offset < sc->sc_shm_size) { 249 pa = (paddr_t)(trunc_page(sc->sc_shm_base) + offset); 250 } 251 252 return pa; 253 } 254