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