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