1 /* $NetBSD: grf.c,v 1.47 2011/06/30 20:09:21 wiz Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Leo Weppelman 5 * Copyright (c) 1988 University of Utah. 6 * Copyright (c) 1990 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * the Systems Programming Group of the University of Utah Computer 11 * Science Department. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * from: Utah $Hdr: grf.c 1.31 91/01/21$ 38 * 39 * @(#)grf.c 7.8 (Berkeley) 5/7/91 40 */ 41 42 /* 43 * Graphics display driver for the Atari 44 * This is the hardware-independent portion of the driver. 45 * Hardware access is through the grf_softc->g_mode routine. 46 */ 47 48 #include <sys/cdefs.h> 49 __KERNEL_RCSID(0, "$NetBSD: grf.c,v 1.47 2011/06/30 20:09:21 wiz Exp $"); 50 51 #include <sys/param.h> 52 #include <sys/proc.h> 53 #include <sys/ioctl.h> 54 #include <sys/device.h> 55 #include <sys/file.h> 56 #include <sys/malloc.h> 57 #include <sys/conf.h> 58 #include <sys/systm.h> 59 #include <sys/vnode.h> 60 #include <sys/mman.h> 61 62 #include <machine/cpu.h> 63 64 #include <uvm/uvm_extern.h> 65 66 #include <atari/atari/device.h> 67 #include <atari/dev/grfioctl.h> 68 #include <atari/dev/grfabs_reg.h> 69 #include <atari/dev/grfvar.h> 70 #include <atari/dev/itevar.h> 71 #include <atari/dev/viewioctl.h> 72 #include <atari/dev/viewvar.h> 73 74 #include "ioconf.h" 75 76 #include "grfcc.h" 77 #include "grfet.h" 78 #define NGRF (NGRFCC + NGRFET) 79 80 #if NGRF > 0 81 82 #include "ite.h" 83 #if NITE == 0 84 #define ite_on(u,f) 85 #define ite_off(u,f) 86 #define ite_reinit(d) 87 #endif 88 89 int grfon(dev_t); 90 int grfoff(dev_t); 91 int grfsinfo(dev_t, struct grfdyninfo *); 92 93 int grfbusprint(void *, const char *); 94 int grfbusmatch(device_t, cfdata_t, void *); 95 void grfbusattach(device_t, device_t, void *); 96 97 /* 98 * pointers to grf drivers device structs 99 */ 100 struct grf_softc *grfsp[NGRF]; /* XXX */ 101 102 CFATTACH_DECL_NEW(grfbus, 0, 103 grfbusmatch, grfbusattach, NULL, NULL); 104 105 dev_type_open(grfopen); 106 dev_type_close(grfclose); 107 dev_type_ioctl(grfioctl); 108 dev_type_mmap(grfmmap); 109 110 const struct cdevsw grf_cdevsw = { 111 grfopen, grfclose, noread, nowrite, grfioctl, 112 nostop, notty, nopoll, grfmmap, nokqfilter, 113 }; 114 115 /* 116 * only used in console init. 117 */ 118 static cfdata_t cfdata_gbus = NULL; 119 120 int 121 grfbusmatch(device_t parent, cfdata_t cf, void *aux) 122 { 123 124 if (strcmp(aux, grfbus_cd.cd_name)) 125 return 0; 126 127 if (atari_realconfig == 0) 128 cfdata_gbus = cf; 129 return 1; /* Always there */ 130 } 131 132 void 133 grfbusattach(device_t parent, device_t self, void *aux) 134 { 135 grf_auxp_t grf_auxp; 136 137 grf_auxp.busprint = grfbusprint; 138 grf_auxp.from_bus_match = 1; 139 140 if (self == NULL) /* Console init */ 141 atari_config_found(cfdata_gbus, NULL, &grf_auxp, grfbusprint); 142 else { 143 printf("\n"); 144 config_found(self, &grf_auxp, grfbusprint); 145 } 146 } 147 148 int 149 grfbusprint(void *aux, const char *name) 150 { 151 152 if (name == NULL) 153 return UNCONF; 154 return QUIET; 155 } 156 157 /*ARGSUSED*/ 158 int 159 grfopen(dev_t dev, int flags, int devtype, struct lwp *l) 160 { 161 struct grf_softc *gp; 162 163 if (GRFUNIT(dev) >= NGRF) 164 return ENXIO; 165 166 gp = grfsp[GRFUNIT(dev)]; 167 if (gp == NULL) 168 return ENXIO; 169 170 if ((gp->g_flags & GF_ALIVE) == 0) 171 return ENXIO; 172 173 if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE)) 174 return EBUSY; 175 grf_viewsync(gp); 176 177 return 0; 178 } 179 180 /*ARGSUSED*/ 181 int 182 grfclose(dev_t dev, int flags, int mode, struct lwp *l) 183 { 184 struct grf_softc *gp; 185 186 gp = grfsp[GRFUNIT(dev)]; 187 (void)grfoff(dev); 188 gp->g_flags &= GF_ALIVE; 189 return 0; 190 } 191 192 /*ARGSUSED*/ 193 int 194 grfioctl(dev_t dev, u_long cmd, void * data, int flag, struct lwp *l) 195 { 196 struct grf_softc *gp; 197 int error; 198 extern const struct cdevsw view_cdevsw; 199 200 gp = grfsp[GRFUNIT(dev)]; 201 error = 0; 202 203 switch (cmd) { 204 case OGRFIOCGINFO: 205 /* argl.. no bank-member.. */ 206 memcpy(data, (void *)&gp->g_display, sizeof(struct grfinfo)-4); 207 break; 208 case GRFIOCGINFO: 209 memcpy(data, (void *)&gp->g_display, sizeof(struct grfinfo)); 210 break; 211 case GRFIOCON: 212 error = grfon(dev); 213 break; 214 case GRFIOCOFF: 215 error = grfoff(dev); 216 break; 217 case GRFIOCSINFO: 218 error = grfsinfo(dev, (struct grfdyninfo *) data); 219 break; 220 case GRFGETVMODE: 221 return gp->g_mode(gp, GM_GRFGETVMODE, data, 0, 0); 222 case GRFSETVMODE: 223 error = gp->g_mode(gp, GM_GRFSETVMODE, data, 0, 0); 224 if (error == 0 && gp->g_itedev) 225 ite_reinit(gp->g_itedev); 226 break; 227 case GRFGETNUMVM: 228 return gp->g_mode(gp, GM_GRFGETNUMVM, data, 0, 0); 229 /* 230 * these are all hardware dependent, and have to be resolved 231 * in the respective driver. 232 */ 233 case GRFIOCPUTCMAP: 234 case GRFIOCGETCMAP: 235 case GRFIOCSSPRITEPOS: 236 case GRFIOCGSPRITEPOS: 237 case GRFIOCSSPRITEINF: 238 case GRFIOCGSPRITEINF: 239 case GRFIOCGSPRITEMAX: 240 default: 241 /* 242 * check to see whether it's a command recognized by the 243 * view code. 244 */ 245 return (*view_cdevsw.d_ioctl)(gp->g_viewdev, 246 cmd, data, flag, l); 247 error = EINVAL; 248 break; 249 250 } 251 return error; 252 } 253 254 /* 255 * map the contents of a graphics display card into process' 256 * memory space. 257 */ 258 paddr_t 259 grfmmap(dev_t dev, off_t off, int prot) 260 { 261 struct grf_softc *gp; 262 struct grfinfo *gi; 263 u_int vgabase, linbase; 264 265 gp = grfsp[GRFUNIT(dev)]; 266 gi = &gp->g_display; 267 268 vgabase = gi->gd_vgabase; 269 linbase = gi->gd_linbase; 270 271 /* 272 * control registers 273 */ 274 if (off >= 0 && off < gi->gd_regsize) 275 return ((paddr_t)gi->gd_regaddr + off) >> PGSHIFT; 276 277 /* 278 * VGA memory 279 */ 280 if (off >= vgabase && off < (vgabase + gi->gd_vgasize)) 281 return ((paddr_t)gi->gd_vgaaddr - vgabase + off) >> PGSHIFT; 282 283 /* 284 * frame buffer 285 */ 286 if (off >= linbase && off < (linbase + gi->gd_fbsize)) 287 return ((paddr_t)gi->gd_fbaddr - linbase + off) >> PGSHIFT; 288 return -1; 289 } 290 291 int 292 grfon(dev_t dev) 293 { 294 struct grf_softc *gp; 295 296 gp = grfsp[GRFUNIT(dev)]; 297 298 if (gp->g_flags & GF_GRFON) 299 return 0; 300 301 gp->g_flags |= GF_GRFON; 302 if (gp->g_itedev != NODEV) 303 ite_off(gp->g_itedev, 3); 304 305 return gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVON : GM_GRFON, 306 NULL, 0, 0); 307 } 308 309 int 310 grfoff(dev_t dev) 311 { 312 struct grf_softc *gp; 313 int error; 314 315 gp = grfsp[GRFUNIT(dev)]; 316 317 if ((gp->g_flags & GF_GRFON) == 0) 318 return 0; 319 320 gp->g_flags &= ~GF_GRFON; 321 error = gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF, 322 NULL, 0, 0); 323 324 /* 325 * Closely tied together no X's 326 */ 327 if (gp->g_itedev != NODEV) 328 ite_on(gp->g_itedev, 2); 329 330 return error; 331 } 332 333 int 334 grfsinfo(dev_t dev, struct grfdyninfo *dyninfo) 335 { 336 struct grf_softc *gp; 337 int error; 338 339 gp = grfsp[GRFUNIT(dev)]; 340 error = gp->g_mode(gp, GM_GRFCONFIG, dyninfo, 0, 0); 341 342 /* 343 * Closely tied together no X's 344 */ 345 if (gp->g_itedev != NODEV) 346 ite_reinit(gp->g_itedev); 347 return error; 348 } 349 350 /* 351 * Get the grf-info in sync with underlying view. 352 */ 353 void 354 grf_viewsync(struct grf_softc *gp) 355 { 356 struct view_size vs; 357 bmap_t bm; 358 struct grfinfo *gi; 359 extern const struct cdevsw view_cdevsw; 360 361 gi = &gp->g_display; 362 363 (*view_cdevsw.d_ioctl)(gp->g_viewdev, VIOCGBMAP, (void *)&bm, 364 0, NOLWP); 365 366 gp->g_data = (void *) 0xDeadBeaf; /* not particularly clean.. */ 367 368 gi->gd_fbaddr = bm.hw_address; 369 gi->gd_fbsize = bm.phys_mappable; 370 gi->gd_linbase = bm.lin_base; 371 gi->gd_regaddr = bm.hw_regs; 372 gi->gd_regsize = bm.reg_size; 373 gi->gd_vgaaddr = bm.vga_address; 374 gi->gd_vgasize = bm.vga_mappable; 375 gi->gd_vgabase = bm.vga_base; 376 377 if ((*view_cdevsw.d_ioctl)(gp->g_viewdev, VIOCGSIZE, (void *)&vs, 0, 378 NOLWP)) { 379 /* 380 * fill in some default values... 381 * XXX: Should _never_ happen 382 */ 383 vs.width = 640; 384 vs.height = 400; 385 vs.depth = 1; 386 } 387 gi->gd_colors = 1 << vs.depth; 388 gi->gd_planes = vs.depth; 389 390 gi->gd_fbwidth = vs.width; 391 gi->gd_fbheight = vs.height; 392 gi->gd_dyn.gdi_fbx = 0; 393 gi->gd_dyn.gdi_fby = 0; 394 gi->gd_dyn.gdi_dwidth = vs.width; 395 gi->gd_dyn.gdi_dheight = vs.height; 396 gi->gd_dyn.gdi_dx = 0; 397 gi->gd_dyn.gdi_dy = 0; 398 } 399 400 /* 401 * Change the mode of the display. 402 * Right now all we can do is grfon/grfoff. 403 * Return a UNIX error number or 0 for success. 404 */ 405 /*ARGSUSED*/ 406 int 407 grf_mode(struct grf_softc *gp, int cmd, void *arg, int a2, int a3) 408 { 409 extern const struct cdevsw view_cdevsw; 410 411 switch (cmd) { 412 case GM_GRFON: 413 /* 414 * Get in sync with view, ite might have changed it. 415 */ 416 grf_viewsync(gp); 417 (*view_cdevsw.d_ioctl)(gp->g_viewdev, VIOCDISPLAY, 418 NULL, 0, NOLWP); 419 return 0; 420 case GM_GRFOFF: 421 (*view_cdevsw.d_ioctl)(gp->g_viewdev, VIOCREMOVE, 422 NULL, 0, NOLWP); 423 return 0; 424 case GM_GRFCONFIG: 425 default: 426 break; 427 } 428 return EPASSTHROUGH; 429 } 430 #endif /* NGRF > 0 */ 431