1 1.74 macallan /* $NetBSD: cgsix.c,v 1.74 2025/04/14 10:05:26 macallan Exp $ */ 2 1.1 pk 3 1.1 pk /*- 4 1.1 pk * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 1.1 pk * All rights reserved. 6 1.1 pk * 7 1.1 pk * This code is derived from software contributed to The NetBSD Foundation 8 1.1 pk * by Paul Kranenburg. 9 1.1 pk * 10 1.1 pk * Redistribution and use in source and binary forms, with or without 11 1.1 pk * modification, are permitted provided that the following conditions 12 1.1 pk * are met: 13 1.1 pk * 1. Redistributions of source code must retain the above copyright 14 1.1 pk * notice, this list of conditions and the following disclaimer. 15 1.1 pk * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 pk * notice, this list of conditions and the following disclaimer in the 17 1.1 pk * documentation and/or other materials provided with the distribution. 18 1.1 pk * 19 1.1 pk * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 pk * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 pk * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 pk * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 pk * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 pk * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 pk * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 pk * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 pk * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 pk * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 pk * POSSIBILITY OF SUCH DAMAGE. 30 1.1 pk */ 31 1.1 pk 32 1.1 pk /* 33 1.1 pk * Copyright (c) 1993 34 1.1 pk * The Regents of the University of California. All rights reserved. 35 1.1 pk * 36 1.1 pk * This software was developed by the Computer Systems Engineering group 37 1.1 pk * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 38 1.1 pk * contributed to Berkeley. 39 1.1 pk * 40 1.1 pk * All advertising materials mentioning features or use of this software 41 1.1 pk * must display the following acknowledgement: 42 1.1 pk * This product includes software developed by the University of 43 1.1 pk * California, Lawrence Berkeley Laboratory. 44 1.1 pk * 45 1.1 pk * Redistribution and use in source and binary forms, with or without 46 1.1 pk * modification, are permitted provided that the following conditions 47 1.1 pk * are met: 48 1.1 pk * 1. Redistributions of source code must retain the above copyright 49 1.1 pk * notice, this list of conditions and the following disclaimer. 50 1.1 pk * 2. Redistributions in binary form must reproduce the above copyright 51 1.1 pk * notice, this list of conditions and the following disclaimer in the 52 1.1 pk * documentation and/or other materials provided with the distribution. 53 1.13 agc * 3. Neither the name of the University nor the names of its contributors 54 1.1 pk * may be used to endorse or promote products derived from this software 55 1.1 pk * without specific prior written permission. 56 1.1 pk * 57 1.1 pk * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 1.1 pk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 1.1 pk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 1.1 pk * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 1.1 pk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 1.1 pk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 1.1 pk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 1.1 pk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 1.1 pk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 1.1 pk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 1.1 pk * SUCH DAMAGE. 68 1.1 pk * 69 1.1 pk * @(#)cgsix.c 8.4 (Berkeley) 1/21/94 70 1.1 pk */ 71 1.1 pk 72 1.1 pk /* 73 1.1 pk * color display (cgsix) driver. 74 1.1 pk * 75 1.1 pk * Does not handle interrupts, even though they can occur. 76 1.1 pk * 77 1.1 pk * XXX should defer colormap updates to vertical retrace interrupts 78 1.1 pk */ 79 1.7 lukem 80 1.7 lukem #include <sys/cdefs.h> 81 1.74 macallan __KERNEL_RCSID(0, "$NetBSD: cgsix.c,v 1.74 2025/04/14 10:05:26 macallan Exp $"); 82 1.1 pk 83 1.1 pk #include <sys/param.h> 84 1.1 pk #include <sys/systm.h> 85 1.1 pk #include <sys/buf.h> 86 1.1 pk #include <sys/device.h> 87 1.1 pk #include <sys/ioctl.h> 88 1.1 pk #include <sys/mman.h> 89 1.1 pk #include <sys/tty.h> 90 1.1 pk #include <sys/conf.h> 91 1.1 pk 92 1.1 pk #ifdef DEBUG 93 1.1 pk #include <sys/proc.h> 94 1.1 pk #include <sys/syslog.h> 95 1.1 pk #endif 96 1.1 pk 97 1.35 ad #include <sys/bus.h> 98 1.1 pk 99 1.1 pk #include <dev/sun/fbio.h> 100 1.1 pk #include <dev/sun/fbvar.h> 101 1.1 pk 102 1.1 pk #include <dev/sun/btreg.h> 103 1.1 pk #include <dev/sun/btvar.h> 104 1.1 pk #include <dev/sun/pfourreg.h> 105 1.1 pk 106 1.18 martin #include <dev/wscons/wsconsio.h> 107 1.18 martin #include <dev/wsfont/wsfont.h> 108 1.1 pk #include <dev/rasops/rasops.h> 109 1.18 martin 110 1.18 martin #include "opt_wsemul.h" 111 1.20 martin #include "rasops_glue.h" 112 1.1 pk 113 1.23 macallan #include <dev/sun/cgsixreg.h> 114 1.23 macallan #include <dev/sun/cgsixvar.h> 115 1.23 macallan 116 1.46 tsutsui #include "ioconf.h" 117 1.46 tsutsui 118 1.39 macallan static void cg6_unblank(device_t); 119 1.33 macallan static void cg6_blank(struct cgsix_softc *, int); 120 1.1 pk 121 1.8 gehenna dev_type_open(cgsixopen); 122 1.8 gehenna dev_type_close(cgsixclose); 123 1.8 gehenna dev_type_ioctl(cgsixioctl); 124 1.8 gehenna dev_type_mmap(cgsixmmap); 125 1.8 gehenna 126 1.8 gehenna const struct cdevsw cgsix_cdevsw = { 127 1.64 dholland .d_open = cgsixopen, 128 1.64 dholland .d_close = cgsixclose, 129 1.64 dholland .d_read = noread, 130 1.64 dholland .d_write = nowrite, 131 1.64 dholland .d_ioctl = cgsixioctl, 132 1.64 dholland .d_stop = nostop, 133 1.64 dholland .d_tty = notty, 134 1.64 dholland .d_poll = nopoll, 135 1.64 dholland .d_mmap = cgsixmmap, 136 1.64 dholland .d_kqfilter = nokqfilter, 137 1.65 dholland .d_discard = nodiscard, 138 1.64 dholland .d_flag = D_OTHER 139 1.8 gehenna }; 140 1.1 pk 141 1.1 pk /* frame buffer generic driver */ 142 1.1 pk static struct fbdriver cg6_fbdriver = { 143 1.9 jdolecek cg6_unblank, cgsixopen, cgsixclose, cgsixioctl, nopoll, cgsixmmap, 144 1.9 jdolecek nokqfilter 145 1.1 pk }; 146 1.1 pk 147 1.1 pk static void cg6_reset (struct cgsix_softc *); 148 1.1 pk static void cg6_loadcmap (struct cgsix_softc *, int, int); 149 1.1 pk static void cg6_loadomap (struct cgsix_softc *); 150 1.1 pk static void cg6_setcursor (struct cgsix_softc *);/* set position */ 151 1.1 pk static void cg6_loadcursor (struct cgsix_softc *);/* set shape */ 152 1.1 pk 153 1.23 macallan static void cg6_setup_palette(struct cgsix_softc *); 154 1.23 macallan 155 1.18 martin struct wsscreen_descr cgsix_defaultscreen = { 156 1.18 martin "std", 157 1.18 martin 0, 0, /* will be filled in -- XXX shouldn't, it's global */ 158 1.23 macallan NULL, /* textops */ 159 1.23 macallan 8, 16, /* font width/height */ 160 1.68 macallan WSSCREEN_WSCOLORS | WSSCREEN_RESIZE | WSSCREEN_UNDERLINE, 161 1.32 martin NULL /* modecookie */ 162 1.18 martin }; 163 1.18 martin 164 1.34 christos static int cgsix_ioctl(void *, void *, u_long, void *, int, struct lwp *); 165 1.30 jmmv static paddr_t cgsix_mmap(void *, void *, off_t, int); 166 1.33 macallan static void cgsix_init_screen(void *, struct vcons_screen *, int, long *); 167 1.33 macallan 168 1.33 macallan static void cgsix_clearscreen(struct cgsix_softc *); 169 1.23 macallan 170 1.23 macallan void cgsix_setup_mono(struct cgsix_softc *, int, int, int, int, uint32_t, 171 1.23 macallan uint32_t); 172 1.23 macallan void cgsix_feed_line(struct cgsix_softc *, int, uint8_t *); 173 1.23 macallan void cgsix_rectfill(struct cgsix_softc *, int, int, int, int, uint32_t); 174 1.57 macallan void cgsix_bitblt(void *, int, int, int, int, int, int, int); 175 1.23 macallan 176 1.23 macallan int cgsix_putcmap(struct cgsix_softc *, struct wsdisplay_cmap *); 177 1.23 macallan int cgsix_getcmap(struct cgsix_softc *, struct wsdisplay_cmap *); 178 1.23 macallan void cgsix_putchar(void *, int, int, u_int, long); 179 1.57 macallan void cgsix_putchar_aa(void *, int, int, u_int, long); 180 1.23 macallan void cgsix_cursor(void *, int, int, int); 181 1.23 macallan 182 1.18 martin struct wsdisplay_accessops cgsix_accessops = { 183 1.18 martin cgsix_ioctl, 184 1.18 martin cgsix_mmap, 185 1.33 macallan NULL, /* alloc_screen */ 186 1.33 macallan NULL, /* free_screen */ 187 1.33 macallan NULL, /* show_screen */ 188 1.18 martin NULL, /* load_font */ 189 1.18 martin NULL, /* pollc */ 190 1.18 martin NULL /* scroll */ 191 1.18 martin }; 192 1.18 martin 193 1.18 martin const struct wsscreen_descr *_cgsix_scrlist[] = { 194 1.18 martin &cgsix_defaultscreen 195 1.18 martin }; 196 1.18 martin 197 1.18 martin struct wsscreen_list cgsix_screenlist = { 198 1.18 martin sizeof(_cgsix_scrlist) / sizeof(struct wsscreen_descr *), 199 1.18 martin _cgsix_scrlist 200 1.18 martin }; 201 1.18 martin 202 1.23 macallan 203 1.23 macallan extern const u_char rasops_cmap[768]; 204 1.23 macallan 205 1.23 macallan void cg6_invert(struct cgsix_softc *, int, int, int, int); 206 1.23 macallan 207 1.33 macallan static struct vcons_screen cg6_console_screen; 208 1.1 pk 209 1.1 pk /* 210 1.1 pk * cg6 accelerated console routines. 211 1.1 pk * 212 1.1 pk * Note that buried in this code in several places is the assumption 213 1.1 pk * that pixels are exactly one byte wide. Since this is cg6-specific 214 1.1 pk * code, this seems safe. This assumption resides in things like the 215 1.1 pk * use of ri_emuwidth without messing around with ri_pelbytes, or the 216 1.1 pk * assumption that ri_font->fontwidth is the right thing to multiply 217 1.1 pk * character-cell counts by to get byte counts. 218 1.1 pk */ 219 1.1 pk 220 1.1 pk /* 221 1.1 pk * Magic values for blitter 222 1.1 pk */ 223 1.1 pk 224 1.5 tsutsui /* Values for the mode register */ 225 1.5 tsutsui #define CG6_MODE ( \ 226 1.5 tsutsui 0x00200000 /* GX_BLIT_SRC */ \ 227 1.5 tsutsui | 0x00020000 /* GX_MODE_COLOR8 */ \ 228 1.5 tsutsui | 0x00008000 /* GX_DRAW_RENDER */ \ 229 1.5 tsutsui | 0x00002000 /* GX_BWRITE0_ENABLE */ \ 230 1.5 tsutsui | 0x00001000 /* GX_BWRITE1_DISABLE */ \ 231 1.5 tsutsui | 0x00000200 /* GX_BREAD_0 */ \ 232 1.5 tsutsui | 0x00000080 /* GX_BDISP_0 */ \ 233 1.5 tsutsui ) 234 1.5 tsutsui #define CG6_MODE_MASK ( \ 235 1.5 tsutsui 0x00300000 /* GX_BLIT_ALL */ \ 236 1.5 tsutsui | 0x00060000 /* GX_MODE_ALL */ \ 237 1.5 tsutsui | 0x00018000 /* GX_DRAW_ALL */ \ 238 1.5 tsutsui | 0x00006000 /* GX_BWRITE0_ALL */ \ 239 1.5 tsutsui | 0x00001800 /* GX_BWRITE1_ALL */ \ 240 1.5 tsutsui | 0x00000600 /* GX_BREAD_ALL */ \ 241 1.5 tsutsui | 0x00000180 /* GX_BDISP_ALL */ \ 242 1.5 tsutsui ) 243 1.5 tsutsui 244 1.1 pk /* Value for the alu register for screen-to-screen copies */ 245 1.1 pk #define CG6_ALU_COPY ( \ 246 1.1 pk 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \ 247 1.1 pk | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \ 248 1.1 pk | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \ 249 1.1 pk | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \ 250 1.1 pk | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \ 251 1.1 pk | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \ 252 1.1 pk | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \ 253 1.1 pk | 0x0000cccc /* ALU = src */ \ 254 1.1 pk ) 255 1.1 pk 256 1.1 pk /* Value for the alu register for region fills */ 257 1.1 pk #define CG6_ALU_FILL ( \ 258 1.1 pk 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \ 259 1.1 pk | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \ 260 1.1 pk | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \ 261 1.1 pk | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \ 262 1.1 pk | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \ 263 1.1 pk | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \ 264 1.1 pk | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \ 265 1.1 pk | 0x0000ff00 /* ALU = fg color */ \ 266 1.1 pk ) 267 1.1 pk 268 1.1 pk /* Value for the alu register for toggling an area */ 269 1.1 pk #define CG6_ALU_FLIP ( \ 270 1.1 pk 0x80000000 /* GX_PLANE_ONES (ignore planemask register) */ \ 271 1.1 pk | 0x20000000 /* GX_PIXEL_ONES (ignore pixelmask register) */ \ 272 1.1 pk | 0x00800000 /* GX_ATTR_SUPP (function unknown) */ \ 273 1.1 pk | 0x00000000 /* GX_RAST_BOOL (function unknown) */ \ 274 1.1 pk | 0x00000000 /* GX_PLOT_PLOT (function unknown) */ \ 275 1.1 pk | 0x08000000 /* GX_PATTERN_ONES (ignore pattern) */ \ 276 1.1 pk | 0x01000000 /* GX_POLYG_OVERLAP (unsure - handle overlap?) */ \ 277 1.1 pk | 0x00005555 /* ALU = ~dst */ \ 278 1.1 pk ) 279 1.1 pk 280 1.1 pk /* 281 1.56 macallan * Run a blitter command 282 1.1 pk */ 283 1.62 martin #define CG6_BLIT(f) { (void)f->fbc_blit; } 284 1.1 pk 285 1.1 pk /* 286 1.56 macallan * Run a drawing command 287 1.1 pk */ 288 1.62 martin #define CG6_DRAW(f) { (void)f->fbc_draw; } 289 1.1 pk 290 1.1 pk /* 291 1.1 pk * Wait for the whole engine to go idle. This may not matter in our case; 292 1.1 pk * I'm not sure whether blits are actually queued or not. It more likely 293 1.1 pk * is intended for lines and such that do get queued. 294 1.1 pk * 0x10000000 bit: GX_INPROGRESS 295 1.1 pk */ 296 1.1 pk #define CG6_DRAIN(fbc) do { \ 297 1.56 macallan while ((fbc)->fbc_s & GX_INPROGRESS) \ 298 1.56 macallan /*EMPTY*/; \ 299 1.56 macallan } while (0) 300 1.56 macallan 301 1.58 macallan /* 302 1.58 macallan * something is missing here 303 1.58 macallan * Waiting for GX_FULL to clear should be enough to send another command 304 1.58 macallan * but some CG6 ( LX onboard for example ) lock up if we do that while 305 1.58 macallan * it works fine on others ( a 4MB TGX+ I've got here ) 306 1.58 macallan * So, until I figure out what's going on we wait for the blitter to go 307 1.58 macallan * fully idle. 308 1.58 macallan */ 309 1.56 macallan #define CG6_WAIT_READY(fbc) do { \ 310 1.58 macallan while (((fbc)->fbc_s & GX_INPROGRESS/*GX_FULL*/) != 0) \ 311 1.1 pk /*EMPTY*/; \ 312 1.1 pk } while (0) 313 1.1 pk 314 1.5 tsutsui static void cg6_ras_init(struct cgsix_softc *); 315 1.5 tsutsui static void cg6_ras_copyrows(void *, int, int, int); 316 1.5 tsutsui static void cg6_ras_copycols(void *, int, int, int, int); 317 1.5 tsutsui static void cg6_ras_erasecols(void *, int, int, int, long int); 318 1.5 tsutsui static void cg6_ras_eraserows(void *, int, int, long int); 319 1.55 macallan 320 1.5 tsutsui static void 321 1.5 tsutsui cg6_ras_init(struct cgsix_softc *sc) 322 1.5 tsutsui { 323 1.5 tsutsui volatile struct cg6_fbc *fbc = sc->sc_fbc; 324 1.5 tsutsui 325 1.5 tsutsui CG6_DRAIN(fbc); 326 1.5 tsutsui fbc->fbc_mode &= ~CG6_MODE_MASK; 327 1.5 tsutsui fbc->fbc_mode |= CG6_MODE; 328 1.55 macallan 329 1.55 macallan /* set some common drawing engine parameters */ 330 1.55 macallan fbc->fbc_clip = 0; 331 1.55 macallan fbc->fbc_s = 0; 332 1.55 macallan fbc->fbc_offx = 0; 333 1.55 macallan fbc->fbc_offy = 0; 334 1.55 macallan fbc->fbc_clipminx = 0; 335 1.55 macallan fbc->fbc_clipminy = 0; 336 1.55 macallan fbc->fbc_clipmaxx = 0x3fff; 337 1.55 macallan fbc->fbc_clipmaxy = 0x3fff; 338 1.5 tsutsui } 339 1.5 tsutsui 340 1.1 pk static void 341 1.71 macallan cg6_ras_nuke_cursor(struct rasops_info *ri) 342 1.71 macallan { 343 1.71 macallan struct vcons_screen *scr = ri->ri_hw; 344 1.71 macallan struct cgsix_softc *sc = scr->scr_cookie; 345 1.71 macallan int wi, he, x, y; 346 1.71 macallan 347 1.71 macallan if (ri->ri_flg & RI_CURSOR) { 348 1.71 macallan wi = ri->ri_font->fontwidth; 349 1.71 macallan he = ri->ri_font->fontheight; 350 1.71 macallan x = ri->ri_ccol * wi + ri->ri_xorigin; 351 1.71 macallan y = ri->ri_crow * he + ri->ri_yorigin; 352 1.71 macallan cg6_invert(sc, x, y, wi, he); 353 1.71 macallan ri->ri_flg &= ~RI_CURSOR; 354 1.71 macallan } 355 1.71 macallan } 356 1.71 macallan 357 1.71 macallan static void 358 1.1 pk cg6_ras_copyrows(void *cookie, int src, int dst, int n) 359 1.1 pk { 360 1.33 macallan struct rasops_info *ri = cookie; 361 1.33 macallan struct vcons_screen *scr = ri->ri_hw; 362 1.33 macallan struct cgsix_softc *sc = scr->scr_cookie; 363 1.33 macallan volatile struct cg6_fbc *fbc = sc->sc_fbc; 364 1.23 macallan 365 1.33 macallan if (dst == src) 366 1.33 macallan return; 367 1.74 macallan 368 1.71 macallan if ((ri->ri_crow >= src && ri->ri_crow < (src + n)) && 369 1.71 macallan (ri->ri_flg & RI_CURSOR)) { 370 1.71 macallan cg6_ras_nuke_cursor(ri); 371 1.71 macallan } 372 1.74 macallan 373 1.74 macallan if (ri->ri_crow >= dst && ri->ri_crow < (dst + n)) 374 1.74 macallan ri->ri_flg &= ~RI_CURSOR; 375 1.74 macallan 376 1.33 macallan n *= ri->ri_font->fontheight; 377 1.33 macallan src *= ri->ri_font->fontheight; 378 1.33 macallan dst *= ri->ri_font->fontheight; 379 1.55 macallan 380 1.56 macallan CG6_WAIT_READY(fbc); 381 1.56 macallan 382 1.33 macallan fbc->fbc_alu = CG6_ALU_COPY; 383 1.55 macallan fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 384 1.55 macallan 385 1.33 macallan fbc->fbc_x0 = ri->ri_xorigin; 386 1.33 macallan fbc->fbc_y0 = ri->ri_yorigin + src; 387 1.33 macallan fbc->fbc_x1 = ri->ri_xorigin + ri->ri_emuwidth - 1; 388 1.33 macallan fbc->fbc_y1 = ri->ri_yorigin + src + n - 1; 389 1.33 macallan fbc->fbc_x2 = ri->ri_xorigin; 390 1.33 macallan fbc->fbc_y2 = ri->ri_yorigin + dst; 391 1.33 macallan fbc->fbc_x3 = ri->ri_xorigin + ri->ri_emuwidth - 1; 392 1.33 macallan fbc->fbc_y3 = ri->ri_yorigin + dst + n - 1; 393 1.56 macallan CG6_BLIT(fbc); 394 1.1 pk } 395 1.1 pk 396 1.1 pk static void 397 1.1 pk cg6_ras_copycols(void *cookie, int row, int src, int dst, int n) 398 1.1 pk { 399 1.33 macallan struct rasops_info *ri = cookie; 400 1.33 macallan struct vcons_screen *scr = ri->ri_hw; 401 1.33 macallan struct cgsix_softc *sc = scr->scr_cookie; 402 1.33 macallan volatile struct cg6_fbc *fbc = sc->sc_fbc; 403 1.23 macallan 404 1.33 macallan if (dst == src) 405 1.33 macallan return; 406 1.74 macallan 407 1.33 macallan if ((row < 0) || (row >= ri->ri_rows)) 408 1.33 macallan return; 409 1.74 macallan 410 1.71 macallan if (ri->ri_crow == row && 411 1.71 macallan (ri->ri_ccol >= src && ri->ri_ccol < (src + n)) && 412 1.71 macallan (ri->ri_flg & RI_CURSOR)) { 413 1.71 macallan cg6_ras_nuke_cursor(ri); 414 1.71 macallan } 415 1.74 macallan 416 1.74 macallan if (ri->ri_crow == row && 417 1.74 macallan (ri->ri_ccol >= dst && ri->ri_ccol < (dst + n))) 418 1.74 macallan ri->ri_flg &= ~RI_CURSOR; 419 1.74 macallan 420 1.33 macallan n *= ri->ri_font->fontwidth; 421 1.33 macallan src *= ri->ri_font->fontwidth; 422 1.33 macallan dst *= ri->ri_font->fontwidth; 423 1.33 macallan row *= ri->ri_font->fontheight; 424 1.55 macallan 425 1.56 macallan CG6_WAIT_READY(fbc); 426 1.56 macallan 427 1.33 macallan fbc->fbc_alu = CG6_ALU_COPY; 428 1.55 macallan fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 429 1.55 macallan 430 1.33 macallan fbc->fbc_x0 = ri->ri_xorigin + src; 431 1.33 macallan fbc->fbc_y0 = ri->ri_yorigin + row; 432 1.33 macallan fbc->fbc_x1 = ri->ri_xorigin + src + n - 1; 433 1.33 macallan fbc->fbc_y1 = ri->ri_yorigin + row + 434 1.33 macallan ri->ri_font->fontheight - 1; 435 1.33 macallan fbc->fbc_x2 = ri->ri_xorigin + dst; 436 1.33 macallan fbc->fbc_y2 = ri->ri_yorigin + row; 437 1.33 macallan fbc->fbc_x3 = ri->ri_xorigin + dst + n - 1; 438 1.33 macallan fbc->fbc_y3 = ri->ri_yorigin + row + 439 1.33 macallan ri->ri_font->fontheight - 1; 440 1.56 macallan CG6_BLIT(fbc); 441 1.1 pk } 442 1.1 pk 443 1.1 pk static void 444 1.1 pk cg6_ras_erasecols(void *cookie, int row, int col, int n, long int attr) 445 1.1 pk { 446 1.33 macallan struct rasops_info *ri = cookie; 447 1.33 macallan struct vcons_screen *scr = ri->ri_hw; 448 1.33 macallan struct cgsix_softc *sc = scr->scr_cookie; 449 1.33 macallan volatile struct cg6_fbc *fbc = sc->sc_fbc; 450 1.23 macallan 451 1.71 macallan if (ri->ri_crow == row && 452 1.71 macallan (ri->ri_ccol >= col && ri->ri_ccol < (col + n))) 453 1.71 macallan ri->ri_flg &= ~RI_CURSOR; 454 1.71 macallan 455 1.33 macallan n *= ri->ri_font->fontwidth; 456 1.33 macallan col *= ri->ri_font->fontwidth; 457 1.33 macallan row *= ri->ri_font->fontheight; 458 1.55 macallan 459 1.56 macallan CG6_WAIT_READY(fbc); 460 1.33 macallan fbc->fbc_alu = CG6_ALU_FILL; 461 1.55 macallan fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 462 1.55 macallan 463 1.33 macallan fbc->fbc_fg = ri->ri_devcmap[(attr >> 16) & 0xff]; 464 1.33 macallan fbc->fbc_arecty = ri->ri_yorigin + row; 465 1.33 macallan fbc->fbc_arectx = ri->ri_xorigin + col; 466 1.33 macallan fbc->fbc_arecty = ri->ri_yorigin + row + 467 1.33 macallan ri->ri_font->fontheight - 1; 468 1.33 macallan fbc->fbc_arectx = ri->ri_xorigin + col + n - 1; 469 1.56 macallan CG6_DRAW(fbc); 470 1.1 pk } 471 1.1 pk 472 1.1 pk static void 473 1.1 pk cg6_ras_eraserows(void *cookie, int row, int n, long int attr) 474 1.1 pk { 475 1.33 macallan struct rasops_info *ri = cookie; 476 1.33 macallan struct vcons_screen *scr = ri->ri_hw; 477 1.33 macallan struct cgsix_softc *sc = scr->scr_cookie; 478 1.33 macallan volatile struct cg6_fbc *fbc = sc->sc_fbc; 479 1.23 macallan 480 1.71 macallan if (ri->ri_crow >= row && ri->ri_crow < (row + n)) 481 1.71 macallan ri->ri_flg &= ~RI_CURSOR; 482 1.71 macallan 483 1.56 macallan CG6_WAIT_READY(fbc); 484 1.33 macallan fbc->fbc_alu = CG6_ALU_FILL; 485 1.55 macallan fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 486 1.55 macallan 487 1.33 macallan fbc->fbc_fg = ri->ri_devcmap[(attr >> 16) & 0xff]; 488 1.33 macallan if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) { 489 1.33 macallan fbc->fbc_arecty = 0; 490 1.33 macallan fbc->fbc_arectx = 0; 491 1.33 macallan fbc->fbc_arecty = ri->ri_height - 1; 492 1.33 macallan fbc->fbc_arectx = ri->ri_width - 1; 493 1.33 macallan } else { 494 1.33 macallan row *= ri->ri_font->fontheight; 495 1.33 macallan fbc->fbc_arecty = ri->ri_yorigin + row; 496 1.33 macallan fbc->fbc_arectx = ri->ri_xorigin; 497 1.33 macallan fbc->fbc_arecty = ri->ri_yorigin + row + 498 1.33 macallan (n * ri->ri_font->fontheight) - 1; 499 1.33 macallan fbc->fbc_arectx = ri->ri_xorigin + ri->ri_emuwidth - 1; 500 1.23 macallan } 501 1.56 macallan CG6_DRAW(fbc); 502 1.1 pk } 503 1.1 pk 504 1.1 pk void 505 1.25 tsutsui cg6attach(struct cgsix_softc *sc, const char *name, int isconsole) 506 1.1 pk { 507 1.1 pk struct fbdevice *fb = &sc->sc_fb; 508 1.18 martin struct wsemuldisplaydev_attach_args aa; 509 1.33 macallan struct rasops_info *ri = &cg6_console_screen.scr_ri; 510 1.18 martin unsigned long defattr; 511 1.33 macallan 512 1.1 pk fb->fb_driver = &cg6_fbdriver; 513 1.1 pk 514 1.1 pk /* Don't have to map the pfour register on the cgsix. */ 515 1.1 pk fb->fb_pfour = NULL; 516 1.1 pk 517 1.1 pk fb->fb_type.fb_cmsize = 256; 518 1.23 macallan fb->fb_type.fb_size = sc->sc_ramsize; 519 1.54 macallan 520 1.1 pk printf(": %s, %d x %d", name, 521 1.1 pk fb->fb_type.fb_width, fb->fb_type.fb_height); 522 1.18 martin if(sc->sc_fhc) { 523 1.23 macallan sc->sc_fhcrev = (*sc->sc_fhc >> FHC_REV_SHIFT) & 524 1.1 pk (FHC_REV_MASK >> FHC_REV_SHIFT); 525 1.18 martin } else 526 1.18 martin sc->sc_fhcrev=-1; 527 1.1 pk printf(", rev %d", sc->sc_fhcrev); 528 1.1 pk 529 1.1 pk /* reset cursor & frame buffer controls */ 530 1.1 pk cg6_reset(sc); 531 1.1 pk 532 1.1 pk /* enable video */ 533 1.1 pk sc->sc_thc->thc_misc |= THC_MISC_VIDEN; 534 1.1 pk 535 1.1 pk if (isconsole) { 536 1.1 pk printf(" (console)"); 537 1.1 pk } 538 1.26 thorpej printf("\n"); 539 1.1 pk 540 1.18 martin fb_attach(&sc->sc_fb, isconsole); 541 1.23 macallan sc->sc_width = fb->fb_type.fb_width; 542 1.23 macallan sc->sc_stride = fb->fb_type.fb_width; 543 1.23 macallan sc->sc_height = fb->fb_type.fb_height; 544 1.60 macallan 545 1.39 macallan printf("%s: framebuffer size: %d MB\n", device_xname(sc->sc_dev), 546 1.24 macallan sc->sc_ramsize >> 20); 547 1.24 macallan 548 1.20 martin /* setup rasops and so on for wsdisplay */ 549 1.41 macallan memcpy(sc->sc_default_cmap, rasops_cmap, 768); 550 1.18 martin wsfont_init(); 551 1.18 martin cg6_ras_init(sc); 552 1.23 macallan sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 553 1.23 macallan sc->sc_bg = WS_DEFAULT_BG; 554 1.52 macallan sc->sc_fb_is_open = FALSE; 555 1.23 macallan 556 1.33 macallan vcons_init(&sc->vd, sc, &cgsix_defaultscreen, &cgsix_accessops); 557 1.33 macallan sc->vd.init_screen = cgsix_init_screen; 558 1.23 macallan 559 1.57 macallan sc->sc_gc.gc_bitblt = cgsix_bitblt; 560 1.57 macallan sc->sc_gc.gc_blitcookie = sc; 561 1.57 macallan sc->sc_gc.gc_rop = CG6_ALU_COPY; 562 1.68 macallan sc->vd.show_screen_cookie = &sc->sc_gc; 563 1.68 macallan sc->vd.show_screen_cb = glyphcache_adapt; 564 1.57 macallan 565 1.27 macallan if(isconsole) { 566 1.27 macallan /* we mess with cg6_console_screen only once */ 567 1.33 macallan vcons_init_screen(&sc->vd, &cg6_console_screen, 1, 568 1.33 macallan &defattr); 569 1.63 macallan sc->sc_bg = (defattr >> 16) & 0xf; /* yes, this is an index into devcmap */ 570 1.63 macallan 571 1.63 macallan /* 572 1.63 macallan * XXX 573 1.63 macallan * Is this actually necessary? We're going to use the blitter later on anyway. 574 1.63 macallan */ 575 1.63 macallan /* We need unaccelerated initial screen clear on old revisions */ 576 1.63 macallan if (sc->sc_fhcrev < 2) { 577 1.63 macallan memset(sc->sc_fb.fb_pixels, ri->ri_devcmap[sc->sc_bg], 578 1.63 macallan sc->sc_stride * sc->sc_height); 579 1.63 macallan } else 580 1.63 macallan cgsix_clearscreen(sc); 581 1.63 macallan 582 1.33 macallan cg6_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 583 1.33 macallan 584 1.27 macallan cgsix_defaultscreen.textops = &ri->ri_ops; 585 1.27 macallan cgsix_defaultscreen.capabilities = ri->ri_caps; 586 1.27 macallan cgsix_defaultscreen.nrows = ri->ri_rows; 587 1.27 macallan cgsix_defaultscreen.ncols = ri->ri_cols; 588 1.33 macallan SCREEN_VISIBLE(&cg6_console_screen); 589 1.33 macallan sc->vd.active = &cg6_console_screen; 590 1.45 macallan wsdisplay_cnattach(&cgsix_defaultscreen, ri, 0, 0, defattr); 591 1.60 macallan if (ri->ri_flg & RI_ENABLE_ALPHA) { 592 1.60 macallan glyphcache_init(&sc->sc_gc, sc->sc_height + 5, 593 1.57 macallan (sc->sc_ramsize / sc->sc_stride) - 594 1.57 macallan sc->sc_height - 5, 595 1.57 macallan sc->sc_width, 596 1.57 macallan ri->ri_font->fontwidth, 597 1.57 macallan ri->ri_font->fontheight, 598 1.57 macallan defattr); 599 1.60 macallan } 600 1.45 macallan vcons_replay_msgbuf(&cg6_console_screen); 601 1.27 macallan } else { 602 1.57 macallan /* 603 1.57 macallan * since we're not the console we can postpone the rest 604 1.57 macallan * until someone actually allocates a screen for us 605 1.27 macallan */ 606 1.57 macallan if (cg6_console_screen.scr_ri.ri_rows == 0) { 607 1.57 macallan /* do some minimal setup to avoid weirdnesses later */ 608 1.57 macallan vcons_init_screen(&sc->vd, &cg6_console_screen, 1, 609 1.57 macallan &defattr); 610 1.61 macallan } else 611 1.61 macallan (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 612 1.63 macallan sc->sc_bg = (defattr >> 16) & 0xf; 613 1.60 macallan if (ri->ri_flg & RI_ENABLE_ALPHA) { 614 1.60 macallan glyphcache_init(&sc->sc_gc, sc->sc_height + 5, 615 1.57 macallan (sc->sc_ramsize / sc->sc_stride) - 616 1.57 macallan sc->sc_height - 5, 617 1.57 macallan sc->sc_width, 618 1.57 macallan ri->ri_font->fontwidth, 619 1.57 macallan ri->ri_font->fontheight, 620 1.57 macallan defattr); 621 1.60 macallan } 622 1.27 macallan } 623 1.57 macallan cg6_setup_palette(sc); 624 1.71 macallan 625 1.27 macallan aa.scrdata = &cgsix_screenlist; 626 1.18 martin aa.console = isconsole; 627 1.18 martin aa.accessops = &cgsix_accessops; 628 1.33 macallan aa.accesscookie = &sc->vd; 629 1.70 thorpej config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE); 630 1.1 pk } 631 1.1 pk 632 1.1 pk 633 1.1 pk int 634 1.28 christos cgsixopen(dev_t dev, int flags, int mode, struct lwp *l) 635 1.1 pk { 636 1.52 macallan device_t dv = device_lookup(&cgsix_cd, minor(dev)); 637 1.52 macallan struct cgsix_softc *sc = device_private(dv); 638 1.1 pk 639 1.52 macallan if (dv == NULL) 640 1.22 martin return ENXIO; 641 1.52 macallan sc->sc_fb_is_open = TRUE; 642 1.52 macallan 643 1.22 martin return 0; 644 1.1 pk } 645 1.1 pk 646 1.1 pk int 647 1.28 christos cgsixclose(dev_t dev, int flags, int mode, struct lwp *l) 648 1.1 pk { 649 1.39 macallan device_t dv = device_lookup(&cgsix_cd, minor(dev)); 650 1.39 macallan struct cgsix_softc *sc = device_private(dv); 651 1.1 pk 652 1.1 pk cg6_reset(sc); 653 1.52 macallan sc->sc_fb_is_open = FALSE; 654 1.1 pk 655 1.52 macallan if (IS_IN_EMUL_MODE(sc)) { 656 1.52 macallan struct vcons_screen *ms = sc->vd.active; 657 1.52 macallan 658 1.52 macallan cg6_ras_init(sc); 659 1.52 macallan cg6_setup_palette(sc); 660 1.59 macallan glyphcache_wipe(&sc->sc_gc); 661 1.52 macallan 662 1.52 macallan /* we don't know if the screen exists */ 663 1.52 macallan if (ms != NULL) 664 1.52 macallan vcons_redraw_screen(ms); 665 1.52 macallan } 666 1.22 martin return 0; 667 1.1 pk } 668 1.1 pk 669 1.1 pk int 670 1.34 christos cgsixioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 671 1.1 pk { 672 1.38 drochner struct cgsix_softc *sc = device_lookup_private(&cgsix_cd, minor(dev)); 673 1.16 chs union cursor_cmap tcm; 674 1.16 chs uint32_t image[32], mask[32]; 675 1.1 pk u_int count; 676 1.1 pk int v, error; 677 1.1 pk 678 1.18 martin #ifdef CGSIX_DEBUG 679 1.52 macallan printf("cgsixioctl(%lx)\n",cmd); 680 1.18 martin #endif 681 1.18 martin 682 1.1 pk switch (cmd) { 683 1.1 pk 684 1.1 pk case FBIOGTYPE: 685 1.1 pk *(struct fbtype *)data = sc->sc_fb.fb_type; 686 1.1 pk break; 687 1.1 pk 688 1.1 pk case FBIOGATTR: 689 1.1 pk #define fba ((struct fbgattr *)data) 690 1.1 pk fba->real_type = sc->sc_fb.fb_type.fb_type; 691 1.1 pk fba->owner = 0; /* XXX ??? */ 692 1.1 pk fba->fbtype = sc->sc_fb.fb_type; 693 1.1 pk fba->sattr.flags = 0; 694 1.1 pk fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 695 1.1 pk fba->sattr.dev_specific[0] = -1; 696 1.1 pk fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 697 1.1 pk fba->emu_types[1] = -1; 698 1.1 pk #undef fba 699 1.1 pk break; 700 1.1 pk 701 1.1 pk case FBIOGETCMAP: 702 1.1 pk #define p ((struct fbcmap *)data) 703 1.1 pk return (bt_getcmap(p, &sc->sc_cmap, 256, 1)); 704 1.1 pk 705 1.1 pk case FBIOPUTCMAP: 706 1.1 pk /* copy to software map */ 707 1.1 pk error = bt_putcmap(p, &sc->sc_cmap, 256, 1); 708 1.1 pk if (error) 709 1.22 martin return error; 710 1.1 pk /* now blast them into the chip */ 711 1.1 pk /* XXX should use retrace interrupt */ 712 1.1 pk cg6_loadcmap(sc, p->index, p->count); 713 1.1 pk #undef p 714 1.1 pk break; 715 1.1 pk 716 1.1 pk case FBIOGVIDEO: 717 1.1 pk *(int *)data = sc->sc_blanked; 718 1.1 pk break; 719 1.1 pk 720 1.1 pk case FBIOSVIDEO: 721 1.33 macallan cg6_blank(sc, !(*(int *)data)); 722 1.1 pk break; 723 1.1 pk 724 1.1 pk /* these are for both FBIOSCURSOR and FBIOGCURSOR */ 725 1.1 pk #define p ((struct fbcursor *)data) 726 1.1 pk #define cc (&sc->sc_cursor) 727 1.1 pk 728 1.1 pk case FBIOGCURSOR: 729 1.1 pk /* do not quite want everything here... */ 730 1.1 pk p->set = FB_CUR_SETALL; /* close enough, anyway */ 731 1.1 pk p->enable = cc->cc_enable; 732 1.1 pk p->pos = cc->cc_pos; 733 1.1 pk p->hot = cc->cc_hot; 734 1.1 pk p->size = cc->cc_size; 735 1.1 pk 736 1.1 pk /* begin ugh ... can we lose some of this crap?? */ 737 1.1 pk if (p->image != NULL) { 738 1.1 pk count = cc->cc_size.y * 32 / NBBY; 739 1.16 chs error = copyout(cc->cc_bits[1], p->image, count); 740 1.1 pk if (error) 741 1.22 martin return error; 742 1.16 chs error = copyout(cc->cc_bits[0], p->mask, count); 743 1.1 pk if (error) 744 1.22 martin return error; 745 1.1 pk } 746 1.1 pk if (p->cmap.red != NULL) { 747 1.1 pk error = bt_getcmap(&p->cmap, 748 1.1 pk (union bt_cmap *)&cc->cc_color, 2, 1); 749 1.1 pk if (error) 750 1.22 martin return error; 751 1.1 pk } else { 752 1.1 pk p->cmap.index = 0; 753 1.1 pk p->cmap.count = 2; 754 1.1 pk } 755 1.1 pk /* end ugh */ 756 1.1 pk break; 757 1.1 pk 758 1.1 pk case FBIOSCURSOR: 759 1.1 pk /* 760 1.1 pk * For setcmap and setshape, verify parameters, so that 761 1.1 pk * we do not get halfway through an update and then crap 762 1.1 pk * out with the software state screwed up. 763 1.1 pk */ 764 1.1 pk v = p->set; 765 1.1 pk if (v & FB_CUR_SETCMAP) { 766 1.1 pk /* 767 1.1 pk * This use of a temporary copy of the cursor 768 1.1 pk * colormap is not terribly efficient, but these 769 1.1 pk * copies are small (8 bytes)... 770 1.1 pk */ 771 1.1 pk tcm = cc->cc_color; 772 1.23 macallan error = bt_putcmap(&p->cmap, (union bt_cmap *)&tcm, 2, 773 1.23 macallan 1); 774 1.1 pk if (error) 775 1.22 martin return error; 776 1.1 pk } 777 1.1 pk if (v & FB_CUR_SETSHAPE) { 778 1.1 pk if ((u_int)p->size.x > 32 || (u_int)p->size.y > 32) 779 1.22 martin return EINVAL; 780 1.1 pk count = p->size.y * 32 / NBBY; 781 1.16 chs error = copyin(p->image, image, count); 782 1.16 chs if (error) 783 1.16 chs return error; 784 1.16 chs error = copyin(p->mask, mask, count); 785 1.16 chs if (error) 786 1.16 chs return error; 787 1.1 pk } 788 1.1 pk 789 1.1 pk /* parameters are OK; do it */ 790 1.1 pk if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) { 791 1.1 pk if (v & FB_CUR_SETCUR) 792 1.1 pk cc->cc_enable = p->enable; 793 1.1 pk if (v & FB_CUR_SETPOS) 794 1.1 pk cc->cc_pos = p->pos; 795 1.1 pk if (v & FB_CUR_SETHOT) 796 1.1 pk cc->cc_hot = p->hot; 797 1.1 pk cg6_setcursor(sc); 798 1.1 pk } 799 1.1 pk if (v & FB_CUR_SETCMAP) { 800 1.1 pk cc->cc_color = tcm; 801 1.1 pk cg6_loadomap(sc); /* XXX defer to vertical retrace */ 802 1.1 pk } 803 1.1 pk if (v & FB_CUR_SETSHAPE) { 804 1.1 pk cc->cc_size = p->size; 805 1.1 pk count = p->size.y * 32 / NBBY; 806 1.16 chs memset(cc->cc_bits, 0, sizeof cc->cc_bits); 807 1.16 chs memcpy(cc->cc_bits[1], image, count); 808 1.16 chs memcpy(cc->cc_bits[0], mask, count); 809 1.1 pk cg6_loadcursor(sc); 810 1.1 pk } 811 1.1 pk break; 812 1.1 pk 813 1.1 pk #undef p 814 1.1 pk #undef cc 815 1.1 pk 816 1.1 pk case FBIOGCURPOS: 817 1.1 pk *(struct fbcurpos *)data = sc->sc_cursor.cc_pos; 818 1.1 pk break; 819 1.1 pk 820 1.1 pk case FBIOSCURPOS: 821 1.1 pk sc->sc_cursor.cc_pos = *(struct fbcurpos *)data; 822 1.1 pk cg6_setcursor(sc); 823 1.1 pk break; 824 1.1 pk 825 1.1 pk case FBIOGCURMAX: 826 1.1 pk /* max cursor size is 32x32 */ 827 1.1 pk ((struct fbcurpos *)data)->x = 32; 828 1.1 pk ((struct fbcurpos *)data)->y = 32; 829 1.1 pk break; 830 1.1 pk 831 1.1 pk default: 832 1.1 pk #ifdef DEBUG 833 1.1 pk log(LOG_NOTICE, "cgsixioctl(0x%lx) (%s[%d])\n", cmd, 834 1.29 christos l->l_proc->p_comm, l->l_proc->p_pid); 835 1.1 pk #endif 836 1.22 martin return ENOTTY; 837 1.1 pk } 838 1.22 martin return 0; 839 1.1 pk } 840 1.1 pk 841 1.1 pk /* 842 1.1 pk * Clean up hardware state (e.g., after bootup or after X crashes). 843 1.1 pk */ 844 1.1 pk static void 845 1.22 martin cg6_reset(struct cgsix_softc *sc) 846 1.1 pk { 847 1.1 pk volatile struct cg6_tec_xxx *tec; 848 1.1 pk int fhc; 849 1.1 pk volatile struct bt_regs *bt; 850 1.1 pk 851 1.1 pk /* hide the cursor, just in case */ 852 1.1 pk sc->sc_thc->thc_cursxy = (THC_CURSOFF << 16) | THC_CURSOFF; 853 1.1 pk 854 1.1 pk /* turn off frobs in transform engine (makes X11 work) */ 855 1.1 pk tec = sc->sc_tec; 856 1.1 pk tec->tec_mv = 0; 857 1.1 pk tec->tec_clip = 0; 858 1.1 pk tec->tec_vdc = 0; 859 1.1 pk 860 1.1 pk /* take care of hardware bugs in old revisions */ 861 1.1 pk if (sc->sc_fhcrev < 5) { 862 1.1 pk /* 863 1.17 wiz * Keep current resolution; set CPU to 68020, set test 864 1.1 pk * window (size 1Kx1K), and for rev 1, disable dest cache. 865 1.1 pk */ 866 1.1 pk fhc = (*sc->sc_fhc & FHC_RES_MASK) | FHC_CPU_68020 | 867 1.1 pk FHC_TEST | 868 1.1 pk (11 << FHC_TESTX_SHIFT) | (11 << FHC_TESTY_SHIFT); 869 1.1 pk if (sc->sc_fhcrev < 2) 870 1.1 pk fhc |= FHC_DST_DISABLE; 871 1.1 pk *sc->sc_fhc = fhc; 872 1.1 pk } 873 1.1 pk 874 1.1 pk /* Enable cursor in Brooktree DAC. */ 875 1.1 pk bt = sc->sc_bt; 876 1.1 pk bt->bt_addr = 0x06 << 24; 877 1.1 pk bt->bt_ctrl |= 0x03 << 24; 878 1.1 pk } 879 1.1 pk 880 1.1 pk static void 881 1.22 martin cg6_setcursor(struct cgsix_softc *sc) 882 1.1 pk { 883 1.1 pk 884 1.1 pk /* we need to subtract the hot-spot value here */ 885 1.1 pk #define COORD(f) (sc->sc_cursor.cc_pos.f - sc->sc_cursor.cc_hot.f) 886 1.1 pk sc->sc_thc->thc_cursxy = sc->sc_cursor.cc_enable ? 887 1.1 pk ((COORD(x) << 16) | (COORD(y) & 0xffff)) : 888 1.1 pk (THC_CURSOFF << 16) | THC_CURSOFF; 889 1.1 pk #undef COORD 890 1.1 pk } 891 1.1 pk 892 1.1 pk static void 893 1.22 martin cg6_loadcursor(struct cgsix_softc *sc) 894 1.1 pk { 895 1.1 pk volatile struct cg6_thc *thc; 896 1.1 pk u_int edgemask, m; 897 1.1 pk int i; 898 1.1 pk 899 1.1 pk /* 900 1.1 pk * Keep the top size.x bits. Here we *throw out* the top 901 1.1 pk * size.x bits from an all-one-bits word, introducing zeros in 902 1.1 pk * the top size.x bits, then invert all the bits to get what 903 1.1 pk * we really wanted as our mask. But this fails if size.x is 904 1.1 pk * 32---a sparc uses only the low 5 bits of the shift count--- 905 1.1 pk * so we have to special case that. 906 1.1 pk */ 907 1.1 pk edgemask = ~0; 908 1.1 pk if (sc->sc_cursor.cc_size.x < 32) 909 1.1 pk edgemask = ~(edgemask >> sc->sc_cursor.cc_size.x); 910 1.1 pk thc = sc->sc_thc; 911 1.1 pk for (i = 0; i < 32; i++) { 912 1.1 pk m = sc->sc_cursor.cc_bits[0][i] & edgemask; 913 1.1 pk thc->thc_cursmask[i] = m; 914 1.1 pk thc->thc_cursbits[i] = m & sc->sc_cursor.cc_bits[1][i]; 915 1.1 pk } 916 1.1 pk } 917 1.1 pk 918 1.1 pk /* 919 1.1 pk * Load a subset of the current (new) colormap into the color DAC. 920 1.1 pk */ 921 1.1 pk static void 922 1.22 martin cg6_loadcmap(struct cgsix_softc *sc, int start, int ncolors) 923 1.1 pk { 924 1.1 pk volatile struct bt_regs *bt; 925 1.1 pk u_int *ip, i; 926 1.1 pk int count; 927 1.1 pk 928 1.1 pk ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */ 929 1.1 pk count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3; 930 1.1 pk bt = sc->sc_bt; 931 1.1 pk bt->bt_addr = BT_D4M4(start) << 24; 932 1.1 pk while (--count >= 0) { 933 1.1 pk i = *ip++; 934 1.1 pk /* hardware that makes one want to pound boards with hammers */ 935 1.1 pk bt->bt_cmap = i; 936 1.1 pk bt->bt_cmap = i << 8; 937 1.1 pk bt->bt_cmap = i << 16; 938 1.1 pk bt->bt_cmap = i << 24; 939 1.1 pk } 940 1.1 pk } 941 1.1 pk 942 1.1 pk /* 943 1.1 pk * Load the cursor (overlay `foreground' and `background') colors. 944 1.1 pk */ 945 1.1 pk static void 946 1.22 martin cg6_loadomap(struct cgsix_softc *sc) 947 1.1 pk { 948 1.1 pk volatile struct bt_regs *bt; 949 1.1 pk u_int i; 950 1.1 pk 951 1.1 pk bt = sc->sc_bt; 952 1.1 pk bt->bt_addr = 0x01 << 24; /* set background color */ 953 1.1 pk i = sc->sc_cursor.cc_color.cm_chip[0]; 954 1.1 pk bt->bt_omap = i; /* R */ 955 1.1 pk bt->bt_omap = i << 8; /* G */ 956 1.1 pk bt->bt_omap = i << 16; /* B */ 957 1.1 pk 958 1.1 pk bt->bt_addr = 0x03 << 24; /* set foreground color */ 959 1.1 pk bt->bt_omap = i << 24; /* R */ 960 1.1 pk i = sc->sc_cursor.cc_color.cm_chip[1]; 961 1.1 pk bt->bt_omap = i; /* G */ 962 1.1 pk bt->bt_omap = i << 8; /* B */ 963 1.1 pk } 964 1.1 pk 965 1.33 macallan /* blank or unblank the screen */ 966 1.33 macallan static void 967 1.33 macallan cg6_blank(struct cgsix_softc *sc, int flag) 968 1.33 macallan { 969 1.33 macallan 970 1.33 macallan if (sc->sc_blanked != flag) { 971 1.33 macallan sc->sc_blanked = flag; 972 1.33 macallan if (flag) { 973 1.33 macallan sc->sc_thc->thc_misc &= ~THC_MISC_VIDEN; 974 1.33 macallan } else { 975 1.33 macallan sc->sc_thc->thc_misc |= THC_MISC_VIDEN; 976 1.33 macallan } 977 1.33 macallan } 978 1.33 macallan } 979 1.33 macallan 980 1.33 macallan /* 981 1.33 macallan * this is called on panic or ddb entry - force the console to the front, reset 982 1.33 macallan * the colour map and enable drawing so we actually see the message even when X 983 1.33 macallan * is running 984 1.33 macallan */ 985 1.1 pk static void 986 1.39 macallan cg6_unblank(device_t dev) 987 1.1 pk { 988 1.38 drochner struct cgsix_softc *sc = device_private(dev); 989 1.1 pk 990 1.33 macallan cg6_blank(sc, 0); 991 1.1 pk } 992 1.1 pk 993 1.1 pk /* XXX the following should be moved to a "user interface" header */ 994 1.1 pk /* 995 1.1 pk * Base addresses at which users can mmap() the various pieces of a cg6. 996 1.1 pk * Note that although the Brooktree color registers do not occupy 8K, 997 1.1 pk * the X server dies if we do not allow it to map 8K there (it just maps 998 1.1 pk * from 0x70000000 forwards, as a contiguous chunk). 999 1.1 pk */ 1000 1.1 pk #define CG6_USER_FBC 0x70000000 1001 1.1 pk #define CG6_USER_TEC 0x70001000 1002 1.1 pk #define CG6_USER_BTREGS 0x70002000 1003 1.1 pk #define CG6_USER_FHC 0x70004000 1004 1.1 pk #define CG6_USER_THC 0x70005000 1005 1.1 pk #define CG6_USER_ROM 0x70006000 1006 1.1 pk #define CG6_USER_RAM 0x70016000 1007 1.1 pk #define CG6_USER_DHC 0x80000000 1008 1.1 pk 1009 1.1 pk struct mmo { 1010 1.2 eeh u_long mo_uaddr; /* user (virtual) address */ 1011 1.2 eeh u_long mo_size; /* size, or 0 for video ram size */ 1012 1.2 eeh u_long mo_physoff; /* offset from sc_physadr */ 1013 1.1 pk }; 1014 1.1 pk 1015 1.1 pk /* 1016 1.1 pk * Return the address that would map the given device at the given 1017 1.1 pk * offset, allowing for the given protection, or return -1 for error. 1018 1.1 pk * 1019 1.1 pk * XXX needs testing against `demanding' applications (e.g., aviator) 1020 1.1 pk */ 1021 1.1 pk paddr_t 1022 1.22 martin cgsixmmap(dev_t dev, off_t off, int prot) 1023 1.1 pk { 1024 1.38 drochner struct cgsix_softc *sc = device_lookup_private(&cgsix_cd, minor(dev)); 1025 1.1 pk struct mmo *mo; 1026 1.68 macallan u_int u, sz, flags; 1027 1.1 pk static struct mmo mmo[] = { 1028 1.1 pk { CG6_USER_RAM, 0, CGSIX_RAM_OFFSET }, 1029 1.1 pk 1030 1.1 pk /* do not actually know how big most of these are! */ 1031 1.1 pk { CG6_USER_FBC, 1, CGSIX_FBC_OFFSET }, 1032 1.1 pk { CG6_USER_TEC, 1, CGSIX_TEC_OFFSET }, 1033 1.1 pk { CG6_USER_BTREGS, 8192 /* XXX */, CGSIX_BT_OFFSET }, 1034 1.1 pk { CG6_USER_FHC, 1, CGSIX_FHC_OFFSET }, 1035 1.1 pk { CG6_USER_THC, sizeof(struct cg6_thc), CGSIX_THC_OFFSET }, 1036 1.1 pk { CG6_USER_ROM, 65536, CGSIX_ROM_OFFSET }, 1037 1.1 pk { CG6_USER_DHC, 1, CGSIX_DHC_OFFSET }, 1038 1.1 pk }; 1039 1.1 pk #define NMMO (sizeof mmo / sizeof *mmo) 1040 1.1 pk 1041 1.1 pk if (off & PGOFSET) 1042 1.1 pk panic("cgsixmmap"); 1043 1.1 pk 1044 1.1 pk /* 1045 1.1 pk * Entries with size 0 map video RAM (i.e., the size in fb data). 1046 1.1 pk * 1047 1.1 pk * Since we work in pages, the fact that the map offset table's 1048 1.1 pk * sizes are sometimes bizarre (e.g., 1) is effectively ignored: 1049 1.1 pk * one byte is as good as one page. 1050 1.1 pk */ 1051 1.1 pk for (mo = mmo; mo < &mmo[NMMO]; mo++) { 1052 1.2 eeh if ((u_long)off < mo->mo_uaddr) 1053 1.1 pk continue; 1054 1.1 pk u = off - mo->mo_uaddr; 1055 1.68 macallan if (mo->mo_size == 0) { 1056 1.73 macallan flags = BUS_SPACE_MAP_LINEAR; 1057 1.68 macallan sz = sc->sc_ramsize; 1058 1.68 macallan } else { 1059 1.68 macallan flags = BUS_SPACE_MAP_LINEAR; 1060 1.68 macallan sz = mo->mo_size; 1061 1.68 macallan } 1062 1.1 pk if (u < sz) { 1063 1.6 eeh return (bus_space_mmap(sc->sc_bustag, 1064 1.6 eeh sc->sc_paddr, u+mo->mo_physoff, 1065 1.68 macallan prot, flags)); 1066 1.1 pk } 1067 1.1 pk } 1068 1.1 pk 1069 1.1 pk #ifdef DEBUG 1070 1.1 pk { 1071 1.10 thorpej struct proc *p = curlwp->l_proc; /* XXX */ 1072 1.4 chs log(LOG_NOTICE, "cgsixmmap(0x%llx) (%s[%d])\n", 1073 1.4 chs (long long)off, p->p_comm, p->p_pid); 1074 1.1 pk } 1075 1.1 pk #endif 1076 1.22 martin return -1; /* not a user-map offset */ 1077 1.1 pk } 1078 1.18 martin 1079 1.23 macallan static void 1080 1.23 macallan cg6_setup_palette(struct cgsix_softc *sc) 1081 1.18 martin { 1082 1.23 macallan int i, j; 1083 1.39 macallan 1084 1.57 macallan rasops_get_cmap(&cg6_console_screen.scr_ri, sc->sc_default_cmap, 1085 1.57 macallan sizeof(sc->sc_default_cmap)); 1086 1.23 macallan j = 0; 1087 1.23 macallan for (i = 0; i < 256; i++) { 1088 1.39 macallan sc->sc_cmap.cm_map[i][0] = sc->sc_default_cmap[j]; 1089 1.23 macallan j++; 1090 1.39 macallan sc->sc_cmap.cm_map[i][1] = sc->sc_default_cmap[j]; 1091 1.23 macallan j++; 1092 1.39 macallan sc->sc_cmap.cm_map[i][2] = sc->sc_default_cmap[j]; 1093 1.23 macallan j++; 1094 1.23 macallan } 1095 1.23 macallan cg6_loadcmap(sc, 0, 256); 1096 1.18 martin } 1097 1.18 martin 1098 1.18 martin int 1099 1.34 christos cgsix_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 1100 1.30 jmmv struct lwp *l) 1101 1.18 martin { 1102 1.18 martin /* we'll probably need to add more stuff here */ 1103 1.33 macallan struct vcons_data *vd = v; 1104 1.33 macallan struct cgsix_softc *sc = vd->cookie; 1105 1.18 martin struct wsdisplay_fbinfo *wdf; 1106 1.33 macallan struct vcons_screen *ms = sc->vd.active; 1107 1.54 macallan 1108 1.18 martin #ifdef CGSIX_DEBUG 1109 1.52 macallan printf("cgsix_ioctl(%lx)\n",cmd); 1110 1.18 martin #endif 1111 1.18 martin switch (cmd) { 1112 1.18 martin case WSDISPLAYIO_GTYPE: 1113 1.18 martin *(u_int *)data = WSDISPLAY_TYPE_SUNTCX; 1114 1.18 martin return 0; 1115 1.18 martin case WSDISPLAYIO_GINFO: 1116 1.18 martin wdf = (void *)data; 1117 1.66 macallan wdf->height = sc->sc_height; 1118 1.66 macallan wdf->width = sc->sc_width; 1119 1.66 macallan wdf->depth = 8; 1120 1.18 martin wdf->cmsize = 256; 1121 1.18 martin return 0; 1122 1.19 perry 1123 1.18 martin case WSDISPLAYIO_GETCMAP: 1124 1.22 martin return cgsix_getcmap(sc, 1125 1.22 martin (struct wsdisplay_cmap *)data); 1126 1.18 martin case WSDISPLAYIO_PUTCMAP: 1127 1.22 martin return cgsix_putcmap(sc, 1128 1.22 martin (struct wsdisplay_cmap *)data); 1129 1.19 perry 1130 1.50 mrg case WSDISPLAYIO_LINEBYTES: 1131 1.50 mrg *(u_int *)data = sc->sc_stride; 1132 1.50 mrg return 0; 1133 1.50 mrg 1134 1.18 martin case WSDISPLAYIO_SMODE: 1135 1.18 martin { 1136 1.23 macallan int new_mode = *(int*)data; 1137 1.52 macallan 1138 1.52 macallan if (new_mode != sc->sc_mode) { 1139 1.23 macallan sc->sc_mode = new_mode; 1140 1.52 macallan if (IS_IN_EMUL_MODE(sc)) { 1141 1.23 macallan cg6_reset(sc); 1142 1.23 macallan cg6_ras_init(sc); 1143 1.33 macallan cg6_setup_palette(sc); 1144 1.59 macallan glyphcache_wipe(&sc->sc_gc); 1145 1.33 macallan vcons_redraw_screen(ms); 1146 1.18 martin } 1147 1.18 martin } 1148 1.18 martin } 1149 1.66 macallan return 0; 1150 1.66 macallan case WSDISPLAYIO_GET_FBINFO: 1151 1.66 macallan { 1152 1.66 macallan struct wsdisplayio_fbinfo *fbi = data; 1153 1.66 macallan 1154 1.66 macallan return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi); 1155 1.66 macallan } 1156 1.18 martin } 1157 1.18 martin return EPASSTHROUGH; 1158 1.18 martin } 1159 1.18 martin 1160 1.18 martin paddr_t 1161 1.30 jmmv cgsix_mmap(void *v, void *vs, off_t offset, int prot) 1162 1.18 martin { 1163 1.33 macallan struct vcons_data *vd = v; 1164 1.33 macallan struct cgsix_softc *sc = vd->cookie; 1165 1.33 macallan 1166 1.52 macallan if (offset < sc->sc_ramsize) { 1167 1.23 macallan return bus_space_mmap(sc->sc_bustag, sc->sc_paddr, 1168 1.68 macallan CGSIX_RAM_OFFSET + offset, prot, 1169 1.68 macallan BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE); 1170 1.18 martin } 1171 1.52 macallan return -1; 1172 1.18 martin } 1173 1.18 martin 1174 1.19 perry int 1175 1.18 martin cgsix_putcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm) 1176 1.18 martin { 1177 1.18 martin u_int index = cm->index; 1178 1.18 martin u_int count = cm->count; 1179 1.54 macallan int error, i; 1180 1.54 macallan 1181 1.18 martin if (index >= 256 || count > 256 || index + count > 256) 1182 1.18 martin return EINVAL; 1183 1.18 martin 1184 1.23 macallan for (i = 0; i < count; i++) 1185 1.18 martin { 1186 1.22 martin error = copyin(&cm->red[i], 1187 1.23 macallan &sc->sc_cmap.cm_map[index + i][0], 1); 1188 1.18 martin if (error) 1189 1.18 martin return error; 1190 1.22 martin error = copyin(&cm->green[i], 1191 1.23 macallan &sc->sc_cmap.cm_map[index + i][1], 1192 1.22 martin 1); 1193 1.18 martin if (error) 1194 1.18 martin return error; 1195 1.22 martin error = copyin(&cm->blue[i], 1196 1.23 macallan &sc->sc_cmap.cm_map[index + i][2], 1); 1197 1.18 martin if (error) 1198 1.18 martin return error; 1199 1.18 martin } 1200 1.23 macallan cg6_loadcmap(sc, index, count); 1201 1.19 perry 1202 1.18 martin return 0; 1203 1.18 martin } 1204 1.18 martin 1205 1.22 martin int 1206 1.22 martin cgsix_getcmap(struct cgsix_softc *sc, struct wsdisplay_cmap *cm) 1207 1.18 martin { 1208 1.18 martin u_int index = cm->index; 1209 1.18 martin u_int count = cm->count; 1210 1.18 martin int error,i; 1211 1.18 martin 1212 1.18 martin if (index >= 256 || count > 256 || index + count > 256) 1213 1.18 martin return EINVAL; 1214 1.18 martin 1215 1.23 macallan for (i = 0; i < count; i++) 1216 1.18 martin { 1217 1.23 macallan error = copyout(&sc->sc_cmap.cm_map[index + i][0], 1218 1.23 macallan &cm->red[i], 1); 1219 1.18 martin if (error) 1220 1.18 martin return error; 1221 1.23 macallan error = copyout(&sc->sc_cmap.cm_map[index + i][1], 1222 1.23 macallan &cm->green[i], 1); 1223 1.18 martin if (error) 1224 1.18 martin return error; 1225 1.23 macallan error = copyout(&sc->sc_cmap.cm_map[index + i][2], 1226 1.23 macallan &cm->blue[i], 1); 1227 1.18 martin if (error) 1228 1.18 martin return error; 1229 1.18 martin } 1230 1.19 perry 1231 1.18 martin return 0; 1232 1.18 martin } 1233 1.23 macallan 1234 1.23 macallan void 1235 1.33 macallan cgsix_init_screen(void *cookie, struct vcons_screen *scr, 1236 1.23 macallan int existing, long *defattr) 1237 1.23 macallan { 1238 1.33 macallan struct cgsix_softc *sc = cookie; 1239 1.33 macallan struct rasops_info *ri = &scr->scr_ri; 1240 1.60 macallan int av; 1241 1.33 macallan 1242 1.23 macallan ri->ri_depth = 8; 1243 1.23 macallan ri->ri_width = sc->sc_width; 1244 1.23 macallan ri->ri_height = sc->sc_height; 1245 1.23 macallan ri->ri_stride = sc->sc_stride; 1246 1.60 macallan av = sc->sc_ramsize - (sc->sc_height * sc->sc_stride); 1247 1.60 macallan ri->ri_flg = RI_CENTER | RI_8BIT_IS_RGB; 1248 1.60 macallan if (av > (128 * 1024)) { 1249 1.68 macallan ri->ri_flg |= RI_ENABLE_ALPHA | RI_PREFER_ALPHA; 1250 1.60 macallan } 1251 1.23 macallan ri->ri_bits = sc->sc_fb.fb_pixels; 1252 1.68 macallan scr->scr_flags |= VCONS_LOADFONT; 1253 1.68 macallan 1254 1.51 macallan rasops_init(ri, 0, 0); 1255 1.68 macallan ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_REVERSE | 1256 1.68 macallan WSSCREEN_UNDERLINE | WSSCREEN_RESIZE; 1257 1.23 macallan rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 1258 1.23 macallan sc->sc_width / ri->ri_font->fontwidth); 1259 1.23 macallan 1260 1.23 macallan /* enable acceleration */ 1261 1.23 macallan ri->ri_hw = scr; 1262 1.23 macallan ri->ri_ops.copyrows = cg6_ras_copyrows; 1263 1.23 macallan ri->ri_ops.copycols = cg6_ras_copycols; 1264 1.23 macallan ri->ri_ops.eraserows = cg6_ras_eraserows; 1265 1.23 macallan ri->ri_ops.erasecols = cg6_ras_erasecols; 1266 1.23 macallan ri->ri_ops.cursor = cgsix_cursor; 1267 1.57 macallan if (FONT_IS_ALPHA(ri->ri_font)) { 1268 1.57 macallan ri->ri_ops.putchar = cgsix_putchar_aa; 1269 1.57 macallan } else 1270 1.57 macallan ri->ri_ops.putchar = cgsix_putchar; 1271 1.23 macallan } 1272 1.23 macallan 1273 1.23 macallan void 1274 1.23 macallan cgsix_rectfill(struct cgsix_softc *sc, int xs, int ys, int wi, int he, 1275 1.23 macallan uint32_t col) 1276 1.23 macallan { 1277 1.23 macallan volatile struct cg6_fbc *fbc = sc->sc_fbc; 1278 1.56 macallan 1279 1.56 macallan CG6_WAIT_READY(fbc); 1280 1.55 macallan 1281 1.23 macallan fbc->fbc_alu = CG6_ALU_FILL; 1282 1.55 macallan fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 1283 1.55 macallan 1284 1.23 macallan fbc->fbc_fg = col; 1285 1.23 macallan fbc->fbc_arecty = ys; 1286 1.23 macallan fbc->fbc_arectx = xs; 1287 1.23 macallan fbc->fbc_arecty = ys + he - 1; 1288 1.23 macallan fbc->fbc_arectx = xs + wi - 1; 1289 1.56 macallan CG6_DRAW(fbc); 1290 1.23 macallan } 1291 1.23 macallan 1292 1.57 macallan void 1293 1.57 macallan cgsix_bitblt(void *cookie, int xs, int ys, int xd, int yd, 1294 1.57 macallan int wi, int he, int rop) 1295 1.57 macallan { 1296 1.57 macallan struct cgsix_softc *sc = cookie; 1297 1.57 macallan volatile struct cg6_fbc *fbc = sc->sc_fbc; 1298 1.57 macallan CG6_WAIT_READY(fbc); 1299 1.57 macallan 1300 1.57 macallan fbc->fbc_alu = rop; 1301 1.57 macallan fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 1302 1.57 macallan 1303 1.57 macallan fbc->fbc_x0 = xs; 1304 1.57 macallan fbc->fbc_y0 = ys; 1305 1.57 macallan fbc->fbc_x1 = xs + wi - 1; 1306 1.57 macallan fbc->fbc_y1 = ys + he - 1; 1307 1.57 macallan fbc->fbc_x2 = xd; 1308 1.57 macallan fbc->fbc_y2 = yd; 1309 1.57 macallan fbc->fbc_x3 = xd + wi - 1; 1310 1.57 macallan fbc->fbc_y3 = yd + he - 1; 1311 1.57 macallan CG6_BLIT(fbc); 1312 1.57 macallan } 1313 1.57 macallan 1314 1.23 macallan void 1315 1.23 macallan cgsix_setup_mono(struct cgsix_softc *sc, int x, int y, int wi, int he, 1316 1.23 macallan uint32_t fg, uint32_t bg) 1317 1.23 macallan { 1318 1.23 macallan volatile struct cg6_fbc *fbc=sc->sc_fbc; 1319 1.56 macallan 1320 1.56 macallan CG6_WAIT_READY(fbc); 1321 1.56 macallan 1322 1.23 macallan fbc->fbc_x0 = x; 1323 1.54 macallan fbc->fbc_x1 = x + wi - 1; 1324 1.23 macallan fbc->fbc_y0 = y; 1325 1.23 macallan fbc->fbc_incx = 0; 1326 1.23 macallan fbc->fbc_incy = 1; 1327 1.23 macallan fbc->fbc_fg = fg; 1328 1.23 macallan fbc->fbc_bg = bg; 1329 1.53 macallan fbc->fbc_mode = GX_BLIT_NOSRC | GX_MODE_COLOR1; 1330 1.53 macallan fbc->fbc_alu = GX_PATTERN_ONES | ROP_OSTP(GX_ROP_CLEAR, GX_ROP_SET); 1331 1.23 macallan sc->sc_mono_width = wi; 1332 1.23 macallan /* now feed the data into the chip */ 1333 1.23 macallan } 1334 1.23 macallan 1335 1.23 macallan void 1336 1.23 macallan cgsix_feed_line(struct cgsix_softc *sc, int count, uint8_t *data) 1337 1.23 macallan { 1338 1.23 macallan int i; 1339 1.23 macallan uint32_t latch, res = 0, shift; 1340 1.23 macallan volatile struct cg6_fbc *fbc = sc->sc_fbc; 1341 1.23 macallan 1342 1.23 macallan if (sc->sc_mono_width > 32) { 1343 1.23 macallan /* ARGH! */ 1344 1.23 macallan } else 1345 1.23 macallan { 1346 1.23 macallan shift = 24; 1347 1.23 macallan for (i = 0; i < count; i++) { 1348 1.23 macallan latch = data[i]; 1349 1.23 macallan res |= latch << shift; 1350 1.23 macallan shift -= 8; 1351 1.23 macallan } 1352 1.23 macallan fbc->fbc_font = res; 1353 1.23 macallan } 1354 1.23 macallan } 1355 1.23 macallan 1356 1.23 macallan void 1357 1.23 macallan cgsix_putchar(void *cookie, int row, int col, u_int c, long attr) 1358 1.23 macallan { 1359 1.33 macallan struct rasops_info *ri = cookie; 1360 1.47 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 1361 1.33 macallan struct vcons_screen *scr = ri->ri_hw; 1362 1.33 macallan struct cgsix_softc *sc = scr->scr_cookie; 1363 1.74 macallan volatile struct cg6_fbc *fbc = sc->sc_fbc; 1364 1.74 macallan int fg, bg, uc, i; 1365 1.74 macallan uint8_t *data; 1366 1.74 macallan int x, y, wi, he; 1367 1.33 macallan int inv; 1368 1.23 macallan 1369 1.74 macallan if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1370 1.74 macallan return; 1371 1.23 macallan 1372 1.74 macallan if (!CHAR_IN_FONT(c, font)) 1373 1.74 macallan return; 1374 1.74 macallan 1375 1.74 macallan if (row == ri->ri_crow && col == ri->ri_ccol) { 1376 1.74 macallan ri->ri_flg &= ~RI_CURSOR; 1377 1.74 macallan } 1378 1.71 macallan 1379 1.74 macallan wi = font->fontwidth; 1380 1.74 macallan he = font->fontheight; 1381 1.33 macallan 1382 1.74 macallan inv = ((attr >> 8) & WSATTR_REVERSE); 1383 1.74 macallan if (inv) { 1384 1.74 macallan fg = (u_char)ri->ri_devcmap[(attr >> 16) & 0xff]; 1385 1.74 macallan bg = (u_char)ri->ri_devcmap[(attr >> 24) & 0xff]; 1386 1.74 macallan } else { 1387 1.74 macallan bg = (u_char)ri->ri_devcmap[(attr >> 16) & 0xff]; 1388 1.74 macallan fg = (u_char)ri->ri_devcmap[(attr >> 24) & 0xff]; 1389 1.74 macallan } 1390 1.74 macallan 1391 1.74 macallan x = ri->ri_xorigin + col * wi; 1392 1.74 macallan y = ri->ri_yorigin + row * he; 1393 1.33 macallan 1394 1.74 macallan if (c == 0x20) { 1395 1.74 macallan cgsix_rectfill(sc, x, y, wi, he, bg); 1396 1.74 macallan } else { 1397 1.74 macallan uc = c - font->firstchar; 1398 1.74 macallan data = (uint8_t *)font->data + uc * ri->ri_fontscale; 1399 1.33 macallan 1400 1.74 macallan cgsix_setup_mono(sc, x, y, wi, 1, fg, bg); 1401 1.74 macallan for (i = 0; i < he; i++) { 1402 1.74 macallan cgsix_feed_line(sc, font->stride, data); 1403 1.74 macallan data += font->stride; 1404 1.23 macallan } 1405 1.74 macallan /* put the chip back to normal */ 1406 1.74 macallan fbc->fbc_incy = 0; 1407 1.23 macallan } 1408 1.23 macallan } 1409 1.23 macallan 1410 1.23 macallan void 1411 1.57 macallan cgsix_putchar_aa(void *cookie, int row, int col, u_int c, long attr) 1412 1.57 macallan { 1413 1.57 macallan struct rasops_info *ri = cookie; 1414 1.57 macallan struct wsdisplay_font *font = PICK_FONT(ri, c); 1415 1.57 macallan struct vcons_screen *scr = ri->ri_hw; 1416 1.57 macallan struct cgsix_softc *sc = scr->scr_cookie; 1417 1.57 macallan volatile struct cg6_fbc *fbc = sc->sc_fbc; 1418 1.57 macallan 1419 1.57 macallan uint32_t bg, latch = 0, bg8, fg8, pixel; 1420 1.57 macallan int i, j, shift, x, y, wi, he, r, g, b, aval; 1421 1.57 macallan int r1, g1, b1, r0, g0, b0, fgo, bgo; 1422 1.57 macallan uint8_t *data8; 1423 1.57 macallan int rv; 1424 1.57 macallan 1425 1.57 macallan if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1426 1.57 macallan return; 1427 1.57 macallan 1428 1.57 macallan if (!CHAR_IN_FONT(c, font)) 1429 1.57 macallan return; 1430 1.57 macallan 1431 1.71 macallan if (row == ri->ri_crow && col == ri->ri_ccol) { 1432 1.71 macallan ri->ri_flg &= ~RI_CURSOR; 1433 1.71 macallan } 1434 1.71 macallan 1435 1.57 macallan wi = font->fontwidth; 1436 1.57 macallan he = font->fontheight; 1437 1.57 macallan 1438 1.57 macallan bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 1439 1.57 macallan x = ri->ri_xorigin + col * wi; 1440 1.57 macallan y = ri->ri_yorigin + row * he; 1441 1.57 macallan if (c == 0x20) { 1442 1.57 macallan cgsix_rectfill(sc, x, y, wi, he, bg); 1443 1.57 macallan return; 1444 1.57 macallan } 1445 1.57 macallan 1446 1.57 macallan rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 1447 1.57 macallan if (rv == GC_OK) 1448 1.57 macallan return; 1449 1.57 macallan 1450 1.57 macallan data8 = WSFONT_GLYPH(c, font); 1451 1.57 macallan 1452 1.57 macallan CG6_WAIT_READY(sc->sc_fbc); 1453 1.57 macallan fbc->fbc_incx = 4; 1454 1.57 macallan fbc->fbc_incy = 0; 1455 1.57 macallan fbc->fbc_mode = GX_BLIT_NOSRC | GX_MODE_COLOR8; 1456 1.57 macallan fbc->fbc_alu = CG6_ALU_COPY; 1457 1.57 macallan fbc->fbc_clipmaxx = x + wi - 1; 1458 1.57 macallan 1459 1.57 macallan /* 1460 1.57 macallan * we need the RGB colours here, so get offsets into rasops_cmap 1461 1.57 macallan */ 1462 1.57 macallan fgo = ((attr >> 24) & 0xf) * 3; 1463 1.57 macallan bgo = ((attr >> 16) & 0xf) * 3; 1464 1.57 macallan 1465 1.57 macallan r0 = rasops_cmap[bgo]; 1466 1.57 macallan r1 = rasops_cmap[fgo]; 1467 1.57 macallan g0 = rasops_cmap[bgo + 1]; 1468 1.57 macallan g1 = rasops_cmap[fgo + 1]; 1469 1.57 macallan b0 = rasops_cmap[bgo + 2]; 1470 1.57 macallan b1 = rasops_cmap[fgo + 2]; 1471 1.57 macallan #define R3G3B2(r, g, b) ((r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6)) 1472 1.57 macallan bg8 = R3G3B2(r0, g0, b0); 1473 1.57 macallan fg8 = R3G3B2(r1, g1, b1); 1474 1.57 macallan 1475 1.57 macallan for (i = 0; i < he; i++) { 1476 1.57 macallan 1477 1.57 macallan CG6_WAIT_READY(fbc); 1478 1.57 macallan fbc->fbc_x0 = x; 1479 1.57 macallan fbc->fbc_x1 = x + 3; 1480 1.57 macallan fbc->fbc_y0 = y + i; 1481 1.57 macallan 1482 1.57 macallan shift = 24; 1483 1.57 macallan for (j = 0; j < wi; j++) { 1484 1.57 macallan aval = *data8; 1485 1.57 macallan if (aval == 0) { 1486 1.57 macallan pixel = bg8; 1487 1.57 macallan } else if (aval == 255) { 1488 1.57 macallan pixel = fg8; 1489 1.57 macallan } else { 1490 1.57 macallan r = aval * r1 + (255 - aval) * r0; 1491 1.57 macallan g = aval * g1 + (255 - aval) * g0; 1492 1.57 macallan b = aval * b1 + (255 - aval) * b0; 1493 1.57 macallan pixel = ((r & 0xe000) >> 8) | 1494 1.57 macallan ((g & 0xe000) >> 11) | 1495 1.57 macallan ((b & 0xc000) >> 14); 1496 1.57 macallan } 1497 1.57 macallan data8++; 1498 1.57 macallan 1499 1.57 macallan latch |= pixel << shift; 1500 1.57 macallan if (shift == 0) { 1501 1.57 macallan fbc->fbc_font = latch; 1502 1.57 macallan latch = 0; 1503 1.57 macallan shift = 24; 1504 1.57 macallan } else 1505 1.57 macallan shift -= 8; 1506 1.57 macallan } 1507 1.57 macallan if (shift != 24) 1508 1.57 macallan fbc->fbc_font = latch; 1509 1.57 macallan } 1510 1.57 macallan fbc->fbc_clipmaxx = 0x3fff; 1511 1.57 macallan 1512 1.57 macallan if (rv == GC_ADD) { 1513 1.57 macallan glyphcache_add(&sc->sc_gc, c, x, y); 1514 1.57 macallan } 1515 1.57 macallan } 1516 1.57 macallan 1517 1.57 macallan void 1518 1.23 macallan cgsix_cursor(void *cookie, int on, int row, int col) 1519 1.23 macallan { 1520 1.33 macallan struct rasops_info *ri = cookie; 1521 1.33 macallan struct vcons_screen *scr = ri->ri_hw; 1522 1.33 macallan struct cgsix_softc *sc = scr->scr_cookie; 1523 1.23 macallan int x, y, wi, he; 1524 1.23 macallan 1525 1.23 macallan wi = ri->ri_font->fontwidth; 1526 1.23 macallan he = ri->ri_font->fontheight; 1527 1.23 macallan 1528 1.33 macallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1529 1.71 macallan if (on) { 1530 1.71 macallan if (ri->ri_flg & RI_CURSOR) { 1531 1.71 macallan cg6_ras_nuke_cursor(ri); 1532 1.71 macallan } 1533 1.71 macallan x = col * wi + ri->ri_xorigin; 1534 1.71 macallan y = row * he + ri->ri_yorigin; 1535 1.23 macallan cg6_invert(sc, x, y, wi, he); 1536 1.71 macallan ri->ri_flg |= RI_CURSOR; 1537 1.23 macallan } 1538 1.33 macallan ri->ri_crow = row; 1539 1.33 macallan ri->ri_ccol = col; 1540 1.33 macallan } else 1541 1.33 macallan { 1542 1.33 macallan ri->ri_crow = row; 1543 1.33 macallan ri->ri_ccol = col; 1544 1.33 macallan ri->ri_flg &= ~RI_CURSOR; 1545 1.23 macallan } 1546 1.23 macallan } 1547 1.23 macallan 1548 1.23 macallan void 1549 1.23 macallan cgsix_clearscreen(struct cgsix_softc *sc) 1550 1.23 macallan { 1551 1.33 macallan struct rasops_info *ri = &cg6_console_screen.scr_ri; 1552 1.23 macallan 1553 1.23 macallan if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1554 1.23 macallan volatile struct cg6_fbc *fbc = sc->sc_fbc; 1555 1.23 macallan 1556 1.56 macallan CG6_WAIT_READY(fbc); 1557 1.55 macallan 1558 1.23 macallan fbc->fbc_alu = CG6_ALU_FILL; 1559 1.55 macallan fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 1560 1.55 macallan 1561 1.23 macallan fbc->fbc_fg = ri->ri_devcmap[sc->sc_bg]; 1562 1.23 macallan fbc->fbc_arectx = 0; 1563 1.23 macallan fbc->fbc_arecty = 0; 1564 1.23 macallan fbc->fbc_arectx = ri->ri_width - 1; 1565 1.23 macallan fbc->fbc_arecty = ri->ri_height - 1; 1566 1.56 macallan CG6_DRAW(fbc); 1567 1.71 macallan ri->ri_flg &= ~RI_CURSOR; 1568 1.23 macallan } 1569 1.23 macallan } 1570 1.23 macallan 1571 1.23 macallan void 1572 1.23 macallan cg6_invert(struct cgsix_softc *sc, int x, int y, int wi, int he) 1573 1.23 macallan { 1574 1.23 macallan volatile struct cg6_fbc *fbc = sc->sc_fbc; 1575 1.23 macallan 1576 1.56 macallan CG6_WAIT_READY(fbc); 1577 1.56 macallan 1578 1.23 macallan fbc->fbc_alu = CG6_ALU_FLIP; 1579 1.55 macallan fbc->fbc_mode = GX_BLIT_SRC | GX_MODE_COLOR8; 1580 1.23 macallan fbc->fbc_arecty = y; 1581 1.23 macallan fbc->fbc_arectx = x; 1582 1.24 macallan fbc->fbc_arecty = y + he - 1; 1583 1.24 macallan fbc->fbc_arectx = x + wi - 1; 1584 1.56 macallan CG6_DRAW(fbc); 1585 1.23 macallan } 1586 1.23 macallan 1587