1 /* $NetBSD: grf.c,v 1.29 2004/01/25 13:17:00 minoura 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.29 2004/01/25 13:17:00 minoura 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/grfioctl.h> 101 102 #include <x68k/dev/grfvar.h> 103 #include <x68k/dev/itevar.h> 104 105 #include <machine/cpu.h> 106 107 #include <uvm/uvm_extern.h> 108 #include <uvm/uvm_map.h> 109 110 #include <miscfs/specfs/specdev.h> 111 112 #include "ite.h" 113 #if NITE == 0 114 #define iteon(u,f) 0 115 #define iteoff(u,f) 116 #define ite_reinit(u) 117 #endif 118 119 #ifdef DEBUG 120 int grfdebug = 0; 121 #define GDB_DEVNO 0x01 122 #define GDB_MMAP 0x02 123 #define GDB_IOMAP 0x04 124 #define GDB_LOCK 0x08 125 #endif 126 127 static int grfon(struct grf_softc *); 128 static int grfoff(struct grf_softc *); 129 static off_t grfaddr(struct grf_softc *, off_t); 130 static int grfmap(dev_t, caddr_t *, struct proc *); 131 static int grfunmap(dev_t, caddr_t, struct proc *); 132 133 extern struct cfdriver grf_cd; 134 135 dev_type_open(grfopen); 136 dev_type_close(grfclose); 137 dev_type_ioctl(grfioctl); 138 dev_type_mmap(grfmmap); 139 140 const struct cdevsw grf_cdevsw = { 141 grfopen, grfclose, nullread, nullwrite, grfioctl, 142 nostop, notty, nopoll, grfmmap, nokqfilter, 143 }; 144 145 /*ARGSUSED*/ 146 int 147 grfopen(dev, flags, mode, p) 148 dev_t dev; 149 int flags, mode; 150 struct proc *p; 151 { 152 int unit = GRFUNIT(dev); 153 register struct grf_softc *gp; 154 int error = 0; 155 156 if (unit >= grf_cd.cd_ndevs || 157 (gp = grf_cd.cd_devs[unit]) == NULL || 158 (gp->g_flags & GF_ALIVE) == 0) 159 return ENXIO; 160 161 if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE)) 162 return EBUSY; 163 164 /* 165 * First open. 166 * XXX: always put in graphics mode. 167 */ 168 error = 0; 169 if ((gp->g_flags & GF_OPEN) == 0) { 170 gp->g_flags |= GF_OPEN; 171 error = grfon(gp); 172 } 173 return error; 174 } 175 176 /*ARGSUSED*/ 177 int 178 grfclose(dev, flags, mode, p) 179 dev_t dev; 180 int flags, mode; 181 struct proc *p; 182 { 183 register struct grf_softc *gp = grf_cd.cd_devs[GRFUNIT(dev)]; 184 185 if ((gp->g_flags & GF_ALIVE) == 0) 186 return ENXIO; 187 188 (void) grfoff(gp); 189 gp->g_flags &= GF_ALIVE; 190 191 return 0; 192 } 193 194 /*ARGSUSED*/ 195 int 196 grfioctl(dev, cmd, data, flag, p) 197 dev_t dev; 198 u_long cmd; 199 caddr_t data; 200 int flag; 201 struct proc *p; 202 { 203 int unit = GRFUNIT(dev); 204 register struct grf_softc *gp = grf_cd.cd_devs[unit]; 205 int error; 206 207 if ((gp->g_flags & GF_ALIVE) == 0) 208 return ENXIO; 209 210 error = 0; 211 switch (cmd) { 212 213 case GRFIOCGINFO: 214 memcpy(data, (caddr_t)&gp->g_display, sizeof(struct grfinfo)); 215 break; 216 217 case GRFIOCON: 218 error = grfon(gp); 219 break; 220 221 case GRFIOCOFF: 222 error = grfoff(gp); 223 break; 224 225 case GRFIOCMAP: 226 error = grfmap(dev, (caddr_t *)data, p); 227 break; 228 229 case GRFIOCUNMAP: 230 error = grfunmap(dev, *(caddr_t *)data, p); 231 break; 232 233 case GRFSETVMODE: 234 error = (*gp->g_sw->gd_mode)(gp, GM_GRFSETVMODE, data); 235 if (error == 0) 236 ite_reinit(unit); 237 break; 238 239 default: 240 error = EINVAL; 241 break; 242 243 } 244 return error; 245 } 246 247 /*ARGSUSED*/ 248 paddr_t 249 grfmmap(dev, off, prot) 250 dev_t dev; 251 off_t off; 252 int prot; 253 { 254 255 return grfaddr(grf_cd.cd_devs[GRFUNIT(dev)], off); 256 } 257 258 int 259 grfon(gp) 260 struct grf_softc *gp; 261 { 262 int unit = gp->g_device.dv_unit; 263 264 /* 265 * XXX: iteoff call relies on devices being in same order 266 * as ITEs and the fact that iteoff only uses the minor part 267 * of the dev arg. 268 */ 269 iteoff(unit, 2); 270 271 return (*gp->g_sw->gd_mode)(gp, GM_GRFON, (caddr_t) 0); 272 } 273 274 int 275 grfoff(gp) 276 struct grf_softc *gp; 277 { 278 int unit = gp->g_device.dv_unit; 279 int error; 280 281 #if 0 /* always fails in EINVAL... */ 282 (void) grfunmap(dev, (caddr_t) 0, curproc); 283 #endif 284 error = (*gp->g_sw->gd_mode)(gp, GM_GRFOFF, (caddr_t) 0); 285 /* XXX: see comment for iteoff above */ 286 iteon(unit, 2); 287 288 return error; 289 } 290 291 off_t 292 grfaddr(gp, off) 293 struct grf_softc *gp; 294 off_t off; 295 { 296 register struct grfinfo *gi = &gp->g_display; 297 298 /* control registers */ 299 if (off >= 0 && off < gi->gd_regsize) 300 return ((u_int)gi->gd_regaddr + off) >> PGSHIFT; 301 302 /* frame buffer */ 303 if (off >= gi->gd_regsize && off < gi->gd_regsize+gi->gd_fbsize) { 304 off -= gi->gd_regsize; 305 return ((u_int)gi->gd_fbaddr + off) >> PGSHIFT; 306 } 307 /* bogus */ 308 return -1; 309 } 310 311 int 312 grfmap(dev, addrp, p) 313 dev_t dev; 314 caddr_t *addrp; 315 struct proc *p; 316 { 317 struct grf_softc *gp = grf_cd.cd_devs[GRFUNIT(dev)]; 318 int len, error; 319 struct vnode vn; 320 struct specinfo si; 321 int flags; 322 323 #ifdef DEBUG 324 if (grfdebug & GDB_MMAP) 325 printf("grfmap(%d): addr %p\n", p->p_pid, *addrp); 326 #endif 327 328 len = gp->g_display.gd_regsize + gp->g_display.gd_fbsize; 329 flags = MAP_SHARED; 330 if (*addrp) 331 flags |= MAP_FIXED; 332 else 333 *addrp = 334 (caddr_t)VM_DEFAULT_ADDRESS(p->p_vmspace->vm_daddr, len); 335 vn.v_type = VCHR; /* XXX */ 336 vn.v_specinfo = &si; /* XXX */ 337 vn.v_rdev = dev; /* XXX */ 338 error = uvm_mmap(&p->p_vmspace->vm_map, (vaddr_t *)addrp, 339 (vsize_t)len, VM_PROT_ALL, VM_PROT_ALL, 340 flags, (caddr_t)&vn, 0, 341 p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur); 342 if (error == 0) 343 (void) (*gp->g_sw->gd_mode)(gp, GM_MAP, *addrp); 344 345 return error; 346 } 347 348 int 349 grfunmap(dev, addr, p) 350 dev_t dev; 351 caddr_t addr; 352 struct proc *p; 353 { 354 struct grf_softc *gp = grf_cd.cd_devs[GRFUNIT(dev)]; 355 vsize_t size; 356 357 #ifdef DEBUG 358 if (grfdebug & GDB_MMAP) 359 printf("grfunmap(%d): dev %x addr %p\n", p->p_pid, dev, addr); 360 #endif 361 if (addr == 0) 362 return EINVAL; /* XXX: how do we deal with this? */ 363 (void) (*gp->g_sw->gd_mode)(gp, GM_UNMAP, 0); 364 size = round_page(gp->g_display.gd_regsize + gp->g_display.gd_fbsize); 365 uvm_unmap(&p->p_vmspace->vm_map, (vaddr_t)addr, 366 (vaddr_t)addr + size); 367 368 return 0; 369 } 370