1 /* $NetBSD: tcx.c,v 1.41 2009/09/17 16:28:13 tsutsui Exp $ */
4 * Copyright (c) 1996, 1998, 2009 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Paul Kranenburg and Michael Lorenz.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * color display (TCX) driver.
35 * Does not handle interrupts, even though they can occur.
37 * XXX should defer colormap updates to vertical retrace interrupts
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: tcx.c,v 1.41 2009/09/17 16:28:13 tsutsui Exp $");
44 * define for cg8 emulation on S24 (24-bit version of tcx) for the SS5;
45 * it is bypassed on the 8-bit version (onboard framebuffer for SS4)
49 #include <sys/param.h>
50 #include <sys/systm.h>
52 #include <sys/device.h>
53 #include <sys/ioctl.h>
54 #include <sys/malloc.h>
61 #include <sys/syslog.h>
65 #include <machine/autoconf.h>
67 #include <dev/sun/fbio.h>
68 #include <dev/sun/fbvar.h>
69 #include <dev/sun/btreg.h>
70 #include <dev/sun/btvar.h>
72 #include <dev/sbus/sbusvar.h>
73 #include <dev/sbus/tcxreg.h>
75 #include <dev/wscons/wsdisplayvar.h>
76 #include <dev/wscons/wsconsio.h>
77 #include <dev/wsfont/wsfont.h>
78 #include <dev/rasops/rasops.h>
80 #include <dev/wscons/wsdisplay_vconsvar.h>
82 #include "opt_wsemul.h"
86 /* per-display variables */
88 device_t sc_dev
; /* base device */
89 struct fbdevice sc_fb
; /* frame buffer device */
90 bus_space_tag_t sc_bustag
;
91 struct openprom_addr sc_physaddr
[TCX_NREG
];/* phys addr of h/w */
93 bus_space_handle_t sc_bt
; /* Brooktree registers */
94 bus_space_handle_t sc_thc
; /* THC registers */
95 uint8_t *sc_fbaddr
; /* framebuffer */
96 uint64_t *sc_rblit
; /* blitspace */
97 uint64_t *sc_rstip
; /* stipple space */
99 short sc_8bit
; /* true if 8-bit hardware */
100 short sc_blanked
; /* true if blanked */
101 u_char sc_cmap_red
[256];
102 u_char sc_cmap_green
[256];
103 u_char sc_cmap_blue
[256];
105 int sc_cursor_x
, sc_cursor_y
;
106 int sc_hotspot_x
, sc_hotspot_y
;
107 struct vcons_data vd
;
110 static struct vcons_screen tcx_console_screen
;
112 extern const u_char rasops_cmap
[768];
114 struct wsscreen_descr tcx_defscreendesc
= {
122 const struct wsscreen_descr
*_tcx_scrlist
[] = {
124 /* XXX other formats, graphics screen? */
127 struct wsscreen_list tcx_screenlist
= {
128 sizeof(_tcx_scrlist
) / sizeof(struct wsscreen_descr
*),
133 * The S24 provides the framebuffer RAM mapped in three ways:
134 * 26 bits per pixel, in 32-bit words; the low-order 24 bits are
135 * blue, green, and red values, and the other two bits select the
136 * display modes, per pixel);
137 * 24 bits per pixel, in 32-bit words; the high-order byte reads as
138 * zero, and is ignored on writes (so the mode bits cannot be altered);
139 * 8 bits per pixel, unpadded; writes to this space do not modify the
142 #define TCX_CTL_8_MAPPED 0x00000000 /* 8 bits, uses color map */
143 #define TCX_CTL_24_MAPPED 0x01000000 /* 24 bits, uses color map */
144 #define TCX_CTL_24_LEVEL 0x03000000 /* 24 bits, ignores color map */
145 #define TCX_CTL_PIXELMASK 0x00FFFFFF /* mask for index/level */
147 /* autoconfiguration driver */
148 static void tcxattach(device_t
, device_t
, void *);
149 static int tcxmatch(device_t
, cfdata_t
, void *);
150 static void tcx_unblank(device_t
);
152 CFATTACH_DECL_NEW(tcx
, sizeof(struct tcx_softc
),
153 tcxmatch
, tcxattach
, NULL
, NULL
);
155 dev_type_open(tcxopen
);
156 dev_type_close(tcxclose
);
157 dev_type_ioctl(tcxioctl
);
158 dev_type_mmap(tcxmmap
);
160 const struct cdevsw tcx_cdevsw
= {
161 tcxopen
, tcxclose
, noread
, nowrite
, tcxioctl
,
162 nostop
, notty
, nopoll
, tcxmmap
, nokqfilter
,
165 /* frame buffer generic driver */
166 static struct fbdriver tcx_fbdriver
= {
167 tcx_unblank
, tcxopen
, tcxclose
, tcxioctl
, nopoll
, tcxmmap
,
171 static void tcx_reset(struct tcx_softc
*);
172 static void tcx_loadcmap(struct tcx_softc
*, int, int);
174 static int tcx_ioctl(void *, void *, u_long
, void *, int, struct lwp
*);
175 static paddr_t
tcx_mmap(void *, void *, off_t
, int);
177 static void tcx_init_screen(void *, struct vcons_screen
*, int, long *);
178 static void tcx_clearscreen(struct tcx_softc
*, int);
179 static void tcx_copyrows(void *, int, int, int);
180 static void tcx_eraserows(void *, int, int, long);
181 static void tcx_putchar(void *, int, int, u_int
, long);
182 static void tcx_set_video(struct tcx_softc
*, int);
183 static int tcx_do_cursor(struct tcx_softc
*, struct wsdisplay_cursor
*);
184 static void tcx_set_cursor(struct tcx_softc
*);
186 struct wsdisplay_accessops tcx_accessops
= {
189 NULL
, /* vcons_alloc_screen */
190 NULL
, /* vcons_free_screen */
191 NULL
, /* vcons_show_screen */
192 NULL
, /* load_font */
197 #define OBPNAME "SUNW,tcx"
201 * For CG8 emulation, we map the 32-bit-deep framebuffer at an offset of
202 * 256K; the cg8 space begins with a mono overlay plane and an overlay
203 * enable plane (128K bytes each, 1 bit per pixel), immediately followed
204 * by the color planes, 32 bits per pixel. We also map just the 32-bit
205 * framebuffer at 0x04000000 (TCX_USER_RAM_COMPAT), for compatibility
206 * with the cg8 driver.
208 #define TCX_CG8OVERLAY (256 * 1024)
209 #define TCX_SIZE_DFB32 (1152 * 900 * 4) /* max size of the framebuffer */
216 tcxmatch(device_t parent
, cfdata_t cf
, void *aux
)
218 struct sbus_attach_args
*sa
= aux
;
220 return (strcmp(sa
->sa_name
, OBPNAME
) == 0);
227 tcxattach(device_t parent
, device_t self
, void *args
)
229 struct tcx_softc
*sc
= device_private(self
);
230 struct sbus_attach_args
*sa
= args
;
231 struct wsemuldisplaydev_attach_args aa
;
232 struct rasops_info
*ri
;
233 unsigned long defattr
;
235 struct fbdevice
*fb
= &sc
->sc_fb
;
236 bus_space_handle_t bh
;
241 sc
->sc_bustag
= sa
->sa_bustag
;
244 sc
->sc_cursor_x
= 0x7fff;
245 sc
->sc_cursor_y
= 0x7fff;
246 sc
->sc_hotspot_x
= 0;
247 sc
->sc_hotspot_y
= 0;
249 fb
->fb_driver
= &tcx_fbdriver
;
250 fb
->fb_device
= sc
->sc_dev
;
251 /* Mask out invalid flags from the user. */
252 fb
->fb_flags
= device_cfdata(sc
->sc_dev
)->cf_flags
& FB_USERMASK
;
254 * The onboard framebuffer on the SS4 supports only 8-bit mode;
255 * it can be distinguished from the S24 card for the SS5 by the
256 * presence of the "tcx-8-bit" attribute on the SS4 version.
258 sc
->sc_8bit
= node_has_property(node
, "tcx-8-bit");
259 fb
->fb_type
.fb_depth
= 8;
260 fb_setsize_obp(fb
, fb
->fb_type
.fb_depth
, 1152, 900, node
);
263 printf(" (8bit only TCX)");
264 ramsize
= 1024 * 1024;
265 /* XXX - fix THC and TEC offsets */
266 sc
->sc_physaddr
[TCX_REG_TEC
].oa_base
+= 0x1000;
267 sc
->sc_physaddr
[TCX_REG_THC
].oa_base
+= 0x1000;
270 ramsize
= 4 * 1024 * 1024;
273 fb
->fb_type
.fb_cmsize
= 256;
274 fb
->fb_type
.fb_size
= ramsize
;
275 printf("%s: %s, %d x %d", device_xname(self
), OBPNAME
,
276 fb
->fb_type
.fb_width
,
277 fb
->fb_type
.fb_height
);
279 fb
->fb_type
.fb_type
= FBTYPE_TCXCOLOR
;
282 if (sa
->sa_nreg
!= TCX_NREG
) {
283 printf("%s: only %d register sets\n",
284 device_xname(self
), sa
->sa_nreg
);
287 memcpy(sc
->sc_physaddr
, sa
->sa_reg
,
288 sa
->sa_nreg
* sizeof(struct openprom_addr
));
290 /* Map the register banks we care about */
291 if (sbus_bus_map(sa
->sa_bustag
,
292 sc
->sc_physaddr
[TCX_REG_THC
].oa_space
,
293 sc
->sc_physaddr
[TCX_REG_THC
].oa_base
,
295 BUS_SPACE_MAP_LINEAR
, &sc
->sc_thc
) != 0) {
296 printf("tcxattach: cannot map thc registers\n");
300 if (sbus_bus_map(sa
->sa_bustag
,
301 sc
->sc_physaddr
[TCX_REG_CMAP
].oa_space
,
302 sc
->sc_physaddr
[TCX_REG_CMAP
].oa_base
,
304 BUS_SPACE_MAP_LINEAR
, &sc
->sc_bt
) != 0) {
305 printf("tcxattach: cannot map bt registers\n");
309 /* map the 8bit dumb FB for the console */
310 if (sbus_bus_map(sa
->sa_bustag
,
311 sc
->sc_physaddr
[TCX_REG_DFB8
].oa_space
,
312 sc
->sc_physaddr
[TCX_REG_DFB8
].oa_base
,
314 BUS_SPACE_MAP_LINEAR
,
316 printf("tcxattach: cannot map framebuffer\n");
319 sc
->sc_fbaddr
= bus_space_vaddr(sa
->sa_bustag
, bh
);
322 if (sbus_bus_map(sa
->sa_bustag
,
323 sc
->sc_physaddr
[TCX_REG_RBLIT
].oa_space
,
324 sc
->sc_physaddr
[TCX_REG_RBLIT
].oa_base
,
326 BUS_SPACE_MAP_LINEAR
| BUS_SPACE_MAP_LARGE
,
328 printf("tcxattach: cannot map RBLIT space\n");
331 sc
->sc_rblit
= bus_space_vaddr(sa
->sa_bustag
, bh
);
334 if (sbus_bus_map(sa
->sa_bustag
,
335 sc
->sc_physaddr
[TCX_REG_RSTIP
].oa_space
,
336 sc
->sc_physaddr
[TCX_REG_RSTIP
].oa_base
,
338 BUS_SPACE_MAP_LINEAR
| BUS_SPACE_MAP_LARGE
,
340 printf("tcxattach: cannot map RSTIP space\n");
343 sc
->sc_rstip
= bus_space_vaddr(sa
->sa_bustag
, bh
);
345 isconsole
= fb_is_console(node
);
347 confreg
= bus_space_read_4(sa
->sa_bustag
, sc
->sc_thc
, THC_CONFIG
);
348 printf(", id %d, rev %d, sense %d",
349 (confreg
& THC_CFG_FBID
) >> THC_CFG_FBID_SHIFT
,
350 (confreg
& THC_CFG_REV
) >> THC_CFG_REV_SHIFT
,
351 (confreg
& THC_CFG_SENSE
) >> THC_CFG_SENSE_SHIFT
354 /* reset cursor & frame buffer controls */
357 /* Initialize the default color map. */
359 for (i
= 0; i
< 256; i
++) {
361 sc
->sc_cmap_red
[i
] = rasops_cmap
[j
];
362 sc
->sc_cmap_green
[i
] = rasops_cmap
[j
+ 1];
363 sc
->sc_cmap_blue
[i
] = rasops_cmap
[j
+ 2];
366 tcx_loadcmap(sc
, 0, 256);
370 confreg
= bus_space_read_4(sa
->sa_bustag
, sc
->sc_thc
, THC_MISC
);
371 confreg
|= THC_MISC_VIDEN
;
372 bus_space_write_4(sa
->sa_bustag
, sc
->sc_thc
, THC_MISC
, confreg
);
375 printf(" (console)\n");
379 fb_attach(&sc
->sc_fb
, isconsole
);
381 sc
->sc_mode
= WSDISPLAYIO_MODE_EMUL
;
384 vcons_init(&sc
->vd
, sc
, &tcx_defscreendesc
, &tcx_accessops
);
385 sc
->vd
.init_screen
= tcx_init_screen
;
387 vcons_init_screen(&sc
->vd
, &tcx_console_screen
, 1, &defattr
);
388 tcx_console_screen
.scr_flags
|= VCONS_SCREEN_IS_STATIC
;
390 sc
->sc_bg
= (defattr
>> 16) & 0xff;
391 tcx_clearscreen(sc
, 0);
393 ri
= &tcx_console_screen
.scr_ri
;
395 tcx_defscreendesc
.nrows
= ri
->ri_rows
;
396 tcx_defscreendesc
.ncols
= ri
->ri_cols
;
397 tcx_defscreendesc
.textops
= &ri
->ri_ops
;
398 tcx_defscreendesc
.capabilities
= ri
->ri_caps
;
401 wsdisplay_cnattach(&tcx_defscreendesc
, ri
, 0, 0, defattr
);
402 vcons_replay_msgbuf(&tcx_console_screen
);
405 aa
.console
= isconsole
;
406 aa
.scrdata
= &tcx_screenlist
;
407 aa
.accessops
= &tcx_accessops
;
408 aa
.accesscookie
= &sc
->vd
;
410 config_found(self
, &aa
, wsemuldisplaydevprint
);
412 * we need to do this again - something overwrites a handful
413 * palette registers and we end up with white in reg. 0
415 tcx_loadcmap(sc
, 0, 256);
419 tcxopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
425 tcxclose(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
427 struct tcx_softc
*sc
= device_lookup_private(&tcx_cd
, minor(dev
));
430 /* we may want to clear and redraw the console here */
435 tcxioctl(dev_t dev
, u_long cmd
, void *data
, int flags
, struct lwp
*l
)
437 struct tcx_softc
*sc
= device_lookup_private(&tcx_cd
, minor(dev
));
442 *(struct fbtype
*)data
= sc
->sc_fb
.fb_type
;
446 #define fba ((struct fbgattr *)data)
447 fba
->real_type
= sc
->sc_fb
.fb_type
.fb_type
;
448 fba
->owner
= 0; /* XXX ??? */
449 fba
->fbtype
= sc
->sc_fb
.fb_type
;
450 fba
->sattr
.flags
= 0;
451 fba
->sattr
.emu_type
= sc
->sc_fb
.fb_type
.fb_type
;
452 fba
->sattr
.dev_specific
[0] = -1;
453 fba
->emu_types
[0] = sc
->sc_fb
.fb_type
.fb_type
;
454 fba
->emu_types
[1] = FBTYPE_SUN3COLOR
;
455 fba
->emu_types
[2] = -1;
460 #define p ((struct fbcmap *)data)
461 if (copyout(&sc
->sc_cmap_red
[p
->index
], p
->red
, p
->count
) != 0)
463 if (copyout(&sc
->sc_cmap_green
[p
->index
], p
->green
, p
->count
)
466 if (copyout(&sc
->sc_cmap_blue
[p
->index
], p
->blue
, p
->count
)
472 /* copy to software map */
473 if (copyin(p
->red
, &sc
->sc_cmap_red
[p
->index
], p
->count
) != 0)
475 if (copyin(p
->green
, &sc
->sc_cmap_green
[p
->index
], p
->count
)
478 if (copyin(p
->blue
, &sc
->sc_cmap_blue
[p
->index
], p
->count
) != 0)
480 tcx_loadcmap(sc
, p
->index
, p
->count
);
484 *(int *)data
= sc
->sc_blanked
;
488 tcx_set_video(sc
, *(int *)data
);
493 log(LOG_NOTICE
, "tcxioctl(0x%lx) (%s[%d])\n", cmd
,
494 l
->l_proc
->p_comm
, l
->l_proc
->p_pid
);
502 * Clean up hardware state (e.g., after bootup or after X crashes).
505 tcx_reset(struct tcx_softc
*sc
)
509 reg
= bus_space_read_4(sc
->sc_bustag
, sc
->sc_thc
, THC_MISC
);
510 reg
|= THC_MISC_CURSRES
;
511 bus_space_write_4(sc
->sc_bustag
, sc
->sc_thc
, THC_MISC
, reg
);
515 tcx_loadcmap(struct tcx_softc
*sc
, int start
, int ncolors
)
519 for (i
= 0; i
< ncolors
; i
++) {
520 bus_space_write_4(sc
->sc_bustag
, sc
->sc_bt
, DAC_ADDRESS
,
522 bus_space_write_4(sc
->sc_bustag
, sc
->sc_bt
, DAC_FB_LUT
,
523 sc
->sc_cmap_red
[i
+ start
] << 24);
524 bus_space_write_4(sc
->sc_bustag
, sc
->sc_bt
, DAC_FB_LUT
,
525 sc
->sc_cmap_green
[i
+ start
] << 24);
526 bus_space_write_4(sc
->sc_bustag
, sc
->sc_bt
, DAC_FB_LUT
,
527 sc
->sc_cmap_blue
[i
+ start
] << 24);
529 bus_space_write_4(sc
->sc_bustag
, sc
->sc_bt
, DAC_ADDRESS
, 0);
533 tcx_unblank(device_t dev
)
535 struct tcx_softc
*sc
= device_private(dev
);
537 if (sc
->sc_blanked
) {
540 reg
= bus_space_read_4(sc
->sc_bustag
, sc
->sc_thc
, THC_MISC
);
541 reg
&= ~THC_MISC_VSYNC_DISABLE
;
542 reg
&= ~THC_MISC_HSYNC_DISABLE
;
543 reg
|= THC_MISC_VIDEN
;
544 bus_space_write_4(sc
->sc_bustag
, sc
->sc_thc
, THC_MISC
, reg
);
549 tcx_set_video(struct tcx_softc
*sc
, int unblank
)
554 reg
= bus_space_read_4(sc
->sc_bustag
, sc
->sc_thc
, THC_MISC
);
555 reg
&= ~THC_MISC_VSYNC_DISABLE
;
556 reg
&= ~THC_MISC_HSYNC_DISABLE
;
557 reg
|= THC_MISC_VIDEN
;
558 bus_space_write_4(sc
->sc_bustag
, sc
->sc_thc
, THC_MISC
, reg
);
561 reg
= bus_space_read_4(sc
->sc_bustag
, sc
->sc_thc
, THC_MISC
);
562 reg
|= THC_MISC_VSYNC_DISABLE
;
563 reg
|= THC_MISC_HSYNC_DISABLE
;
564 reg
&= ~THC_MISC_VIDEN
;
565 bus_space_write_4(sc
->sc_bustag
, sc
->sc_thc
, THC_MISC
, reg
);
570 * Base addresses at which users can mmap() the various pieces of a tcx.
572 #define TCX_USER_RAM 0x00000000
573 #define TCX_USER_RAM24 0x01000000
574 #define TCX_USER_RAM_COMPAT 0x04000000 /* cg3 emulation */
575 #define TCX_USER_STIP 0x10000000
576 #define TCX_USER_BLIT 0x20000000
577 #define TCX_USER_RDFB32 0x28000000
578 #define TCX_USER_RSTIP 0x30000000
579 #define TCX_USER_RBLIT 0x38000000
580 #define TCX_USER_TEC 0x70001000
581 #define TCX_USER_BTREGS 0x70002000
582 #define TCX_USER_THC 0x70004000
583 #define TCX_USER_DHC 0x70008000
584 #define TCX_USER_ALT 0x7000a000
585 #define TCX_USER_UART 0x7000c000
586 #define TCX_USER_VRT 0x7000e000
587 #define TCX_USER_ROM 0x70010000
590 u_int mo_uaddr
; /* user (virtual) address */
591 u_int mo_size
; /* size, or 0 for video ram size */
592 u_int mo_bank
; /* register bank number */
596 * Return the address that would map the given device at the given
597 * offset, allowing for the given protection, or return -1 for error.
599 * XXX needs testing against `demanding' applications (e.g., aviator)
602 tcxmmap(dev_t dev
, off_t off
, int prot
)
604 struct tcx_softc
*sc
= device_lookup_private(&tcx_cd
, minor(dev
));
605 struct openprom_addr
*rr
= sc
->sc_physaddr
;
606 struct mmo
*mo
, *mo_end
;
608 static struct mmo mmo
[] = {
609 { TCX_USER_RAM
, 0, TCX_REG_DFB8
},
610 { TCX_USER_RAM24
, 0, TCX_REG_DFB24
},
611 { TCX_USER_RAM_COMPAT
, 0, TCX_REG_DFB8
},
613 { TCX_USER_STIP
, 1, TCX_REG_STIP
},
614 { TCX_USER_BLIT
, 1, TCX_REG_BLIT
},
615 { TCX_USER_RDFB32
, 0, TCX_REG_RDFB32
},
616 { TCX_USER_RSTIP
, 1, TCX_REG_RSTIP
},
617 { TCX_USER_RBLIT
, 1, TCX_REG_RBLIT
},
618 { TCX_USER_TEC
, 1, TCX_REG_TEC
},
619 { TCX_USER_BTREGS
, 8192 /* XXX */, TCX_REG_CMAP
},
620 { TCX_USER_THC
, 0x2000, TCX_REG_THC
},
621 { TCX_USER_DHC
, 1, TCX_REG_DHC
},
622 { TCX_USER_ALT
, 1, TCX_REG_ALT
},
623 { TCX_USER_ROM
, 65536, TCX_REG_ROM
},
625 #define NMMO (sizeof mmo / sizeof *mmo)
631 * Entries with size 0 map video RAM (i.e., the size in fb data).
632 * Entries that map 32-bit deep regions are adjusted for their
633 * depth (fb_size gives the size of the 8-bit-deep region).
635 * Since we work in pages, the fact that the map offset table's
636 * sizes are sometimes bizarre (e.g., 1) is effectively ignored:
637 * one byte is as good as one page.
643 for (; mo
< mo_end
; mo
++) {
644 if ((u_int
)off
< mo
->mo_uaddr
)
647 u
= off
- mo
->mo_uaddr
;
651 sz
= sc
->sc_fb
.fb_type
.fb_size
;
653 * check for the 32-bit-deep regions and adjust
656 if (mo
->mo_uaddr
== TCX_USER_RAM24
||
657 mo
->mo_uaddr
== TCX_USER_RDFB32
) {
660 * not present on 8-bit hardware
668 sz
= rr
[mo
->mo_bank
].oa_size
;
671 return (bus_space_mmap(sc
->sc_bustag
,
672 BUS_ADDR(rr
[mo
->mo_bank
].oa_space
,
673 rr
[mo
->mo_bank
].oa_base
),
676 BUS_SPACE_MAP_LINEAR
));
683 tcx_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
,
686 struct vcons_data
*vd
= v
;
687 struct tcx_softc
*sc
= vd
->cookie
;
688 struct wsdisplay_fbinfo
*wdf
;
689 struct vcons_screen
*ms
= vd
->active
;
692 case WSDISPLAYIO_GTYPE
:
693 *(u_int
*)data
= WSDISPLAY_TYPE_SUNTCX
;
697 case WSDISPLAYIO_GVIDEO
:
698 *(int *)data
= !sc
->sc_blanked
;
701 case WSDISPLAYIO_SVIDEO
:
703 tcx_set_video(sc
, *(int *)data
);
706 case WSDISPLAYIO_GINFO
:
708 wdf
->height
= ms
->scr_ri
.ri_height
;
709 wdf
->width
= ms
->scr_ri
.ri_width
;
717 case WSDISPLAYIO_LINEBYTES
:
719 int *ret
= (int *)data
;
720 *ret
= sc
->sc_8bit
? ms
->scr_ri
.ri_width
:
721 ms
->scr_ri
.ri_width
<< 2;
725 case WSDISPLAYIO_GETCMAP
:
726 return tcx_getcmap(sc
, (struct wsdisplay_cmap
*)data
);
728 case WSDISPLAYIO_PUTCMAP
:
729 return tcx_putcmap(sc
, (struct wsdisplay_cmap
*)data
);
731 case WSDISPLAYIO_SMODE
:
733 int new_mode
= *(int*)data
;
734 if (new_mode
!= sc
->sc_mode
)
736 sc
->sc_mode
= new_mode
;
737 if (new_mode
== WSDISPLAYIO_MODE_EMUL
)
739 tcx_loadcmap(sc
, 0, 256);
740 tcx_clearscreen(sc
, 0);
741 vcons_redraw_screen(ms
);
742 } else if (!sc
->sc_8bit
)
743 tcx_clearscreen(sc
, 3);
746 case WSDISPLAYIO_GCURPOS
:
748 struct wsdisplay_curpos
*cp
= (void *)data
;
750 cp
->x
= sc
->sc_cursor_x
;
751 cp
->y
= sc
->sc_cursor_y
;
755 case WSDISPLAYIO_SCURPOS
:
757 struct wsdisplay_curpos
*cp
= (void *)data
;
759 sc
->sc_cursor_x
= cp
->x
;
760 sc
->sc_cursor_y
= cp
->y
;
765 case WSDISPLAYIO_GCURMAX
:
767 struct wsdisplay_curpos
*cp
= (void *)data
;
774 case WSDISPLAYIO_SCURSOR
:
776 struct wsdisplay_cursor
*cursor
= (void *)data
;
778 return tcx_do_cursor(sc
, cursor
);
785 tcx_mmap(void *v
, void *vs
, off_t offset
, int prot
)
787 struct vcons_data
*vd
= v
;
788 struct tcx_softc
*sc
= vd
->cookie
;
790 /* 'regular' framebuffer mmap()ing */
792 /* on 8Bit boards hand over the 8 bit aperture */
793 if (offset
> 1024 * 1024)
795 return bus_space_mmap(sc
->sc_bustag
,
796 sc
->sc_physaddr
[TCX_REG_DFB8
].oa_base
+ offset
, 0, prot
,
797 BUS_SPACE_MAP_LINEAR
);
799 /* ... but if we have a 24bit aperture we use it */
800 if (offset
> 1024 * 1024 * 4)
802 return bus_space_mmap(sc
->sc_bustag
,
803 sc
->sc_physaddr
[TCX_REG_DFB24
].oa_base
+ offset
, 0, prot
,
804 BUS_SPACE_MAP_LINEAR
);
810 tcx_init_screen(void *cookie
, struct vcons_screen
*scr
,
811 int existing
, long *defattr
)
813 struct tcx_softc
*sc
= cookie
;
814 struct rasops_info
*ri
= &scr
->scr_ri
;
817 ri
->ri_width
= sc
->sc_fb
.fb_type
.fb_width
;
818 ri
->ri_height
= sc
->sc_fb
.fb_type
.fb_height
;
819 ri
->ri_stride
= sc
->sc_fb
.fb_linebytes
;
820 ri
->ri_flg
= RI_CENTER
| RI_FULLCLEAR
;
822 ri
->ri_bits
= sc
->sc_fbaddr
;
824 rasops_init(ri
, ri
->ri_height
/8, ri
->ri_width
/8);
825 ri
->ri_caps
= WSSCREEN_WSCOLORS
;
826 rasops_reconfig(ri
, ri
->ri_height
/ ri
->ri_font
->fontheight
,
827 ri
->ri_width
/ ri
->ri_font
->fontwidth
);
829 /* enable acceleration */
830 ri
->ri_ops
.copyrows
= tcx_copyrows
;
831 ri
->ri_ops
.eraserows
= tcx_eraserows
;
832 ri
->ri_ops
.putchar
= tcx_putchar
;
834 ri
->ri_ops
.cursor
= tcx_cursor
;
835 ri
->ri_ops
.copycols
= tcx_copycols
;
836 ri
->ri_ops
.erasecols
= tcx_erasecols
;
841 tcx_clearscreen(struct tcx_softc
*sc
, int spc
)
843 uint64_t bg
= ((uint64_t)sc
->sc_bg
<< 32) | 0xffffffffLL
;
850 for (i
= 0; i
< 1024 * 1024; i
+= 32)
851 sc
->sc_rstip
[i
] = bg
| spc64
;
855 tcx_copyrows(void *cookie
, int srcrow
, int dstrow
, int nrows
)
857 struct rasops_info
*ri
= cookie
;
858 struct vcons_screen
*scr
= ri
->ri_hw
;
859 struct tcx_softc
*sc
= scr
->scr_cookie
;
860 int i
, last
, first
, len
, dest
, leftover
;
862 i
= ri
->ri_width
* ri
->ri_font
->fontheight
* nrows
;
865 if (srcrow
< dstrow
) {
866 /* we must go bottom to top */
867 first
= ri
->ri_width
*
868 (ri
->ri_font
->fontheight
* srcrow
+ ri
->ri_yorigin
);
870 dest
= ri
->ri_width
*
871 (ri
->ri_font
->fontheight
* dstrow
+ ri
->ri_yorigin
) + len
;
873 sc
->sc_rblit
[dest
+ 32] =
874 (uint64_t)((leftover
- 1) << 24) |
877 for (i
= last
; i
>= first
; i
-= 32) {
878 sc
->sc_rblit
[dest
] = 0x300000001f000000LL
| (uint64_t)i
;
883 first
= ri
->ri_width
*
884 (ri
->ri_font
->fontheight
* srcrow
+ ri
->ri_yorigin
);
885 dest
= ri
->ri_width
*
886 (ri
->ri_font
->fontheight
* dstrow
+ ri
->ri_yorigin
);
888 for (i
= first
; i
<= last
; i
+= 32) {
889 sc
->sc_rblit
[dest
] = 0x300000001f000000LL
| (uint64_t)i
;
894 (uint64_t)((leftover
- 1) << 24) | (uint64_t)i
;
900 tcx_eraserows(void *cookie
, int start
, int nrows
, long attr
)
902 struct rasops_info
*ri
= cookie
;
903 struct vcons_screen
*scr
= ri
->ri_hw
;
904 struct tcx_softc
*sc
= scr
->scr_cookie
;
906 int i
, last
, first
, len
, leftover
;
908 i
= ri
->ri_width
* ri
->ri_font
->fontheight
* nrows
;
911 first
= ri
->ri_width
*
912 (ri
->ri_font
->fontheight
* start
+ ri
->ri_yorigin
);
914 temp
= 0x30000000ffffffffLL
|
915 ((uint64_t)ri
->ri_devcmap
[(attr
>> 16) & 0xff] << 32);
917 for (i
= first
; i
<= last
; i
+= 32)
918 sc
->sc_rblit
[i
] = temp
;
921 temp
&= 0xffffffffffffffffLL
<< (32 - leftover
);
922 sc
->sc_rblit
[i
] = temp
;
926 * The stipple engine is 100% retarded. All drawing operations have to start
927 * at 32 pixel boundaries so we'll have to deal with characters being split.
931 tcx_putchar(void *cookie
, int row
, int col
, u_int c
, long attr
)
933 struct rasops_info
*ri
= cookie
;
934 struct vcons_screen
*scr
= ri
->ri_hw
;
935 struct tcx_softc
*sc
= scr
->scr_cookie
;
936 uint64_t bg
, fg
, temp
, mask
;
937 int addr
, i
, uc
, shift
;
942 addr
= ri
->ri_xorigin
+
943 col
* ri
->ri_font
->fontwidth
+
944 (ri
->ri_yorigin
+ row
* ri
->ri_font
->fontheight
) * ri
->ri_width
;
946 /* check if the character is crossing a 32 pixel boundary */
947 if ((addr
& 0xffffe0) ==
948 ((addr
+ ri
->ri_font
->fontwidth
- 1) & 0xffffe0)) {
949 /* phew, not split */
952 fmask
= 0xffffffff >> (32 - ri
->ri_font
->fontwidth
);
953 fmask
= fmask
<< (32 - ri
->ri_font
->fontwidth
- shift
);
955 bg
= 0x3000000000000000LL
|
956 ((uint64_t)ri
->ri_devcmap
[(attr
>> 16) & 0xff] &
959 temp
= 0x3000000000000000LL
|
960 ((uint64_t)ri
->ri_devcmap
[(attr
>> 24) & 0xff] & 0xff) <<
962 uc
= c
- ri
->ri_font
->firstchar
;
963 cdata
= (uint8_t *)ri
->ri_font
->data
+ uc
* ri
->ri_fontscale
;
965 if (ri
->ri_font
->fontwidth
< 9) {
967 for (i
= 0; i
< ri
->ri_font
->fontheight
; i
++) {
968 sc
->sc_rstip
[addr
] = bg
;
971 fg
= (uint64_t)*cdata
>>
974 fg
= (uint64_t)*cdata
<<
977 sc
->sc_rstip
[addr
] = fg
| temp
;
980 addr
+= ri
->ri_width
;
982 } else if (ri
->ri_font
->fontwidth
< 17) {
984 wdata
= (uint16_t *)cdata
;
985 for (i
= 0; i
< ri
->ri_font
->fontheight
; i
++) {
986 sc
->sc_rstip
[addr
] = bg
;
989 fg
= temp
| (uint64_t)*wdata
>>
992 fg
= temp
| (uint64_t)*wdata
<<
995 sc
->sc_rstip
[addr
] = fg
;
998 addr
+= ri
->ri_width
;
1002 /* and now the split case ( man this hardware is dumb ) */
1003 uint64_t bgr
, maskr
, fgr
;
1006 shift
= addr
& 0x1f;
1008 mask
= 0xffffffff >> shift
;
1009 maskr
= (uint64_t)(0xffffffffUL
<<
1010 (32 - (ri
->ri_font
->fontwidth
+ shift
- 32)));
1011 bg
= 0x3000000000000000LL
|
1012 ((uint64_t)ri
->ri_devcmap
[(attr
>> 16) & 0xff] &
1016 temp
= 0x3000000000000000LL
|
1017 ((uint64_t)ri
->ri_devcmap
[(attr
>> 24) & 0xff] & 0xff) <<
1020 uc
= c
- ri
->ri_font
->firstchar
;
1021 cdata
= (uint8_t *)ri
->ri_font
->data
+ uc
* ri
->ri_fontscale
;
1023 if (ri
->ri_font
->fontwidth
< 9) {
1025 for (i
= 0; i
< ri
->ri_font
->fontheight
; i
++) {
1026 sc
->sc_rstip
[addr
] = bg
;
1027 sc
->sc_rstip
[addr
+ 32] = bgr
;
1030 fg
= (uint64_t)bork
>> (shift
- 24);
1031 sc
->sc_rstip
[addr
] = fg
| temp
;
1032 fgr
= (uint64_t)(bork
<< (52 - shift
));
1033 sc
->sc_rstip
[addr
] = fgr
| temp
;
1036 addr
+= ri
->ri_width
;
1038 } else if (ri
->ri_font
->fontwidth
< 17) {
1039 /* short by short */
1040 wdata
= (uint16_t *)cdata
;
1041 for (i
= 0; i
< ri
->ri_font
->fontheight
; i
++) {
1042 sc
->sc_rstip
[addr
] = bg
;
1043 sc
->sc_rstip
[addr
+ 32] = bgr
;
1046 fg
= (uint64_t)bork
>> (shift
- 16);
1047 sc
->sc_rstip
[addr
] = fg
| temp
;
1048 fgr
= (uint64_t)(bork
<< (48 - shift
));
1049 sc
->sc_rstip
[addr
+ 32] = fgr
| temp
;
1052 addr
+= ri
->ri_width
;
1060 tcx_do_cursor(struct tcx_softc
*sc
, struct wsdisplay_cursor
*cur
)
1062 if (cur
->which
& WSDISPLAY_CURSOR_DOCUR
) {
1067 /* move the cursor out of sight */
1068 bus_space_write_4(sc
->sc_bustag
, sc
->sc_thc
,
1069 THC_CURSOR_POS
, 0x7fff7fff);
1072 if (cur
->which
& WSDISPLAY_CURSOR_DOHOT
) {
1074 sc
->sc_hotspot_x
= cur
->hot
.x
;
1075 sc
->sc_hotspot_y
= cur
->hot
.y
;
1078 if (cur
->which
& WSDISPLAY_CURSOR_DOPOS
) {
1080 sc
->sc_cursor_x
= cur
->pos
.x
;
1081 sc
->sc_cursor_y
= cur
->pos
.y
;
1084 if (cur
->which
& WSDISPLAY_CURSOR_DOCMAP
) {
1087 * apparently we're not writing in the right register here - if we do
1088 * this the screen goes all funky
1092 for (i
= 0; i
< cur
->cmap
.count
; i
++) {
1093 bus_space_write_4(sc
->sc_bustag
, sc
->sc_bt
, DAC_ADDRESS
,
1094 (cur
->cmap
.index
+ i
+ 2) << 24);
1095 bus_space_write_4(sc
->sc_bustag
, sc
->sc_bt
,
1096 DAC_CURSOR_LUT
, cur
->cmap
.red
[i
] << 24);
1097 bus_space_write_4(sc
->sc_bustag
, sc
->sc_bt
,
1098 DAC_CURSOR_LUT
, cur
->cmap
.green
[i
] << 24);
1099 bus_space_write_4(sc
->sc_bustag
, sc
->sc_bt
,
1100 DAC_CURSOR_LUT
, cur
->cmap
.blue
[i
] << 24);
1104 if (cur
->which
& WSDISPLAY_CURSOR_DOSHAPE
) {
1106 uint32_t temp
, poof
;
1108 for (i
= 0; i
< 128; i
+= 4) {
1109 memcpy(&temp
, &cur
->mask
[i
], 4);
1110 printf("%08x -> ", temp
);
1111 poof
= ((temp
& 0x80808080) >> 7) |
1112 ((temp
& 0x40404040) >> 5) |
1113 ((temp
& 0x20202020) >> 3) |
1114 ((temp
& 0x10101010) >> 1) |
1115 ((temp
& 0x08080808) << 1) |
1116 ((temp
& 0x04040404) << 3) |
1117 ((temp
& 0x02020202) << 5) |
1118 ((temp
& 0x01010101) << 7);
1119 printf("%08x\n", poof
);
1120 bus_space_write_4(sc
->sc_bustag
, sc
->sc_thc
,
1121 THC_CURSOR_1
+ i
, poof
);
1122 memcpy(&temp
, &cur
->image
[i
], 4);
1123 poof
= ((temp
& 0x80808080) >> 7) |
1124 ((temp
& 0x40404040) >> 5) |
1125 ((temp
& 0x20202020) >> 3) |
1126 ((temp
& 0x10101010) >> 1) |
1127 ((temp
& 0x08080808) << 1) |
1128 ((temp
& 0x04040404) << 3) |
1129 ((temp
& 0x02020202) << 5) |
1130 ((temp
& 0x01010101) << 7);
1131 bus_space_write_4(sc
->sc_bustag
, sc
->sc_thc
,
1132 THC_CURSOR_0
+ i
, poof
);
1139 tcx_set_cursor(struct tcx_softc
*sc
)
1143 reg
= (sc
->sc_cursor_x
- sc
->sc_hotspot_x
) << 16 |
1144 ((sc
->sc_cursor_y
- sc
->sc_hotspot_y
) & 0xffff);
1145 bus_space_write_4(sc
->sc_bustag
, sc
->sc_thc
, THC_CURSOR_POS
, reg
);