1 1.66 andvar /* $NetBSD: hpcfb.c,v 1.66 2024/02/29 22:01:57 andvar Exp $ */ 2 1.1 uch 3 1.1 uch /*- 4 1.1 uch * Copyright (c) 1999 5 1.1 uch * Shin Takemura and PocketBSD Project. All rights reserved. 6 1.1 uch * Copyright (c) 2000,2001 7 1.1 uch * SATO Kazumi. All rights reserved. 8 1.1 uch * 9 1.1 uch * Redistribution and use in source and binary forms, with or without 10 1.1 uch * modification, are permitted provided that the following conditions 11 1.1 uch * are met: 12 1.1 uch * 1. Redistributions of source code must retain the above copyright 13 1.1 uch * notice, this list of conditions and the following disclaimer. 14 1.1 uch * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 uch * notice, this list of conditions and the following disclaimer in the 16 1.1 uch * documentation and/or other materials provided with the distribution. 17 1.1 uch * 3. All advertising materials mentioning features or use of this software 18 1.1 uch * must display the following acknowledgement: 19 1.1 uch * This product includes software developed by the PocketBSD project 20 1.1 uch * and its contributors. 21 1.1 uch * 4. Neither the name of the project nor the names of its contributors 22 1.1 uch * may be used to endorse or promote products derived from this software 23 1.1 uch * without specific prior written permission. 24 1.1 uch * 25 1.1 uch * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 1.1 uch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 1.1 uch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 1.1 uch * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 1.1 uch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 1.1 uch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 1.1 uch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 1.1 uch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 1.1 uch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 1.1 uch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 1.1 uch * SUCH DAMAGE. 36 1.1 uch * 37 1.1 uch */ 38 1.1 uch 39 1.1 uch /* 40 1.31 perry * jump scroll, scroll thread, multiscreen, virtual text vram 41 1.1 uch * and hpcfb_emulops functions 42 1.1 uch * written by SATO Kazumi. 43 1.1 uch */ 44 1.1 uch 45 1.15 lukem #include <sys/cdefs.h> 46 1.66 andvar __KERNEL_RCSID(0, "$NetBSD: hpcfb.c,v 1.66 2024/02/29 22:01:57 andvar Exp $"); 47 1.15 lukem 48 1.38 peter #ifdef _KERNEL_OPT 49 1.38 peter #include "opt_hpcfb.h" 50 1.38 peter #endif 51 1.1 uch 52 1.1 uch #include <sys/param.h> 53 1.1 uch #include <sys/systm.h> 54 1.1 uch #include <sys/kernel.h> 55 1.1 uch #include <sys/signalvar.h> 56 1.1 uch #include <sys/proc.h> 57 1.1 uch #include <sys/kthread.h> 58 1.1 uch #include <sys/device.h> 59 1.1 uch #include <sys/conf.h> 60 1.1 uch #include <sys/malloc.h> 61 1.1 uch #include <sys/buf.h> 62 1.1 uch #include <sys/ioctl.h> 63 1.1 uch 64 1.43 ad #include <sys/bus.h> 65 1.1 uch 66 1.1 uch #include <dev/wscons/wsconsio.h> 67 1.1 uch #include <dev/wscons/wsdisplayvar.h> 68 1.1 uch #include <dev/wscons/wscons_callbacks.h> 69 1.1 uch 70 1.1 uch #include <dev/wsfont/wsfont.h> 71 1.1 uch #include <dev/rasops/rasops.h> 72 1.1 uch 73 1.1 uch #include <dev/hpc/hpcfbvar.h> 74 1.1 uch #include <dev/hpc/hpcfbio.h> 75 1.1 uch 76 1.1 uch #include "bivideo.h" 77 1.1 uch #if NBIVIDEO > 0 78 1.1 uch #include <dev/hpc/bivideovar.h> 79 1.1 uch #endif 80 1.1 uch 81 1.1 uch #ifdef FBDEBUG 82 1.1 uch int hpcfb_debug = 0; 83 1.39 uwe #define DPRINTF(arg) if (hpcfb_debug) printf arg 84 1.1 uch #else 85 1.39 uwe #define DPRINTF(arg) do {} while (/* CONSTCOND */ 0) 86 1.1 uch #endif 87 1.1 uch 88 1.1 uch #ifndef HPCFB_MAX_COLUMN 89 1.1 uch #define HPCFB_MAX_COLUMN 130 90 1.1 uch #endif /* HPCFB_MAX_COLUMN */ 91 1.1 uch #ifndef HPCFB_MAX_ROW 92 1.1 uch #define HPCFB_MAX_ROW 80 93 1.1 uch #endif /* HPCFB_MAX_ROW */ 94 1.1 uch 95 1.1 uch /* 96 1.1 uch * currently experimental 97 1.1 uch #define HPCFB_JUMP 98 1.1 uch */ 99 1.1 uch 100 1.1 uch struct hpcfb_vchar { 101 1.1 uch u_int c; 102 1.1 uch long attr; 103 1.1 uch }; 104 1.1 uch 105 1.1 uch struct hpcfb_tvrow { 106 1.1 uch int maxcol; 107 1.1 uch int spacecol; 108 1.1 uch struct hpcfb_vchar col[HPCFB_MAX_COLUMN]; 109 1.1 uch }; 110 1.1 uch 111 1.1 uch struct hpcfb_devconfig { 112 1.9 toshii struct rasops_info dc_rinfo; /* rasops information */ 113 1.1 uch 114 1.1 uch int dc_blanked; /* currently had video disabled */ 115 1.1 uch struct hpcfb_softc *dc_sc; 116 1.1 uch int dc_rows; 117 1.1 uch int dc_cols; 118 1.1 uch struct hpcfb_tvrow *dc_tvram; 119 1.1 uch int dc_curx; 120 1.1 uch int dc_cury; 121 1.1 uch #ifdef HPCFB_JUMP 122 1.1 uch int dc_min_row; 123 1.1 uch int dc_max_row; 124 1.1 uch int dc_scroll; 125 1.1 uch struct callout dc_scroll_ch; 126 1.1 uch int dc_scroll_src; 127 1.1 uch int dc_scroll_dst; 128 1.1 uch int dc_scroll_num; 129 1.1 uch #endif /* HPCFB_JUMP */ 130 1.1 uch volatile int dc_state; 131 1.1 uch #define HPCFB_DC_CURRENT 0x80000000 132 1.1 uch #define HPCFB_DC_DRAWING 0x01 /* drawing raster ops */ 133 1.1 uch #define HPCFB_DC_TDRAWING 0x02 /* drawing tvram */ 134 1.1 uch #define HPCFB_DC_SCROLLPENDING 0x04 /* scroll is pending */ 135 1.1 uch #define HPCFB_DC_UPDATE 0x08 /* tvram update */ 136 1.1 uch #define HPCFB_DC_SCRDELAY 0x10 /* scroll time but delay it */ 137 1.1 uch #define HPCFB_DC_SCRTHREAD 0x20 /* in scroll thread or callout */ 138 1.1 uch #define HPCFB_DC_UPDATEALL 0x40 /* need to redraw all */ 139 1.1 uch #define HPCFB_DC_ABORT 0x80 /* abort redrawing */ 140 1.12 sato #define HPCFB_DC_SWITCHREQ 0x100 /* switch request exist */ 141 1.1 uch int dc_memsize; 142 1.1 uch u_char *dc_fbaddr; 143 1.1 uch }; 144 1.1 uch 145 1.12 sato #define IS_DRAWABLE(dc) \ 146 1.12 sato (((dc)->dc_state&HPCFB_DC_CURRENT)&& \ 147 1.12 sato (((dc)->dc_state&(HPCFB_DC_DRAWING|HPCFB_DC_SWITCHREQ)) == 0)) 148 1.12 sato 149 1.1 uch #define HPCFB_MAX_SCREEN 5 150 1.1 uch #define HPCFB_MAX_JUMP 5 151 1.1 uch 152 1.1 uch struct hpcfb_softc { 153 1.49 uwe device_t sc_dev; 154 1.1 uch struct hpcfb_devconfig *sc_dc; /* device configuration */ 155 1.1 uch const struct hpcfb_accessops *sc_accessops; 156 1.1 uch void *sc_accessctx; 157 1.49 uwe device_t sc_wsdisplay; 158 1.1 uch int sc_screen_resumed; 159 1.1 uch int sc_polling; 160 1.1 uch int sc_mapping; 161 1.1 uch struct proc *sc_thread; 162 1.1 uch void *sc_wantedscreen; 163 1.4 uch void (*sc_switchcb)(void *, int, int); 164 1.1 uch void *sc_switchcbarg; 165 1.1 uch struct callout sc_switch_callout; 166 1.10 takemura int sc_nfbconf; 167 1.10 takemura struct hpcfb_fbconf *sc_fbconflist; 168 1.1 uch }; 169 1.1 uch 170 1.1 uch /* 171 1.1 uch * function prototypes 172 1.1 uch */ 173 1.49 uwe int hpcfbmatch(device_t, cfdata_t, void *); 174 1.49 uwe void hpcfbattach(device_t, device_t, void *); 175 1.4 uch int hpcfbprint(void *, const char *); 176 1.4 uch 177 1.41 christos int hpcfb_ioctl(void *, void *, u_long, void *, int, struct lwp *); 178 1.36 jmmv paddr_t hpcfb_mmap(void *, void *, off_t, int); 179 1.4 uch 180 1.4 uch void hpcfb_refresh_screen(struct hpcfb_softc *); 181 1.4 uch void hpcfb_doswitch(struct hpcfb_softc *); 182 1.4 uch 183 1.4 uch #ifdef HPCFB_JUMP 184 1.4 uch static void hpcfb_thread(void *); 185 1.4 uch #endif /* HPCFB_JUMP */ 186 1.4 uch 187 1.4 uch static int hpcfb_init(struct hpcfb_fbconf *, struct hpcfb_devconfig *); 188 1.4 uch static int hpcfb_alloc_screen(void *, const struct wsscreen_descr *, 189 1.4 uch void **, int *, int *, long *); 190 1.4 uch static void hpcfb_free_screen(void *, void *); 191 1.4 uch static int hpcfb_show_screen(void *, void *, int, 192 1.4 uch void (*) (void *, int, int), void *); 193 1.4 uch static void hpcfb_pollc(void *, int); 194 1.4 uch static void hpcfb_cmap_reorder(struct hpcfb_fbconf *, 195 1.4 uch struct hpcfb_devconfig *); 196 1.4 uch 197 1.50 uwe static void hpcfb_power(int, void *); 198 1.53 dyoung static bool hpcfb_suspend(device_t, const pmf_qual_t *); 199 1.53 dyoung static bool hpcfb_resume(device_t, const pmf_qual_t *); 200 1.50 uwe 201 1.50 uwe 202 1.4 uch void hpcfb_cursor(void *, int, int, int); 203 1.4 uch int hpcfb_mapchar(void *, int, unsigned int *); 204 1.4 uch void hpcfb_putchar(void *, int, int, u_int, long); 205 1.4 uch void hpcfb_copycols(void *, int, int, int, int); 206 1.4 uch void hpcfb_erasecols(void *, int, int, int, long); 207 1.4 uch void hpcfb_redraw(void *, int, int, int); 208 1.4 uch void hpcfb_copyrows(void *, int, int, int); 209 1.4 uch void hpcfb_eraserows(void *, int, int, long); 210 1.21 junyoung int hpcfb_allocattr(void *, int, int, int, long *); 211 1.4 uch void hpcfb_cursor_raw(void *, int, int, int); 212 1.4 uch 213 1.4 uch #ifdef HPCFB_JUMP 214 1.4 uch void hpcfb_update(void *); 215 1.4 uch void hpcfb_do_scroll(void *); 216 1.4 uch void hpcfb_check_update(void *); 217 1.1 uch #endif /* HPCFB_JUMP */ 218 1.1 uch 219 1.1 uch struct wsdisplay_emulops hpcfb_emulops = { 220 1.39 uwe .cursor = hpcfb_cursor, 221 1.39 uwe .mapchar = hpcfb_mapchar, 222 1.39 uwe .putchar = hpcfb_putchar, 223 1.39 uwe .copycols = hpcfb_copycols, 224 1.39 uwe .erasecols = hpcfb_erasecols, 225 1.39 uwe .copyrows = hpcfb_copyrows, 226 1.39 uwe .eraserows = hpcfb_eraserows, 227 1.39 uwe .allocattr = hpcfb_allocattr, 228 1.39 uwe .replaceattr = NULL, 229 1.1 uch }; 230 1.1 uch 231 1.1 uch /* 232 1.1 uch * static variables 233 1.1 uch */ 234 1.49 uwe CFATTACH_DECL_NEW(hpcfb, sizeof(struct hpcfb_softc), 235 1.27 thorpej hpcfbmatch, hpcfbattach, NULL, NULL); 236 1.1 uch 237 1.1 uch struct wsscreen_descr hpcfb_stdscreen = { 238 1.39 uwe .name = "std", 239 1.39 uwe .textops = &hpcfb_emulops, /* XXX */ 240 1.39 uwe .capabilities = WSSCREEN_REVERSE, 241 1.39 uwe /* XXX: ncols/nrows will be filled in -- shouldn't, they are global */ 242 1.1 uch }; 243 1.1 uch 244 1.1 uch const struct wsscreen_descr *_hpcfb_scrlist[] = { 245 1.1 uch &hpcfb_stdscreen, 246 1.1 uch /* XXX other formats, graphics screen? */ 247 1.1 uch }; 248 1.1 uch 249 1.1 uch struct wsscreen_list hpcfb_screenlist = { 250 1.39 uwe .nscreens = __arraycount(_hpcfb_scrlist), 251 1.39 uwe .screens = _hpcfb_scrlist, 252 1.1 uch }; 253 1.1 uch 254 1.1 uch struct wsdisplay_accessops hpcfb_accessops = { 255 1.39 uwe .ioctl = hpcfb_ioctl, 256 1.39 uwe .mmap = hpcfb_mmap, 257 1.39 uwe .alloc_screen = hpcfb_alloc_screen, 258 1.39 uwe .free_screen = hpcfb_free_screen, 259 1.39 uwe .show_screen = hpcfb_show_screen, 260 1.39 uwe .load_font = NULL, 261 1.39 uwe .pollc = hpcfb_pollc, 262 1.39 uwe .scroll = NULL, 263 1.1 uch }; 264 1.1 uch 265 1.4 uch void hpcfb_tv_putchar(struct hpcfb_devconfig *, int, int, u_int, long); 266 1.4 uch void hpcfb_tv_copycols(struct hpcfb_devconfig *, int, int, int, int); 267 1.4 uch void hpcfb_tv_erasecols(struct hpcfb_devconfig *, int, int, int, long); 268 1.4 uch void hpcfb_tv_copyrows(struct hpcfb_devconfig *, int, int, int); 269 1.4 uch void hpcfb_tv_eraserows(struct hpcfb_devconfig *, int, int, long); 270 1.1 uch 271 1.1 uch struct wsdisplay_emulops rasops_emul; 272 1.1 uch 273 1.1 uch static int hpcfbconsole; 274 1.1 uch struct hpcfb_devconfig hpcfb_console_dc; 275 1.1 uch struct wsscreen_descr hpcfb_console_wsscreen; 276 1.1 uch struct hpcfb_tvrow hpcfb_console_tvram[HPCFB_MAX_ROW]; 277 1.1 uch 278 1.1 uch /* 279 1.1 uch * function bodies 280 1.1 uch */ 281 1.1 uch 282 1.1 uch int 283 1.49 uwe hpcfbmatch(device_t parent, cfdata_t match, void *aux) 284 1.1 uch { 285 1.1 uch return (1); 286 1.1 uch } 287 1.1 uch 288 1.1 uch void 289 1.49 uwe hpcfbattach(device_t parent, device_t self, void *aux) 290 1.1 uch { 291 1.49 uwe struct hpcfb_softc *sc; 292 1.1 uch struct hpcfb_attach_args *ha = aux; 293 1.1 uch struct wsemuldisplaydev_attach_args wa; 294 1.1 uch 295 1.49 uwe sc = device_private(self); 296 1.49 uwe sc->sc_dev = self; 297 1.49 uwe 298 1.1 uch sc->sc_accessops = ha->ha_accessops; 299 1.1 uch sc->sc_accessctx = ha->ha_accessctx; 300 1.10 takemura sc->sc_nfbconf = ha->ha_nfbconf; 301 1.10 takemura sc->sc_fbconflist = ha->ha_fbconflist; 302 1.1 uch 303 1.1 uch if (hpcfbconsole) { 304 1.10 takemura sc->sc_dc = &hpcfb_console_dc; 305 1.55 tsutsui sc->sc_dc->dc_rinfo.ri_flg &= ~RI_NO_AUTO; 306 1.1 uch hpcfb_console_dc.dc_sc = sc; 307 1.10 takemura printf(": %dx%d pixels, %d colors, %dx%d chars", 308 1.10 takemura sc->sc_dc->dc_rinfo.ri_width,sc->sc_dc->dc_rinfo.ri_height, 309 1.26 reinoud (1 << sc->sc_dc->dc_rinfo.ri_depth), 310 1.10 takemura sc->sc_dc->dc_rinfo.ri_cols,sc->sc_dc->dc_rinfo.ri_rows); 311 1.10 takemura /* Set video chip dependent CLUT if any. */ 312 1.10 takemura if (sc->sc_accessops->setclut) 313 1.31 perry sc->sc_accessops->setclut(sc->sc_accessctx, 314 1.10 takemura &hpcfb_console_dc.dc_rinfo); 315 1.1 uch } 316 1.10 takemura printf("\n"); 317 1.10 takemura 318 1.1 uch sc->sc_polling = 0; /* XXX */ 319 1.1 uch sc->sc_mapping = 0; /* XXX */ 320 1.42 ad callout_init(&sc->sc_switch_callout, 0); 321 1.1 uch 322 1.1 uch wa.console = hpcfbconsole; 323 1.1 uch wa.scrdata = &hpcfb_screenlist; 324 1.1 uch wa.accessops = &hpcfb_accessops; 325 1.1 uch wa.accesscookie = sc; 326 1.1 uch 327 1.61 thorpej sc->sc_wsdisplay = config_found(self, &wa, wsemuldisplaydevprint, 328 1.63 thorpej CFARGS_NONE); 329 1.1 uch 330 1.1 uch #ifdef HPCFB_JUMP 331 1.1 uch /* 332 1.1 uch * Create a kernel thread to scroll, 333 1.1 uch */ 334 1.42 ad if (kthread_create(PRI_NONE, 0, NULL, hpcfb_thread, sc, 335 1.49 uwe &sc->sc_thread, "%s", device_xname(sc->sc_dev)) != 0) { 336 1.42 ad /* 337 1.42 ad * We were unable to create the HPCFB thread; bail out. 338 1.42 ad */ 339 1.42 ad sc->sc_thread = 0; 340 1.49 uwe aprint_error_dev(sc->sc_dev, "unable to create thread, kernel " 341 1.47 cegger "hpcfb scroll support disabled\n"); 342 1.42 ad } 343 1.1 uch #endif /* HPCFB_JUMP */ 344 1.50 uwe 345 1.50 uwe if (!pmf_device_register(self, hpcfb_suspend, hpcfb_resume)) 346 1.50 uwe aprint_error_dev(self, "unable to establish power handler\n"); 347 1.1 uch } 348 1.1 uch 349 1.1 uch #ifdef HPCFB_JUMP 350 1.1 uch void 351 1.4 uch hpcfb_thread(void *arg) 352 1.1 uch { 353 1.1 uch struct hpcfb_softc *sc = arg; 354 1.1 uch 355 1.1 uch /* 356 1.1 uch * Loop forever, doing a periodic check for update events. 357 1.1 uch */ 358 1.1 uch for (;;) { 359 1.1 uch /* HPCFB_LOCK(sc); */ 360 1.31 perry sc->sc_dc->dc_state |= HPCFB_DC_SCRTHREAD; 361 1.1 uch if (!sc->sc_mapping) /* draw only EMUL mode */ 362 1.1 uch hpcfb_update(sc->sc_dc); 363 1.31 perry sc->sc_dc->dc_state &= ~HPCFB_DC_SCRTHREAD; 364 1.1 uch /* APM_UNLOCK(sc); */ 365 1.1 uch (void) tsleep(sc, PWAIT, "hpcfb", (8 * hz) / 7 / 10); 366 1.1 uch } 367 1.1 uch } 368 1.1 uch #endif /* HPCFB_JUMP */ 369 1.1 uch 370 1.1 uch /* Print function (for parent devices). */ 371 1.1 uch int 372 1.40 christos hpcfbprint(void *aux, const char *pnp) 373 1.1 uch { 374 1.1 uch if (pnp) 375 1.28 thorpej aprint_normal("hpcfb at %s", pnp); 376 1.1 uch 377 1.1 uch return (UNCONF); 378 1.1 uch } 379 1.1 uch 380 1.1 uch int 381 1.4 uch hpcfb_cnattach(struct hpcfb_fbconf *fbconf) 382 1.1 uch { 383 1.39 uwe #if NBIVIDEO > 0 384 1.39 uwe struct hpcfb_fbconf __fbconf; 385 1.39 uwe #endif 386 1.1 uch long defattr; 387 1.1 uch 388 1.10 takemura DPRINTF(("%s(%d): hpcfb_cnattach()\n", __FILE__, __LINE__)); 389 1.1 uch #if NBIVIDEO > 0 390 1.39 uwe if (fbconf == NULL) { 391 1.1 uch memset(&__fbconf, 0, sizeof(struct hpcfb_fbconf)); 392 1.1 uch if (bivideo_getcnfb(&__fbconf) != 0) 393 1.1 uch return (ENXIO); 394 1.1 uch fbconf = &__fbconf; 395 1.1 uch } 396 1.1 uch #endif /* NBIVIDEO > 0 */ 397 1.7 toshii memset(&hpcfb_console_dc, 0, sizeof(struct hpcfb_devconfig)); 398 1.1 uch if (hpcfb_init(fbconf, &hpcfb_console_dc) != 0) 399 1.1 uch return (ENXIO); 400 1.10 takemura hpcfb_console_dc.dc_state |= HPCFB_DC_CURRENT; 401 1.1 uch 402 1.1 uch hpcfb_console_dc.dc_tvram = hpcfb_console_tvram; 403 1.10 takemura /* clear screen */ 404 1.7 toshii memset(hpcfb_console_tvram, 0, sizeof(hpcfb_console_tvram)); 405 1.10 takemura hpcfb_redraw(&hpcfb_console_dc, 0, hpcfb_console_dc.dc_rows, 1); 406 1.1 uch 407 1.1 uch hpcfb_console_wsscreen = hpcfb_stdscreen; 408 1.1 uch hpcfb_console_wsscreen.nrows = hpcfb_console_dc.dc_rows; 409 1.1 uch hpcfb_console_wsscreen.ncols = hpcfb_console_dc.dc_cols; 410 1.1 uch hpcfb_console_wsscreen.capabilities = hpcfb_console_dc.dc_rinfo.ri_caps; 411 1.21 junyoung hpcfb_allocattr(&hpcfb_console_dc, 412 1.21 junyoung WSCOL_WHITE, WSCOL_BLACK, 0, &defattr); 413 1.62 rin #if NBIVIDEO > 0 414 1.62 rin /* 415 1.62 rin * This is early console. Do not really attach wsdisplay. 416 1.62 rin */ 417 1.62 rin if (fbconf == &__fbconf) 418 1.62 rin wsdisplay_preattach(&hpcfb_console_wsscreen, &hpcfb_console_dc, 419 1.62 rin 0, 0, defattr); 420 1.62 rin else 421 1.62 rin #endif 422 1.62 rin wsdisplay_cnattach(&hpcfb_console_wsscreen, &hpcfb_console_dc, 423 1.62 rin 0, 0, defattr); 424 1.1 uch hpcfbconsole = 1; 425 1.1 uch 426 1.1 uch return (0); 427 1.1 uch } 428 1.1 uch 429 1.1 uch int 430 1.4 uch hpcfb_init(struct hpcfb_fbconf *fbconf, struct hpcfb_devconfig *dc) 431 1.1 uch { 432 1.1 uch struct rasops_info *ri; 433 1.1 uch vaddr_t fbaddr; 434 1.1 uch 435 1.1 uch fbaddr = (vaddr_t)fbconf->hf_baseaddr; 436 1.1 uch dc->dc_fbaddr = (u_char *)fbaddr; 437 1.1 uch 438 1.1 uch /* init rasops */ 439 1.1 uch ri = &dc->dc_rinfo; 440 1.7 toshii memset(ri, 0, sizeof(struct rasops_info)); 441 1.1 uch ri->ri_depth = fbconf->hf_pixel_width; 442 1.41 christos ri->ri_bits = (void *)fbaddr; 443 1.1 uch ri->ri_width = fbconf->hf_width; 444 1.1 uch ri->ri_height = fbconf->hf_height; 445 1.1 uch ri->ri_stride = fbconf->hf_bytes_per_line; 446 1.1 uch #if 0 447 1.1 uch ri->ri_flg = RI_FORCEMONO | RI_CURSOR; 448 1.1 uch #else 449 1.1 uch ri->ri_flg = RI_CURSOR; 450 1.1 uch #endif 451 1.54 tsutsui if (dc == &hpcfb_console_dc) 452 1.54 tsutsui ri->ri_flg |= RI_NO_AUTO; 453 1.54 tsutsui 454 1.19 takemura switch (ri->ri_depth) { 455 1.19 takemura case 8: 456 1.19 takemura if (32 <= fbconf->hf_pack_width && 457 1.19 takemura (fbconf->hf_order_flags & HPCFB_REVORDER_BYTE) && 458 1.19 takemura (fbconf->hf_order_flags & HPCFB_REVORDER_WORD)) { 459 1.19 takemura ri->ri_flg |= RI_BSWAP; 460 1.19 takemura } 461 1.19 takemura break; 462 1.19 takemura default: 463 1.19 takemura if (fbconf->hf_order_flags & HPCFB_REVORDER_BYTE) { 464 1.11 takemura #if BYTE_ORDER == BIG_ENDIAN 465 1.19 takemura ri->ri_flg |= RI_BSWAP; 466 1.11 takemura #endif 467 1.19 takemura } else { 468 1.11 takemura #if BYTE_ORDER == LITTLE_ENDIAN 469 1.19 takemura ri->ri_flg |= RI_BSWAP; 470 1.11 takemura #endif 471 1.19 takemura } 472 1.19 takemura break; 473 1.5 uch } 474 1.5 uch 475 1.33 uwe if (fbconf->hf_class == HPCFB_CLASS_RGBCOLOR) { 476 1.33 uwe ri->ri_rnum = fbconf->hf_u.hf_rgb.hf_red_width; 477 1.33 uwe ri->ri_rpos = fbconf->hf_u.hf_rgb.hf_red_shift; 478 1.33 uwe ri->ri_gnum = fbconf->hf_u.hf_rgb.hf_green_width; 479 1.33 uwe ri->ri_gpos = fbconf->hf_u.hf_rgb.hf_green_shift; 480 1.33 uwe ri->ri_bnum = fbconf->hf_u.hf_rgb.hf_blue_width; 481 1.33 uwe ri->ri_bpos = fbconf->hf_u.hf_rgb.hf_blue_shift; 482 1.33 uwe } 483 1.33 uwe 484 1.1 uch if (rasops_init(ri, HPCFB_MAX_ROW, HPCFB_MAX_COLUMN)) { 485 1.60 ozaki aprint_error_dev(dc->dc_sc->sc_dev, "rasops_init() failed!"); 486 1.59 christos return -1; 487 1.1 uch } 488 1.1 uch 489 1.1 uch /* over write color map of rasops */ 490 1.1 uch hpcfb_cmap_reorder (fbconf, dc); 491 1.1 uch 492 1.1 uch dc->dc_curx = -1; 493 1.1 uch dc->dc_cury = -1; 494 1.1 uch dc->dc_rows = dc->dc_rinfo.ri_rows; 495 1.1 uch dc->dc_cols = dc->dc_rinfo.ri_cols; 496 1.1 uch #ifdef HPCFB_JUMP 497 1.1 uch dc->dc_max_row = 0; 498 1.1 uch dc->dc_min_row = dc->dc_rows; 499 1.1 uch dc->dc_scroll = 0; 500 1.42 ad callout_init(&dc->dc_scroll_ch, 0); 501 1.1 uch #endif /* HPCFB_JUMP */ 502 1.1 uch dc->dc_memsize = ri->ri_stride * ri->ri_height; 503 1.1 uch /* hook rasops in hpcfb_ops */ 504 1.1 uch rasops_emul = ri->ri_ops; /* struct copy */ 505 1.1 uch ri->ri_ops = hpcfb_emulops; /* struct copy */ 506 1.1 uch 507 1.1 uch return (0); 508 1.1 uch } 509 1.1 uch 510 1.1 uch static void 511 1.4 uch hpcfb_cmap_reorder(struct hpcfb_fbconf *fbconf, struct hpcfb_devconfig *dc) 512 1.1 uch { 513 1.1 uch struct rasops_info *ri = &dc->dc_rinfo; 514 1.1 uch int reverse = fbconf->hf_access_flags & HPCFB_ACCESS_REVERSE; 515 1.1 uch int *cmap = ri->ri_devcmap; 516 1.1 uch int i, j, bg, fg, tmp; 517 1.1 uch 518 1.1 uch /* 519 1.65 andvar * Set foreground and background so that the screen 520 1.1 uch * looks black on white. 521 1.1 uch * Normally, black = 00 and white = ff. 522 1.1 uch * HPCFB_ACCESS_REVERSE means black = ff and white = 00. 523 1.1 uch */ 524 1.1 uch switch (fbconf->hf_pixel_width) { 525 1.1 uch case 1: 526 1.1 uch /* FALLTHROUGH */ 527 1.1 uch case 2: 528 1.1 uch /* FALLTHROUGH */ 529 1.1 uch case 4: 530 1.1 uch if (reverse) { 531 1.1 uch bg = 0; 532 1.1 uch fg = ~0; 533 1.1 uch } else { 534 1.1 uch bg = ~0; 535 1.1 uch fg = 0; 536 1.1 uch } 537 1.1 uch /* for gray-scale LCD, hi-contrast color map */ 538 1.1 uch cmap[0] = bg; 539 1.1 uch for (i = 1; i < 16; i++) 540 1.1 uch cmap[i] = fg; 541 1.1 uch break; 542 1.1 uch case 8: 543 1.1 uch /* FALLTHROUGH */ 544 1.1 uch case 16: 545 1.1 uch if (reverse) { 546 1.1 uch for (i = 0, j = 15; i < 8; i++, j--) { 547 1.1 uch tmp = cmap[i]; 548 1.1 uch cmap[i] = cmap[j]; 549 1.1 uch cmap[j] = tmp; 550 1.1 uch } 551 1.1 uch } 552 1.1 uch break; 553 1.1 uch } 554 1.1 uch } 555 1.1 uch 556 1.1 uch int 557 1.41 christos hpcfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 558 1.36 jmmv struct lwp *l) 559 1.1 uch { 560 1.1 uch struct hpcfb_softc *sc = v; 561 1.1 uch struct hpcfb_devconfig *dc = sc->sc_dc; 562 1.1 uch struct wsdisplay_fbinfo *wdf; 563 1.1 uch 564 1.10 takemura DPRINTF(("hpcfb_ioctl(cmd=0x%lx)\n", cmd)); 565 1.1 uch switch (cmd) { 566 1.1 uch case WSDISPLAYIO_GTYPE: 567 1.1 uch *(u_int *)data = WSDISPLAY_TYPE_HPCFB; 568 1.4 uch return (0); 569 1.1 uch 570 1.1 uch case WSDISPLAYIO_GINFO: 571 1.1 uch wdf = (void *)data; 572 1.1 uch wdf->height = dc->dc_rinfo.ri_height; 573 1.1 uch wdf->width = dc->dc_rinfo.ri_width; 574 1.1 uch wdf->depth = dc->dc_rinfo.ri_depth; 575 1.1 uch wdf->cmsize = 256; /* XXXX */ 576 1.4 uch return (0); 577 1.31 perry 578 1.56 tsutsui case WSDISPLAYIO_LINEBYTES: 579 1.56 tsutsui *(u_int *)data = dc->dc_rinfo.ri_stride; 580 1.56 tsutsui return 0; 581 1.56 tsutsui 582 1.1 uch case WSDISPLAYIO_SMODE: 583 1.31 perry if (*(int *)data == WSDISPLAYIO_MODE_EMUL){ 584 1.1 uch if (sc->sc_mapping){ 585 1.1 uch sc->sc_mapping = 0; 586 1.1 uch if (dc->dc_state&HPCFB_DC_DRAWING) 587 1.1 uch dc->dc_state &= ~HPCFB_DC_ABORT; 588 1.1 uch #ifdef HPCFB_FORCE_REDRAW 589 1.1 uch hpcfb_refresh_screen(sc); 590 1.1 uch #else 591 1.1 uch dc->dc_state |= HPCFB_DC_UPDATEALL; 592 1.1 uch #endif 593 1.1 uch } 594 1.1 uch } else { 595 1.1 uch if (!sc->sc_mapping) { 596 1.1 uch sc->sc_mapping = 1; 597 1.1 uch dc->dc_state |= HPCFB_DC_ABORT; 598 1.1 uch } 599 1.1 uch sc->sc_mapping = 1; 600 1.1 uch } 601 1.1 uch if (sc && sc->sc_accessops->iodone) 602 1.1 uch (*sc->sc_accessops->iodone)(sc->sc_accessctx); 603 1.31 perry return (0); 604 1.1 uch 605 1.1 uch case WSDISPLAYIO_GETCMAP: 606 1.1 uch case WSDISPLAYIO_PUTCMAP: 607 1.22 takemura case WSDISPLAYIO_SVIDEO: 608 1.22 takemura case WSDISPLAYIO_GVIDEO: 609 1.1 uch case WSDISPLAYIO_GETPARAM: 610 1.1 uch case WSDISPLAYIO_SETPARAM: 611 1.1 uch case HPCFBIO_GCONF: 612 1.1 uch case HPCFBIO_SCONF: 613 1.1 uch case HPCFBIO_GDSPCONF: 614 1.1 uch case HPCFBIO_SDSPCONF: 615 1.1 uch case HPCFBIO_GOP: 616 1.1 uch case HPCFBIO_SOP: 617 1.4 uch return ((*sc->sc_accessops->ioctl)(sc->sc_accessctx, 618 1.34 christos cmd, data, flag, l)); 619 1.1 uch 620 1.1 uch default: 621 1.1 uch if (IOCGROUP(cmd) != 't') 622 1.1 uch DPRINTF(("%s(%d): hpcfb_ioctl(%lx, %lx) grp=%c num=%ld\n", 623 1.4 uch __FILE__, __LINE__, 624 1.4 uch cmd, (u_long)data, (char)IOCGROUP(cmd), cmd&0xff)); 625 1.1 uch break; 626 1.1 uch } 627 1.1 uch 628 1.18 atatat return (EPASSTHROUGH); /* Inappropriate ioctl for device */ 629 1.1 uch } 630 1.1 uch 631 1.1 uch paddr_t 632 1.40 christos hpcfb_mmap(void *v, void *vs, off_t offset, int prot) 633 1.1 uch { 634 1.1 uch struct hpcfb_softc *sc = v; 635 1.1 uch 636 1.4 uch return ((*sc->sc_accessops->mmap)(sc->sc_accessctx, offset, prot)); 637 1.1 uch } 638 1.1 uch 639 1.31 perry static void 640 1.4 uch hpcfb_power(int why, void *arg) 641 1.1 uch { 642 1.1 uch struct hpcfb_softc *sc = arg; 643 1.17 takemura 644 1.17 takemura if (sc->sc_dc == NULL) 645 1.17 takemura return; /* You have no screen yet. */ 646 1.1 uch 647 1.1 uch switch (why) { 648 1.1 uch case PWR_STANDBY: 649 1.1 uch break; 650 1.44 peter case PWR_SOFTSUSPEND: { 651 1.44 peter struct wsdisplay_softc *wsc = device_private(sc->sc_wsdisplay); 652 1.44 peter 653 1.44 peter sc->sc_screen_resumed = wsdisplay_getactivescreen(wsc); 654 1.44 peter 655 1.1 uch if (wsdisplay_switch(sc->sc_wsdisplay, 656 1.44 peter WSDISPLAY_NULLSCREEN, 1 /* waitok */) == 0) { 657 1.44 peter wsscreen_switchwait(wsc, WSDISPLAY_NULLSCREEN); 658 1.1 uch } else { 659 1.1 uch sc->sc_screen_resumed = WSDISPLAY_NULLSCREEN; 660 1.1 uch } 661 1.8 sato 662 1.8 sato sc->sc_dc->dc_state &= ~HPCFB_DC_CURRENT; 663 1.1 uch break; 664 1.44 peter } 665 1.1 uch case PWR_SOFTRESUME: 666 1.8 sato sc->sc_dc->dc_state |= HPCFB_DC_CURRENT; 667 1.1 uch if (sc->sc_screen_resumed != WSDISPLAY_NULLSCREEN) 668 1.1 uch wsdisplay_switch(sc->sc_wsdisplay, 669 1.44 peter sc->sc_screen_resumed, 1 /* waitok */); 670 1.1 uch break; 671 1.1 uch } 672 1.1 uch } 673 1.1 uch 674 1.50 uwe static bool 675 1.53 dyoung hpcfb_suspend(device_t self, const pmf_qual_t *qual) 676 1.50 uwe { 677 1.50 uwe struct hpcfb_softc *sc = device_private(self); 678 1.50 uwe 679 1.50 uwe hpcfb_power(PWR_SOFTSUSPEND, sc); 680 1.50 uwe return true; 681 1.50 uwe } 682 1.50 uwe 683 1.50 uwe static bool 684 1.53 dyoung hpcfb_resume(device_t self, const pmf_qual_t *qual) 685 1.50 uwe { 686 1.50 uwe struct hpcfb_softc *sc = device_private(self); 687 1.50 uwe 688 1.50 uwe hpcfb_power(PWR_SOFTRESUME, sc); 689 1.50 uwe return true; 690 1.50 uwe } 691 1.50 uwe 692 1.1 uch void 693 1.4 uch hpcfb_refresh_screen(struct hpcfb_softc *sc) 694 1.1 uch { 695 1.1 uch struct hpcfb_devconfig *dc = sc->sc_dc; 696 1.1 uch int x, y; 697 1.1 uch 698 1.66 andvar DPRINTF(("hpcfb_refresh_screen()\n")); 699 1.1 uch if (dc == NULL) 700 1.1 uch return; 701 1.1 uch 702 1.1 uch #ifdef HPCFB_JUMP 703 1.1 uch if (dc->dc_state&HPCFB_DC_SCROLLPENDING) { 704 1.1 uch dc->dc_state &= ~HPCFB_DC_SCROLLPENDING; 705 1.1 uch dc->dc_state &= ~HPCFB_DC_UPDATE; 706 1.1 uch callout_stop(&dc->dc_scroll_ch); 707 1.1 uch } 708 1.1 uch #endif /* HPCFB_JUMP */ 709 1.1 uch /* 710 1.1 uch * refresh screen 711 1.1 uch */ 712 1.1 uch dc->dc_state &= ~HPCFB_DC_UPDATEALL; 713 1.1 uch x = dc->dc_curx; 714 1.1 uch y = dc->dc_cury; 715 1.1 uch if (0 <= x && 0 <= y) 716 1.1 uch hpcfb_cursor_raw(dc, 0, y, x); /* disable cursor */ 717 1.1 uch /* redraw all text */ 718 1.1 uch hpcfb_redraw(dc, 0, dc->dc_rows, 1); 719 1.1 uch if (0 <= x && 0 <= y) 720 1.1 uch hpcfb_cursor_raw(dc, 1, y, x); /* enable cursor */ 721 1.1 uch } 722 1.1 uch 723 1.1 uch static int 724 1.40 christos hpcfb_alloc_screen(void *v, const struct wsscreen_descr *type, 725 1.39 uwe void **cookiep, int *curxp, int *curyp, long *attrp) 726 1.1 uch { 727 1.1 uch struct hpcfb_softc *sc = v; 728 1.1 uch struct hpcfb_devconfig *dc; 729 1.1 uch 730 1.1 uch DPRINTF(("%s(%d): hpcfb_alloc_screen()\n", __FILE__, __LINE__)); 731 1.1 uch 732 1.59 christos dc = malloc(sizeof(*dc), M_DEVBUF, M_WAITOK|M_ZERO); 733 1.10 takemura if (dc == NULL) 734 1.59 christos return ENOMEM; 735 1.1 uch 736 1.1 uch dc->dc_sc = sc; 737 1.59 christos if (hpcfb_init(&sc->sc_fbconflist[0], dc) != 0) { 738 1.59 christos free(dc, M_DEVBUF); 739 1.59 christos return EINVAL; 740 1.59 christos } 741 1.1 uch if (sc->sc_accessops->font) { 742 1.31 perry sc->sc_accessops->font(sc->sc_accessctx, 743 1.10 takemura dc->dc_rinfo.ri_font); 744 1.10 takemura } 745 1.10 takemura /* Set video chip dependent CLUT if any. */ 746 1.10 takemura if (sc->sc_accessops->setclut) 747 1.10 takemura sc->sc_accessops->setclut(sc->sc_accessctx, &dc->dc_rinfo); 748 1.10 takemura printf("hpcfb: %dx%d pixels, %d colors, %dx%d chars\n", 749 1.10 takemura dc->dc_rinfo.ri_width, dc->dc_rinfo.ri_height, 750 1.26 reinoud (1 << dc->dc_rinfo.ri_depth), 751 1.10 takemura dc->dc_rinfo.ri_cols, dc->dc_rinfo.ri_rows); 752 1.10 takemura 753 1.10 takemura /* 754 1.10 takemura * XXX, wsdisplay won't reffer the information in wsscreen_descr 755 1.10 takemura * structure until alloc_screen will be called, at least, under 756 1.10 takemura * current implementation... 757 1.10 takemura */ 758 1.10 takemura hpcfb_stdscreen.nrows = dc->dc_rows; 759 1.10 takemura hpcfb_stdscreen.ncols = dc->dc_cols; 760 1.10 takemura hpcfb_stdscreen.capabilities = dc->dc_rinfo.ri_caps; 761 1.1 uch 762 1.1 uch dc->dc_fbaddr = dc->dc_rinfo.ri_bits; 763 1.1 uch dc->dc_rows = dc->dc_rinfo.ri_rows; 764 1.1 uch dc->dc_cols = dc->dc_rinfo.ri_cols; 765 1.1 uch dc->dc_memsize = dc->dc_rinfo.ri_stride * dc->dc_rinfo.ri_height; 766 1.1 uch 767 1.1 uch dc->dc_curx = -1; 768 1.1 uch dc->dc_cury = -1; 769 1.10 takemura dc->dc_tvram = malloc(sizeof(struct hpcfb_tvrow)*dc->dc_rows, 770 1.16 tsutsui M_DEVBUF, M_WAITOK|M_ZERO); 771 1.1 uch if (dc->dc_tvram == NULL){ 772 1.10 takemura free(dc, M_DEVBUF); 773 1.10 takemura return (ENOMEM); 774 1.1 uch } 775 1.31 perry 776 1.1 uch *curxp = 0; 777 1.1 uch *curyp = 0; 778 1.31 perry *cookiep = dc; 779 1.21 junyoung hpcfb_allocattr(*cookiep, WSCOL_WHITE, WSCOL_BLACK, 0, attrp); 780 1.32 christos DPRINTF(("%s(%d): hpcfb_alloc_screen(): %p\n", 781 1.10 takemura __FILE__, __LINE__, dc)); 782 1.10 takemura 783 1.1 uch return (0); 784 1.1 uch } 785 1.1 uch 786 1.1 uch static void 787 1.40 christos hpcfb_free_screen(void *v, void *cookie) 788 1.1 uch { 789 1.10 takemura struct hpcfb_devconfig *dc = cookie; 790 1.1 uch 791 1.32 christos DPRINTF(("%s(%d): hpcfb_free_screen(%p)\n", 792 1.10 takemura __FILE__, __LINE__, cookie)); 793 1.10 takemura #ifdef DIAGNOSTIC 794 1.10 takemura if (dc == &hpcfb_console_dc) 795 1.1 uch panic("hpcfb_free_screen: console"); 796 1.10 takemura #endif 797 1.10 takemura free(dc->dc_tvram, M_DEVBUF); 798 1.10 takemura free(dc, M_DEVBUF); 799 1.1 uch } 800 1.1 uch 801 1.1 uch static int 802 1.40 christos hpcfb_show_screen(void *v, void *cookie, int waitok, 803 1.4 uch void (*cb)(void *, int, int), void *cbarg) 804 1.1 uch { 805 1.1 uch struct hpcfb_softc *sc = v; 806 1.1 uch struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 807 1.1 uch struct hpcfb_devconfig *odc; 808 1.1 uch 809 1.32 christos DPRINTF(("%s(%d): hpcfb_show_screen(%p)\n", 810 1.10 takemura __FILE__, __LINE__, dc)); 811 1.1 uch 812 1.1 uch odc = sc->sc_dc; 813 1.1 uch 814 1.1 uch if (dc == NULL || odc == dc) { 815 1.1 uch hpcfb_refresh_screen(sc); 816 1.4 uch return (0); 817 1.1 uch } 818 1.12 sato 819 1.13 toshii if (odc != NULL) { 820 1.13 toshii odc->dc_state |= HPCFB_DC_SWITCHREQ; 821 1.13 toshii 822 1.13 toshii if ((odc->dc_state&HPCFB_DC_DRAWING) != 0) { 823 1.13 toshii odc->dc_state |= HPCFB_DC_ABORT; 824 1.13 toshii } 825 1.12 sato } 826 1.1 uch 827 1.1 uch sc->sc_wantedscreen = cookie; 828 1.1 uch sc->sc_switchcb = cb; 829 1.1 uch sc->sc_switchcbarg = cbarg; 830 1.1 uch if (cb) { 831 1.1 uch callout_reset(&sc->sc_switch_callout, 0, 832 1.4 uch (void(*)(void *))hpcfb_doswitch, sc); 833 1.4 uch return (EAGAIN); 834 1.1 uch } 835 1.1 uch 836 1.1 uch hpcfb_doswitch(sc); 837 1.4 uch return (0); 838 1.1 uch } 839 1.1 uch 840 1.1 uch void 841 1.4 uch hpcfb_doswitch(struct hpcfb_softc *sc) 842 1.1 uch { 843 1.1 uch struct hpcfb_devconfig *dc; 844 1.1 uch struct hpcfb_devconfig *odc; 845 1.1 uch 846 1.10 takemura DPRINTF(("hpcfb_doswitch()\n")); 847 1.1 uch odc = sc->sc_dc; 848 1.1 uch dc = sc->sc_wantedscreen; 849 1.1 uch 850 1.1 uch if (!dc) { 851 1.1 uch (*sc->sc_switchcb)(sc->sc_switchcbarg, EIO, 0); 852 1.12 sato odc->dc_state &= ~HPCFB_DC_SWITCHREQ; 853 1.1 uch return; 854 1.1 uch } 855 1.1 uch 856 1.12 sato if (odc == dc) { 857 1.12 sato odc->dc_state &= ~HPCFB_DC_SWITCHREQ; 858 1.1 uch return; 859 1.12 sato } 860 1.1 uch 861 1.1 uch if (odc) { 862 1.1 uch #ifdef HPCFB_JUMP 863 1.1 uch odc->dc_state |= HPCFB_DC_ABORT; 864 1.1 uch #endif /* HPCFB_JUMP */ 865 1.1 uch 866 1.1 uch if (odc->dc_curx >= 0 && odc->dc_cury >= 0) 867 1.1 uch hpcfb_cursor_raw(odc, 0, odc->dc_cury, odc->dc_curx); 868 1.4 uch /* disable cursor */ 869 1.1 uch /* disable old screen */ 870 1.1 uch odc->dc_state &= ~HPCFB_DC_CURRENT; 871 1.10 takemura /* XXX, This is too dangerous. 872 1.1 uch odc->dc_rinfo.ri_bits = NULL; 873 1.10 takemura */ 874 1.1 uch } 875 1.1 uch /* switch screen to new one */ 876 1.1 uch dc->dc_state |= HPCFB_DC_CURRENT; 877 1.12 sato dc->dc_state &= ~HPCFB_DC_ABORT; 878 1.1 uch dc->dc_rinfo.ri_bits = dc->dc_fbaddr; 879 1.1 uch sc->sc_dc = dc; 880 1.1 uch 881 1.1 uch /* redraw screen image */ 882 1.1 uch hpcfb_refresh_screen(sc); 883 1.1 uch 884 1.1 uch sc->sc_wantedscreen = NULL; 885 1.1 uch if (sc->sc_switchcb) 886 1.1 uch (*sc->sc_switchcb)(sc->sc_switchcbarg, 0, 0); 887 1.1 uch 888 1.13 toshii if (odc != NULL) 889 1.13 toshii odc->dc_state &= ~HPCFB_DC_SWITCHREQ; 890 1.12 sato dc->dc_state &= ~HPCFB_DC_SWITCHREQ; 891 1.1 uch return; 892 1.1 uch } 893 1.1 uch 894 1.1 uch static void 895 1.4 uch hpcfb_pollc(void *v, int on) 896 1.1 uch { 897 1.1 uch struct hpcfb_softc *sc = v; 898 1.1 uch 899 1.1 uch if (sc == NULL) 900 1.1 uch return; 901 1.1 uch sc->sc_polling = on; 902 1.1 uch if (sc->sc_accessops->iodone) 903 1.1 uch (*sc->sc_accessops->iodone)(sc->sc_accessctx); 904 1.1 uch if (on) { 905 1.1 uch hpcfb_refresh_screen(sc); 906 1.1 uch if (sc->sc_accessops->iodone) 907 1.1 uch (*sc->sc_accessops->iodone)(sc->sc_accessctx); 908 1.1 uch } 909 1.1 uch 910 1.1 uch return; 911 1.1 uch } 912 1.1 uch 913 1.1 uch /* 914 1.1 uch * cursor 915 1.1 uch */ 916 1.1 uch void 917 1.4 uch hpcfb_cursor(void *cookie, int on, int row, int col) 918 1.1 uch { 919 1.1 uch struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 920 1.1 uch 921 1.1 uch if (on) { 922 1.1 uch dc->dc_curx = col; 923 1.1 uch dc->dc_cury = row; 924 1.1 uch } else { 925 1.1 uch dc->dc_curx = -1; 926 1.1 uch dc->dc_cury = -1; 927 1.1 uch } 928 1.1 uch 929 1.1 uch hpcfb_cursor_raw(cookie, on, row, col); 930 1.1 uch } 931 1.1 uch 932 1.1 uch void 933 1.48 dsl hpcfb_cursor_raw(void *cookie, int on, int row, int col) 934 1.1 uch { 935 1.1 uch struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 936 1.1 uch struct hpcfb_softc *sc = dc->dc_sc; 937 1.1 uch struct rasops_info *ri = &dc->dc_rinfo; 938 1.1 uch int curwidth, curheight; 939 1.1 uch int xoff, yoff; 940 1.1 uch 941 1.1 uch #ifdef HPCFB_JUMP 942 1.1 uch if (dc->dc_state&HPCFB_DC_SCROLLPENDING) { 943 1.1 uch dc->dc_state |= HPCFB_DC_UPDATE; 944 1.1 uch return; 945 1.1 uch } 946 1.1 uch #endif /* HPCFB_JUMP */ 947 1.12 sato if (!IS_DRAWABLE(dc)) { 948 1.1 uch return; 949 1.12 sato } 950 1.1 uch 951 1.1 uch if (ri->ri_bits == NULL) 952 1.1 uch return; 953 1.1 uch 954 1.1 uch dc->dc_state |= HPCFB_DC_DRAWING; 955 1.1 uch if (sc && sc->sc_accessops->cursor) { 956 1.1 uch xoff = col * ri->ri_font->fontwidth; 957 1.1 uch yoff = row * ri->ri_font->fontheight; 958 1.1 uch curheight = ri->ri_font->fontheight; 959 1.1 uch curwidth = ri->ri_font->fontwidth; 960 1.1 uch (*sc->sc_accessops->cursor)(sc->sc_accessctx, 961 1.4 uch on, xoff, yoff, curwidth, curheight); 962 1.31 perry } else 963 1.1 uch rasops_emul.cursor(ri, on, row, col); 964 1.1 uch dc->dc_state &= ~HPCFB_DC_DRAWING; 965 1.1 uch } 966 1.1 uch 967 1.1 uch /* 968 1.1 uch * mapchar 969 1.1 uch */ 970 1.1 uch int 971 1.4 uch hpcfb_mapchar(void *cookie, int c, unsigned int *cp) 972 1.1 uch { 973 1.1 uch struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 974 1.1 uch struct rasops_info *ri = &dc->dc_rinfo; 975 1.1 uch 976 1.4 uch return (rasops_emul.mapchar(ri, c, cp)); 977 1.1 uch } 978 1.1 uch 979 1.1 uch /* 980 1.1 uch * putchar 981 1.1 uch */ 982 1.1 uch void 983 1.4 uch hpcfb_tv_putchar(struct hpcfb_devconfig *dc, int row, int col, u_int uc, 984 1.4 uch long attr) 985 1.1 uch { 986 1.1 uch struct hpcfb_tvrow *vscn = dc->dc_tvram; 987 1.1 uch struct hpcfb_vchar *vc = &vscn[row].col[col]; 988 1.1 uch struct hpcfb_vchar *vcb; 989 1.1 uch 990 1.1 uch if (vscn == 0) 991 1.1 uch return; 992 1.1 uch 993 1.1 uch dc->dc_state |= HPCFB_DC_TDRAWING; 994 1.1 uch #ifdef HPCFB_JUMP 995 1.1 uch if (row < dc->dc_min_row) 996 1.1 uch dc->dc_min_row = row; 997 1.1 uch if (row > dc->dc_max_row) 998 1.1 uch dc->dc_max_row = row; 999 1.1 uch 1000 1.1 uch #endif /* HPCFB_JUMP */ 1001 1.1 uch if (vscn[row].maxcol +1 == col) 1002 1.1 uch vscn[row].maxcol = col; 1003 1.1 uch else if (vscn[row].maxcol < col) { 1004 1.1 uch vcb = &vscn[row].col[vscn[row].maxcol+1]; 1005 1.7 toshii memset(vcb, 0, 1006 1.7 toshii sizeof(struct hpcfb_vchar)*(col-vscn[row].maxcol-1)); 1007 1.1 uch vscn[row].maxcol = col; 1008 1.1 uch } 1009 1.1 uch vc->c = uc; 1010 1.1 uch vc->attr = attr; 1011 1.1 uch dc->dc_state &= ~HPCFB_DC_TDRAWING; 1012 1.1 uch #ifdef HPCFB_JUMP 1013 1.1 uch hpcfb_check_update(dc); 1014 1.1 uch #endif /* HPCFB_JUMP */ 1015 1.1 uch } 1016 1.1 uch 1017 1.1 uch void 1018 1.4 uch hpcfb_putchar(void *cookie, int row, int col, u_int uc, long attr) 1019 1.1 uch { 1020 1.1 uch struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 1021 1.1 uch struct hpcfb_softc *sc = dc->dc_sc; 1022 1.1 uch struct rasops_info *ri = &dc->dc_rinfo; 1023 1.1 uch int xoff; 1024 1.1 uch int yoff; 1025 1.1 uch int fclr, uclr; 1026 1.1 uch struct wsdisplay_font *font; 1027 1.1 uch 1028 1.1 uch hpcfb_tv_putchar(dc, row, col, uc, attr); 1029 1.1 uch #ifdef HPCFB_JUMP 1030 1.1 uch if (dc->dc_state&HPCFB_DC_SCROLLPENDING) { 1031 1.1 uch dc->dc_state |= HPCFB_DC_UPDATE; 1032 1.1 uch return; 1033 1.1 uch } 1034 1.1 uch #endif /* HPCFB_JUMP */ 1035 1.1 uch 1036 1.12 sato if (!IS_DRAWABLE(dc)) { 1037 1.1 uch return; 1038 1.12 sato } 1039 1.12 sato 1040 1.1 uch if (ri->ri_bits == NULL) 1041 1.1 uch return; 1042 1.1 uch 1043 1.1 uch dc->dc_state |= HPCFB_DC_DRAWING; 1044 1.31 perry if (sc && sc->sc_accessops->putchar 1045 1.4 uch && (dc->dc_state&HPCFB_DC_CURRENT)) { 1046 1.1 uch font = ri->ri_font; 1047 1.1 uch yoff = row * ri->ri_font->fontheight; 1048 1.1 uch xoff = col * ri->ri_font->fontwidth; 1049 1.1 uch fclr = ri->ri_devcmap[((u_int)attr >> 24) & 15]; 1050 1.1 uch uclr = ri->ri_devcmap[((u_int)attr >> 16) & 15]; 1051 1.1 uch 1052 1.1 uch (*sc->sc_accessops->putchar)(sc->sc_accessctx, 1053 1.4 uch xoff, yoff, font, fclr, uclr, uc, attr); 1054 1.1 uch } else 1055 1.1 uch rasops_emul.putchar(ri, row, col, uc, attr); 1056 1.1 uch dc->dc_state &= ~HPCFB_DC_DRAWING; 1057 1.1 uch #ifdef HPCFB_JUMP 1058 1.1 uch hpcfb_check_update(dc); 1059 1.1 uch #endif /* HPCFB_JUMP */ 1060 1.1 uch } 1061 1.1 uch 1062 1.1 uch /* 1063 1.1 uch * copycols 1064 1.1 uch */ 1065 1.1 uch void 1066 1.4 uch hpcfb_tv_copycols(struct hpcfb_devconfig *dc, int row, int srccol, int dstcol, 1067 1.4 uch int ncols) 1068 1.1 uch { 1069 1.1 uch struct hpcfb_tvrow *vscn = dc->dc_tvram; 1070 1.1 uch struct hpcfb_vchar *svc = &vscn[row].col[srccol]; 1071 1.1 uch struct hpcfb_vchar *dvc = &vscn[row].col[dstcol]; 1072 1.1 uch 1073 1.1 uch if (vscn == 0) 1074 1.1 uch return; 1075 1.1 uch 1076 1.1 uch dc->dc_state |= HPCFB_DC_TDRAWING; 1077 1.1 uch #ifdef HPCFB_JUMP 1078 1.1 uch if (row < dc->dc_min_row) 1079 1.1 uch dc->dc_min_row = row; 1080 1.1 uch if (row > dc->dc_max_row) 1081 1.1 uch dc->dc_max_row = row; 1082 1.1 uch #endif /* HPCFB_JUMP */ 1083 1.1 uch 1084 1.7 toshii memcpy(dvc, svc, ncols*sizeof(struct hpcfb_vchar)); 1085 1.1 uch if (vscn[row].maxcol < srccol+ncols-1) 1086 1.1 uch vscn[row].maxcol = srccol+ncols-1; 1087 1.1 uch if (vscn[row].maxcol < dstcol+ncols-1) 1088 1.1 uch vscn[row].maxcol = dstcol+ncols-1; 1089 1.1 uch dc->dc_state &= ~HPCFB_DC_TDRAWING; 1090 1.1 uch #ifdef HPCFB_JUMP 1091 1.1 uch hpcfb_check_update(dc); 1092 1.1 uch #endif /* HPCFB_JUMP */ 1093 1.1 uch } 1094 1.1 uch 1095 1.1 uch void 1096 1.4 uch hpcfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1097 1.1 uch { 1098 1.1 uch struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 1099 1.1 uch struct hpcfb_softc *sc = dc->dc_sc; 1100 1.1 uch struct rasops_info *ri = &dc->dc_rinfo; 1101 1.1 uch int srcxoff,dstxoff; 1102 1.1 uch int srcyoff,dstyoff; 1103 1.1 uch int height, width; 1104 1.1 uch 1105 1.1 uch hpcfb_tv_copycols(dc, row, srccol, dstcol, ncols); 1106 1.1 uch #ifdef HPCFB_JUMP 1107 1.1 uch if (dc->dc_state&HPCFB_DC_SCROLLPENDING) { 1108 1.1 uch dc->dc_state |= HPCFB_DC_UPDATE; 1109 1.1 uch return; 1110 1.1 uch } 1111 1.1 uch #endif /* HPCFB_JUMP */ 1112 1.12 sato if (!IS_DRAWABLE(dc)) { 1113 1.1 uch return; 1114 1.12 sato } 1115 1.12 sato 1116 1.1 uch if (ri->ri_bits == NULL) 1117 1.1 uch return; 1118 1.1 uch 1119 1.1 uch dc->dc_state |= HPCFB_DC_DRAWING; 1120 1.1 uch if (sc && sc->sc_accessops->bitblit 1121 1.4 uch && (dc->dc_state&HPCFB_DC_CURRENT)) { 1122 1.1 uch srcxoff = srccol * ri->ri_font->fontwidth; 1123 1.1 uch srcyoff = row * ri->ri_font->fontheight; 1124 1.1 uch dstxoff = dstcol * ri->ri_font->fontwidth; 1125 1.1 uch dstyoff = row * ri->ri_font->fontheight; 1126 1.1 uch width = ncols * ri->ri_font->fontwidth; 1127 1.1 uch height = ri->ri_font->fontheight; 1128 1.1 uch (*sc->sc_accessops->bitblit)(sc->sc_accessctx, 1129 1.4 uch srcxoff, srcyoff, dstxoff, dstyoff, height, width); 1130 1.1 uch } else 1131 1.1 uch rasops_emul.copycols(ri, row, srccol, dstcol, ncols); 1132 1.1 uch dc->dc_state &= ~HPCFB_DC_DRAWING; 1133 1.1 uch #ifdef HPCFB_JUMP 1134 1.1 uch hpcfb_check_update(dc); 1135 1.1 uch #endif /* HPCFB_JUMP */ 1136 1.1 uch } 1137 1.1 uch 1138 1.1 uch 1139 1.1 uch /* 1140 1.1 uch * erasecols 1141 1.1 uch */ 1142 1.1 uch void 1143 1.39 uwe hpcfb_tv_erasecols(struct hpcfb_devconfig *dc, 1144 1.40 christos int row, int startcol, int ncols, long attr) 1145 1.1 uch { 1146 1.1 uch struct hpcfb_tvrow *vscn = dc->dc_tvram; 1147 1.1 uch 1148 1.1 uch if (vscn == 0) 1149 1.1 uch return; 1150 1.1 uch 1151 1.1 uch dc->dc_state |= HPCFB_DC_TDRAWING; 1152 1.1 uch #ifdef HPCFB_JUMP 1153 1.1 uch if (row < dc->dc_min_row) 1154 1.1 uch dc->dc_min_row = row; 1155 1.1 uch if (row > dc->dc_max_row) 1156 1.1 uch dc->dc_max_row = row; 1157 1.1 uch #endif /* HPCFB_JUMP */ 1158 1.1 uch 1159 1.1 uch vscn[row].maxcol = startcol-1; 1160 1.1 uch if (vscn[row].spacecol < startcol+ncols-1) 1161 1.1 uch vscn[row].spacecol = startcol+ncols-1; 1162 1.1 uch dc->dc_state &= ~HPCFB_DC_TDRAWING; 1163 1.1 uch #ifdef HPCFB_JUMP 1164 1.1 uch hpcfb_check_update(dc); 1165 1.1 uch #endif /* HPCFB_JUMP */ 1166 1.1 uch } 1167 1.1 uch 1168 1.1 uch void 1169 1.4 uch hpcfb_erasecols(void *cookie, int row, int startcol, int ncols, long attr) 1170 1.1 uch { 1171 1.1 uch struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 1172 1.1 uch struct hpcfb_softc *sc = dc->dc_sc; 1173 1.1 uch struct rasops_info *ri = &dc->dc_rinfo; 1174 1.1 uch int xoff, yoff; 1175 1.1 uch int width, height; 1176 1.1 uch 1177 1.1 uch hpcfb_tv_erasecols(dc, row, startcol, ncols, attr); 1178 1.1 uch #ifdef HPCFB_JUMP 1179 1.1 uch if (dc->dc_state&HPCFB_DC_SCROLLPENDING) { 1180 1.1 uch dc->dc_state |= HPCFB_DC_UPDATE; 1181 1.1 uch return; 1182 1.1 uch } 1183 1.1 uch #endif /* HPCFB_JUMP */ 1184 1.12 sato if (!IS_DRAWABLE(dc)) { 1185 1.1 uch return; 1186 1.12 sato } 1187 1.12 sato 1188 1.1 uch if (ri->ri_bits == NULL) 1189 1.1 uch return; 1190 1.1 uch 1191 1.1 uch dc->dc_state |= HPCFB_DC_DRAWING; 1192 1.1 uch if (sc && sc->sc_accessops->erase 1193 1.4 uch && (dc->dc_state&HPCFB_DC_CURRENT)) { 1194 1.1 uch xoff = startcol * ri->ri_font->fontwidth; 1195 1.1 uch yoff = row * ri->ri_font->fontheight; 1196 1.1 uch width = ncols * ri->ri_font->fontwidth; 1197 1.1 uch height = ri->ri_font->fontheight; 1198 1.1 uch (*sc->sc_accessops->erase)(sc->sc_accessctx, 1199 1.4 uch xoff, yoff, height, width, attr); 1200 1.31 perry } else 1201 1.1 uch rasops_emul.erasecols(ri, row, startcol, ncols, attr); 1202 1.1 uch dc->dc_state &= ~HPCFB_DC_DRAWING; 1203 1.1 uch #ifdef HPCFB_JUMP 1204 1.1 uch hpcfb_check_update(dc); 1205 1.1 uch #endif /* HPCFB_JUMP */ 1206 1.1 uch } 1207 1.1 uch 1208 1.1 uch /* 1209 1.1 uch * Copy rows. 1210 1.1 uch */ 1211 1.1 uch void 1212 1.4 uch hpcfb_tv_copyrows(struct hpcfb_devconfig *dc, int src, int dst, int num) 1213 1.1 uch { 1214 1.1 uch struct hpcfb_tvrow *vscn = dc->dc_tvram; 1215 1.1 uch struct hpcfb_tvrow *svc = &vscn[src]; 1216 1.1 uch struct hpcfb_tvrow *dvc = &vscn[dst]; 1217 1.1 uch int i; 1218 1.1 uch int d; 1219 1.1 uch 1220 1.1 uch if (vscn == 0) 1221 1.1 uch return; 1222 1.1 uch 1223 1.1 uch dc->dc_state |= HPCFB_DC_TDRAWING; 1224 1.1 uch #ifdef HPCFB_JUMP 1225 1.1 uch if (dst < dc->dc_min_row) 1226 1.1 uch dc->dc_min_row = dst; 1227 1.1 uch if (dst + num > dc->dc_max_row) 1228 1.1 uch dc->dc_max_row = dst + num -1; 1229 1.1 uch #endif /* HPCFB_JUMP */ 1230 1.1 uch 1231 1.1 uch if (svc > dvc) 1232 1.1 uch d = 1; 1233 1.1 uch else if (svc < dvc) { 1234 1.1 uch svc += num-1; 1235 1.1 uch dvc += num-1; 1236 1.1 uch d = -1; 1237 1.1 uch } else { 1238 1.1 uch dc->dc_state &= ~HPCFB_DC_TDRAWING; 1239 1.1 uch #ifdef HPCFB_JUMP 1240 1.1 uch hpcfb_check_update(dc); 1241 1.1 uch #endif /* HPCFB_JUMP */ 1242 1.31 perry return; 1243 1.1 uch } 1244 1.1 uch 1245 1.1 uch for (i = 0; i < num; i++) { 1246 1.7 toshii memcpy(&dvc->col[0], &svc->col[0], sizeof(struct hpcfb_vchar)*(svc->maxcol+1)); 1247 1.1 uch if (svc->maxcol < dvc->maxcol && dvc->spacecol < dvc->maxcol) 1248 1.1 uch dvc->spacecol = dvc->maxcol; 1249 1.1 uch dvc->maxcol = svc->maxcol; 1250 1.1 uch svc+=d; 1251 1.1 uch dvc+=d; 1252 1.1 uch } 1253 1.1 uch dc->dc_state &= ~HPCFB_DC_TDRAWING; 1254 1.1 uch #ifdef HPCFB_JUMP 1255 1.1 uch hpcfb_check_update(dc); 1256 1.1 uch #endif /* HPCFB_JUMP */ 1257 1.1 uch } 1258 1.1 uch 1259 1.1 uch void 1260 1.48 dsl hpcfb_redraw(void *cookie, int row, int num, int all) 1261 1.1 uch { 1262 1.1 uch struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 1263 1.1 uch struct rasops_info *ri = &dc->dc_rinfo; 1264 1.1 uch int cols; 1265 1.1 uch struct hpcfb_tvrow *vscn = dc->dc_tvram; 1266 1.1 uch struct hpcfb_vchar *svc; 1267 1.1 uch int i, j; 1268 1.1 uch 1269 1.1 uch #ifdef HPCFB_JUMP 1270 1.1 uch if (dc->dc_state&HPCFB_DC_SCROLLPENDING) { 1271 1.1 uch dc->dc_state |= HPCFB_DC_UPDATE; 1272 1.1 uch return; 1273 1.1 uch } 1274 1.1 uch #endif /* HPCFB_JUMP */ 1275 1.1 uch if (dc->dc_sc != NULL 1276 1.1 uch && !dc->dc_sc->sc_polling 1277 1.1 uch && dc->dc_sc->sc_mapping) 1278 1.1 uch return; 1279 1.1 uch 1280 1.1 uch dc->dc_state &= ~HPCFB_DC_ABORT; 1281 1.1 uch 1282 1.12 sato if (vscn == 0) 1283 1.1 uch return; 1284 1.12 sato 1285 1.12 sato if (!IS_DRAWABLE(dc)) { 1286 1.1 uch return; 1287 1.12 sato } 1288 1.1 uch 1289 1.1 uch if (ri->ri_bits == NULL) 1290 1.1 uch return; 1291 1.1 uch 1292 1.1 uch dc->dc_state |= HPCFB_DC_DRAWING; 1293 1.1 uch dc->dc_state |= HPCFB_DC_TDRAWING; 1294 1.1 uch for (i = 0; i < num; i++) { 1295 1.1 uch if (dc->dc_state&HPCFB_DC_ABORT) 1296 1.1 uch break; 1297 1.12 sato if ((dc->dc_state&HPCFB_DC_CURRENT) == 0) 1298 1.12 sato break; 1299 1.1 uch cols = vscn[row+i].maxcol; 1300 1.1 uch for (j = 0; j <= cols; j++) { 1301 1.1 uch if (dc->dc_state&HPCFB_DC_ABORT) 1302 1.1 uch continue; 1303 1.12 sato if ((dc->dc_state&HPCFB_DC_CURRENT) == 0) 1304 1.12 sato continue; 1305 1.1 uch svc = &vscn[row+i].col[j]; 1306 1.1 uch rasops_emul.putchar(ri, row + i, j, svc->c, svc->attr); 1307 1.1 uch } 1308 1.1 uch if (all) 1309 1.1 uch cols = dc->dc_cols-1; 1310 1.1 uch else 1311 1.1 uch cols = vscn[row+i].spacecol; 1312 1.1 uch for (; j <= cols; j++) { 1313 1.1 uch if (dc->dc_state&HPCFB_DC_ABORT) 1314 1.1 uch continue; 1315 1.12 sato if ((dc->dc_state&HPCFB_DC_CURRENT) == 0) 1316 1.12 sato continue; 1317 1.1 uch rasops_emul.putchar(ri, row + i, j, ' ', 0); 1318 1.1 uch } 1319 1.1 uch vscn[row+i].spacecol = 0; 1320 1.1 uch } 1321 1.1 uch if (dc->dc_state&HPCFB_DC_ABORT) 1322 1.1 uch dc->dc_state &= ~HPCFB_DC_ABORT; 1323 1.1 uch dc->dc_state &= ~HPCFB_DC_DRAWING; 1324 1.1 uch dc->dc_state &= ~HPCFB_DC_TDRAWING; 1325 1.1 uch #ifdef HPCFB_JUMP 1326 1.1 uch hpcfb_check_update(dc); 1327 1.1 uch #endif /* HPCFB_JUMP */ 1328 1.1 uch } 1329 1.1 uch 1330 1.1 uch #ifdef HPCFB_JUMP 1331 1.1 uch void 1332 1.4 uch hpcfb_update(void *v) 1333 1.1 uch { 1334 1.1 uch struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)v; 1335 1.1 uch 1336 1.1 uch /* callout_stop(&dc->dc_scroll_ch); */ 1337 1.1 uch dc->dc_state &= ~HPCFB_DC_SCROLLPENDING; 1338 1.1 uch if (dc->dc_curx > 0 && dc->dc_cury > 0) 1339 1.31 perry hpcfb_cursor_raw(dc, 0, dc->dc_cury, dc->dc_curx); 1340 1.1 uch if ((dc->dc_state&HPCFB_DC_UPDATEALL)) { 1341 1.1 uch hpcfb_redraw(dc, 0, dc->dc_rows, 1); 1342 1.1 uch dc->dc_state &= ~(HPCFB_DC_UPDATE|HPCFB_DC_UPDATEALL); 1343 1.1 uch } else if ((dc->dc_state&HPCFB_DC_UPDATE)) { 1344 1.31 perry hpcfb_redraw(dc, dc->dc_min_row, 1345 1.4 uch dc->dc_max_row - dc->dc_min_row, 0); 1346 1.1 uch dc->dc_state &= ~HPCFB_DC_UPDATE; 1347 1.1 uch } else { 1348 1.1 uch hpcfb_redraw(dc, dc->dc_scroll_dst, dc->dc_scroll_num, 0); 1349 1.1 uch } 1350 1.1 uch if (dc->dc_curx > 0 && dc->dc_cury > 0) 1351 1.31 perry hpcfb_cursor_raw(dc, 1, dc->dc_cury, dc->dc_curx); 1352 1.1 uch } 1353 1.1 uch 1354 1.1 uch void 1355 1.4 uch hpcfb_do_scroll(void *v) 1356 1.1 uch { 1357 1.1 uch struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)v; 1358 1.1 uch 1359 1.31 perry dc->dc_state |= HPCFB_DC_SCRTHREAD; 1360 1.1 uch if (dc->dc_state&(HPCFB_DC_DRAWING|HPCFB_DC_TDRAWING)) 1361 1.1 uch dc->dc_state |= HPCFB_DC_SCRDELAY; 1362 1.1 uch else if (dc->dc_sc != NULL && dc->dc_sc->sc_thread) 1363 1.1 uch wakeup(dc->dc_sc); 1364 1.1 uch else if (dc->dc_sc != NULL && !dc->dc_sc->sc_mapping) { 1365 1.1 uch /* draw only EMUL mode */ 1366 1.1 uch hpcfb_update(v); 1367 1.1 uch } 1368 1.31 perry dc->dc_state &= ~HPCFB_DC_SCRTHREAD; 1369 1.1 uch } 1370 1.1 uch 1371 1.1 uch void 1372 1.4 uch hpcfb_check_update(void *v) 1373 1.1 uch { 1374 1.1 uch struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)v; 1375 1.1 uch 1376 1.31 perry if (dc->dc_sc != NULL 1377 1.31 perry && dc->dc_sc->sc_polling 1378 1.4 uch && (dc->dc_state&HPCFB_DC_SCROLLPENDING)){ 1379 1.1 uch callout_stop(&dc->dc_scroll_ch); 1380 1.1 uch dc->dc_state &= ~HPCFB_DC_SCRDELAY; 1381 1.1 uch hpcfb_update(v); 1382 1.1 uch } 1383 1.1 uch else if (dc->dc_state&HPCFB_DC_SCRDELAY){ 1384 1.1 uch dc->dc_state &= ~HPCFB_DC_SCRDELAY; 1385 1.1 uch hpcfb_update(v); 1386 1.1 uch } else if (dc->dc_state&HPCFB_DC_UPDATEALL){ 1387 1.1 uch dc->dc_state &= ~HPCFB_DC_UPDATEALL; 1388 1.1 uch hpcfb_update(v); 1389 1.1 uch } 1390 1.1 uch } 1391 1.1 uch #endif /* HPCFB_JUMP */ 1392 1.1 uch 1393 1.1 uch void 1394 1.4 uch hpcfb_copyrows(void *cookie, int src, int dst, int num) 1395 1.1 uch { 1396 1.1 uch struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 1397 1.1 uch struct rasops_info *ri = &dc->dc_rinfo; 1398 1.1 uch struct hpcfb_softc *sc = dc->dc_sc; 1399 1.1 uch int srcyoff, dstyoff; 1400 1.1 uch int width, height; 1401 1.1 uch 1402 1.1 uch hpcfb_tv_copyrows(cookie, src, dst, num); 1403 1.1 uch 1404 1.12 sato if (!IS_DRAWABLE(dc)) { 1405 1.1 uch return; 1406 1.12 sato } 1407 1.12 sato 1408 1.1 uch if (ri->ri_bits == NULL) 1409 1.1 uch return; 1410 1.1 uch 1411 1.1 uch if (sc && sc->sc_accessops->bitblit 1412 1.4 uch && (dc->dc_state&HPCFB_DC_CURRENT)) { 1413 1.1 uch dc->dc_state |= HPCFB_DC_DRAWING; 1414 1.1 uch srcyoff = src * ri->ri_font->fontheight; 1415 1.1 uch dstyoff = dst * ri->ri_font->fontheight; 1416 1.1 uch width = dc->dc_cols * ri->ri_font->fontwidth; 1417 1.1 uch height = num * ri->ri_font->fontheight; 1418 1.1 uch (*sc->sc_accessops->bitblit)(sc->sc_accessctx, 1419 1.4 uch 0, srcyoff, 0, dstyoff, height, width); 1420 1.1 uch dc->dc_state &= ~HPCFB_DC_DRAWING; 1421 1.1 uch } 1422 1.1 uch else { 1423 1.1 uch #ifdef HPCFB_JUMP 1424 1.1 uch if (sc && sc->sc_polling) { 1425 1.1 uch hpcfb_check_update(dc); 1426 1.1 uch } else if ((dc->dc_state&HPCFB_DC_SCROLLPENDING) == 0) { 1427 1.1 uch dc->dc_state |= HPCFB_DC_SCROLLPENDING; 1428 1.1 uch dc->dc_scroll = 1; 1429 1.1 uch dc->dc_scroll_src = src; 1430 1.1 uch dc->dc_scroll_dst = dst; 1431 1.1 uch dc->dc_scroll_num = num; 1432 1.1 uch callout_reset(&dc->dc_scroll_ch, hz/100, &hpcfb_do_scroll, dc); 1433 1.1 uch return; 1434 1.1 uch } else if (dc->dc_scroll++ < dc->dc_rows/HPCFB_MAX_JUMP) { 1435 1.1 uch dc->dc_state |= HPCFB_DC_UPDATE; 1436 1.1 uch return; 1437 1.1 uch } else { 1438 1.1 uch dc->dc_state &= ~HPCFB_DC_SCROLLPENDING; 1439 1.1 uch callout_stop(&dc->dc_scroll_ch); 1440 1.1 uch } 1441 1.1 uch if (dc->dc_state&HPCFB_DC_UPDATE) { 1442 1.1 uch dc->dc_state &= ~HPCFB_DC_UPDATE; 1443 1.31 perry hpcfb_redraw(cookie, dc->dc_min_row, 1444 1.4 uch dc->dc_max_row - dc->dc_min_row, 0); 1445 1.1 uch dc->dc_max_row = 0; 1446 1.1 uch dc->dc_min_row = dc->dc_rows; 1447 1.1 uch if (dc->dc_curx > 0 && dc->dc_cury > 0) 1448 1.31 perry hpcfb_cursor(dc, 1, dc->dc_cury, dc->dc_curx); 1449 1.1 uch return; 1450 1.1 uch } 1451 1.1 uch #endif /* HPCFB_JUMP */ 1452 1.1 uch hpcfb_redraw(cookie, dst, num, 0); 1453 1.1 uch } 1454 1.1 uch #ifdef HPCFB_JUMP 1455 1.1 uch hpcfb_check_update(dc); 1456 1.1 uch #endif /* HPCFB_JUMP */ 1457 1.1 uch } 1458 1.1 uch 1459 1.1 uch /* 1460 1.1 uch * eraserows 1461 1.1 uch */ 1462 1.1 uch void 1463 1.39 uwe hpcfb_tv_eraserows(struct hpcfb_devconfig *dc, 1464 1.40 christos int row, int nrow, long attr) 1465 1.1 uch { 1466 1.1 uch struct hpcfb_tvrow *vscn = dc->dc_tvram; 1467 1.1 uch int cols; 1468 1.1 uch int i; 1469 1.1 uch 1470 1.1 uch if (vscn == 0) 1471 1.1 uch return; 1472 1.1 uch 1473 1.1 uch dc->dc_state |= HPCFB_DC_TDRAWING; 1474 1.1 uch dc->dc_state &= ~HPCFB_DC_TDRAWING; 1475 1.1 uch #ifdef HPCFB_JUMP 1476 1.1 uch if (row < dc->dc_min_row) 1477 1.1 uch dc->dc_min_row = row; 1478 1.1 uch if (row + nrow > dc->dc_max_row) 1479 1.1 uch dc->dc_max_row = row + nrow; 1480 1.1 uch #endif /* HPCFB_JUMP */ 1481 1.1 uch 1482 1.1 uch for (i = 0; i < nrow; i++) { 1483 1.1 uch cols = vscn[row+i].maxcol; 1484 1.1 uch if (vscn[row+i].spacecol < cols) 1485 1.1 uch vscn[row+i].spacecol = cols; 1486 1.1 uch vscn[row+i].maxcol = -1; 1487 1.1 uch } 1488 1.1 uch #ifdef HPCFB_JUMP 1489 1.1 uch hpcfb_check_update(dc); 1490 1.1 uch #endif /* HPCFB_JUMP */ 1491 1.1 uch } 1492 1.1 uch 1493 1.1 uch void 1494 1.4 uch hpcfb_eraserows(void *cookie, int row, int nrow, long attr) 1495 1.1 uch { 1496 1.1 uch struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 1497 1.1 uch struct hpcfb_softc *sc = dc->dc_sc; 1498 1.1 uch struct rasops_info *ri = &dc->dc_rinfo; 1499 1.1 uch int yoff; 1500 1.1 uch int width; 1501 1.1 uch int height; 1502 1.1 uch 1503 1.1 uch hpcfb_tv_eraserows(dc, row, nrow, attr); 1504 1.1 uch #ifdef HPCFB_JUMP 1505 1.1 uch if (dc->dc_state&HPCFB_DC_SCROLLPENDING) { 1506 1.1 uch dc->dc_state |= HPCFB_DC_UPDATE; 1507 1.1 uch return; 1508 1.1 uch } 1509 1.1 uch #endif /* HPCFB_JUMP */ 1510 1.12 sato if (!IS_DRAWABLE(dc)) { 1511 1.1 uch return; 1512 1.12 sato } 1513 1.12 sato 1514 1.1 uch if (ri->ri_bits == NULL) 1515 1.1 uch return; 1516 1.1 uch 1517 1.1 uch dc->dc_state |= HPCFB_DC_DRAWING; 1518 1.1 uch if (sc && sc->sc_accessops->erase 1519 1.4 uch && (dc->dc_state&HPCFB_DC_CURRENT)) { 1520 1.1 uch yoff = row * ri->ri_font->fontheight; 1521 1.1 uch width = dc->dc_cols * ri->ri_font->fontwidth; 1522 1.1 uch height = nrow * ri->ri_font->fontheight; 1523 1.1 uch (*sc->sc_accessops->erase)(sc->sc_accessctx, 1524 1.4 uch 0, yoff, height, width, attr); 1525 1.31 perry } else 1526 1.1 uch rasops_emul.eraserows(ri, row, nrow, attr); 1527 1.1 uch dc->dc_state &= ~HPCFB_DC_DRAWING; 1528 1.1 uch #ifdef HPCFB_JUMP 1529 1.1 uch hpcfb_check_update(dc); 1530 1.1 uch #endif /* HPCFB_JUMP */ 1531 1.1 uch } 1532 1.1 uch 1533 1.1 uch /* 1534 1.21 junyoung * allocattr 1535 1.1 uch */ 1536 1.1 uch int 1537 1.21 junyoung hpcfb_allocattr(void *cookie, int fg, int bg, int flags, long *attrp) 1538 1.1 uch { 1539 1.1 uch struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 1540 1.1 uch struct rasops_info *ri = &dc->dc_rinfo; 1541 1.1 uch 1542 1.21 junyoung return (rasops_emul.allocattr(ri, fg, bg, flags, attrp)); 1543 1.1 uch } 1544