1 1.47 thorpej /* $NetBSD: grf.c,v 1.47 2023/12/20 00:40:44 thorpej Exp $ */ 2 1.1 oki 3 1.1 oki /* 4 1.40 rmind * Copyright (c) 1988 University of Utah. 5 1.1 oki * Copyright (c) 1990, 1993 6 1.1 oki * The Regents of the University of California. All rights reserved. 7 1.1 oki * 8 1.1 oki * This code is derived from software contributed to Berkeley by 9 1.1 oki * the Systems Programming Group of the University of Utah Computer 10 1.1 oki * Science Department. 11 1.1 oki * 12 1.1 oki * Redistribution and use in source and binary forms, with or without 13 1.1 oki * modification, are permitted provided that the following conditions 14 1.1 oki * are met: 15 1.1 oki * 1. Redistributions of source code must retain the above copyright 16 1.1 oki * notice, this list of conditions and the following disclaimer. 17 1.1 oki * 2. Redistributions in binary form must reproduce the above copyright 18 1.1 oki * notice, this list of conditions and the following disclaimer in the 19 1.1 oki * documentation and/or other materials provided with the distribution. 20 1.28 agc * 3. Neither the name of the University nor the names of its contributors 21 1.28 agc * may be used to endorse or promote products derived from this software 22 1.28 agc * without specific prior written permission. 23 1.28 agc * 24 1.28 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 1.28 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 1.28 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 1.28 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 1.28 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 1.28 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 1.28 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 1.28 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 1.28 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 1.28 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 1.28 agc * SUCH DAMAGE. 35 1.28 agc * 36 1.28 agc * from: Utah $Hdr: grf.c 1.36 93/08/13$ 37 1.28 agc * 38 1.28 agc * @(#)grf.c 8.4 (Berkeley) 1/12/94 39 1.28 agc */ 40 1.1 oki 41 1.1 oki /* 42 1.1 oki * Graphics display driver for the X68K machines. 43 1.1 oki * This is the hardware-independent portion of the driver. 44 1.1 oki * Hardware access is through the machine dependent grf switch routines. 45 1.1 oki */ 46 1.27 lukem 47 1.27 lukem #include <sys/cdefs.h> 48 1.47 thorpej __KERNEL_RCSID(0, "$NetBSD: grf.c,v 1.47 2023/12/20 00:40:44 thorpej Exp $"); 49 1.1 oki 50 1.1 oki #include <sys/param.h> 51 1.2 oki #include <sys/systm.h> 52 1.1 oki #include <sys/device.h> 53 1.1 oki #include <sys/proc.h> 54 1.16 minoura #include <sys/resourcevar.h> 55 1.1 oki #include <sys/ioctl.h> 56 1.6 oki #include <sys/conf.h> 57 1.1 oki 58 1.38 isaki #include <machine/cpu.h> 59 1.10 minoura #include <machine/grfioctl.h> 60 1.10 minoura 61 1.1 oki #include <x68k/dev/grfvar.h> 62 1.1 oki #include <x68k/dev/itevar.h> 63 1.1 oki 64 1.13 mrg #include <uvm/uvm_extern.h> 65 1.9 msaitoh 66 1.1 oki #include <miscfs/specfs/specdev.h> 67 1.1 oki 68 1.46 tsutsui #include "ioconf.h" 69 1.46 tsutsui 70 1.1 oki #include "ite.h" 71 1.1 oki #if NITE == 0 72 1.29 minoura #define iteon(u,f) 0 73 1.1 oki #define iteoff(u,f) 74 1.9 msaitoh #define ite_reinit(u) 75 1.1 oki #endif 76 1.1 oki 77 1.1 oki #ifdef DEBUG 78 1.1 oki int grfdebug = 0; 79 1.1 oki #define GDB_DEVNO 0x01 80 1.1 oki #define GDB_MMAP 0x02 81 1.1 oki #define GDB_IOMAP 0x04 82 1.1 oki #define GDB_LOCK 0x08 83 1.1 oki #endif 84 1.1 oki 85 1.29 minoura static int grfon(struct grf_softc *); 86 1.29 minoura static int grfoff(struct grf_softc *); 87 1.29 minoura static off_t grfaddr(struct grf_softc *, off_t); 88 1.33 christos static int grfmap(dev_t, void **, struct proc *); 89 1.33 christos static int grfunmap(dev_t, void *, struct proc *); 90 1.7 thorpej 91 1.22 gehenna dev_type_open(grfopen); 92 1.22 gehenna dev_type_close(grfclose); 93 1.22 gehenna dev_type_ioctl(grfioctl); 94 1.22 gehenna dev_type_mmap(grfmmap); 95 1.22 gehenna 96 1.22 gehenna const struct cdevsw grf_cdevsw = { 97 1.43 dholland .d_open = grfopen, 98 1.43 dholland .d_close = grfclose, 99 1.43 dholland .d_read = nullread, 100 1.43 dholland .d_write = nullwrite, 101 1.43 dholland .d_ioctl = grfioctl, 102 1.43 dholland .d_stop = nostop, 103 1.43 dholland .d_tty = notty, 104 1.43 dholland .d_poll = nopoll, 105 1.43 dholland .d_mmap = grfmmap, 106 1.43 dholland .d_kqfilter = nokqfilter, 107 1.44 dholland .d_discard = nodiscard, 108 1.43 dholland .d_flag = 0 109 1.22 gehenna }; 110 1.6 oki 111 1.1 oki /*ARGSUSED*/ 112 1.2 oki int 113 1.31 christos grfopen(dev_t dev, int flags, int mode, struct lwp *l) 114 1.1 oki { 115 1.30 chs struct grf_softc *gp; 116 1.1 oki int error = 0; 117 1.1 oki 118 1.35 cegger gp = device_lookup_private(&grf_cd, GRFUNIT(dev)); 119 1.35 cegger if (gp == NULL) 120 1.35 cegger return ENXIO; 121 1.35 cegger 122 1.36 isaki if ((gp->g_flags & GF_ALIVE) == 0) 123 1.29 minoura return ENXIO; 124 1.9 msaitoh 125 1.1 oki if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE)) 126 1.29 minoura return EBUSY; 127 1.29 minoura 128 1.1 oki /* 129 1.1 oki * First open. 130 1.1 oki * XXX: always put in graphics mode. 131 1.1 oki */ 132 1.1 oki error = 0; 133 1.1 oki if ((gp->g_flags & GF_OPEN) == 0) { 134 1.1 oki gp->g_flags |= GF_OPEN; 135 1.29 minoura error = grfon(gp); 136 1.1 oki } 137 1.29 minoura return error; 138 1.1 oki } 139 1.1 oki 140 1.1 oki /*ARGSUSED*/ 141 1.2 oki int 142 1.31 christos grfclose(dev_t dev, int flags, int mode, struct lwp *l) 143 1.1 oki { 144 1.35 cegger struct grf_softc *gp = device_lookup_private(&grf_cd, GRFUNIT(dev)); 145 1.1 oki 146 1.9 msaitoh if ((gp->g_flags & GF_ALIVE) == 0) 147 1.29 minoura return ENXIO; 148 1.9 msaitoh 149 1.29 minoura (void) grfoff(gp); 150 1.1 oki gp->g_flags &= GF_ALIVE; 151 1.29 minoura 152 1.29 minoura return 0; 153 1.1 oki } 154 1.1 oki 155 1.1 oki /*ARGSUSED*/ 156 1.2 oki int 157 1.33 christos grfioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 158 1.1 oki { 159 1.1 oki int unit = GRFUNIT(dev); 160 1.35 cegger struct grf_softc *gp = device_lookup_private(&grf_cd, GRFUNIT(dev)); 161 1.1 oki int error; 162 1.1 oki 163 1.9 msaitoh if ((gp->g_flags & GF_ALIVE) == 0) 164 1.29 minoura return ENXIO; 165 1.9 msaitoh 166 1.1 oki error = 0; 167 1.1 oki switch (cmd) { 168 1.1 oki 169 1.1 oki case GRFIOCGINFO: 170 1.33 christos memcpy(data, (void *)&gp->g_display, sizeof(struct grfinfo)); 171 1.1 oki break; 172 1.1 oki 173 1.1 oki case GRFIOCON: 174 1.29 minoura error = grfon(gp); 175 1.1 oki break; 176 1.1 oki 177 1.1 oki case GRFIOCOFF: 178 1.29 minoura error = grfoff(gp); 179 1.1 oki break; 180 1.1 oki 181 1.1 oki case GRFIOCMAP: 182 1.33 christos error = grfmap(dev, (void **)data, l->l_proc); 183 1.1 oki break; 184 1.1 oki 185 1.1 oki case GRFIOCUNMAP: 186 1.33 christos error = grfunmap(dev, *(void **)data, l->l_proc); 187 1.1 oki break; 188 1.1 oki 189 1.1 oki case GRFSETVMODE: 190 1.1 oki error = (*gp->g_sw->gd_mode)(gp, GM_GRFSETVMODE, data); 191 1.1 oki if (error == 0) 192 1.1 oki ite_reinit(unit); 193 1.1 oki break; 194 1.1 oki 195 1.1 oki default: 196 1.1 oki error = EINVAL; 197 1.1 oki break; 198 1.1 oki 199 1.1 oki } 200 1.29 minoura return error; 201 1.1 oki } 202 1.1 oki 203 1.1 oki /*ARGSUSED*/ 204 1.17 simonb paddr_t 205 1.30 chs grfmmap(dev_t dev, off_t off, int prot) 206 1.1 oki { 207 1.9 msaitoh 208 1.35 cegger return grfaddr(device_lookup_private(&grf_cd, GRFUNIT(dev)), off); 209 1.1 oki } 210 1.1 oki 211 1.2 oki int 212 1.30 chs grfon(struct grf_softc *gp) 213 1.1 oki { 214 1.37 isaki int unit = device_unit(gp->g_device); 215 1.1 oki 216 1.1 oki /* 217 1.1 oki * XXX: iteoff call relies on devices being in same order 218 1.1 oki * as ITEs and the fact that iteoff only uses the minor part 219 1.1 oki * of the dev arg. 220 1.1 oki */ 221 1.1 oki iteoff(unit, 2); 222 1.29 minoura 223 1.33 christos return (*gp->g_sw->gd_mode)(gp, GM_GRFON, (void *) 0); 224 1.1 oki } 225 1.1 oki 226 1.2 oki int 227 1.30 chs grfoff(struct grf_softc *gp) 228 1.1 oki { 229 1.37 isaki int unit = device_unit(gp->g_device); 230 1.1 oki int error; 231 1.1 oki 232 1.29 minoura #if 0 /* always fails in EINVAL... */ 233 1.33 christos (void) grfunmap(dev, (void *) 0, curproc); 234 1.29 minoura #endif 235 1.33 christos error = (*gp->g_sw->gd_mode)(gp, GM_GRFOFF, (void *) 0); 236 1.1 oki /* XXX: see comment for iteoff above */ 237 1.1 oki iteon(unit, 2); 238 1.29 minoura 239 1.29 minoura return error; 240 1.1 oki } 241 1.1 oki 242 1.17 simonb off_t 243 1.30 chs grfaddr(struct grf_softc *gp, off_t off) 244 1.1 oki { 245 1.30 chs struct grfinfo *gi = &gp->g_display; 246 1.1 oki 247 1.1 oki /* control registers */ 248 1.1 oki if (off >= 0 && off < gi->gd_regsize) 249 1.29 minoura return ((u_int)gi->gd_regaddr + off) >> PGSHIFT; 250 1.1 oki 251 1.1 oki /* frame buffer */ 252 1.1 oki if (off >= gi->gd_regsize && off < gi->gd_regsize+gi->gd_fbsize) { 253 1.1 oki off -= gi->gd_regsize; 254 1.29 minoura return ((u_int)gi->gd_fbaddr + off) >> PGSHIFT; 255 1.1 oki } 256 1.1 oki /* bogus */ 257 1.29 minoura return -1; 258 1.1 oki } 259 1.1 oki 260 1.2 oki int 261 1.33 christos grfmap(dev_t dev, void **addrp, struct proc *p) 262 1.1 oki { 263 1.35 cegger struct grf_softc *gp = device_lookup_private(&grf_cd, GRFUNIT(dev)); 264 1.45 chs size_t len; 265 1.45 chs int error; 266 1.1 oki 267 1.1 oki #ifdef DEBUG 268 1.1 oki if (grfdebug & GDB_MMAP) 269 1.4 christos printf("grfmap(%d): addr %p\n", p->p_pid, *addrp); 270 1.1 oki #endif 271 1.29 minoura 272 1.1 oki len = gp->g_display.gd_regsize + gp->g_display.gd_fbsize; 273 1.45 chs 274 1.45 chs error = uvm_mmap_dev(p, addrp, len, dev, 0); 275 1.1 oki if (error == 0) 276 1.1 oki (void) (*gp->g_sw->gd_mode)(gp, GM_MAP, *addrp); 277 1.29 minoura 278 1.29 minoura return error; 279 1.1 oki } 280 1.1 oki 281 1.2 oki int 282 1.33 christos grfunmap(dev_t dev, void *addr, struct proc *p) 283 1.1 oki { 284 1.35 cegger struct grf_softc *gp = device_lookup_private(&grf_cd, GRFUNIT(dev)); 285 1.11 minoura vsize_t size; 286 1.1 oki 287 1.1 oki #ifdef DEBUG 288 1.39 isaki if (grfdebug & GDB_MMAP) { 289 1.39 isaki printf("grfunmap(%d): dev %x addr %p\n", 290 1.39 isaki p->p_pid, GRFUNIT(dev), addr); 291 1.39 isaki } 292 1.1 oki #endif 293 1.1 oki if (addr == 0) 294 1.29 minoura return EINVAL; /* XXX: how do we deal with this? */ 295 1.1 oki (void) (*gp->g_sw->gd_mode)(gp, GM_UNMAP, 0); 296 1.1 oki size = round_page(gp->g_display.gd_regsize + gp->g_display.gd_fbsize); 297 1.20 chs uvm_unmap(&p->p_vmspace->vm_map, (vaddr_t)addr, 298 1.12 chuck (vaddr_t)addr + size); 299 1.29 minoura 300 1.20 chs return 0; 301 1.1 oki } 302