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