1 /* $NetBSD: vidcvideo.c,v 1.37 2009/03/18 16:00:09 cegger Exp $ */
4 * Copyright (c) 2001 Reinoud Zandijk
5 * Copyright (c) 1998, 1999 Tohru Nishimura. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * Created vidcvideo.c from /dev/tc/cfb.c to fit the Acorn/ARM VIDC1 and VIDC20 chips
31 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
33 __KERNEL_RCSID(0, "$NetBSD: vidcvideo.c,v 1.37 2009/03/18 16:00:09 cegger Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/device.h>
39 #include <sys/malloc.h>
41 #include <sys/ioctl.h>
43 #include <arm/mainbus/mainbus.h>
44 #include <machine/bus.h>
45 #include <machine/intr.h>
47 #include <dev/wscons/wsconsio.h>
48 #include <dev/wscons/wsdisplayvar.h>
50 #include <dev/rasops/rasops.h>
51 #include <dev/wsfont/wsfont.h>
53 #include <dev/wscons/wsdisplay_vconsvar.h>
55 #include <uvm/uvm_extern.h>
56 #include <arm/arm32/pmap.h>
57 #include <arm/cpufunc.h>
59 /* for vidc_mode ... needs to be MI indepenent one day */
60 #include <arm/iomd/vidc.h>
61 #include <arm/iomd/vidc20config.h>
62 #include <arm/iomd/vidcvideo.h>
63 #include <machine/bootconfig.h>
66 extern videomemory_t videomemory
;
69 #define CMAP_SIZE 256 /* 256 R/G/B entries */
76 /* XXX for CURSOR_MAX_WIDTH = 32 */
78 struct wsdisplay_curpos cc_pos
;
79 struct wsdisplay_curpos cc_hot
;
80 struct wsdisplay_curpos cc_size
;
81 uint8_t cc_color
[6]; /* how many? */
82 uint32_t cc_image
[(CURSOR_MAX_WIDTH
/4) * CURSOR_MAX_HEIGHT
];
83 uint32_t cc_mask
[(CURSOR_MAX_WIDTH
/4) * CURSOR_MAX_HEIGHT
];
88 vaddr_t dc_vaddr
; /* memory space virtual base address */
89 paddr_t dc_paddr
; /* memory space physical base address */
90 vsize_t dc_size
; /* size of slot memory */
91 int dc_width
; /* width of frame buffer */
92 int dc_height
; /* height of frame buffer */
93 int dc_log2_depth
; /* log2 of bits per pixel */
94 int dc_depth
; /* depth, bits per pixel */
95 int dc_rowbytes
; /* bytes in a FB scan line */
96 vaddr_t dc_videobase
; /* base of flat frame buffer */
97 int dc_blanked
; /* currently has video disabled */
98 void *dc_hwscroll_cookie
; /* cookie for hardware scroll */
99 void *dc_ih
; /* interrupt handler for dc */
101 int dc_curenb
; /* is cursor sprite enabled ? */
102 int _internal_dc_changed
; /* need update of hardware */
103 int dc_writeback_delay
; /* Screenarea write back vsync counter */
104 #define WSDISPLAY_CMAP_DOLUT 0x20
105 #define WSDISPLAY_VIDEO_ONOFF 0x40
106 #define WSDISPLAY_WB_COUNTER 0x80
108 struct hwcmap256 dc_cmap
; /* software copy of colormap */
109 struct hwcursor32 dc_cursor
; /* software copy of cursor */
111 struct vidc_mode mode_info
;
113 struct wsdisplay_emulops orig_ri_ops
; /* Rasops functions for deligation */
115 /* virtual console support */
116 struct vcons_data dc_vd
;
117 struct vcons_screen dc_console
;
121 struct vidcvideo_softc
{
122 struct device sc_dev
;
123 struct fb_devconfig
*sc_dc
; /* device configuration */
127 /* Function prototypes for glue */
128 static int vidcvideo_match(struct device
*, struct cfdata
*, void *);
129 static void vidcvideo_attach(struct device
*, struct device
*, void *);
133 CFATTACH_DECL(vidcvideo
, sizeof(struct vidcvideo_softc
),
134 vidcvideo_match
, vidcvideo_attach
, NULL
, NULL
);
136 static struct fb_devconfig vidcvideo_console_dc
;
137 static bool vidcvideo_is_console
= false;
140 static struct wsscreen_descr vidcvideo_stdscreen
= {
144 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
,
148 static const struct wsscreen_descr
*_vidcvideo_scrlist
[] = {
149 &vidcvideo_stdscreen
,
152 static const struct wsscreen_list vidcvideo_screenlist
= {
153 sizeof(_vidcvideo_scrlist
) / sizeof(struct wsscreen_descr
*),
157 static int vidcvideoioctl(void *, void *, u_long
, void *, int,
159 static paddr_t
vidcvideommap(void *, void *, off_t
, int);
160 static void vidcvideoinit_screen(void *, struct vcons_screen
*, int, long *);
162 static void vidcvideo_queue_dc_change(struct fb_devconfig
*, int);
163 static int flush_dc_changes_to_screen(struct fb_devconfig
*);
165 static struct wsdisplay_accessops vidcvideo_accessops
= {
168 NULL
, /* alloc_screen */
169 NULL
, /* free_screen */
170 NULL
, /* show_screen */
171 NULL
, /* load_font */
177 /* Function prototypes */
178 int vidcvideo_cnattach(vaddr_t
);
179 static void vidcvideo_colourmap_and_cursor_init(struct fb_devconfig
*);
181 static int get_cmap(struct vidcvideo_softc
*, struct wsdisplay_cmap
*);
182 static int set_cmap(struct vidcvideo_softc
*, struct wsdisplay_cmap
*);
183 static int set_cursor(struct vidcvideo_softc
*, struct wsdisplay_cursor
*);
184 static int get_cursor(struct vidcvideo_softc
*, struct wsdisplay_cursor
*);
185 static void set_curpos(struct vidcvideo_softc
*, struct wsdisplay_curpos
*);
186 static void vidcvideo_getdevconfig(vaddr_t
, u_int
, struct fb_devconfig
*);
188 static int vidcvideointr(void *);
190 /* Acceleration function prototypes */
191 static void vv_copyrows(void *, int, int, int);
192 static void vv_eraserows(void *, int, int, long);
193 static void vv_putchar(void *c
, int row
, int col
, u_int uc
, long attr
);
197 vidcvideo_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
200 /* Can't probe AFAIK ; how ? */
206 vidcvideo_getdevconfig(vaddr_t dense_addr
, u_int mem_size
,
207 struct fb_devconfig
*dc
)
210 dc
->dc_vaddr
= dense_addr
;
211 (void) pmap_extract(pmap_kernel(), dc
->dc_vaddr
, &(dc
->dc_paddr
));
213 vidcvideo_getmode(&dc
->mode_info
);
215 dc
->dc_width
= dc
->mode_info
.timings
.hdisplay
;
216 dc
->dc_height
= dc
->mode_info
.timings
.vdisplay
;
217 dc
->dc_log2_depth
= dc
->mode_info
.log2_bpp
;
218 dc
->dc_depth
= 1 << dc
->dc_log2_depth
;
219 dc
->dc_videobase
= dc
->dc_vaddr
;
222 /* this should/could be done somewhat more elegant! */
223 switch (dc
->dc_depth
) {
225 dc
->dc_rowbytes
= dc
->dc_width
/ 8;
228 dc
->dc_rowbytes
= dc
->dc_width
/ 4;
231 dc
->dc_rowbytes
= dc
->dc_width
/ 2;
234 dc
->dc_rowbytes
= dc
->dc_width
;
237 dc
->dc_rowbytes
= dc
->dc_width
* 2;
240 dc
->dc_rowbytes
= dc
->dc_width
* 4;
243 printf("Unknown colour depth %d ... what to do ?", dc
->dc_depth
);
247 /* setup the correct size */
248 dc
->dc_size
= mem_size
;
250 /* initialize colormap and cursor resource */
251 vidcvideo_colourmap_and_cursor_init(dc
);
253 /* blank the memory */
254 memset((void*)dc
->dc_vaddr
, 0, dc
->dc_size
);
256 /* intitialise miscelanious */
257 dc
->dc_writeback_delay
= 0;
261 vidcvideoinit_screen(void *cookie
, struct vcons_screen
*scr
,
262 int existing
, long *defattr
)
264 struct rasops_info
*ri
= &scr
->scr_ri
;
265 struct fb_devconfig
*dc
= cookie
;
267 if ((scr
== &dc
->dc_console
) && (dc
->dc_vd
.active
!= NULL
))
270 ri
->ri_flg
= 0; /* RI_CENTER | RI_FULLCLEAR; */
271 ri
->ri_depth
= dc
->dc_depth
;
272 ri
->ri_bits
= (void *) dc
->dc_videobase
;
273 ri
->ri_width
= dc
->dc_width
;
274 ri
->ri_height
= dc
->dc_height
;
275 ri
->ri_stride
= dc
->dc_rowbytes
;
276 ri
->ri_hw
= &dc
->dc_console
; /* link back */
282 ri
->ri_caps
= WSSCREEN_WSCOLORS
;
285 ri
->ri_height
/ ri
->ri_font
->fontheight
,
286 ri
->ri_width
/ ri
->ri_font
->fontwidth
);
289 * Provide a hook for the acceleration functions and make a copy of the
290 * original rasops functions for passing on calls
292 memcpy(&(dc
->orig_ri_ops
), &(ri
->ri_ops
),
293 sizeof(struct wsdisplay_emulops
));
295 /* add our accelerated functions */
296 ri
->ri_ops
.eraserows
= vv_eraserows
;
297 ri
->ri_ops
.copyrows
= vv_copyrows
;
299 /* add the extra activity measuring functions; they just delegate on */
300 ri
->ri_ops
.putchar
= vv_putchar
;
302 vidcvideo_stdscreen
.nrows
= ri
->ri_rows
;
303 vidcvideo_stdscreen
.ncols
= ri
->ri_cols
;
304 vidcvideo_stdscreen
.textops
= &ri
->ri_ops
;
305 vidcvideo_stdscreen
.capabilities
= ri
->ri_caps
;
309 vidcvideo_attach(struct device
*parent
, struct device
*self
, void *aux
)
311 struct vidcvideo_softc
*sc
= (struct vidcvideo_softc
*)self
;
312 struct fb_devconfig
*dc
;
313 struct wsemuldisplaydev_attach_args waa
;
316 dc
= sc
->sc_dc
= &vidcvideo_console_dc
;
319 * for reasons which are crazy we init vidcvideo twice,
320 * the second time sets up the cursor
323 if (!vidcvideo_is_console
) {
324 vidcvideo_getdevconfig(videomemory
.vidm_vbase
,
325 videomemory
.vidm_size
,
329 vcons_init(&dc
->dc_vd
, dc
, &vidcvideo_stdscreen
, &vidcvideo_accessops
);
330 dc
->dc_vd
.init_screen
= vidcvideoinit_screen
;
332 vcons_init_screen(&dc
->dc_vd
, &dc
->dc_console
, 1, &defattr
);
334 dc
->dc_console
.scr_flags
|= VCONS_SCREEN_IS_STATIC
;
336 vidcvideo_printdetails();
337 printf(": mode %s, %dbpp\n", dc
->mode_info
.timings
.name
,
340 /* set up interrupt flags */
341 vidcvideo_queue_dc_change(dc
, WSDISPLAY_CMAP_DOLUT
);
343 /* Establish an interrupt handler, and clear any pending interrupts */
344 dc
->dc_ih
= intr_claim(IRQ_FLYBACK
, IPL_TTY
, "vblank", vidcvideointr
, dc
);
346 waa
.console
= (vidcvideo_is_console
? 1 : 0);
347 waa
.scrdata
= &vidcvideo_screenlist
;
348 waa
.accessops
= &vidcvideo_accessops
;
349 waa
.accesscookie
= &dc
->dc_vd
;
351 config_found(self
, &waa
, wsemuldisplaydevprint
);
356 vidcvideoioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
,
359 struct vcons_data
*vd
= v
;
360 struct vidcvideo_softc
*sc
= vd
->cookie
;
361 struct fb_devconfig
*dc
= sc
->sc_dc
;
362 struct vcons_screen
*ms
= vd
->active
;
366 case WSDISPLAYIO_GTYPE
:
367 *(u_int
*)data
= WSDISPLAY_TYPE_VIDC
;
370 case WSDISPLAYIO_GINFO
:
373 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
374 wsd_fbip
->height
= dc
->dc_height
;
375 wsd_fbip
->width
= dc
->dc_width
;
376 wsd_fbip
->depth
= dc
->dc_depth
;
377 wsd_fbip
->cmsize
= CMAP_SIZE
;
381 case WSDISPLAYIO_GETCMAP
:
382 return get_cmap(sc
, (struct wsdisplay_cmap
*)data
);
384 case WSDISPLAYIO_PUTCMAP
:
385 return set_cmap(sc
, (struct wsdisplay_cmap
*)data
);
387 case WSDISPLAYIO_LINEBYTES
:
388 *(u_int
*)data
= dc
->dc_rowbytes
;
391 case WSDISPLAYIO_SVIDEO
:
392 state
= *(int *)data
;
393 dc
->dc_blanked
= (state
== WSDISPLAYIO_VIDEO_OFF
);
394 vidcvideo_queue_dc_change(dc
, WSDISPLAY_VIDEO_ONOFF
);
395 /* done on video blank */
398 case WSDISPLAYIO_GVIDEO
:
399 *(u_int
*)data
= dc
->dc_blanked
?
400 WSDISPLAYIO_VIDEO_OFF
: WSDISPLAYIO_VIDEO_ON
;
403 case WSDISPLAYIO_GCURPOS
:
404 *(struct wsdisplay_curpos
*)data
= dc
->dc_cursor
.cc_pos
;
407 case WSDISPLAYIO_SCURPOS
:
408 set_curpos(sc
, (struct wsdisplay_curpos
*)data
);
409 vidcvideo_queue_dc_change(dc
, WSDISPLAY_CURSOR_DOPOS
);
412 case WSDISPLAYIO_GCURMAX
:
413 ((struct wsdisplay_curpos
*)data
)->x
= CURSOR_MAX_WIDTH
;
414 ((struct wsdisplay_curpos
*)data
)->y
= CURSOR_MAX_HEIGHT
;
417 case WSDISPLAYIO_GCURSOR
:
418 return get_cursor(sc
, (struct wsdisplay_cursor
*)data
);
420 case WSDISPLAYIO_SCURSOR
:
421 return set_cursor(sc
, (struct wsdisplay_cursor
*)data
);
423 case WSDISPLAYIO_SMODE
:
424 state
= *(int *)data
;
425 if (state
== WSDISPLAYIO_MODE_MAPPED
)
426 dc
->dc_hwscroll_cookie
= vidcvideo_hwscroll_reset();
427 if (state
== WSDISPLAYIO_MODE_EMUL
)
428 vidcvideo_hwscroll_back(dc
->dc_hwscroll_cookie
);
429 vidcvideo_progr_scroll();
438 vidcvideommap(void *v
, void *vs
, off_t offset
, int prot
)
440 struct vcons_data
*vd
= v
;
441 struct vidcvideo_softc
*sc
= vd
->cookie
;
443 if (offset
>= sc
->sc_dc
->dc_size
|| offset
< 0)
446 return arm_btop(sc
->sc_dc
->dc_paddr
+ offset
);
451 vidcvideo_cnattach(vaddr_t addr
)
453 struct fb_devconfig
*dc
= &vidcvideo_console_dc
;
454 struct rasops_info
*ri
;
459 /* fetch current framebuffer config */
460 vidcvideo_getdevconfig(videomemory
.vidm_vbase
,
461 videomemory
.vidm_size
,
464 dc
->dc_vd
.active
= NULL
;
465 vidcvideoinit_screen(dc
, &dc
->dc_console
, 1, &defattr
);
467 ri
= &(dc
->dc_console
.scr_ri
);
468 ri
->ri_hw
= &dc
->dc_console
;
469 dc
->dc_console
.scr_cookie
= dc
;
471 (*ri
->ri_ops
.allocattr
)(ri
,
472 WS_DEFAULT_FG
, /* fg */
473 WS_DEFAULT_BG
, /* bg */
477 wsdisplay_cnattach(&vidcvideo_stdscreen
,
479 0, 0, /* cursor position */
482 vidcvideo_is_console
= true;
489 vidcvideointr(void *arg
)
491 struct fb_devconfig
*dc
= arg
;
493 return flush_dc_changes_to_screen(dc
);
497 flush_dc_changes_to_screen(struct fb_devconfig
*dc
)
501 v
= dc
->_internal_dc_changed
;
504 disable_irq(IRQ_FLYBACK
);
508 if (v
& WSDISPLAY_WB_COUNTER
) {
509 dc
->dc_writeback_delay
--;
510 if (dc
->dc_writeback_delay
== 0) {
511 cpu_dcache_wb_range(dc
->dc_vaddr
, dc
->dc_size
);
512 cleared
|= WSDISPLAY_WB_COUNTER
;
516 if (v
& WSDISPLAY_CMAP_DOLUT
) {
517 struct hwcmap256
*cm
= &dc
->dc_cmap
;
520 if (dc
->dc_depth
== 4) {
521 /* palette for 4 bpp is different from 8bpp */
522 vidcvideo_write(VIDC_PALREG
, 0x00000000);
523 for (index
=0; index
< (1 << dc
->dc_depth
); index
++)
524 vidcvideo_write(VIDC_PALETTE
,
525 VIDC_COL(cm
->r
[index
],
530 if (dc
->dc_depth
== 8) {
532 * dunno what to do in more than 8bpp
533 * palettes only make sense in 8bpp and less modes
536 vidcvideo_write(VIDC_PALREG
, 0x00000000);
537 for (index
= 0; index
< CMAP_SIZE
; index
++) {
538 vidcvideo_write(VIDC_PALETTE
,
539 VIDC_COL(cm
->r
[index
], cm
->g
[index
],
543 cleared
|= WSDISPLAY_CMAP_DOLUT
;
546 if (v
& WSDISPLAY_VIDEO_ONOFF
) {
547 vidcvideo_blank(dc
->dc_blanked
);
548 cleared
|= WSDISPLAY_VIDEO_ONOFF
;
551 if (v
& (WSDISPLAY_CURSOR_DOPOS
| WSDISPLAY_CURSOR_DOHOT
)) {
553 x
= dc
->dc_cursor
.cc_pos
.x
- dc
->dc_cursor
.cc_hot
.x
;
554 y
= dc
->dc_cursor
.cc_pos
.y
- dc
->dc_cursor
.cc_hot
.y
;
556 vidcvideo_updatecursor(x
, y
);
557 cleared
|= WSDISPLAY_CURSOR_DOPOS
| WSDISPLAY_CURSOR_DOHOT
;
560 if (v
& WSDISPLAY_CURSOR_DOCUR
) {
561 vidcvideo_enablecursor(dc
->dc_curenb
);
562 cleared
|= WSDISPLAY_CURSOR_DOCUR
;
565 dc
->_internal_dc_changed
^= cleared
;
567 if (dc
->_internal_dc_changed
== 0) {
568 disable_irq(IRQ_FLYBACK
);
575 static void vidcvideo_queue_dc_change(struct fb_devconfig
*dc
, int dc_change
)
577 dc
->_internal_dc_changed
|= dc_change
;
579 if (curcpl() == IPL_HIGH
) {
580 /* running in ddb or without interrupts */
581 dc
->dc_writeback_delay
= 1;
582 flush_dc_changes_to_screen(dc
);
585 * running with interrupts so handle this in the next
589 enable_irq(IRQ_FLYBACK
);
595 static const u_char ri_col_data
[6][6] = {
596 { 0, 0, 0, 0, 0, 0}, /* 1 bpp */
597 { 0, 0, 0, 0, 0, 0}, /* 2 bpp */
598 { 0, 0, 0, 0, 0, 0}, /* 4 bpp */
599 { 0, 0, 0, 0, 0, 0}, /* 8 bpp */
600 { 6, 5, 5, 0, 6, 11}, /* 16 bpp */
601 { 8, 8, 8, 0, 8, 16}, /* 32 bpp */
605 vidcvideo_colourmap_and_cursor_init(struct fb_devconfig
*dc
)
607 struct rasops_info
*ri
= &dc
->dc_console
.scr_ri
;
608 const u_char
*rgbdat
;
609 struct hwcmap256
*cm
;
613 /* Whatever we do later... just make sure we have a
614 * sane palette to start with
616 vidcvideo_stdpalette();
618 /* set up rgb bit pattern values for rasops_init */
619 rgbdat
= ri_col_data
[dc
->dc_log2_depth
];
620 ri
->ri_rnum
= rgbdat
[0];
621 ri
->ri_gnum
= rgbdat
[1];
622 ri
->ri_bnum
= rgbdat
[2];
623 ri
->ri_rpos
= rgbdat
[3];
624 ri
->ri_gpos
= rgbdat
[4];
625 ri
->ri_bpos
= rgbdat
[5];
627 /* initialise color map */
630 for (index
= 0; index
< CMAP_SIZE
; index
++, p
+= 3) {
635 /* flush to hardware */
636 vidcvideo_queue_dc_change(dc
, WSDISPLAY_CMAP_DOLUT
);
641 get_cmap(struct vidcvideo_softc
*sc
, struct wsdisplay_cmap
*p
)
643 u_int index
= p
->index
, count
= p
->count
;
646 if (index
>= CMAP_SIZE
|| count
> CMAP_SIZE
- index
)
649 error
= copyout(&sc
->sc_dc
->dc_cmap
.r
[index
], p
->red
, count
);
652 error
= copyout(&sc
->sc_dc
->dc_cmap
.g
[index
], p
->green
, count
);
655 error
= copyout(&sc
->sc_dc
->dc_cmap
.b
[index
], p
->blue
, count
);
661 set_cmap(struct vidcvideo_softc
*sc
, struct wsdisplay_cmap
*p
)
663 struct fb_devconfig
*dc
= sc
->sc_dc
;
664 struct hwcmap256 cmap
;
665 u_int index
= p
->index
, count
= p
->count
;
668 if (index
>= CMAP_SIZE
|| (index
+ count
) > CMAP_SIZE
)
671 error
= copyin(p
->red
, &cmap
.r
[index
], count
);
674 error
= copyin(p
->green
, &cmap
.g
[index
], count
);
677 error
= copyin(p
->blue
, &cmap
.b
[index
], count
);
680 memcpy(&dc
->dc_cmap
.r
[index
], &cmap
.r
[index
], count
);
681 memcpy(&dc
->dc_cmap
.g
[index
], &cmap
.g
[index
], count
);
682 memcpy(&dc
->dc_cmap
.b
[index
], &cmap
.b
[index
], count
);
683 vidcvideo_queue_dc_change(dc
, WSDISPLAY_CMAP_DOLUT
);
689 set_cursor(struct vidcvideo_softc
*sc
, struct wsdisplay_cursor
*p
)
691 #define cc (&dc->dc_cursor)
692 struct fb_devconfig
*dc
= sc
->sc_dc
;
693 u_int v
, index
= 0, count
= 0, icount
= 0;
694 uint8_t r
[2], g
[2], b
[2], image
[512], mask
[512];
697 /* XXX gcc does not detect identical conditions */
698 index
= count
= icount
= 0;
701 if (v
& WSDISPLAY_CURSOR_DOCMAP
) {
702 index
= p
->cmap
.index
;
703 count
= p
->cmap
.count
;
704 if (index
>= CURSOR_MAX_COLOURS
||
705 (index
+ count
) > CURSOR_MAX_COLOURS
)
707 error
= copyin(p
->cmap
.red
, &r
[index
], count
);
710 error
= copyin(p
->cmap
.green
, &g
[index
], count
);
713 error
= copyin(p
->cmap
.blue
, &b
[index
], count
);
717 if (v
& WSDISPLAY_CURSOR_DOSHAPE
) {
718 if (p
->size
.x
> CURSOR_MAX_WIDTH
||
719 p
->size
.y
> CURSOR_MAX_HEIGHT
)
721 icount
= sizeof(u_int32_t
) * p
->size
.y
;
722 error
= copyin(p
->image
, &image
, icount
);
725 error
= copyin(p
->mask
, &mask
, icount
);
730 if (v
& WSDISPLAY_CURSOR_DOCUR
)
731 dc
->dc_curenb
= p
->enable
;
732 if (v
& WSDISPLAY_CURSOR_DOPOS
)
733 set_curpos(sc
, &p
->pos
);
734 if (v
& WSDISPLAY_CURSOR_DOHOT
)
736 if (v
& WSDISPLAY_CURSOR_DOCMAP
) {
737 memcpy(&cc
->cc_color
[index
], &r
[index
], count
);
738 memcpy(&cc
->cc_color
[index
+ 2], &g
[index
], count
);
739 memcpy(&cc
->cc_color
[index
+ 4], &b
[index
], count
);
741 if (v
& WSDISPLAY_CURSOR_DOSHAPE
) {
742 cc
->cc_size
= p
->size
;
743 memset(cc
->cc_image
, 0, sizeof cc
->cc_image
);
744 memcpy(cc
->cc_image
, image
, icount
);
745 memset(cc
->cc_mask
, 0, sizeof cc
->cc_mask
);
746 memcpy(cc
->cc_mask
, mask
, icount
);
748 vidcvideo_queue_dc_change(dc
, v
);
756 get_cursor(struct vidcvideo_softc
*sc
, struct wsdisplay_cursor
*p
)
759 return EPASSTHROUGH
; /* XXX */
764 set_curpos(struct vidcvideo_softc
*sc
, struct wsdisplay_curpos
*curpos
)
766 struct fb_devconfig
*dc
= sc
->sc_dc
;
767 int x
= curpos
->x
, y
= curpos
->y
;
771 else if (y
> dc
->dc_height
)
775 else if (x
> dc
->dc_width
)
777 dc
->dc_cursor
.cc_pos
.x
= x
;
778 dc
->dc_cursor
.cc_pos
.y
= y
;
782 static void vv_copyrows(void *id
, int srcrow
, int dstrow
, int nrows
)
784 struct rasops_info
*ri
= id
;
785 int height
, offset
, size
;
786 int scrollup
, scrolldown
;
787 unsigned char *src
, *dst
;
788 struct vcons_screen
*scr
= ri
->ri_hw
;
789 struct fb_devconfig
*dc
= (struct fb_devconfig
*) (scr
->scr_cookie
);
791 /* All movements are done in multiples of character heigths */
792 height
= ri
->ri_font
->fontheight
* nrows
;
793 offset
= (srcrow
- dstrow
) * ri
->ri_yscale
;
794 size
= height
* ri
->ri_stride
;
796 /* check if we are full screen scrolling */
797 scrollup
= (srcrow
+ nrows
>= ri
->ri_rows
);
798 scrolldown
= (dstrow
+ nrows
>= ri
->ri_rows
);
801 if ((scrollup
|| scrolldown
) &&
802 (videomemory
.vidm_type
== VIDEOMEM_TYPE_VRAM
)) {
803 ri
->ri_bits
= vidcvideo_hwscroll(offset
);
804 vidcvideo_progr_scroll(); /* sadistic ; shouldnt this be on vsync? */
806 /* wipe out remains of the screen if nessisary */
807 if (ri
->ri_emuheight
!= ri
->ri_height
)
808 vv_eraserows(id
, ri
->ri_rows
, 1, 0);
814 * Else we just copy the area : we're braindead for now
815 * Note: we can't use hardware scrolling when the softc isnt
816 * known yet... if its not known we dont have interrupts and
817 * we can't change the display address reliable other than in
821 src
= ri
->ri_bits
+ srcrow
* ri
->ri_font
->fontheight
* ri
->ri_stride
;
822 dst
= ri
->ri_bits
+ dstrow
* ri
->ri_font
->fontheight
* ri
->ri_stride
;
824 memmove(dst
, src
, size
);
826 /* delay the write back operation of the screen area */
827 dc
->dc_writeback_delay
= SCREEN_WRITE_BACK_DELAY
;
828 vidcvideo_queue_dc_change(dc
, WSDISPLAY_WB_COUNTER
);
832 static void vv_eraserows(void *id
, int startrow
, int nrows
, long attr
)
834 struct rasops_info
*ri
= id
;
837 struct vcons_screen
*scr
= ri
->ri_hw
;
838 struct fb_devconfig
*dc
= (struct fb_devconfig
*) (scr
->scr_cookie
);
840 /* we're braindead for now */
841 height
= ri
->ri_font
->fontheight
* nrows
* ri
->ri_stride
;
843 src
= ri
->ri_bits
+ startrow
* ri
->ri_font
->fontheight
* ri
->ri_stride
;
845 memset(src
, 0, height
);
847 /* delay the write back operation of the screen area */
848 dc
->dc_writeback_delay
= SCREEN_WRITE_BACK_DELAY
;
849 vidcvideo_queue_dc_change(dc
, WSDISPLAY_WB_COUNTER
);
853 static void vv_putchar(void *id
, int row
, int col
, u_int uc
, long attr
)
855 struct rasops_info
*ri
= id
;
856 struct vcons_screen
*scr
= ri
->ri_hw
;
857 struct fb_devconfig
*dc
= (struct fb_devconfig
*) (scr
->scr_cookie
);
860 dc
->orig_ri_ops
.putchar(id
, row
, col
, uc
, attr
);
862 /* delay the write back operation of the screen area */
863 dc
->dc_writeback_delay
= SCREEN_WRITE_BACK_DELAY
;
864 vidcvideo_queue_dc_change(dc
, WSDISPLAY_WB_COUNTER
);