1 1.15 tsutsui /* $NetBSD: topcat.c,v 1.15 2025/05/27 18:44:31 tsutsui Exp $ */ 2 1.1 tsutsui /* $OpenBSD: topcat.c,v 1.15 2006/08/11 18:33:13 miod Exp $ */ 3 1.1 tsutsui 4 1.1 tsutsui /* 5 1.1 tsutsui * Copyright (c) 2005, Miodrag Vallat. 6 1.1 tsutsui * All rights reserved. 7 1.1 tsutsui * 8 1.1 tsutsui * Redistribution and use in source and binary forms, with or without 9 1.1 tsutsui * modification, are permitted provided that the following conditions 10 1.1 tsutsui * are met: 11 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright 12 1.1 tsutsui * notice, this list of conditions and the following disclaimer. 13 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the 15 1.1 tsutsui * documentation and/or other materials provided with the distribution. 16 1.1 tsutsui * 17 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 1.1 tsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 1.1 tsutsui * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 1.1 tsutsui * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 21 1.1 tsutsui * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 1.1 tsutsui * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 1.1 tsutsui * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 1.1 tsutsui * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 1.1 tsutsui * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 26 1.1 tsutsui * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 1.1 tsutsui * POSSIBILITY OF SUCH DAMAGE. 28 1.1 tsutsui * 29 1.1 tsutsui */ 30 1.1 tsutsui /*- 31 1.1 tsutsui * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. 32 1.1 tsutsui * All rights reserved. 33 1.1 tsutsui * 34 1.1 tsutsui * This code is derived from software contributed to The NetBSD Foundation 35 1.1 tsutsui * by Jason R. Thorpe. 36 1.1 tsutsui * 37 1.1 tsutsui * Redistribution and use in source and binary forms, with or without 38 1.1 tsutsui * modification, are permitted provided that the following conditions 39 1.1 tsutsui * are met: 40 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright 41 1.1 tsutsui * notice, this list of conditions and the following disclaimer. 42 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright 43 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the 44 1.1 tsutsui * documentation and/or other materials provided with the distribution. 45 1.1 tsutsui * 46 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 47 1.1 tsutsui * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 48 1.1 tsutsui * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 49 1.1 tsutsui * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 50 1.1 tsutsui * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 51 1.1 tsutsui * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 52 1.1 tsutsui * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 53 1.1 tsutsui * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 54 1.1 tsutsui * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 55 1.1 tsutsui * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 56 1.1 tsutsui * POSSIBILITY OF SUCH DAMAGE. 57 1.1 tsutsui */ 58 1.1 tsutsui 59 1.1 tsutsui /* 60 1.1 tsutsui * Copyright (c) 1988 University of Utah. 61 1.1 tsutsui * Copyright (c) 1990, 1993 62 1.1 tsutsui * The Regents of the University of California. All rights reserved. 63 1.1 tsutsui * 64 1.1 tsutsui * This code is derived from software contributed to Berkeley by 65 1.1 tsutsui * the Systems Programming Group of the University of Utah Computer 66 1.1 tsutsui * Science Department. 67 1.1 tsutsui * 68 1.1 tsutsui * Redistribution and use in source and binary forms, with or without 69 1.1 tsutsui * modification, are permitted provided that the following conditions 70 1.1 tsutsui * are met: 71 1.1 tsutsui * 1. Redistributions of source code must retain the above copyright 72 1.1 tsutsui * notice, this list of conditions and the following disclaimer. 73 1.1 tsutsui * 2. Redistributions in binary form must reproduce the above copyright 74 1.1 tsutsui * notice, this list of conditions and the following disclaimer in the 75 1.1 tsutsui * documentation and/or other materials provided with the distribution. 76 1.1 tsutsui * 3. Neither the name of the University nor the names of its contributors 77 1.1 tsutsui * may be used to endorse or promote products derived from this software 78 1.1 tsutsui * without specific prior written permission. 79 1.1 tsutsui * 80 1.1 tsutsui * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 81 1.1 tsutsui * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 82 1.1 tsutsui * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 83 1.1 tsutsui * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 84 1.1 tsutsui * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 85 1.1 tsutsui * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 86 1.1 tsutsui * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 87 1.1 tsutsui * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 88 1.1 tsutsui * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 89 1.1 tsutsui * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 90 1.1 tsutsui * SUCH DAMAGE. 91 1.1 tsutsui * 92 1.1 tsutsui * from: Utah $Hdr: grf_tc.c 1.20 93/08/13$ 93 1.1 tsutsui * 94 1.1 tsutsui * @(#)grf_tc.c 8.4 (Berkeley) 1/12/94 95 1.1 tsutsui */ 96 1.1 tsutsui 97 1.1 tsutsui /* 98 1.1 tsutsui * Graphics routines for TOPCAT, CATSEYE and KATHMANDU frame buffers 99 1.1 tsutsui */ 100 1.1 tsutsui 101 1.1 tsutsui #include <sys/param.h> 102 1.1 tsutsui #include <sys/systm.h> 103 1.1 tsutsui #include <sys/conf.h> 104 1.1 tsutsui #include <sys/device.h> 105 1.1 tsutsui #include <sys/proc.h> 106 1.1 tsutsui #include <sys/ioctl.h> 107 1.1 tsutsui #include <sys/bus.h> 108 1.1 tsutsui #include <sys/cpu.h> 109 1.1 tsutsui 110 1.1 tsutsui #include <machine/autoconf.h> 111 1.1 tsutsui 112 1.1 tsutsui #include <hp300/dev/dioreg.h> 113 1.1 tsutsui #include <hp300/dev/diovar.h> 114 1.1 tsutsui #include <hp300/dev/diodevs.h> 115 1.1 tsutsui #include <hp300/dev/intiovar.h> 116 1.1 tsutsui 117 1.1 tsutsui #include <dev/wscons/wsconsio.h> 118 1.1 tsutsui #include <dev/wscons/wsdisplayvar.h> 119 1.1 tsutsui #include <dev/rasops/rasops.h> 120 1.1 tsutsui 121 1.1 tsutsui #include <hp300/dev/diofbreg.h> 122 1.1 tsutsui #include <hp300/dev/diofbvar.h> 123 1.1 tsutsui #include <hp300/dev/topcatreg.h> 124 1.1 tsutsui 125 1.1 tsutsui struct topcat_softc { 126 1.1 tsutsui device_t sc_dev; 127 1.1 tsutsui struct diofb *sc_fb; 128 1.1 tsutsui struct diofb sc_fb_store; 129 1.1 tsutsui int sc_scode; 130 1.1 tsutsui }; 131 1.1 tsutsui 132 1.3 tsutsui static int topcat_dio_match(device_t, cfdata_t, void *); 133 1.3 tsutsui static void topcat_dio_attach(device_t, device_t, void *); 134 1.3 tsutsui static int topcat_intio_match(device_t, cfdata_t, void *); 135 1.3 tsutsui static void topcat_intio_attach(device_t, device_t, void *); 136 1.1 tsutsui 137 1.1 tsutsui CFATTACH_DECL_NEW(topcat_dio, sizeof(struct topcat_softc), 138 1.1 tsutsui topcat_dio_match, topcat_dio_attach, NULL, NULL); 139 1.1 tsutsui 140 1.1 tsutsui CFATTACH_DECL_NEW(topcat_intio, sizeof(struct topcat_softc), 141 1.1 tsutsui topcat_intio_match, topcat_intio_attach, NULL, NULL); 142 1.1 tsutsui 143 1.3 tsutsui static void topcat_end_attach(struct topcat_softc *, uint8_t); 144 1.3 tsutsui static int topcat_reset(struct diofb *, int, struct diofbreg *); 145 1.3 tsutsui static void topcat_restore(struct diofb *); 146 1.3 tsutsui static int topcat_setcmap(struct diofb *, struct wsdisplay_cmap *); 147 1.3 tsutsui static void topcat_setcolor(struct diofb *, u_int); 148 1.3 tsutsui static int topcat_windowmove(struct diofb *, uint16_t, uint16_t, uint16_t, 149 1.3 tsutsui uint16_t, uint16_t, uint16_t, int16_t, int16_t); 150 1.1 tsutsui 151 1.3 tsutsui static int topcat_ioctl(void *, void *, u_long, void *, int, struct lwp *); 152 1.11 tsutsui static void topcat_putchar8(void *, int, int, u_int, long); 153 1.11 tsutsui static void topcat_putchar1_4(void *, int, int, u_int, long); 154 1.1 tsutsui 155 1.3 tsutsui static struct wsdisplay_accessops topcat_accessops = { 156 1.15 tsutsui .ioctl = topcat_ioctl, 157 1.15 tsutsui .mmap = diofb_mmap, 158 1.15 tsutsui .alloc_screen = diofb_alloc_screen, 159 1.15 tsutsui .free_screen = diofb_free_screen, 160 1.15 tsutsui .show_screen = diofb_show_screen, 161 1.15 tsutsui .load_font = NULL, 162 1.1 tsutsui }; 163 1.1 tsutsui 164 1.1 tsutsui /* 165 1.1 tsutsui * Attachment glue 166 1.1 tsutsui */ 167 1.1 tsutsui 168 1.1 tsutsui int 169 1.1 tsutsui topcat_intio_match(device_t parent, cfdata_t cf, void *aux) 170 1.1 tsutsui { 171 1.1 tsutsui struct intio_attach_args *ia = aux; 172 1.1 tsutsui struct diofbreg *fbr; 173 1.1 tsutsui 174 1.1 tsutsui if (strcmp("fb", ia->ia_modname) != 0) 175 1.1 tsutsui return 0; 176 1.1 tsutsui 177 1.1 tsutsui fbr = (struct diofbreg *)ia->ia_addr; 178 1.1 tsutsui 179 1.1 tsutsui if (badaddr((void *)fbr)) 180 1.2 tsutsui return 0; 181 1.1 tsutsui 182 1.1 tsutsui if (fbr->id == GRFHWID) { 183 1.1 tsutsui switch (fbr->fbid) { 184 1.1 tsutsui case GID_TOPCAT: 185 1.1 tsutsui case GID_LRCATSEYE: 186 1.1 tsutsui case GID_HRCCATSEYE: 187 1.1 tsutsui case GID_HRMCATSEYE: 188 1.1 tsutsui #if 0 189 1.1 tsutsui case GID_XXXCATSEYE: 190 1.1 tsutsui #endif 191 1.2 tsutsui return 1; 192 1.1 tsutsui } 193 1.1 tsutsui } 194 1.1 tsutsui 195 1.2 tsutsui return 0; 196 1.1 tsutsui } 197 1.1 tsutsui 198 1.1 tsutsui void 199 1.1 tsutsui topcat_intio_attach(device_t parent, device_t self, void *aux) 200 1.1 tsutsui { 201 1.1 tsutsui struct topcat_softc *sc = device_private(self); 202 1.1 tsutsui struct intio_attach_args *ia = aux; 203 1.1 tsutsui struct diofbreg *fbr; 204 1.1 tsutsui 205 1.1 tsutsui sc->sc_dev = self; 206 1.1 tsutsui fbr = (struct diofbreg *)ia->ia_addr; 207 1.1 tsutsui sc->sc_scode = CONSCODE_INTERNAL; 208 1.1 tsutsui 209 1.1 tsutsui if (sc->sc_scode == conscode) { 210 1.1 tsutsui sc->sc_fb = &diofb_cn; 211 1.1 tsutsui } else { 212 1.1 tsutsui sc->sc_fb = &sc->sc_fb_store; 213 1.1 tsutsui topcat_reset(sc->sc_fb, sc->sc_scode, fbr); 214 1.1 tsutsui } 215 1.1 tsutsui 216 1.1 tsutsui topcat_end_attach(sc, fbr->fbid); 217 1.1 tsutsui } 218 1.1 tsutsui 219 1.1 tsutsui int 220 1.1 tsutsui topcat_dio_match(device_t parent, cfdata_t cf, void *aux) 221 1.1 tsutsui { 222 1.1 tsutsui struct dio_attach_args *da = aux; 223 1.1 tsutsui 224 1.1 tsutsui if (da->da_id == DIO_DEVICE_ID_FRAMEBUFFER) { 225 1.1 tsutsui switch (da->da_secid) { 226 1.1 tsutsui case DIO_DEVICE_SECID_TOPCAT: 227 1.1 tsutsui case DIO_DEVICE_SECID_LRCATSEYE: 228 1.1 tsutsui case DIO_DEVICE_SECID_HRCCATSEYE: 229 1.1 tsutsui case DIO_DEVICE_SECID_HRMCATSEYE: 230 1.1 tsutsui #if 0 231 1.1 tsutsui case DIO_DEVICE_SECID_XXXCATSEYE: 232 1.1 tsutsui #endif 233 1.2 tsutsui return 1; 234 1.1 tsutsui } 235 1.1 tsutsui } 236 1.1 tsutsui 237 1.2 tsutsui return 0; 238 1.1 tsutsui } 239 1.1 tsutsui 240 1.1 tsutsui void 241 1.1 tsutsui topcat_dio_attach(device_t parent, device_t self, void *aux) 242 1.1 tsutsui { 243 1.1 tsutsui struct topcat_softc *sc = device_private(self); 244 1.1 tsutsui struct dio_attach_args *da = aux; 245 1.1 tsutsui bus_space_handle_t bsh; 246 1.1 tsutsui struct diofbreg *fbr; 247 1.1 tsutsui 248 1.1 tsutsui sc->sc_dev = self; 249 1.1 tsutsui sc->sc_scode = da->da_scode; 250 1.1 tsutsui if (sc->sc_scode == conscode) { 251 1.1 tsutsui fbr = (struct diofbreg *)conaddr; /* already mapped */ 252 1.1 tsutsui sc->sc_fb = &diofb_cn; 253 1.1 tsutsui } else { 254 1.1 tsutsui sc->sc_fb = &sc->sc_fb_store; 255 1.1 tsutsui if (bus_space_map(da->da_bst, da->da_addr, da->da_size, 0, 256 1.1 tsutsui &bsh)) { 257 1.1 tsutsui aprint_error(": can't map framebuffer\n"); 258 1.1 tsutsui return; 259 1.1 tsutsui } 260 1.1 tsutsui fbr = bus_space_vaddr(da->da_bst, bsh); 261 1.1 tsutsui if (topcat_reset(sc->sc_fb, sc->sc_scode, fbr) != 0) { 262 1.4 tsutsui aprint_error(": can't reset framebuffer\n"); 263 1.1 tsutsui return; 264 1.1 tsutsui } 265 1.1 tsutsui } 266 1.1 tsutsui 267 1.1 tsutsui topcat_end_attach(sc, fbr->fbid); 268 1.1 tsutsui } 269 1.1 tsutsui 270 1.1 tsutsui void 271 1.2 tsutsui topcat_end_attach(struct topcat_softc *sc, uint8_t id) 272 1.1 tsutsui { 273 1.1 tsutsui const char *fbname = "unknown"; 274 1.1 tsutsui 275 1.1 tsutsui switch (id) { 276 1.1 tsutsui case GID_TOPCAT: 277 1.1 tsutsui switch (sc->sc_fb->planes) { 278 1.1 tsutsui case 1: 279 1.5 tsutsui if (sc->sc_fb->dheight == 400) 280 1.5 tsutsui fbname = "HP98542 topcat"; 281 1.5 tsutsui else 282 1.5 tsutsui fbname = "HP98544 topcat"; 283 1.1 tsutsui break; 284 1.1 tsutsui case 4: 285 1.1 tsutsui if (sc->sc_fb->dheight == 400) 286 1.1 tsutsui fbname = "HP98543 topcat"; 287 1.1 tsutsui else 288 1.1 tsutsui fbname = "HP98545 topcat"; 289 1.1 tsutsui break; 290 1.1 tsutsui case 6: 291 1.1 tsutsui fbname = "HP98547 topcat"; 292 1.1 tsutsui break; 293 1.1 tsutsui } 294 1.1 tsutsui break; 295 1.1 tsutsui case GID_HRCCATSEYE: 296 1.1 tsutsui fbname = "HP98550 catseye"; /* also A1416 kathmandu */ 297 1.1 tsutsui break; 298 1.1 tsutsui case GID_LRCATSEYE: 299 1.1 tsutsui fbname = "HP98549 catseye"; 300 1.1 tsutsui break; 301 1.1 tsutsui case GID_HRMCATSEYE: 302 1.1 tsutsui fbname = "HP98548 catseye"; 303 1.1 tsutsui break; 304 1.1 tsutsui } 305 1.1 tsutsui 306 1.1 tsutsui diofb_end_attach(sc->sc_dev, &topcat_accessops, sc->sc_fb, 307 1.1 tsutsui sc->sc_scode == conscode, fbname); 308 1.1 tsutsui } 309 1.1 tsutsui 310 1.1 tsutsui /* 311 1.1 tsutsui * Initialize hardware and display routines. 312 1.1 tsutsui */ 313 1.1 tsutsui int 314 1.1 tsutsui topcat_reset(struct diofb *fb, int scode, struct diofbreg *fbr) 315 1.1 tsutsui { 316 1.1 tsutsui volatile struct tcboxfb *tc = (struct tcboxfb *)fbr; 317 1.11 tsutsui struct rasops_info *ri = &fb->ri; 318 1.1 tsutsui int rc; 319 1.1 tsutsui u_int i; 320 1.11 tsutsui bool sparse = false; 321 1.1 tsutsui 322 1.1 tsutsui if ((rc = diofb_fbinquire(fb, scode, fbr)) != 0) 323 1.2 tsutsui return rc; 324 1.1 tsutsui 325 1.1 tsutsui /* 326 1.1 tsutsui * If we could not get a valid number of planes, determine it 327 1.1 tsutsui * by writing to the first frame buffer display location, 328 1.1 tsutsui * then reading it back. 329 1.1 tsutsui */ 330 1.1 tsutsui if (fb->planes == 0) { 331 1.2 tsutsui volatile uint8_t *fbp; 332 1.2 tsutsui uint8_t save; 333 1.1 tsutsui 334 1.2 tsutsui fbp = (uint8_t *)fb->fbkva; 335 1.1 tsutsui tc->fben = ~0; 336 1.1 tsutsui tc->wen = ~0; 337 1.1 tsutsui tc->ren = ~0; 338 1.1 tsutsui tc->prr = RR_COPY; 339 1.1 tsutsui save = *fbp; 340 1.1 tsutsui *fbp = 0xff; 341 1.1 tsutsui fb->planemask = *fbp; 342 1.1 tsutsui *fbp = save; 343 1.1 tsutsui 344 1.1 tsutsui for (fb->planes = 1; fb->planemask >= (1 << fb->planes); 345 1.1 tsutsui fb->planes++); 346 1.1 tsutsui if (fb->planes > 8) 347 1.1 tsutsui fb->planes = 8; 348 1.1 tsutsui fb->planemask = (1 << fb->planes) - 1; 349 1.1 tsutsui } 350 1.1 tsutsui 351 1.7 tsutsui /* 352 1.7 tsutsui * Some displays, such as the HP332 and HP340 internal video 353 1.7 tsutsui * and HP98542/98543 appear to return a display width of 1024 354 1.12 tsutsui * instead of 512. It looks these boards have actually have 355 1.12 tsutsui * enough 64KB (1bpp) or 256KB (4bpp) VRAM and RAMDAC capabilities 356 1.12 tsutsui * to display 1024x400 pixels. 357 1.13 tsutsui * 358 1.14 andvar * However HP's official "Service Information Manual" for 359 1.12 tsutsui * "HP 900 Series 300 Computers Models 330/350" says: 360 1.12 tsutsui * "The medium-resolution board uses eight memory chips per plane. 361 1.12 tsutsui * This is enough to display 512 doubled pixels by 400 scan lines." 362 1.12 tsutsui * 363 1.12 tsutsui * This "512 doubled pixels" implies that the native HP-UX treated 364 1.12 tsutsui * these 1024x400 framebuffers as pseudo 512x400 ones because 365 1.12 tsutsui * ancient 1980s CRTs (such as 35741) didn't display such higher 366 1.12 tsutsui * resolution. Furthermore, even modern LCDs can only handle 367 1.12 tsutsui * upto 720 pixels in the "400 line" as VGA compatible mode. 368 1.12 tsutsui * 369 1.12 tsutsui * As mentioned above, we treat these 1024x400 1 bit or 4 bit 370 1.12 tsutsui * framebuffers as "2 bytes per pixel" ones, so we have to handle 371 1.12 tsutsui * 512 pixels per line with 1024 bytes per line. 372 1.7 tsutsui */ 373 1.7 tsutsui if (fb->planes <= 4 && fb->dwidth == 1024 && fb->dheight == 400) { 374 1.7 tsutsui fb->dwidth = 512; 375 1.11 tsutsui sparse = true; 376 1.7 tsutsui } 377 1.7 tsutsui 378 1.1 tsutsui fb->bmv = topcat_windowmove; 379 1.1 tsutsui topcat_restore(fb); 380 1.1 tsutsui diofb_fbsetup(fb); 381 1.11 tsutsui if (!sparse) { 382 1.11 tsutsui /* save original rasops putchar op */ 383 1.11 tsutsui fb->wsputchar = ri->ri_ops.putchar; 384 1.11 tsutsui ri->ri_ops.putchar = topcat_putchar8; 385 1.11 tsutsui } else { 386 1.11 tsutsui ri->ri_ops.putchar = topcat_putchar1_4; 387 1.11 tsutsui /* copycols and erasecols ops require byte size of fontwidth */ 388 1.11 tsutsui fb->wsd.fontwidth *= 2; 389 1.11 tsutsui /* copyrows and eraserows ops require byte size per line */ 390 1.11 tsutsui ri->ri_emuwidth *= 2; 391 1.11 tsutsui } 392 1.1 tsutsui for (i = 0; i <= fb->planemask; i++) 393 1.1 tsutsui topcat_setcolor(fb, i); 394 1.1 tsutsui 395 1.2 tsutsui return 0; 396 1.1 tsutsui } 397 1.1 tsutsui 398 1.1 tsutsui void 399 1.1 tsutsui topcat_restore(struct diofb *fb) 400 1.1 tsutsui { 401 1.1 tsutsui volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva; 402 1.1 tsutsui 403 1.1 tsutsui /* 404 1.1 tsutsui * Catseye looks a lot like a topcat, but not completely. 405 1.1 tsutsui * So, we set some bits to make it work. 406 1.1 tsutsui */ 407 1.1 tsutsui if (tc->regs.fbid != GID_TOPCAT) { 408 1.1 tsutsui while ((tc->catseye_status & 1)) 409 1.1 tsutsui ; 410 1.1 tsutsui tc->catseye_status = 0x0; 411 1.1 tsutsui tc->vb_select = 0x0; 412 1.1 tsutsui tc->tcntrl = 0x0; 413 1.1 tsutsui tc->acntrl = 0x0; 414 1.1 tsutsui tc->pncntrl = 0x0; 415 1.1 tsutsui tc->rug_cmdstat = 0x90; 416 1.1 tsutsui } 417 1.1 tsutsui 418 1.1 tsutsui /* 419 1.1 tsutsui * Enable reading/writing of all the planes. 420 1.1 tsutsui */ 421 1.1 tsutsui tc->fben = fb->planemask; 422 1.1 tsutsui tc->wen = fb->planemask; 423 1.1 tsutsui tc->ren = fb->planemask; 424 1.1 tsutsui tc->prr = RR_COPY; 425 1.1 tsutsui 426 1.1 tsutsui /* Enable display */ 427 1.8 tsutsui tc->nblank = fb->planemask; 428 1.1 tsutsui } 429 1.1 tsutsui 430 1.1 tsutsui int 431 1.1 tsutsui topcat_ioctl(void *v, void *vs, u_long cmd, void *data, int flags, 432 1.1 tsutsui struct lwp *l) 433 1.1 tsutsui { 434 1.1 tsutsui struct diofb *fb = v; 435 1.1 tsutsui struct wsdisplay_fbinfo *wdf; 436 1.1 tsutsui u_int i; 437 1.1 tsutsui 438 1.1 tsutsui switch (cmd) { 439 1.1 tsutsui case WSDISPLAYIO_GTYPE: 440 1.1 tsutsui *(u_int *)data = WSDISPLAY_TYPE_TOPCAT; 441 1.1 tsutsui return 0; 442 1.1 tsutsui case WSDISPLAYIO_SMODE: 443 1.1 tsutsui fb->mapmode = *(u_int *)data; 444 1.1 tsutsui if (fb->mapmode == WSDISPLAYIO_MODE_EMUL) { 445 1.1 tsutsui topcat_restore(fb); 446 1.1 tsutsui for (i = 0; i <= fb->planemask; i++) 447 1.1 tsutsui topcat_setcolor(fb, i); 448 1.1 tsutsui } 449 1.1 tsutsui return 0; 450 1.1 tsutsui case WSDISPLAYIO_GINFO: 451 1.1 tsutsui wdf = (void *)data; 452 1.1 tsutsui wdf->width = fb->ri.ri_width; 453 1.1 tsutsui wdf->height = fb->ri.ri_height; 454 1.1 tsutsui wdf->depth = fb->ri.ri_depth; 455 1.1 tsutsui wdf->cmsize = 1 << fb->planes; 456 1.1 tsutsui return 0; 457 1.1 tsutsui case WSDISPLAYIO_LINEBYTES: 458 1.1 tsutsui *(u_int *)data = fb->ri.ri_stride; 459 1.1 tsutsui return 0; 460 1.1 tsutsui case WSDISPLAYIO_GETCMAP: 461 1.5 tsutsui if (fb->planemask == 1) 462 1.5 tsutsui return EPASSTHROUGH; 463 1.2 tsutsui return diofb_getcmap(fb, (struct wsdisplay_cmap *)data); 464 1.1 tsutsui case WSDISPLAYIO_PUTCMAP: 465 1.5 tsutsui if (fb->planemask == 1) 466 1.5 tsutsui return EPASSTHROUGH; 467 1.2 tsutsui return topcat_setcmap(fb, (struct wsdisplay_cmap *)data); 468 1.1 tsutsui case WSDISPLAYIO_GVIDEO: 469 1.1 tsutsui case WSDISPLAYIO_SVIDEO: 470 1.1 tsutsui return EPASSTHROUGH; 471 1.1 tsutsui } 472 1.1 tsutsui 473 1.1 tsutsui return EPASSTHROUGH; 474 1.1 tsutsui } 475 1.1 tsutsui 476 1.1 tsutsui void 477 1.1 tsutsui topcat_setcolor(struct diofb *fb, u_int index) 478 1.1 tsutsui { 479 1.1 tsutsui volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva; 480 1.1 tsutsui 481 1.5 tsutsui /* No color map registers on monochrome framebuffers. */ 482 1.5 tsutsui if (fb->planemask == 1) 483 1.5 tsutsui return; 484 1.5 tsutsui 485 1.9 tsutsui tc_waitbusy(tc, fb->planemask); 486 1.9 tsutsui 487 1.1 tsutsui if (tc->regs.fbid != GID_TOPCAT) { 488 1.1 tsutsui tccm_waitbusy(tc); 489 1.8 tsutsui tc->plane_mask = fb->planemask; 490 1.1 tsutsui tc->cindex = ~index; 491 1.1 tsutsui tc->rdata = fb->cmap.r[index]; 492 1.1 tsutsui tc->gdata = fb->cmap.g[index]; 493 1.1 tsutsui tc->bdata = fb->cmap.b[index]; 494 1.1 tsutsui tc->strobe = 0xff; 495 1.6 tsutsui /* XXX delay required on 68020/30 to avoid bus error */ 496 1.6 tsutsui DELAY(100); 497 1.1 tsutsui 498 1.1 tsutsui tccm_waitbusy(tc); 499 1.1 tsutsui tc->cindex = 0; 500 1.1 tsutsui } else { 501 1.1 tsutsui tccm_waitbusy(tc); 502 1.8 tsutsui tc->plane_mask = fb->planemask; 503 1.1 tsutsui tc->rdata = fb->cmap.r[index]; 504 1.1 tsutsui tc->gdata = fb->cmap.g[index]; 505 1.1 tsutsui tc->bdata = fb->cmap.b[index]; 506 1.10 tsutsui DELAY(1); /* necessary for at least old HP98543 */ 507 1.1 tsutsui tc->cindex = ~index; 508 1.10 tsutsui DELAY(1); /* necessary for at least old HP98543 */ 509 1.1 tsutsui tc->strobe = 0xff; 510 1.6 tsutsui /* XXX delay required on 68020/30 to avoid bus error */ 511 1.6 tsutsui DELAY(100); 512 1.1 tsutsui 513 1.1 tsutsui tccm_waitbusy(tc); 514 1.1 tsutsui tc->rdata = 0; 515 1.1 tsutsui tc->gdata = 0; 516 1.1 tsutsui tc->bdata = 0; 517 1.1 tsutsui tc->cindex = 0; 518 1.1 tsutsui } 519 1.1 tsutsui } 520 1.1 tsutsui 521 1.1 tsutsui int 522 1.1 tsutsui topcat_setcmap(struct diofb *fb, struct wsdisplay_cmap *cm) 523 1.1 tsutsui { 524 1.2 tsutsui uint8_t r[256], g[256], b[256]; 525 1.1 tsutsui u_int index = cm->index, count = cm->count; 526 1.1 tsutsui u_int colcount = 1 << fb->planes; 527 1.1 tsutsui int error; 528 1.1 tsutsui 529 1.1 tsutsui if (index >= colcount || count > colcount - index) 530 1.2 tsutsui return EINVAL; 531 1.1 tsutsui 532 1.1 tsutsui if ((error = copyin(cm->red, r, count)) != 0) 533 1.2 tsutsui return error; 534 1.1 tsutsui if ((error = copyin(cm->green, g, count)) != 0) 535 1.2 tsutsui return error; 536 1.1 tsutsui if ((error = copyin(cm->blue, b, count)) != 0) 537 1.2 tsutsui return error; 538 1.1 tsutsui 539 1.1 tsutsui memcpy(fb->cmap.r + index, r, count); 540 1.1 tsutsui memcpy(fb->cmap.g + index, g, count); 541 1.1 tsutsui memcpy(fb->cmap.b + index, b, count); 542 1.1 tsutsui 543 1.1 tsutsui while (count-- != 0) 544 1.1 tsutsui topcat_setcolor(fb, index++); 545 1.1 tsutsui 546 1.2 tsutsui return 0; 547 1.1 tsutsui } 548 1.1 tsutsui 549 1.1 tsutsui /* 550 1.1 tsutsui * Accelerated routines 551 1.1 tsutsui */ 552 1.1 tsutsui 553 1.1 tsutsui int 554 1.2 tsutsui topcat_windowmove(struct diofb *fb, uint16_t sx, uint16_t sy, 555 1.2 tsutsui uint16_t dx, uint16_t dy, uint16_t cx, uint16_t cy, int16_t rop, 556 1.1 tsutsui int16_t planemask) 557 1.1 tsutsui { 558 1.1 tsutsui volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva; 559 1.1 tsutsui 560 1.1 tsutsui tc_waitbusy(tc, fb->planemask); 561 1.1 tsutsui 562 1.1 tsutsui if (planemask != 0xff) { 563 1.1 tsutsui tc->wen = planemask ^ 0xff; 564 1.1 tsutsui tc->wmrr = rop ^ 0x0f; 565 1.1 tsutsui tc->wen = fb->planemask; 566 1.8 tsutsui } else { 567 1.8 tsutsui tc->wen = planemask; 568 1.8 tsutsui tc->wmrr = rop; 569 1.1 tsutsui } 570 1.1 tsutsui tc->source_y = sy; 571 1.1 tsutsui tc->source_x = sx; 572 1.1 tsutsui tc->dest_y = dy; 573 1.1 tsutsui tc->dest_x = dx; 574 1.1 tsutsui tc->wheight = cy; 575 1.1 tsutsui tc->wwidth = cx; 576 1.1 tsutsui tc->wmove = fb->planemask; 577 1.1 tsutsui 578 1.2 tsutsui return 0; 579 1.1 tsutsui } 580 1.1 tsutsui 581 1.11 tsutsui static void 582 1.11 tsutsui topcat_putchar8(void *cookie, int row, int col, u_int uc, long attr) 583 1.11 tsutsui { 584 1.11 tsutsui struct rasops_info *ri = (struct rasops_info *)cookie; 585 1.11 tsutsui struct diofb *diofb = ri->ri_hw; 586 1.11 tsutsui volatile struct tcboxfb *tc = (struct tcboxfb *)diofb->regkva; 587 1.11 tsutsui 588 1.11 tsutsui /* Wait windowmove ops complete before drawing a glyph */ 589 1.11 tsutsui tc_waitbusy(tc, diofb->planemask); 590 1.11 tsutsui 591 1.11 tsutsui /* Call the original rasops putchar */ 592 1.11 tsutsui (*diofb->wsputchar)(cookie, row, col, uc, attr); 593 1.11 tsutsui } 594 1.11 tsutsui 595 1.11 tsutsui /* 596 1.12 tsutsui * Put a single character on 1 bpp (98542) or 4 bpp (98543) variants 597 1.12 tsutsui * with 1024x400 VRAM to treat them as a pseudo 512x400 bitmap. 598 1.11 tsutsui */ 599 1.11 tsutsui static void 600 1.11 tsutsui topcat_putchar1_4(void *cookie, int row, int col, u_int uc, long attr) 601 1.11 tsutsui { 602 1.11 tsutsui int width, height, cnt, fs; 603 1.11 tsutsui uint32_t fb; 604 1.11 tsutsui uint8_t *fr, clr[2]; 605 1.11 tsutsui uint8_t *dp, *rp; 606 1.11 tsutsui struct rasops_info *ri; 607 1.11 tsutsui struct diofb *diofb; 608 1.11 tsutsui volatile struct tcboxfb *tc; 609 1.11 tsutsui 610 1.11 tsutsui ri = (struct rasops_info *)cookie; 611 1.11 tsutsui 612 1.11 tsutsui if (!CHAR_IN_FONT(uc, ri->ri_font)) 613 1.11 tsutsui return; 614 1.11 tsutsui 615 1.11 tsutsui rp = ri->ri_bits + (row * ri->ri_yscale) + 616 1.11 tsutsui (col * ri->ri_xscale * 2); 617 1.11 tsutsui 618 1.11 tsutsui height = ri->ri_font->fontheight; 619 1.11 tsutsui width = ri->ri_font->fontwidth; 620 1.11 tsutsui clr[0] = (uint8_t)ri->ri_devcmap[(attr >> 16) & 0xf]; 621 1.11 tsutsui clr[1] = (uint8_t)ri->ri_devcmap[(attr >> 24) & 0xf]; 622 1.11 tsutsui 623 1.11 tsutsui /* Wait windowmove ops complete before drawing a glyph */ 624 1.11 tsutsui diofb = ri->ri_hw; 625 1.11 tsutsui tc = (struct tcboxfb *)diofb->regkva; 626 1.11 tsutsui tc_waitbusy(tc, diofb->planemask); 627 1.11 tsutsui 628 1.11 tsutsui /* 629 1.12 tsutsui * We have to put pixel data to both odd and even addresses 630 1.12 tsutsui * to handle "doubled pixels" as noted above. 631 1.11 tsutsui */ 632 1.11 tsutsui if (uc == ' ') { 633 1.11 tsutsui uint16_t c = clr[0]; 634 1.11 tsutsui 635 1.11 tsutsui c = c << 8 | c; 636 1.11 tsutsui while (height--) { 637 1.11 tsutsui dp = rp; 638 1.11 tsutsui rp += ri->ri_stride; 639 1.11 tsutsui 640 1.11 tsutsui for (cnt = width; cnt; cnt--) { 641 1.11 tsutsui *(uint16_t *)dp = c; 642 1.11 tsutsui dp += 2; 643 1.11 tsutsui } 644 1.11 tsutsui } 645 1.11 tsutsui } else { 646 1.11 tsutsui uc -= ri->ri_font->firstchar; 647 1.11 tsutsui fr = (uint8_t *)ri->ri_font->data + uc * ri->ri_fontscale; 648 1.11 tsutsui fs = ri->ri_font->stride; 649 1.11 tsutsui 650 1.11 tsutsui while (height--) { 651 1.11 tsutsui dp = rp; 652 1.11 tsutsui fb = be32dec(fr); 653 1.11 tsutsui fr += fs; 654 1.11 tsutsui rp += ri->ri_stride; 655 1.11 tsutsui 656 1.11 tsutsui for (cnt = width; cnt; cnt--) { 657 1.11 tsutsui uint16_t c = clr[(fb >> 31) & 1]; 658 1.11 tsutsui 659 1.11 tsutsui c = c << 8 | c; 660 1.11 tsutsui *(uint16_t *)dp = c; 661 1.11 tsutsui dp += 2; 662 1.11 tsutsui fb <<= 1; 663 1.11 tsutsui } 664 1.11 tsutsui } 665 1.11 tsutsui } 666 1.11 tsutsui 667 1.11 tsutsui /* Do underline */ 668 1.11 tsutsui if ((attr & WSATTR_UNDERLINE) != 0) { 669 1.11 tsutsui uint16_t c = clr[1]; 670 1.11 tsutsui 671 1.11 tsutsui c = c << 8 | c; 672 1.11 tsutsui rp -= ri->ri_stride * ri->ri_ul.off; 673 1.11 tsutsui 674 1.11 tsutsui while (width--) { 675 1.11 tsutsui *(uint16_t *)rp = c; 676 1.11 tsutsui rp += 2; 677 1.11 tsutsui } 678 1.11 tsutsui } 679 1.11 tsutsui } 680 1.1 tsutsui 681 1.1 tsutsui /* 682 1.1 tsutsui * Topcat/catseye console attachment 683 1.1 tsutsui */ 684 1.1 tsutsui 685 1.1 tsutsui int 686 1.1 tsutsui topcatcnattach(bus_space_tag_t bst, bus_addr_t addr, int scode) 687 1.1 tsutsui { 688 1.1 tsutsui bus_space_handle_t bsh; 689 1.1 tsutsui void *va; 690 1.1 tsutsui struct diofbreg *fbr; 691 1.1 tsutsui struct diofb *fb = &diofb_cn; 692 1.1 tsutsui int size; 693 1.1 tsutsui 694 1.1 tsutsui if (bus_space_map(bst, addr, PAGE_SIZE, 0, &bsh)) 695 1.1 tsutsui return 1; 696 1.1 tsutsui va = bus_space_vaddr(bst, bsh); 697 1.1 tsutsui fbr = va; 698 1.1 tsutsui 699 1.1 tsutsui if (badaddr(va) || fbr->id != GRFHWID) { 700 1.1 tsutsui bus_space_unmap(bst, bsh, PAGE_SIZE); 701 1.1 tsutsui return 1; 702 1.1 tsutsui } 703 1.1 tsutsui 704 1.1 tsutsui switch (fbr->fbid) { 705 1.1 tsutsui case GID_TOPCAT: 706 1.1 tsutsui case GID_LRCATSEYE: 707 1.1 tsutsui case GID_HRCCATSEYE: 708 1.1 tsutsui case GID_HRMCATSEYE: 709 1.1 tsutsui break; 710 1.1 tsutsui 711 1.1 tsutsui default: 712 1.1 tsutsui bus_space_unmap(bst, bsh, PAGE_SIZE); 713 1.1 tsutsui return 1; 714 1.1 tsutsui } 715 1.1 tsutsui 716 1.1 tsutsui size = DIO_SIZE(scode, va); 717 1.1 tsutsui 718 1.1 tsutsui bus_space_unmap(bst, bsh, PAGE_SIZE); 719 1.1 tsutsui if (bus_space_map(bst, addr, size, 0, &bsh)) 720 1.1 tsutsui return 1; 721 1.1 tsutsui va = bus_space_vaddr(bst, bsh); 722 1.1 tsutsui 723 1.1 tsutsui /* 724 1.1 tsutsui * Initialize the framebuffer hardware. 725 1.1 tsutsui */ 726 1.1 tsutsui conscode = scode; 727 1.1 tsutsui conaddr = va; 728 1.1 tsutsui topcat_reset(fb, conscode, (struct diofbreg *)conaddr); 729 1.1 tsutsui 730 1.1 tsutsui /* 731 1.1 tsutsui * Initialize the terminal emulator. 732 1.1 tsutsui */ 733 1.1 tsutsui diofb_cnattach(fb); 734 1.1 tsutsui return 0; 735 1.1 tsutsui } 736