1 /* $NetBSD: grf_obio.c,v 1.58 2012/10/27 17:18:00 chs Exp $ */ 2 3 /* 4 * Copyright (C) 1998 Scott Reynolds 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 /* 30 * Copyright (c) 1995 Allen Briggs. All rights reserved. 31 * 32 * Redistribution and use in source and binary forms, with or without 33 * modification, are permitted provided that the following conditions 34 * are met: 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 2. Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in the 39 * documentation and/or other materials provided with the distribution. 40 * 3. All advertising materials mentioning features or use of this software 41 * must display the following acknowledgement: 42 * This product includes software developed by Allen Briggs. 43 * 4. The name of the author may not be used to endorse or promote products 44 * derived from this software without specific prior written permission. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 51 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 52 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 55 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 */ 57 /* 58 * Graphics display driver for the Macintosh internal video for machines 59 * that don't map it into a fake nubus card. 60 */ 61 62 #include <sys/cdefs.h> 63 __KERNEL_RCSID(0, "$NetBSD: grf_obio.c,v 1.58 2012/10/27 17:18:00 chs Exp $"); 64 65 #include <sys/param.h> 66 #include <sys/device.h> 67 #include <sys/ioctl.h> 68 #include <sys/file.h> 69 #include <sys/malloc.h> 70 #include <sys/mman.h> 71 #include <sys/proc.h> 72 #include <sys/systm.h> 73 74 #include <machine/autoconf.h> 75 #include <machine/bus.h> 76 #include <machine/cpu.h> 77 #include <machine/grfioctl.h> 78 #include <machine/viareg.h> 79 #include <machine/video.h> 80 81 #include <mac68k/nubus/nubus.h> 82 #include <mac68k/obio/obiovar.h> 83 #include <mac68k/dev/grfvar.h> 84 85 static int grfiv_mode(struct grf_softc *, int, void *); 86 static int grfiv_match(device_t, cfdata_t, void *); 87 static void grfiv_attach(device_t, device_t, void *); 88 89 CFATTACH_DECL_NEW(intvid, sizeof(struct grfbus_softc), 90 grfiv_match, grfiv_attach, NULL, NULL); 91 92 #define DAFB_BASE 0xf9000000 93 #define DAFB_CONTROL_BASE 0xf9800000 94 #define CIVIC_BASE 0x50100000 95 #define CIVIC_CONTROL_BASE 0x50036000 96 #define VALKYRIE_BASE 0xf9000000 97 #define VALKYRIE_CONTROL_BASE 0x50f2a000 98 99 static int 100 grfiv_match(device_t parent, cfdata_t cf, void *aux) 101 { 102 struct obio_attach_args *oa = (struct obio_attach_args *)aux; 103 bus_space_handle_t bsh; 104 int found; 105 u_int base; 106 107 found = 1; 108 109 switch (current_mac_model->class) { 110 case MACH_CLASSQ2: 111 if (current_mac_model->machineid != MACH_MACLC575) { 112 base = VALKYRIE_CONTROL_BASE; 113 114 if (bus_space_map(oa->oa_tag, base, 0x40, 0, &bsh)) 115 return 0; 116 117 /* Disable interrupts */ 118 bus_space_write_1(oa->oa_tag, bsh, 0x18, 0x1); 119 120 bus_space_unmap(oa->oa_tag, bsh, 0x40); 121 break; 122 } 123 /* 124 * Note: the only system in this class that does not have 125 * the Valkyrie chip -- at least, that we know of -- is 126 * the Performa/LC 57x series. This system has a version 127 * of the DAFB controller, instead. 128 * 129 * If this assumption proves false, we'll have to be more 130 * intelligent here. 131 */ 132 /*FALLTHROUGH*/ 133 case MACH_CLASSQ: 134 /* 135 * Assume DAFB for all of these, unless we can't 136 * access the memory. 137 */ 138 base = DAFB_CONTROL_BASE; 139 140 if (bus_space_map(oa->oa_tag, base, 0x20, 0, &bsh)) 141 return 0; 142 143 if (mac68k_bus_space_probe(oa->oa_tag, bsh, 0x1c, 4) == 0) { 144 bus_space_unmap(oa->oa_tag, bsh, 0x20); 145 return 0; 146 } 147 148 bus_space_unmap(oa->oa_tag, bsh, 0x20); 149 150 if (bus_space_map(oa->oa_tag, base + 0x100, 0x20, 0, &bsh)) 151 return 0; 152 153 if (mac68k_bus_space_probe(oa->oa_tag, bsh, 0x04, 4) == 0) { 154 bus_space_unmap(oa->oa_tag, bsh, 0x20); 155 return 0; 156 } 157 158 /* Disable interrupts */ 159 bus_space_write_4(oa->oa_tag, bsh, 0x04, 0); 160 161 /* Clear any interrupts */ 162 bus_space_write_4(oa->oa_tag, bsh, 0x0C, 0); 163 bus_space_write_4(oa->oa_tag, bsh, 0x10, 0); 164 bus_space_write_4(oa->oa_tag, bsh, 0x14, 0); 165 166 bus_space_unmap(oa->oa_tag, bsh, 0x20); 167 break; 168 case MACH_CLASSAV: 169 base = CIVIC_CONTROL_BASE; 170 171 if (bus_space_map(oa->oa_tag, base, 0x1000, 0, &bsh)) 172 return 0; 173 174 /* Disable interrupts */ 175 bus_space_write_1(oa->oa_tag, bsh, 0x120, 0); 176 177 bus_space_unmap(oa->oa_tag, bsh, 0x1000); 178 break; 179 case MACH_CLASSIIci: 180 case MACH_CLASSIIsi: 181 if (mac68k_video.mv_len == 0 || 182 (via2_reg(rMonitor) & RBVMonitorMask) == RBVMonIDNone) 183 found = 0; 184 break; 185 default: 186 if (mac68k_video.mv_len == 0) 187 found = 0; 188 break; 189 } 190 191 return found; 192 } 193 194 static void 195 grfiv_attach(device_t parent, device_t self, void *aux) 196 { 197 struct obio_attach_args *oa = (struct obio_attach_args *)aux; 198 struct grfbus_softc *sc; 199 struct grfmode *gm; 200 u_long base, length; 201 u_int32_t vbase1, vbase2; 202 203 sc = device_private(self); 204 sc->sc_dev = self; 205 206 sc->card_id = 0; 207 208 switch (current_mac_model->class) { 209 case MACH_CLASSQ2: 210 if (current_mac_model->machineid != MACH_MACLC575) { 211 sc->sc_basepa = VALKYRIE_BASE; 212 length = 0x00100000; /* 1MB */ 213 214 if (sc->sc_basepa <= mac68k_video.mv_phys && 215 mac68k_video.mv_phys < (sc->sc_basepa + length)) { 216 sc->sc_fbofs = 217 mac68k_video.mv_phys - sc->sc_basepa; 218 } else { 219 sc->sc_basepa = 220 m68k_trunc_page(mac68k_video.mv_phys); 221 sc->sc_fbofs = 222 m68k_page_offset(mac68k_video.mv_phys); 223 length = mac68k_video.mv_len + sc->sc_fbofs; 224 } 225 226 printf(" @ %lx: Valkyrie video subsystem\n", 227 sc->sc_basepa + sc->sc_fbofs); 228 break; 229 } 230 /* See note in grfiv_match() */ 231 /*FALLTHROUGH*/ 232 case MACH_CLASSQ: 233 base = DAFB_CONTROL_BASE; 234 sc->sc_tag = oa->oa_tag; 235 if (bus_space_map(sc->sc_tag, base, 0x20, 0, &sc->sc_regh)) { 236 printf(": failed to map DAFB register space\n"); 237 return; 238 } 239 240 sc->sc_basepa = DAFB_BASE; 241 length = 0x00100000; /* 1MB */ 242 243 /* Compute the current frame buffer offset */ 244 vbase1 = bus_space_read_4(sc->sc_tag, sc->sc_regh, 0x0) & 0xfff; 245 #if 1 246 /* 247 * XXX The following exists because the DAFB v7 in these 248 * systems doesn't return reasonable values to use for fbofs. 249 * Ken'ichi Ishizaka gets credit for this hack. (sar 19990426) 250 * (Does this get us the correct result for _all_ DAFB- 251 * equipped systems and monitor combinations? It seems 252 * possible, if not likely...) 253 */ 254 switch (current_mac_model->machineid) { 255 case MACH_MACLC475: 256 case MACH_MACLC475_33: 257 case MACH_MACLC575: 258 case MACH_MACQ605: 259 case MACH_MACQ605_33: 260 vbase1 &= 0x3f; 261 break; 262 } 263 #endif 264 vbase2 = bus_space_read_4(sc->sc_tag, sc->sc_regh, 0x4) & 0xf; 265 sc->sc_fbofs = (vbase1 << 9) | (vbase2 << 5); 266 267 printf(" @ %lx: DAFB video subsystem, monitor sense %x\n", 268 sc->sc_basepa + sc->sc_fbofs, 269 (bus_space_read_4(sc->sc_tag, sc->sc_regh, 0x1c) & 0x7)); 270 271 bus_space_unmap(sc->sc_tag, sc->sc_regh, 0x20); 272 break; 273 case MACH_CLASSAV: 274 sc->sc_basepa = CIVIC_BASE; 275 length = 0x00200000; /* 2MB */ 276 if (mac68k_video.mv_phys >= sc->sc_basepa && 277 mac68k_video.mv_phys < (sc->sc_basepa + length)) { 278 sc->sc_fbofs = mac68k_video.mv_phys - sc->sc_basepa; 279 } else { 280 sc->sc_basepa = m68k_trunc_page(mac68k_video.mv_phys); 281 sc->sc_fbofs = m68k_page_offset(mac68k_video.mv_phys); 282 length = mac68k_video.mv_len + sc->sc_fbofs; 283 } 284 285 printf(" @ %lx: CIVIC video subsystem\n", 286 sc->sc_basepa + sc->sc_fbofs); 287 break; 288 case MACH_CLASSIIci: 289 case MACH_CLASSIIsi: 290 sc->sc_basepa = m68k_trunc_page(mac68k_video.mv_phys); 291 sc->sc_fbofs = m68k_page_offset(mac68k_video.mv_phys); 292 length = mac68k_video.mv_len + sc->sc_fbofs; 293 294 printf(" @ %lx: RBV video subsystem, ", 295 sc->sc_basepa + sc->sc_fbofs); 296 switch (via2_reg(rMonitor) & RBVMonitorMask) { 297 case RBVMonIDBWP: 298 printf("15\" monochrome portrait"); 299 break; 300 case RBVMonIDRGB12: 301 printf("12\" color"); 302 break; 303 case RBVMonIDRGB15: 304 printf("15\" color"); 305 break; 306 case RBVMonIDStd: 307 printf("Macintosh II"); 308 break; 309 default: 310 printf("unrecognized"); 311 break; 312 } 313 printf(" display\n"); 314 315 break; 316 default: 317 sc->sc_basepa = m68k_trunc_page(mac68k_video.mv_phys); 318 sc->sc_fbofs = m68k_page_offset(mac68k_video.mv_phys); 319 length = mac68k_video.mv_len + sc->sc_fbofs; 320 321 printf(" @ %lx: On-board video\n", 322 sc->sc_basepa + sc->sc_fbofs); 323 break; 324 } 325 326 if (bus_space_map(sc->sc_tag, sc->sc_basepa, length, 0, 327 &sc->sc_handle)) { 328 printf("%s: failed to map video RAM\n", device_xname(sc->sc_dev)); 329 return; 330 } 331 332 if (sc->sc_basepa <= mac68k_video.mv_phys && 333 mac68k_video.mv_phys < (sc->sc_basepa + length)) { 334 /* XXX Hack */ 335 mac68k_video.mv_kvaddr = sc->sc_handle.base + sc->sc_fbofs; 336 } 337 338 gm = &(sc->curr_mode); 339 gm->mode_id = 0; 340 gm->psize = mac68k_video.mv_depth; 341 gm->ptype = 0; 342 gm->width = mac68k_video.mv_width; 343 gm->height = mac68k_video.mv_height; 344 gm->rowbytes = mac68k_video.mv_stride; 345 gm->hres = 80; /* XXX hack */ 346 gm->vres = 80; /* XXX hack */ 347 gm->fbsize = gm->height * gm->rowbytes; 348 gm->fbbase = (void *)sc->sc_handle.base; /* XXX yet another hack */ 349 gm->fboff = sc->sc_fbofs; 350 351 /* Perform common video attachment. */ 352 grf_establish(sc, NULL, grfiv_mode); 353 } 354 355 static int 356 grfiv_mode(struct grf_softc *sc, int cmd, void *arg) 357 { 358 switch (cmd) { 359 case GM_GRFON: 360 case GM_GRFOFF: 361 return 0; 362 case GM_CURRMODE: 363 break; 364 case GM_NEWMODE: 365 break; 366 case GM_LISTMODES: 367 break; 368 } 369 return EINVAL; 370 } 371