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