1 /* $NetBSD: grf.c,v 1.48 2014/03/16 05:20:23 dholland 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.48 2014/03/16 05:20:23 dholland 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 .d_open = grfopen, 112 .d_close = grfclose, 113 .d_read = noread, 114 .d_write = nowrite, 115 .d_ioctl = grfioctl, 116 .d_stop = nostop, 117 .d_tty = notty, 118 .d_poll = nopoll, 119 .d_mmap = grfmmap, 120 .d_kqfilter = nokqfilter, 121 .d_flag = 0 122 }; 123 124 /* 125 * only used in console init. 126 */ 127 static cfdata_t cfdata_gbus = NULL; 128 129 int 130 grfbusmatch(device_t parent, cfdata_t cf, void *aux) 131 { 132 133 if (strcmp(aux, grfbus_cd.cd_name)) 134 return 0; 135 136 if (atari_realconfig == 0) 137 cfdata_gbus = cf; 138 return 1; /* Always there */ 139 } 140 141 void 142 grfbusattach(device_t parent, device_t self, void *aux) 143 { 144 grf_auxp_t grf_auxp; 145 146 grf_auxp.busprint = grfbusprint; 147 grf_auxp.from_bus_match = 1; 148 149 if (self == NULL) /* Console init */ 150 atari_config_found(cfdata_gbus, NULL, &grf_auxp, grfbusprint); 151 else { 152 printf("\n"); 153 config_found(self, &grf_auxp, grfbusprint); 154 } 155 } 156 157 int 158 grfbusprint(void *aux, const char *name) 159 { 160 161 if (name == NULL) 162 return UNCONF; 163 return QUIET; 164 } 165 166 /*ARGSUSED*/ 167 int 168 grfopen(dev_t dev, int flags, int devtype, struct lwp *l) 169 { 170 struct grf_softc *gp; 171 172 if (GRFUNIT(dev) >= NGRF) 173 return ENXIO; 174 175 gp = grfsp[GRFUNIT(dev)]; 176 if (gp == NULL) 177 return ENXIO; 178 179 if ((gp->g_flags & GF_ALIVE) == 0) 180 return ENXIO; 181 182 if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE)) 183 return EBUSY; 184 grf_viewsync(gp); 185 186 return 0; 187 } 188 189 /*ARGSUSED*/ 190 int 191 grfclose(dev_t dev, int flags, int mode, struct lwp *l) 192 { 193 struct grf_softc *gp; 194 195 gp = grfsp[GRFUNIT(dev)]; 196 (void)grfoff(dev); 197 gp->g_flags &= GF_ALIVE; 198 return 0; 199 } 200 201 /*ARGSUSED*/ 202 int 203 grfioctl(dev_t dev, u_long cmd, void * data, int flag, struct lwp *l) 204 { 205 struct grf_softc *gp; 206 int error; 207 extern const struct cdevsw view_cdevsw; 208 209 gp = grfsp[GRFUNIT(dev)]; 210 error = 0; 211 212 switch (cmd) { 213 case OGRFIOCGINFO: 214 /* argl.. no bank-member.. */ 215 memcpy(data, (void *)&gp->g_display, sizeof(struct grfinfo)-4); 216 break; 217 case GRFIOCGINFO: 218 memcpy(data, (void *)&gp->g_display, sizeof(struct grfinfo)); 219 break; 220 case GRFIOCON: 221 error = grfon(dev); 222 break; 223 case GRFIOCOFF: 224 error = grfoff(dev); 225 break; 226 case GRFIOCSINFO: 227 error = grfsinfo(dev, (struct grfdyninfo *) data); 228 break; 229 case GRFGETVMODE: 230 return gp->g_mode(gp, GM_GRFGETVMODE, data, 0, 0); 231 case GRFSETVMODE: 232 error = gp->g_mode(gp, GM_GRFSETVMODE, data, 0, 0); 233 if (error == 0 && gp->g_itedev) 234 ite_reinit(gp->g_itedev); 235 break; 236 case GRFGETNUMVM: 237 return gp->g_mode(gp, GM_GRFGETNUMVM, data, 0, 0); 238 /* 239 * these are all hardware dependent, and have to be resolved 240 * in the respective driver. 241 */ 242 case GRFIOCPUTCMAP: 243 case GRFIOCGETCMAP: 244 case GRFIOCSSPRITEPOS: 245 case GRFIOCGSPRITEPOS: 246 case GRFIOCSSPRITEINF: 247 case GRFIOCGSPRITEINF: 248 case GRFIOCGSPRITEMAX: 249 default: 250 /* 251 * check to see whether it's a command recognized by the 252 * view code. 253 */ 254 return (*view_cdevsw.d_ioctl)(gp->g_viewdev, 255 cmd, data, flag, l); 256 error = EINVAL; 257 break; 258 259 } 260 return error; 261 } 262 263 /* 264 * map the contents of a graphics display card into process' 265 * memory space. 266 */ 267 paddr_t 268 grfmmap(dev_t dev, off_t off, int prot) 269 { 270 struct grf_softc *gp; 271 struct grfinfo *gi; 272 u_int vgabase, linbase; 273 274 gp = grfsp[GRFUNIT(dev)]; 275 gi = &gp->g_display; 276 277 vgabase = gi->gd_vgabase; 278 linbase = gi->gd_linbase; 279 280 /* 281 * control registers 282 */ 283 if (off >= 0 && off < gi->gd_regsize) 284 return ((paddr_t)gi->gd_regaddr + off) >> PGSHIFT; 285 286 /* 287 * VGA memory 288 */ 289 if (off >= vgabase && off < (vgabase + gi->gd_vgasize)) 290 return ((paddr_t)gi->gd_vgaaddr - vgabase + off) >> PGSHIFT; 291 292 /* 293 * frame buffer 294 */ 295 if (off >= linbase && off < (linbase + gi->gd_fbsize)) 296 return ((paddr_t)gi->gd_fbaddr - linbase + off) >> PGSHIFT; 297 return -1; 298 } 299 300 int 301 grfon(dev_t dev) 302 { 303 struct grf_softc *gp; 304 305 gp = grfsp[GRFUNIT(dev)]; 306 307 if (gp->g_flags & GF_GRFON) 308 return 0; 309 310 gp->g_flags |= GF_GRFON; 311 if (gp->g_itedev != NODEV) 312 ite_off(gp->g_itedev, 3); 313 314 return gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVON : GM_GRFON, 315 NULL, 0, 0); 316 } 317 318 int 319 grfoff(dev_t dev) 320 { 321 struct grf_softc *gp; 322 int error; 323 324 gp = grfsp[GRFUNIT(dev)]; 325 326 if ((gp->g_flags & GF_GRFON) == 0) 327 return 0; 328 329 gp->g_flags &= ~GF_GRFON; 330 error = gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF, 331 NULL, 0, 0); 332 333 /* 334 * Closely tied together no X's 335 */ 336 if (gp->g_itedev != NODEV) 337 ite_on(gp->g_itedev, 2); 338 339 return error; 340 } 341 342 int 343 grfsinfo(dev_t dev, struct grfdyninfo *dyninfo) 344 { 345 struct grf_softc *gp; 346 int error; 347 348 gp = grfsp[GRFUNIT(dev)]; 349 error = gp->g_mode(gp, GM_GRFCONFIG, dyninfo, 0, 0); 350 351 /* 352 * Closely tied together no X's 353 */ 354 if (gp->g_itedev != NODEV) 355 ite_reinit(gp->g_itedev); 356 return error; 357 } 358 359 /* 360 * Get the grf-info in sync with underlying view. 361 */ 362 void 363 grf_viewsync(struct grf_softc *gp) 364 { 365 struct view_size vs; 366 bmap_t bm; 367 struct grfinfo *gi; 368 extern const struct cdevsw view_cdevsw; 369 370 gi = &gp->g_display; 371 372 (*view_cdevsw.d_ioctl)(gp->g_viewdev, VIOCGBMAP, (void *)&bm, 373 0, NOLWP); 374 375 gp->g_data = (void *) 0xDeadBeaf; /* not particularly clean.. */ 376 377 gi->gd_fbaddr = bm.hw_address; 378 gi->gd_fbsize = bm.phys_mappable; 379 gi->gd_linbase = bm.lin_base; 380 gi->gd_regaddr = bm.hw_regs; 381 gi->gd_regsize = bm.reg_size; 382 gi->gd_vgaaddr = bm.vga_address; 383 gi->gd_vgasize = bm.vga_mappable; 384 gi->gd_vgabase = bm.vga_base; 385 386 if ((*view_cdevsw.d_ioctl)(gp->g_viewdev, VIOCGSIZE, (void *)&vs, 0, 387 NOLWP)) { 388 /* 389 * fill in some default values... 390 * XXX: Should _never_ happen 391 */ 392 vs.width = 640; 393 vs.height = 400; 394 vs.depth = 1; 395 } 396 gi->gd_colors = 1 << vs.depth; 397 gi->gd_planes = vs.depth; 398 399 gi->gd_fbwidth = vs.width; 400 gi->gd_fbheight = vs.height; 401 gi->gd_dyn.gdi_fbx = 0; 402 gi->gd_dyn.gdi_fby = 0; 403 gi->gd_dyn.gdi_dwidth = vs.width; 404 gi->gd_dyn.gdi_dheight = vs.height; 405 gi->gd_dyn.gdi_dx = 0; 406 gi->gd_dyn.gdi_dy = 0; 407 } 408 409 /* 410 * Change the mode of the display. 411 * Right now all we can do is grfon/grfoff. 412 * Return a UNIX error number or 0 for success. 413 */ 414 /*ARGSUSED*/ 415 int 416 grf_mode(struct grf_softc *gp, int cmd, void *arg, int a2, int a3) 417 { 418 extern const struct cdevsw view_cdevsw; 419 420 switch (cmd) { 421 case GM_GRFON: 422 /* 423 * Get in sync with view, ite might have changed it. 424 */ 425 grf_viewsync(gp); 426 (*view_cdevsw.d_ioctl)(gp->g_viewdev, VIOCDISPLAY, 427 NULL, 0, NOLWP); 428 return 0; 429 case GM_GRFOFF: 430 (*view_cdevsw.d_ioctl)(gp->g_viewdev, VIOCREMOVE, 431 NULL, 0, NOLWP); 432 return 0; 433 case GM_GRFCONFIG: 434 default: 435 break; 436 } 437 return EPASSTHROUGH; 438 } 439 #endif /* NGRF > 0 */ 440