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