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