1 /* $NetBSD: igsfb.c,v 1.47 2009/11/18 21:59:38 macallan Exp $ */
4 * Copyright (c) 2002, 2003 Valeriy E. Ushakov
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.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * Integraphics Systems IGA 168x and CyberPro series.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: igsfb.c,v 1.47 2009/11/18 21:59:38 macallan Exp $");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/device.h>
40 #include <sys/malloc.h>
41 #include <sys/ioctl.h>
45 #include <dev/wscons/wsdisplayvar.h>
46 #include <dev/wscons/wsconsio.h>
47 #include <dev/wsfont/wsfont.h>
48 #include <dev/rasops/rasops.h>
50 #include <dev/wscons/wsdisplay_vconsvar.h>
52 #include <dev/ic/igsfbreg.h>
53 #include <dev/ic/igsfbvar.h>
56 struct igsfb_devconfig igsfb_console_dc
= {
65 /* filled from rasops_info in igsfb_init_wsdisplay */
66 static struct wsscreen_descr igsfb_stdscreen
= {
70 static const struct wsscreen_descr
*_igsfb_scrlist
[] = {
74 static const struct wsscreen_list igsfb_screenlist
= {
75 .nscreens
= sizeof(_igsfb_scrlist
) / sizeof(_igsfb_scrlist
[0]),
76 .screens
= _igsfb_scrlist
,
84 static int igsfb_ioctl(void *, void *, u_long
, void *, int, struct lwp
*);
85 static paddr_t
igsfb_mmap(void *, void *, off_t
, int);
87 static struct wsdisplay_accessops igsfb_accessops
= {
96 static int igsfb_make_text_cursor(struct igsfb_devconfig
*,
97 struct vcons_screen
*);
98 static void igsfb_accel_cursor(void *, int, int, int);
100 static int igsfb_accel_wait(struct igsfb_devconfig
*);
101 static void igsfb_accel_fill(struct igsfb_devconfig
*,
102 uint32_t, uint32_t, uint16_t, uint16_t);
103 static void igsfb_accel_copy(struct igsfb_devconfig
*,
104 uint32_t, uint32_t, uint16_t, uint16_t);
106 static void igsfb_accel_copycols(void *, int, int, int, int);
107 static void igsfb_accel_erasecols(void *, int, int, int, long);
108 static void igsfb_accel_copyrows(void *, int, int, int);
109 static void igsfb_accel_eraserows(void *, int, int, long);
110 static void igsfb_accel_putchar(void *, int, int, u_int
, long);
116 static int igsfb_init_video(struct igsfb_devconfig
*);
117 static void igsfb_init_cmap(struct igsfb_devconfig
*);
118 static uint16_t igsfb_spread_bits_8(uint8_t);
119 static void igsfb_init_bit_table(struct igsfb_devconfig
*);
120 static void igsfb_init_wsdisplay(void *, struct vcons_screen
*, int,
124 static void igsfb_blank_screen(struct igsfb_devconfig
*, int);
125 static int igsfb_get_cmap(struct igsfb_devconfig
*,
126 struct wsdisplay_cmap
*);
127 static int igsfb_set_cmap(struct igsfb_devconfig
*,
128 const struct wsdisplay_cmap
*);
129 static void igsfb_update_cmap(struct igsfb_devconfig
*, u_int
, u_int
);
130 static void igsfb_set_curpos(struct igsfb_devconfig
*,
131 const struct wsdisplay_curpos
*);
132 static void igsfb_update_curpos(struct igsfb_devconfig
*);
133 static int igsfb_get_cursor(struct igsfb_devconfig
*,
134 struct wsdisplay_cursor
*);
135 static int igsfb_set_cursor(struct igsfb_devconfig
*,
136 const struct wsdisplay_cursor
*);
137 static void igsfb_update_cursor(struct igsfb_devconfig
*, u_int
);
138 static void igsfb_convert_cursor_data(struct igsfb_devconfig
*,
143 igsfb_cnattach_subr(struct igsfb_devconfig
*dc
)
145 struct rasops_info
*ri
;
148 KASSERT(dc
== &igsfb_console_dc
);
150 igsfb_init_video(dc
);
151 dc
->dc_vd
.active
= NULL
;
152 igsfb_init_wsdisplay(dc
, &dc
->dc_console
, 1, &defattr
);
154 ri
= &dc
->dc_console
.scr_ri
;
155 ri
->ri_hw
= &dc
->dc_console
;
156 dc
->dc_console
.scr_cookie
= dc
;
158 (*ri
->ri_ops
.allocattr
)(ri
,
159 WS_DEFAULT_FG
, /* fg */
160 WS_DEFAULT_BG
, /* bg */
164 wsdisplay_cnattach(&igsfb_stdscreen
,
166 0, 0, /* cursor position */
173 * Finish off the attach. Bus specific attach method should have
174 * enabled io and memory accesses and mapped io (and cop?) registers.
177 igsfb_attach_subr(struct igsfb_softc
*sc
, int isconsole
)
179 struct igsfb_devconfig
*dc
= sc
->sc_dc
;
180 struct wsemuldisplaydev_attach_args waa
;
181 struct rasops_info
*ri
;
187 igsfb_init_video(dc
);
190 vcons_init(&dc
->dc_vd
, dc
, &igsfb_stdscreen
, &igsfb_accessops
);
191 dc
->dc_vd
.init_screen
= igsfb_init_wsdisplay
;
193 vcons_init_screen(&dc
->dc_vd
, &dc
->dc_console
, 1, &defattr
);
194 dc
->dc_console
.scr_flags
|= VCONS_SCREEN_IS_STATIC
;
196 printf("%s: %dMB, %s%dx%d, %dbpp\n",
197 device_xname(&sc
->sc_dev
),
198 (uint32_t)(dc
->dc_vmemsz
>> 20),
199 (dc
->dc_hwflags
& IGSFB_HW_BSWAP
)
200 ? (dc
->dc_hwflags
& IGSFB_HW_BE_SELECT
)
201 ? "hardware bswap, " : "software bswap, "
203 dc
->dc_width
, dc
->dc_height
, dc
->dc_depth
);
204 printf("%s: using %dbpp for X\n", device_xname(&sc
->sc_dev
),
206 ri
= &dc
->dc_console
.scr_ri
;
207 ri
->ri_ops
.eraserows(ri
, 0, ri
->ri_rows
, defattr
);
210 vcons_replay_msgbuf(&dc
->dc_console
);
212 /* attach wsdisplay */
213 waa
.console
= isconsole
;
214 waa
.scrdata
= &igsfb_screenlist
;
215 waa
.accessops
= &igsfb_accessops
;
216 waa
.accesscookie
= &dc
->dc_vd
;
218 config_found(&sc
->sc_dev
, &waa
, wsemuldisplaydevprint
);
223 igsfb_init_video(struct igsfb_devconfig
*dc
)
225 bus_space_handle_t tmph
;
228 bus_addr_t fbaddr
, craddr
;
230 uint8_t busctl
, curctl
;
233 /* Total amount of video memory. */
234 busctl
= igs_ext_read(dc
->dc_iot
, dc
->dc_ioh
, IGS_EXT_BUS_CTL
);
237 else if (busctl
& 0x1)
241 dc
->dc_vmemsz
<<= 20; /* megabytes -> bytes */
244 * Check for endianness mismatch by writing a word at the end of
245 * the video memory (off-screen) and reading it back byte-by-byte.
247 if (bus_space_map(dc
->dc_memt
,
248 dc
->dc_memaddr
+ dc
->dc_vmemsz
- sizeof(uint32_t),
250 dc
->dc_memflags
| BUS_SPACE_MAP_LINEAR
,
253 printf("unable to map video memory for endianness test\n");
257 p
= bus_space_vaddr(dc
->dc_memt
, tmph
);
258 #if BYTE_ORDER == BIG_ENDIAN
259 *((uint32_t *)p
) = 0x12345678;
261 *((uint32_t *)p
) = 0x78563412;
263 if (p
[0] == 0x12 && p
[1] == 0x34 && p
[2] == 0x56 && p
[3] == 0x78)
268 bus_space_unmap(dc
->dc_memt
, tmph
, sizeof(uint32_t));
271 * On CyberPro we can use magic bswap bit in linear address.
273 fbaddr
= dc
->dc_memaddr
;
275 dc
->dc_hwflags
|= IGSFB_HW_BSWAP
;
276 if (dc
->dc_id
>= 0x2000) {
277 dc
->dc_hwflags
|= IGSFB_HW_BE_SELECT
;
278 fbaddr
|= IGS_MEM_BE_SELECT
;
283 * XXX: TODO: make it possible to select the desired video mode.
284 * For now - hardcode to 1024x768/8bpp. This is what Krups OFW uses.
289 * Don't map in all N megs, just the amount we need for the wsscreen.
291 dc
->dc_fbsz
= dc
->dc_stride
* dc
->dc_height
;
292 if (bus_space_map(dc
->dc_memt
, fbaddr
, dc
->dc_fbsz
,
293 dc
->dc_memflags
| BUS_SPACE_MAP_LINEAR
,
296 bus_space_unmap(dc
->dc_iot
, dc
->dc_ioh
, IGS_REG_SIZE
);
297 printf("unable to map framebuffer\n");
304 * 1KB for cursor sprite data at the very end of the video memory.
306 croffset
= dc
->dc_vmemsz
- IGS_CURSOR_DATA_SIZE
;
307 craddr
= fbaddr
+ croffset
;
308 if (bus_space_map(dc
->dc_memt
, craddr
, IGS_CURSOR_DATA_SIZE
,
309 dc
->dc_memflags
| BUS_SPACE_MAP_LINEAR
,
312 bus_space_unmap(dc
->dc_iot
, dc
->dc_ioh
, IGS_REG_SIZE
);
313 bus_space_unmap(dc
->dc_memt
, dc
->dc_fbh
, dc
->dc_fbsz
);
314 printf("unable to map cursor sprite region\n");
319 * Tell the device where cursor sprite data are located in the
320 * linear space (it takes data offset in 1KB units).
322 croffset
>>= 10; /* bytes -> kilobytes */
323 igs_ext_write(dc
->dc_iot
, dc
->dc_ioh
,
324 IGS_EXT_SPRITE_DATA_LO
, croffset
& 0xff);
325 igs_ext_write(dc
->dc_iot
, dc
->dc_ioh
,
326 IGS_EXT_SPRITE_DATA_HI
, (croffset
>> 8) & 0xf);
328 /* init the bit expansion table for cursor sprite data conversion */
329 igsfb_init_bit_table(dc
);
331 /* XXX: fill dc_cursor and use igsfb_update_cursor() instead? */
332 memset(&dc
->dc_cursor
, 0, sizeof(struct igs_hwcursor
));
333 va
= bus_space_vaddr(dc
->dc_memt
, dc
->dc_crh
);
334 memset(va
, /* transparent */ 0xaa, IGS_CURSOR_DATA_SIZE
);
336 curctl
= igs_ext_read(dc
->dc_iot
, dc
->dc_ioh
, IGS_EXT_SPRITE_CTL
);
337 curctl
|= IGS_EXT_SPRITE_64x64
;
338 curctl
&= ~IGS_EXT_SPRITE_VISIBLE
;
339 igs_ext_write(dc
->dc_iot
, dc
->dc_ioh
, IGS_EXT_SPRITE_CTL
, curctl
);
343 * Map and init graphic coprocessor for accelerated rasops.
345 if (dc
->dc_id
>= 0x2000) { /* XXX */
346 if (bus_space_map(dc
->dc_iot
,
347 dc
->dc_iobase
+ IGS_COP_BASE_B
, IGS_COP_SIZE
,
351 printf("unable to map COP registers\n");
355 /* XXX: hardcoded 8bpp */
356 bus_space_write_2(dc
->dc_iot
, dc
->dc_coph
,
357 IGS_COP_SRC_MAP_WIDTH_REG
,
359 bus_space_write_2(dc
->dc_iot
, dc
->dc_coph
,
360 IGS_COP_DST_MAP_WIDTH_REG
,
363 bus_space_write_1(dc
->dc_iot
, dc
->dc_coph
,
368 /* make sure screen is not blanked */
370 igsfb_blank_screen(dc
, dc
->dc_blanked
);
377 igsfb_init_cmap(struct igsfb_devconfig
*dc
)
379 bus_space_tag_t iot
= dc
->dc_iot
;
380 bus_space_handle_t ioh
= dc
->dc_ioh
;
384 p
= rasops_cmap
; /* "ANSI" color map */
386 /* init software copy */
387 for (i
= 0; i
< IGS_CMAP_SIZE
; ++i
, p
+= 3) {
388 dc
->dc_cmap
.r
[i
] = p
[0];
389 dc
->dc_cmap
.g
[i
] = p
[1];
390 dc
->dc_cmap
.b
[i
] = p
[2];
393 /* propagate to the device */
394 igsfb_update_cmap(dc
, 0, IGS_CMAP_SIZE
);
396 /* set overscan color (XXX: use defattr's background?) */
397 igs_ext_write(iot
, ioh
, IGS_EXT_OVERSCAN_RED
, 0);
398 igs_ext_write(iot
, ioh
, IGS_EXT_OVERSCAN_GREEN
, 0);
399 igs_ext_write(iot
, ioh
, IGS_EXT_OVERSCAN_BLUE
, 0);
404 igsfb_init_wsdisplay(void *cookie
, struct vcons_screen
*scr
, int existing
,
407 struct igsfb_devconfig
*dc
= cookie
;
408 struct rasops_info
*ri
= &scr
->scr_ri
;
411 if ((scr
== &dc
->dc_console
) && (dc
->dc_vd
.active
!= NULL
))
415 ri
->ri_flg
= RI_CENTER
| RI_FULLCLEAR
;
416 if (IGSFB_HW_SOFT_BSWAP(dc
))
417 ri
->ri_flg
|= RI_BSWAP
;
419 ri
->ri_depth
= dc
->dc_depth
;
420 ri
->ri_width
= dc
->dc_width
;
421 ri
->ri_height
= dc
->dc_height
;
422 ri
->ri_stride
= dc
->dc_stride
;
423 ri
->ri_bits
= bus_space_vaddr(dc
->dc_memt
, dc
->dc_fbh
);
426 * Initialize wsfont related stuff.
430 /* prefer gallant that is identical to the one the prom uses */
431 wsfcookie
= wsfont_find("Gallant", 12, 22, 0,
432 WSDISPLAY_FONTORDER_L2R
,
433 WSDISPLAY_FONTORDER_L2R
);
434 if (wsfcookie
<= 0) {
436 printf("unable to find font Gallant 12x22\n");
438 wsfcookie
= wsfont_find(NULL
, 0, 0, 0, /* any font at all? */
439 WSDISPLAY_FONTORDER_L2R
,
440 WSDISPLAY_FONTORDER_L2R
);
443 if (wsfcookie
<= 0) {
444 printf("unable to find any fonts\n");
448 if (wsfont_lock(wsfcookie
, &ri
->ri_font
) != 0) {
449 printf("unable to lock font\n");
452 ri
->ri_wsfcookie
= wsfcookie
;
455 /* XXX: TODO: compute term size based on font dimensions? */
456 rasops_init(ri
, 34, 80);
457 rasops_reconfig(ri
, ri
->ri_height
/ ri
->ri_font
->fontheight
,
458 ri
->ri_width
/ ri
->ri_font
->fontwidth
);
461 /* use the sprite for the text mode cursor */
462 igsfb_make_text_cursor(dc
, scr
);
464 /* the cursor is "busy" while we are in the text mode */
465 dc
->dc_hwflags
|= IGSFB_HW_TEXT_CURSOR
;
467 /* propagate sprite data to the device */
468 igsfb_update_cursor(dc
, WSDISPLAY_CURSOR_DOSHAPE
);
470 /* accelerated text cursor */
471 ri
->ri_ops
.cursor
= igsfb_accel_cursor
;
473 if (dc
->dc_id
>= 0x2000) { /* XXX */
474 /* accelerated erase/copy */
475 ri
->ri_ops
.copycols
= igsfb_accel_copycols
;
476 ri
->ri_ops
.erasecols
= igsfb_accel_erasecols
;
477 ri
->ri_ops
.copyrows
= igsfb_accel_copyrows
;
478 ri
->ri_ops
.eraserows
= igsfb_accel_eraserows
;
480 /* putchar hook to sync with the cop */
481 dc
->dc_ri_putchar
= ri
->ri_ops
.putchar
;
482 ri
->ri_ops
.putchar
= igsfb_accel_putchar
;
485 igsfb_stdscreen
.nrows
= ri
->ri_rows
;
486 igsfb_stdscreen
.ncols
= ri
->ri_cols
;
487 igsfb_stdscreen
.textops
= &ri
->ri_ops
;
488 igsfb_stdscreen
.capabilities
= ri
->ri_caps
;
493 * Init cursor data in dc_cursor for the accelerated text cursor.
496 igsfb_make_text_cursor(struct igsfb_devconfig
*dc
, struct vcons_screen
*scr
)
498 struct rasops_info
*ri
= &scr
->scr_ri
;
499 struct wsdisplay_font
*f
= ri
->ri_font
;
500 uint16_t cc_scan
[8]; /* one sprite scanline */
504 KASSERT(f
->fontwidth
<= IGS_CURSOR_MAX_SIZE
);
505 KASSERT(f
->fontheight
<= IGS_CURSOR_MAX_SIZE
);
508 for (i
= 0; i
< f
->stride
; ++i
) {
510 s
= 0xffff; /* all inverted */
513 /* first w pixels inverted, the rest is transparent */
514 s
= ~(0x5555 << (w
* 2));
521 dc
->dc_cursor
.cc_size
.x
= f
->fontwidth
;
522 dc
->dc_cursor
.cc_size
.y
= f
->fontheight
;
524 dc
->dc_cursor
.cc_hot
.x
= 0;
525 dc
->dc_cursor
.cc_hot
.y
= 0;
527 /* init sprite array to be all transparent */
528 memset(dc
->dc_cursor
.cc_sprite
, 0xaa, IGS_CURSOR_DATA_SIZE
);
530 for (i
= 0; i
< f
->fontheight
; ++i
)
531 memcpy(&dc
->dc_cursor
.cc_sprite
[i
* 8],
532 cc_scan
, f
->stride
* sizeof(uint16_t));
539 * Spread a byte (abcd.efgh) into two (0a0b.0c0d 0e0f.0g0h).
540 * Helper function for igsfb_init_bit_table().
543 igsfb_spread_bits_8(uint8_t b
)
547 s
= ((s
& 0x00f0) << 4) | (s
& 0x000f);
548 s
= ((s
& 0x0c0c) << 2) | (s
& 0x0303);
549 s
= ((s
& 0x2222) << 1) | (s
& 0x1111);
555 * Cursor sprite data are in 2bpp. Incoming image/mask are in 1bpp.
556 * Prebuild the table to expand 1bpp->2bpp, with bswapping if necessary.
559 igsfb_init_bit_table(struct igsfb_devconfig
*dc
)
561 uint16_t *expand
= dc
->dc_bexpand
;
565 for (i
= 0; i
< 256; ++i
) {
566 s
= igsfb_spread_bits_8(i
);
567 expand
[i
] = htole16(s
);
573 * wsdisplay_accessops: mmap()
574 * XXX: security considerations for allowing mmapping i/o mapped i/o regs?
577 igsfb_mmap(void *v
, void *vs
, off_t offset
, int prot
)
579 struct vcons_data
*vd
= v
;
580 struct igsfb_devconfig
*dc
= vd
->cookie
;
582 if (offset
< dc
->dc_memsz
&& offset
>= 0)
583 return bus_space_mmap(dc
->dc_memt
, dc
->dc_memaddr
, offset
,
584 prot
, dc
->dc_memflags
| BUS_SPACE_MAP_LINEAR
);
586 return dc
->dc_mmap(v
, vs
, offset
, prot
);
592 * wsdisplay_accessops: ioctl()
595 igsfb_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
,
598 struct vcons_data
*vd
= v
;
599 struct igsfb_devconfig
*dc
= vd
->cookie
;
603 /* don't permit cursor ioctls if we use sprite for text cursor */
604 cursor_busy
= !dc
->dc_mapped
605 && (dc
->dc_hwflags
& IGSFB_HW_TEXT_CURSOR
);
609 case WSDISPLAYIO_GTYPE
:
610 *(u_int
*)data
= WSDISPLAY_TYPE_PCIMISC
;
613 case WSDISPLAYIO_GINFO
:
614 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
615 wsd_fbip
->height
= dc
->dc_height
;
616 wsd_fbip
->width
= dc
->dc_width
;
617 wsd_fbip
->depth
= dc
->dc_maxdepth
;
618 wsd_fbip
->cmsize
= IGS_CMAP_SIZE
;
622 case WSDISPLAYIO_LINEBYTES
:
623 *(int *)data
= dc
->dc_width
* (dc
->dc_maxdepth
>> 3);
626 case WSDISPLAYIO_SMODE
:
627 #define d (*(int *)data)
628 if (d
!= WSDISPLAYIO_MODE_EMUL
) {
630 /* turn off hardware cursor */
631 if (dc
->dc_hwflags
& IGSFB_HW_TEXT_CURSOR
) {
633 igsfb_update_cursor(dc
,
634 WSDISPLAY_CURSOR_DOCUR
);
636 if ((dc
->dc_mode
!= NULL
) && (dc
->dc_maxdepth
!= 8))
637 igsfb_set_mode(dc
, dc
->dc_mode
,
641 if ((dc
->dc_mode
!= NULL
) && (dc
->dc_maxdepth
!= 8))
642 igsfb_set_mode(dc
, dc
->dc_mode
, 8);
644 /* reinit sprite for text cursor */
645 if (dc
->dc_hwflags
& IGSFB_HW_TEXT_CURSOR
) {
646 igsfb_make_text_cursor(dc
, dc
->dc_vd
.active
);
648 igsfb_update_cursor(dc
,
649 WSDISPLAY_CURSOR_DOSHAPE
650 | WSDISPLAY_CURSOR_DOCUR
);
652 vcons_redraw_screen(vd
->active
);
656 case WSDISPLAYIO_GVIDEO
:
657 *(u_int
*)data
= dc
->dc_blanked
?
658 WSDISPLAYIO_VIDEO_OFF
: WSDISPLAYIO_VIDEO_ON
;
661 case WSDISPLAYIO_SVIDEO
:
662 turnoff
= (*(u_int
*)data
== WSDISPLAYIO_VIDEO_OFF
);
663 if (dc
->dc_blanked
!= turnoff
) {
664 dc
->dc_blanked
= turnoff
;
665 igsfb_blank_screen(dc
, dc
->dc_blanked
);
669 case WSDISPLAYIO_GETCMAP
:
670 return igsfb_get_cmap(dc
, (struct wsdisplay_cmap
*)data
);
672 case WSDISPLAYIO_PUTCMAP
:
673 return igsfb_set_cmap(dc
, (struct wsdisplay_cmap
*)data
);
675 case WSDISPLAYIO_GCURMAX
:
676 ((struct wsdisplay_curpos
*)data
)->x
= IGS_CURSOR_MAX_SIZE
;
677 ((struct wsdisplay_curpos
*)data
)->y
= IGS_CURSOR_MAX_SIZE
;
680 case WSDISPLAYIO_GCURPOS
:
683 *(struct wsdisplay_curpos
*)data
= dc
->dc_cursor
.cc_pos
;
686 case WSDISPLAYIO_SCURPOS
:
689 igsfb_set_curpos(dc
, (struct wsdisplay_curpos
*)data
);
692 case WSDISPLAYIO_GCURSOR
:
695 return igsfb_get_cursor(dc
, (struct wsdisplay_cursor
*)data
);
697 case WSDISPLAYIO_SCURSOR
:
700 return igsfb_set_cursor(dc
, (struct wsdisplay_cursor
*)data
);
708 * wsdisplay_accessops: ioctl(WSDISPLAYIO_SVIDEO)
711 igsfb_blank_screen(struct igsfb_devconfig
*dc
, int blank
)
714 igs_ext_write(dc
->dc_iot
, dc
->dc_ioh
,
716 blank
? IGS_EXT_SYNC_H0
| IGS_EXT_SYNC_V0
722 * wsdisplay_accessops: ioctl(WSDISPLAYIO_GETCMAP)
723 * Served from the software cmap copy.
726 igsfb_get_cmap(struct igsfb_devconfig
*dc
, struct wsdisplay_cmap
*p
)
734 if (index
>= IGS_CMAP_SIZE
|| count
> IGS_CMAP_SIZE
- index
)
737 err
= copyout(&dc
->dc_cmap
.r
[index
], p
->red
, count
);
740 err
= copyout(&dc
->dc_cmap
.g
[index
], p
->green
, count
);
743 err
= copyout(&dc
->dc_cmap
.b
[index
], p
->blue
, count
);
752 * wsdisplay_accessops: ioctl(WSDISPLAYIO_PUTCMAP)
753 * Set the software cmap copy and propagate changed range to the device.
756 igsfb_set_cmap(struct igsfb_devconfig
*dc
, const struct wsdisplay_cmap
*p
)
759 uint8_t r
[IGS_CMAP_SIZE
];
760 uint8_t g
[IGS_CMAP_SIZE
];
761 uint8_t b
[IGS_CMAP_SIZE
];
766 if (index
>= IGS_CMAP_SIZE
|| count
> IGS_CMAP_SIZE
- index
)
768 error
= copyin(p
->red
, &r
[index
], count
);
771 error
= copyin(p
->green
, &g
[index
], count
);
774 error
= copyin(p
->blue
, &b
[index
], count
);
778 memcpy(&dc
->dc_cmap
.r
[index
], &r
[index
], count
);
779 memcpy(&dc
->dc_cmap
.g
[index
], &g
[index
], count
);
780 memcpy(&dc
->dc_cmap
.b
[index
], &b
[index
], count
);
782 /* propagate changes to the device */
783 igsfb_update_cmap(dc
, index
, count
);
789 * Propagate specified part of the software cmap copy to the device.
792 igsfb_update_cmap(struct igsfb_devconfig
*dc
, u_int index
, u_int count
)
795 bus_space_handle_t h
;
798 if (index
>= IGS_CMAP_SIZE
)
801 last
= index
+ count
;
802 if (last
> IGS_CMAP_SIZE
)
803 last
= IGS_CMAP_SIZE
;
808 /* start palette writing, index is autoincremented by hardware */
809 bus_space_write_1(t
, h
, IGS_DAC_PEL_WRITE_IDX
, index
);
811 for (i
= index
; i
< last
; ++i
) {
812 bus_space_write_1(t
, h
, IGS_DAC_PEL_DATA
, dc
->dc_cmap
.r
[i
]);
813 bus_space_write_1(t
, h
, IGS_DAC_PEL_DATA
, dc
->dc_cmap
.g
[i
]);
814 bus_space_write_1(t
, h
, IGS_DAC_PEL_DATA
, dc
->dc_cmap
.b
[i
]);
820 * wsdisplay_accessops: ioctl(WSDISPLAYIO_SCURPOS)
823 igsfb_set_curpos(struct igsfb_devconfig
*dc
,
824 const struct wsdisplay_curpos
*curpos
)
826 struct rasops_info
*ri
= &dc
->dc_vd
.active
->scr_ri
;
827 u_int x
= curpos
->x
, y
= curpos
->y
;
829 if (x
>= ri
->ri_width
)
830 x
= ri
->ri_width
- 1;
831 if (y
>= ri
->ri_height
)
832 y
= ri
->ri_height
- 1;
834 dc
->dc_cursor
.cc_pos
.x
= x
;
835 dc
->dc_cursor
.cc_pos
.y
= y
;
837 /* propagate changes to the device */
838 igsfb_update_curpos(dc
);
843 igsfb_update_curpos(struct igsfb_devconfig
*dc
)
846 bus_space_handle_t h
;
847 int x
, xoff
, y
, yoff
;
850 x
= dc
->dc_cursor
.cc_pos
.x
- dc
->dc_cursor
.cc_hot
.x
;
857 y
= dc
->dc_cursor
.cc_pos
.y
- dc
->dc_cursor
.cc_hot
.y
;
866 igs_ext_write(t
, h
, IGS_EXT_SPRITE_HSTART_LO
, x
& 0xff);
867 igs_ext_write(t
, h
, IGS_EXT_SPRITE_HSTART_HI
, (x
>> 8) & 0x07);
868 igs_ext_write(t
, h
, IGS_EXT_SPRITE_HPRESET
, xoff
& 0x3f);
870 igs_ext_write(t
, h
, IGS_EXT_SPRITE_VSTART_LO
, y
& 0xff);
871 igs_ext_write(t
, h
, IGS_EXT_SPRITE_VSTART_HI
, (y
>> 8) & 0x07);
872 igs_ext_write(t
, h
, IGS_EXT_SPRITE_VPRESET
, yoff
& 0x3f);
877 * wsdisplay_accessops: ioctl(WSDISPLAYIO_GCURSOR)
880 igsfb_get_cursor(struct igsfb_devconfig
*dc
, struct wsdisplay_cursor
*p
)
889 * wsdisplay_accessops: ioctl(WSDISPLAYIO_SCURSOR)
892 igsfb_set_cursor(struct igsfb_devconfig
*dc
, const struct wsdisplay_cursor
*p
)
894 struct igs_hwcursor
*cc
;
895 struct wsdisplay_curpos pos
, hot
;
896 u_int v
, index
, count
, icount
, iwidth
;
897 uint8_t r
[2], g
[2], b
[2], image
[512], mask
[512];
902 index
= count
= icount
= iwidth
= 0; /* XXX: gcc */
903 pos
.x
= pos
.y
= 0; /* XXX: gcc */
905 /* copy in the new cursor colormap */
906 if (v
& WSDISPLAY_CURSOR_DOCMAP
) {
907 index
= p
->cmap
.index
;
908 count
= p
->cmap
.count
;
909 if (index
>= 2 || (index
+ count
) > 2)
911 error
= copyin(p
->cmap
.red
, &r
[index
], count
);
914 error
= copyin(p
->cmap
.green
, &g
[index
], count
);
917 error
= copyin(p
->cmap
.blue
, &b
[index
], count
);
922 /* verify that the new cursor data are valid */
923 if (v
& WSDISPLAY_CURSOR_DOSHAPE
) {
924 if (p
->size
.x
> IGS_CURSOR_MAX_SIZE
925 || p
->size
.y
> IGS_CURSOR_MAX_SIZE
)
928 iwidth
= (p
->size
.x
+ 7) >> 3; /* bytes per scan line */
929 icount
= iwidth
* p
->size
.y
;
930 error
= copyin(p
->image
, image
, icount
);
933 error
= copyin(p
->mask
, mask
, icount
);
938 /* enforce that the position is within screen bounds */
939 if (v
& WSDISPLAY_CURSOR_DOPOS
) {
940 struct rasops_info
*ri
= &dc
->dc_vd
.active
->scr_ri
;
942 pos
= p
->pos
; /* local copy we can write to */
943 if (pos
.x
>= ri
->ri_width
)
944 pos
.x
= ri
->ri_width
- 1;
945 if (pos
.y
>= ri
->ri_height
)
946 pos
.y
= ri
->ri_height
- 1;
949 /* enforce that the hot spot is within sprite bounds */
950 if (v
& WSDISPLAY_CURSOR_DOHOT
)
951 hot
= p
->hot
; /* local copy we can write to */
953 if (v
& (WSDISPLAY_CURSOR_DOHOT
| WSDISPLAY_CURSOR_DOSHAPE
)) {
954 const struct wsdisplay_curpos
*nsize
;
955 struct wsdisplay_curpos
*nhot
;
957 nsize
= (v
& WSDISPLAY_CURSOR_DOSHAPE
) ?
958 &p
->size
: &cc
->cc_size
;
959 nhot
= (v
& WSDISPLAY_CURSOR_DOHOT
) ? &hot
: &cc
->cc_hot
;
961 if (nhot
->x
>= nsize
->x
)
962 nhot
->x
= nsize
->x
- 1;
963 if (nhot
->y
>= nsize
->y
)
964 nhot
->y
= nsize
->y
- 1;
967 /* copy data to the driver's cursor info */
968 if (v
& WSDISPLAY_CURSOR_DOCUR
)
969 dc
->dc_curenb
= p
->enable
;
970 if (v
& WSDISPLAY_CURSOR_DOPOS
)
971 cc
->cc_pos
= pos
; /* local copy, possibly corrected */
972 if (v
& WSDISPLAY_CURSOR_DOHOT
)
973 cc
->cc_hot
= hot
; /* local copy, possibly corrected */
974 if (v
& WSDISPLAY_CURSOR_DOCMAP
) {
975 memcpy(&cc
->cc_color
[index
], &r
[index
], count
);
976 memcpy(&cc
->cc_color
[index
+ 2], &g
[index
], count
);
977 memcpy(&cc
->cc_color
[index
+ 4], &b
[index
], count
);
979 if (v
& WSDISPLAY_CURSOR_DOSHAPE
) {
982 memcpy(cc
->cc_image
, image
, icount
);
983 memcpy(cc
->cc_mask
, mask
, icount
);
984 cc
->cc_size
= p
->size
;
986 /* clear trailing bits in the "partial" mask bytes */
987 trailing_bits
= p
->size
.x
& 0x07;
988 if (trailing_bits
!= 0) {
989 const u_int cutmask
= ~((~0) << trailing_bits
);
993 mp
= cc
->cc_mask
+ iwidth
- 1;
994 for (i
= 0; i
< p
->size
.y
; ++i
) {
999 igsfb_convert_cursor_data(dc
, iwidth
, p
->size
.y
);
1002 /* propagate changes to the device */
1003 igsfb_update_cursor(dc
, v
);
1010 * Convert incoming 1bpp cursor image/mask into native 2bpp format.
1013 igsfb_convert_cursor_data(struct igsfb_devconfig
*dc
,
1014 u_int width
, u_int height
)
1016 struct igs_hwcursor
*cc
= &dc
->dc_cursor
;
1017 uint16_t *expand
= dc
->dc_bexpand
;
1019 uint16_t is
, ms
, *dp
;
1022 /* init sprite to be all transparent */
1023 memset(cc
->cc_sprite
, 0xaa, IGS_CURSOR_DATA_SIZE
);
1025 /* first scanline */
1030 for (line
= 0; line
< height
; ++line
) {
1031 for (i
= 0; i
< width
; ++i
) {
1032 is
= expand
[ip
[i
]]; /* image: 0 -> 00, 1 -> 01 */
1033 ms
= expand
[mp
[i
]]; /* mask: 0 -> 00, 1 -> 11 */
1035 dp
[i
] = (0xaaaa & ~ms
) | (is
& ms
);
1041 dp
+= 8; /* 64 pixels, 2bpp, 8 pixels per short = 8 shorts */
1047 * Propagate cursor changes to the device.
1048 * "which" is composed of WSDISPLAY_CURSOR_DO* bits.
1051 igsfb_update_cursor(struct igsfb_devconfig
*dc
, u_int which
)
1053 bus_space_tag_t iot
= dc
->dc_iot
;
1054 bus_space_handle_t ioh
= dc
->dc_ioh
;
1057 curctl
= 0; /* XXX: gcc */
1060 * We will need to tweak sprite control register for cursor
1061 * visibility and cursor color map manipulation.
1063 if (which
& (WSDISPLAY_CURSOR_DOCUR
| WSDISPLAY_CURSOR_DOCMAP
)) {
1064 curctl
= igs_ext_read(iot
, ioh
, IGS_EXT_SPRITE_CTL
);
1067 if (which
& WSDISPLAY_CURSOR_DOSHAPE
) {
1068 uint8_t *dst
= bus_space_vaddr(dc
->dc_memt
, dc
->dc_crh
);
1071 * memcpy between spaces of different endianness would
1072 * be ... special. We cannot be sure if memcpy gonna
1073 * push data in 4-byte chunks, we can't pre-bswap it,
1074 * so do it byte-by-byte to preserve byte ordering.
1076 if (IGSFB_HW_SOFT_BSWAP(dc
)) {
1077 uint8_t *src
= (uint8_t *)dc
->dc_cursor
.cc_sprite
;
1080 for (i
= 0; i
< IGS_CURSOR_DATA_SIZE
; ++i
)
1083 memcpy(dst
, dc
->dc_cursor
.cc_sprite
,
1084 IGS_CURSOR_DATA_SIZE
);
1088 if (which
& (WSDISPLAY_CURSOR_DOPOS
| WSDISPLAY_CURSOR_DOHOT
)) {
1089 /* code shared with WSDISPLAYIO_SCURPOS */
1090 igsfb_update_curpos(dc
);
1093 if (which
& WSDISPLAY_CURSOR_DOCMAP
) {
1096 /* tell DAC we want access to the cursor palette */
1097 igs_ext_write(iot
, ioh
, IGS_EXT_SPRITE_CTL
,
1098 curctl
| IGS_EXT_SPRITE_DAC_PEL
);
1100 p
= dc
->dc_cursor
.cc_color
;
1102 bus_space_write_1(iot
, ioh
, IGS_DAC_PEL_WRITE_IDX
, 0);
1103 bus_space_write_1(iot
, ioh
, IGS_DAC_PEL_DATA
, p
[0]);
1104 bus_space_write_1(iot
, ioh
, IGS_DAC_PEL_DATA
, p
[2]);
1105 bus_space_write_1(iot
, ioh
, IGS_DAC_PEL_DATA
, p
[4]);
1107 bus_space_write_1(iot
, ioh
, IGS_DAC_PEL_WRITE_IDX
, 1);
1108 bus_space_write_1(iot
, ioh
, IGS_DAC_PEL_DATA
, p
[1]);
1109 bus_space_write_1(iot
, ioh
, IGS_DAC_PEL_DATA
, p
[3]);
1110 bus_space_write_1(iot
, ioh
, IGS_DAC_PEL_DATA
, p
[5]);
1112 /* restore access to the normal palette */
1113 igs_ext_write(iot
, ioh
, IGS_EXT_SPRITE_CTL
, curctl
);
1116 if (which
& WSDISPLAY_CURSOR_DOCUR
) {
1117 if ((curctl
& IGS_EXT_SPRITE_VISIBLE
) == 0
1119 igs_ext_write(iot
, ioh
, IGS_EXT_SPRITE_CTL
,
1120 curctl
| IGS_EXT_SPRITE_VISIBLE
);
1121 else if ((curctl
& IGS_EXT_SPRITE_VISIBLE
) != 0
1123 igs_ext_write(iot
, ioh
, IGS_EXT_SPRITE_CTL
,
1124 curctl
& ~IGS_EXT_SPRITE_VISIBLE
);
1130 * Accelerated text mode cursor that uses hardware sprite.
1133 igsfb_accel_cursor(void *cookie
, int on
, int row
, int col
)
1135 struct rasops_info
*ri
= (struct rasops_info
*)cookie
;
1136 struct vcons_screen
*scr
= ri
->ri_hw
;
1137 struct igsfb_devconfig
*dc
= scr
->scr_cookie
;
1138 struct igs_hwcursor
*cc
= &dc
->dc_cursor
;
1146 ri
->ri_flg
|= RI_CURSOR
;
1148 /* only bother to move the cursor if it's visible */
1149 cc
->cc_pos
.x
= ri
->ri_xorigin
1150 + ri
->ri_ccol
* ri
->ri_font
->fontwidth
;
1151 cc
->cc_pos
.y
= ri
->ri_yorigin
1152 + ri
->ri_crow
* ri
->ri_font
->fontheight
;
1153 which
|= WSDISPLAY_CURSOR_DOPOS
;
1155 ri
->ri_flg
&= ~RI_CURSOR
;
1157 if (dc
->dc_curenb
!= on
) {
1159 which
|= WSDISPLAY_CURSOR_DOCUR
;
1162 /* propagate changes to the device */
1163 igsfb_update_cursor(dc
, which
);
1169 * Accelerated raster ops that use graphic coprocessor.
1173 igsfb_accel_wait(struct igsfb_devconfig
*dc
)
1175 bus_space_tag_t t
= dc
->dc_iot
;
1176 bus_space_handle_t h
= dc
->dc_coph
;
1180 bus_space_write_1(t
, h
, IGS_COP_MAP_FMT_REG
, (dc
->dc_depth
>> 3) - 1);
1182 reg
= bus_space_read_1(t
, h
, IGS_COP_CTL_REG
);
1183 if ((reg
& IGS_COP_CTL_BUSY
) == 0)
1192 igsfb_accel_copy(struct igsfb_devconfig
*dc
, uint32_t src
, uint32_t dst
,
1193 uint16_t width
, uint16_t height
)
1195 bus_space_tag_t t
= dc
->dc_iot
;
1196 bus_space_handle_t h
= dc
->dc_coph
;
1200 drawcmd
= IGS_COP_DRAW_ALL
;
1202 toend
= dc
->dc_vd
.active
->scr_ri
.ri_width
* (height
- 1) + (width
- 1);
1205 drawcmd
|= IGS_COP_OCTANT_X_NEG
| IGS_COP_OCTANT_Y_NEG
;
1208 igsfb_accel_wait(dc
);
1209 bus_space_write_1(t
, h
, IGS_COP_CTL_REG
, 0);
1211 bus_space_write_1(t
, h
, IGS_COP_FG_MIX_REG
, IGS_COP_MIX_S
);
1213 bus_space_write_2(t
, h
, IGS_COP_WIDTH_REG
, width
- 1);
1214 bus_space_write_2(t
, h
, IGS_COP_HEIGHT_REG
, height
- 1);
1216 bus_space_write_4(t
, h
, IGS_COP_SRC_START_REG
, src
);
1217 bus_space_write_4(t
, h
, IGS_COP_DST_START_REG
, dst
);
1219 bus_space_write_1(t
, h
, IGS_COP_PIXEL_OP_0_REG
, drawcmd
);
1220 bus_space_write_1(t
, h
, IGS_COP_PIXEL_OP_1_REG
, IGS_COP_PPM_FIXED_FG
);
1221 bus_space_write_1(t
, h
, IGS_COP_PIXEL_OP_2_REG
, 0);
1222 bus_space_write_1(t
, h
, IGS_COP_PIXEL_OP_3_REG
,
1223 IGS_COP_OP_PXBLT
| IGS_COP_OP_FG_FROM_SRC
);
1228 igsfb_accel_fill(struct igsfb_devconfig
*dc
, uint32_t color
, uint32_t dst
,
1229 uint16_t width
, uint16_t height
)
1231 bus_space_tag_t t
= dc
->dc_iot
;
1232 bus_space_handle_t h
= dc
->dc_coph
;
1234 igsfb_accel_wait(dc
);
1235 bus_space_write_1(t
, h
, IGS_COP_CTL_REG
, 0);
1237 bus_space_write_1(t
, h
, IGS_COP_FG_MIX_REG
, IGS_COP_MIX_S
);
1239 bus_space_write_2(t
, h
, IGS_COP_WIDTH_REG
, width
- 1);
1240 bus_space_write_2(t
, h
, IGS_COP_HEIGHT_REG
, height
- 1);
1242 bus_space_write_4(t
, h
, IGS_COP_DST_START_REG
, dst
);
1243 bus_space_write_4(t
, h
, IGS_COP_FG_REG
, color
);
1245 bus_space_write_1(t
, h
, IGS_COP_PIXEL_OP_0_REG
, IGS_COP_DRAW_ALL
);
1246 bus_space_write_1(t
, h
, IGS_COP_PIXEL_OP_1_REG
, IGS_COP_PPM_FIXED_FG
);
1247 bus_space_write_1(t
, h
, IGS_COP_PIXEL_OP_2_REG
, 0);
1248 bus_space_write_1(t
, h
, IGS_COP_PIXEL_OP_3_REG
, IGS_COP_OP_PXBLT
);
1253 igsfb_accel_copyrows(void *cookie
, int src
, int dst
, int num
)
1255 struct rasops_info
*ri
= (struct rasops_info
*)cookie
;
1256 struct vcons_screen
*scr
= ri
->ri_hw
;
1257 struct igsfb_devconfig
*dc
= (struct igsfb_devconfig
*)scr
->scr_cookie
;
1259 uint16_t width
, height
;
1261 width
= ri
->ri_emuwidth
;
1262 height
= num
* ri
->ri_font
->fontheight
;
1264 srp
= ri
->ri_xorigin
1265 + ri
->ri_width
* (ri
->ri_yorigin
1266 + src
* ri
->ri_font
->fontheight
);
1267 dsp
= ri
->ri_xorigin
1268 + ri
->ri_width
* (ri
->ri_yorigin
1269 + dst
* ri
->ri_font
->fontheight
);
1271 igsfb_accel_copy(dc
, srp
, dsp
, width
, height
);
1276 igsfb_accel_copycols(void *cookie
, int row
, int src
, int dst
, int num
)
1278 struct rasops_info
*ri
= (struct rasops_info
*)cookie
;
1279 struct vcons_screen
*scr
= ri
->ri_hw
;
1280 struct igsfb_devconfig
*dc
= (struct igsfb_devconfig
*)scr
->scr_cookie
;
1281 uint32_t rowp
, srp
, dsp
;
1282 uint16_t width
, height
;
1284 width
= num
* ri
->ri_font
->fontwidth
;
1285 height
= ri
->ri_font
->fontheight
;
1287 rowp
= ri
->ri_xorigin
1288 + ri
->ri_width
* (ri
->ri_yorigin
1289 + row
* ri
->ri_font
->fontheight
);
1291 srp
= rowp
+ src
* ri
->ri_font
->fontwidth
;
1292 dsp
= rowp
+ dst
* ri
->ri_font
->fontwidth
;
1294 igsfb_accel_copy(dc
, srp
, dsp
, width
, height
);
1299 igsfb_accel_eraserows(void *cookie
, int row
, int num
, long attr
)
1301 struct rasops_info
*ri
= (struct rasops_info
*)cookie
;
1302 struct vcons_screen
*scr
= ri
->ri_hw
;
1303 struct igsfb_devconfig
*dc
= (struct igsfb_devconfig
*)scr
->scr_cookie
;
1306 uint16_t width
, height
;
1308 if (num
== ri
->ri_rows
&& (ri
->ri_flg
& RI_FULLCLEAR
) != 0) {
1309 width
= ri
->ri_width
;
1310 height
= ri
->ri_height
;
1313 width
= ri
->ri_emuwidth
;
1314 height
= num
* ri
->ri_font
->fontheight
;
1316 dsp
= ri
->ri_xorigin
1317 + ri
->ri_width
* (ri
->ri_yorigin
1318 + row
* ri
->ri_font
->fontheight
);
1321 /* XXX: we "know" the encoding that rasops' allocattr uses */
1322 color
= (attr
>> 16) & 0xff;
1324 igsfb_accel_fill(dc
, color
, dsp
, width
, height
);
1329 igsfb_accel_erasecols(void *cookie
, int row
, int col
, int num
, long attr
)
1331 struct rasops_info
*ri
= (struct rasops_info
*)cookie
;
1332 struct vcons_screen
*scr
= ri
->ri_hw
;
1333 struct igsfb_devconfig
*dc
= (struct igsfb_devconfig
*)scr
->scr_cookie
;
1336 uint16_t width
, height
;
1338 width
= num
* ri
->ri_font
->fontwidth
;
1339 height
= ri
->ri_font
->fontheight
;
1341 rowp
= ri
->ri_xorigin
1342 + ri
->ri_width
* (ri
->ri_yorigin
1343 + row
* ri
->ri_font
->fontheight
);
1345 dsp
= rowp
+ col
* ri
->ri_font
->fontwidth
;
1347 /* XXX: we "know" the encoding that rasops' allocattr uses */
1348 color
= (attr
>> 16) & 0xff;
1350 igsfb_accel_fill(dc
, color
, dsp
, width
, height
);
1355 * Not really implemented here, but we need to hook into the one
1356 * supplied by rasops so that we can synchronize with the COP.
1359 igsfb_accel_putchar(void *cookie
, int row
, int col
, u_int uc
, long attr
)
1361 struct rasops_info
*ri
= (struct rasops_info
*)cookie
;
1362 struct vcons_screen
*scr
= ri
->ri_hw
;
1363 struct igsfb_devconfig
*dc
= (struct igsfb_devconfig
*)scr
->scr_cookie
;
1365 igsfb_accel_wait(dc
);
1366 (*dc
->dc_ri_putchar
)(cookie
, row
, col
, uc
, attr
);