| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: tcx.c,v 1.31 2009/05/12 14:43:59 cegger Exp $ */ | | 1 | /* $NetBSD: tcx.c,v 1.32 2009/08/06 18:26:03 macallan Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1996,1998 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1996,1998 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Paul Kranenburg. | | 8 | * by Paul Kranenburg. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -28,27 +28,27 @@ | | | @@ -28,27 +28,27 @@ |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * color display (TCX) driver. | | 33 | * color display (TCX) driver. |
34 | * | | 34 | * |
35 | * Does not handle interrupts, even though they can occur. | | 35 | * Does not handle interrupts, even though they can occur. |
36 | * | | 36 | * |
37 | * XXX should defer colormap updates to vertical retrace interrupts | | 37 | * XXX should defer colormap updates to vertical retrace interrupts |
38 | */ | | 38 | */ |
39 | | | 39 | |
40 | #include <sys/cdefs.h> | | 40 | #include <sys/cdefs.h> |
41 | __KERNEL_RCSID(0, "$NetBSD: tcx.c,v 1.31 2009/05/12 14:43:59 cegger Exp $"); | | 41 | __KERNEL_RCSID(0, "$NetBSD: tcx.c,v 1.32 2009/08/06 18:26:03 macallan Exp $"); |
42 | | | 42 | |
43 | /* | | 43 | /* |
44 | * define for cg8 emulation on S24 (24-bit version of tcx) for the SS5; | | 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) | | 45 | * it is bypassed on the 8-bit version (onboard framebuffer for SS4) |
46 | */ | | 46 | */ |
47 | #undef TCX_CG8 | | 47 | #undef TCX_CG8 |
48 | | | 48 | |
49 | #include <sys/param.h> | | 49 | #include <sys/param.h> |
50 | #include <sys/systm.h> | | 50 | #include <sys/systm.h> |
51 | #include <sys/buf.h> | | 51 | #include <sys/buf.h> |
52 | #include <sys/device.h> | | 52 | #include <sys/device.h> |
53 | #include <sys/ioctl.h> | | 53 | #include <sys/ioctl.h> |
54 | #include <sys/malloc.h> | | 54 | #include <sys/malloc.h> |
| @@ -62,42 +62,78 @@ __KERNEL_RCSID(0, "$NetBSD: tcx.c,v 1.31 | | | @@ -62,42 +62,78 @@ __KERNEL_RCSID(0, "$NetBSD: tcx.c,v 1.31 |
62 | #endif | | 62 | #endif |
63 | | | 63 | |
64 | #include <sys/bus.h> | | 64 | #include <sys/bus.h> |
65 | #include <machine/autoconf.h> | | 65 | #include <machine/autoconf.h> |
66 | | | 66 | |
67 | #include <dev/sun/fbio.h> | | 67 | #include <dev/sun/fbio.h> |
68 | #include <dev/sun/fbvar.h> | | 68 | #include <dev/sun/fbvar.h> |
69 | #include <dev/sun/btreg.h> | | 69 | #include <dev/sun/btreg.h> |
70 | #include <dev/sun/btvar.h> | | 70 | #include <dev/sun/btvar.h> |
71 | | | 71 | |
72 | #include <dev/sbus/sbusvar.h> | | 72 | #include <dev/sbus/sbusvar.h> |
73 | #include <dev/sbus/tcxreg.h> | | 73 | #include <dev/sbus/tcxreg.h> |
74 | | | 74 | |
| | | 75 | #include <dev/wscons/wsdisplayvar.h> |
| | | 76 | #include <dev/wscons/wsconsio.h> |
| | | 77 | #include <dev/wsfont/wsfont.h> |
| | | 78 | #include <dev/rasops/rasops.h> |
| | | 79 | |
| | | 80 | #include <dev/wscons/wsdisplay_vconsvar.h> |
| | | 81 | |
| | | 82 | #include "opt_wsemul.h" |
| | | 83 | |
75 | /* per-display variables */ | | 84 | /* per-display variables */ |
76 | struct tcx_softc { | | 85 | struct tcx_softc { |
77 | struct device sc_dev; /* base device */ | | 86 | struct device sc_dev; /* base device */ |
78 | struct sbusdev sc_sd; /* sbus device */ | | 87 | struct sbusdev sc_sd; /* sbus device */ |
79 | struct fbdevice sc_fb; /* frame buffer device */ | | 88 | struct fbdevice sc_fb; /* frame buffer device */ |
80 | bus_space_tag_t sc_bustag; | | 89 | bus_space_tag_t sc_bustag; |
81 | struct openprom_addr sc_physadr[TCX_NREG];/* phys addr of h/w */ | | 90 | struct openprom_addr sc_physadr[TCX_NREG];/* phys addr of h/w */ |
82 | | | 91 | |
83 | volatile struct bt_regs *sc_bt; /* Brooktree registers */ | | 92 | bus_space_handle_t sc_bt; /* Brooktree registers */ |
84 | volatile struct tcx_thc *sc_thc;/* THC registers */ | | 93 | bus_space_handle_t sc_thc; /* THC registers */ |
85 | #ifdef TCX_CG8 | | 94 | uint8_t *sc_fbaddr; /* framebuffer */ |
86 | volatile ulong *sc_cplane; /* framebuffer with control planes */ | | 95 | uint64_t *sc_rblit; /* blitspace */ |
87 | #endif | | 96 | uint64_t *sc_rstip; /* stipple space */ |
| | | 97 | |
88 | short sc_8bit; /* true if 8-bit hardware */ | | 98 | short sc_8bit; /* true if 8-bit hardware */ |
89 | short sc_blanked; /* true if blanked */ | | 99 | short sc_blanked; /* true if blanked */ |
90 | union bt_cmap sc_cmap; /* Brooktree color map */ | | 100 | u_char sc_cmap_red[256]; |
| | | 101 | u_char sc_cmap_green[256]; |
| | | 102 | u_char sc_cmap_blue[256]; |
| | | 103 | int sc_mode, sc_bg; |
| | | 104 | struct vcons_data vd; |
| | | 105 | }; |
| | | 106 | |
| | | 107 | static struct vcons_screen tcx_console_screen; |
| | | 108 | |
| | | 109 | extern const u_char rasops_cmap[768]; |
| | | 110 | |
| | | 111 | struct wsscreen_descr tcx_defscreendesc = { |
| | | 112 | "default", |
| | | 113 | 0, 0, |
| | | 114 | NULL, |
| | | 115 | 8, 16, |
| | | 116 | WSSCREEN_WSCOLORS, |
| | | 117 | }; |
| | | 118 | |
| | | 119 | const struct wsscreen_descr *_tcx_scrlist[] = { |
| | | 120 | &tcx_defscreendesc, |
| | | 121 | /* XXX other formats, graphics screen? */ |
| | | 122 | }; |
| | | 123 | |
| | | 124 | struct wsscreen_list tcx_screenlist = { |
| | | 125 | sizeof(_tcx_scrlist) / sizeof(struct wsscreen_descr *), |
| | | 126 | _tcx_scrlist |
91 | }; | | 127 | }; |
92 | | | 128 | |
93 | /* | | 129 | /* |
94 | * The S24 provides the framebuffer RAM mapped in three ways: | | 130 | * The S24 provides the framebuffer RAM mapped in three ways: |
95 | * 26 bits per pixel, in 32-bit words; the low-order 24 bits are | | 131 | * 26 bits per pixel, in 32-bit words; the low-order 24 bits are |
96 | * blue, green, and red values, and the other two bits select the | | 132 | * blue, green, and red values, and the other two bits select the |
97 | * display modes, per pixel); | | 133 | * display modes, per pixel); |
98 | * 24 bits per pixel, in 32-bit words; the high-order byte reads as | | 134 | * 24 bits per pixel, in 32-bit words; the high-order byte reads as |
99 | * zero, and is ignored on writes (so the mode bits cannot be altered); | | 135 | * zero, and is ignored on writes (so the mode bits cannot be altered); |
100 | * 8 bits per pixel, unpadded; writes to this space do not modify the | | 136 | * 8 bits per pixel, unpadded; writes to this space do not modify the |
101 | * other 18 bits. | | 137 | * other 18 bits. |
102 | */ | | 138 | */ |
103 | #define TCX_CTL_8_MAPPED 0x00000000 /* 8 bits, uses color map */ | | 139 | #define TCX_CTL_8_MAPPED 0x00000000 /* 8 bits, uses color map */ |
| @@ -124,26 +160,46 @@ const struct cdevsw tcx_cdevsw = { | | | @@ -124,26 +160,46 @@ const struct cdevsw tcx_cdevsw = { |
124 | tcxopen, tcxclose, noread, nowrite, tcxioctl, | | 160 | tcxopen, tcxclose, noread, nowrite, tcxioctl, |
125 | nostop, notty, nopoll, tcxmmap, nokqfilter, | | 161 | nostop, notty, nopoll, tcxmmap, nokqfilter, |
126 | }; | | 162 | }; |
127 | | | 163 | |
128 | /* frame buffer generic driver */ | | 164 | /* frame buffer generic driver */ |
129 | static struct fbdriver tcx_fbdriver = { | | 165 | static struct fbdriver tcx_fbdriver = { |
130 | tcx_unblank, tcxopen, tcxclose, tcxioctl, nopoll, tcxmmap, | | 166 | tcx_unblank, tcxopen, tcxclose, tcxioctl, nopoll, tcxmmap, |
131 | nokqfilter | | 167 | nokqfilter |
132 | }; | | 168 | }; |
133 | | | 169 | |
134 | static void tcx_reset(struct tcx_softc *); | | 170 | static void tcx_reset(struct tcx_softc *); |
135 | static void tcx_loadcmap(struct tcx_softc *, int, int); | | 171 | static void tcx_loadcmap(struct tcx_softc *, int, int); |
136 | | | 172 | |
| | | 173 | static int tcx_ioctl(void *, void *, u_long, void *, int, struct lwp *); |
| | | 174 | static paddr_t tcx_mmap(void *, void *, off_t, int); |
| | | 175 | |
| | | 176 | static void tcx_init_screen(void *, struct vcons_screen *, int, long *); |
| | | 177 | static void tcx_clearscreen(struct tcx_softc *); |
| | | 178 | static void tcx_copyrows(void *, int, int, int); |
| | | 179 | static void tcx_eraserows(void *, int, int, long); |
| | | 180 | static void tcx_putchar(void *, int, int, u_int, long); |
| | | 181 | |
| | | 182 | struct wsdisplay_accessops tcx_accessops = { |
| | | 183 | tcx_ioctl, |
| | | 184 | tcx_mmap, |
| | | 185 | NULL, /* vcons_alloc_screen */ |
| | | 186 | NULL, /* vcons_free_screen */ |
| | | 187 | NULL, /* vcons_show_screen */ |
| | | 188 | NULL, /* load_font */ |
| | | 189 | NULL, /* polls */ |
| | | 190 | NULL, /* scroll */ |
| | | 191 | }; |
| | | 192 | |
137 | #define OBPNAME "SUNW,tcx" | | 193 | #define OBPNAME "SUNW,tcx" |
138 | | | 194 | |
139 | #ifdef TCX_CG8 | | 195 | #ifdef TCX_CG8 |
140 | /* | | 196 | /* |
141 | * For CG8 emulation, we map the 32-bit-deep framebuffer at an offset of | | 197 | * For CG8 emulation, we map the 32-bit-deep framebuffer at an offset of |
142 | * 256K; the cg8 space begins with a mono overlay plane and an overlay | | 198 | * 256K; the cg8 space begins with a mono overlay plane and an overlay |
143 | * enable plane (128K bytes each, 1 bit per pixel), immediately followed | | 199 | * enable plane (128K bytes each, 1 bit per pixel), immediately followed |
144 | * by the color planes, 32 bits per pixel. We also map just the 32-bit | | 200 | * by the color planes, 32 bits per pixel. We also map just the 32-bit |
145 | * framebuffer at 0x04000000 (TCX_USER_RAM_COMPAT), for compatibility | | 201 | * framebuffer at 0x04000000 (TCX_USER_RAM_COMPAT), for compatibility |
146 | * with the cg8 driver. | | 202 | * with the cg8 driver. |
147 | */ | | 203 | */ |
148 | #define TCX_CG8OVERLAY (256 * 1024) | | 204 | #define TCX_CG8OVERLAY (256 * 1024) |
149 | #define TCX_SIZE_DFB32 (1152 * 900 * 4) /* max size of the framebuffer */ | | 205 | #define TCX_SIZE_DFB32 (1152 * 900 * 4) /* max size of the framebuffer */ |
| @@ -158,181 +214,208 @@ tcxmatch(device_t parent, cfdata_t cf, v | | | @@ -158,181 +214,208 @@ tcxmatch(device_t parent, cfdata_t cf, v |
158 | struct sbus_attach_args *sa = aux; | | 214 | struct sbus_attach_args *sa = aux; |
159 | | | 215 | |
160 | return (strcmp(sa->sa_name, OBPNAME) == 0); | | 216 | return (strcmp(sa->sa_name, OBPNAME) == 0); |
161 | } | | 217 | } |
162 | | | 218 | |
163 | /* | | 219 | /* |
164 | * Attach a display. | | 220 | * Attach a display. |
165 | */ | | 221 | */ |
166 | void | | 222 | void |
167 | tcxattach(device_t parent, device_t self, void *args) | | 223 | tcxattach(device_t parent, device_t self, void *args) |
168 | { | | 224 | { |
169 | struct tcx_softc *sc = device_private(self); | | 225 | struct tcx_softc *sc = device_private(self); |
170 | struct sbus_attach_args *sa = args; | | 226 | struct sbus_attach_args *sa = args; |
| | | 227 | struct wsemuldisplaydev_attach_args aa; |
| | | 228 | struct rasops_info *ri; |
| | | 229 | unsigned long defattr; |
171 | int node, ramsize; | | 230 | int node, ramsize; |
172 | volatile struct bt_regs *bt; | | | |
173 | struct fbdevice *fb = &sc->sc_fb; | | 231 | struct fbdevice *fb = &sc->sc_fb; |
174 | bus_space_handle_t bh; | | 232 | bus_space_handle_t bh; |
175 | int isconsole; | | 233 | int isconsole, i, j; |
| | | 234 | uint32_t confreg; |
176 | | | 235 | |
177 | sc->sc_bustag = sa->sa_bustag; | | 236 | sc->sc_bustag = sa->sa_bustag; |
178 | node = sa->sa_node; | | 237 | node = sa->sa_node; |
179 | | | 238 | |
180 | fb->fb_driver = &tcx_fbdriver; | | 239 | fb->fb_driver = &tcx_fbdriver; |
181 | fb->fb_device = &sc->sc_dev; | | 240 | fb->fb_device = &sc->sc_dev; |
182 | /* Mask out invalid flags from the user. */ | | 241 | /* Mask out invalid flags from the user. */ |
183 | fb->fb_flags = device_cfdata(&sc->sc_dev)->cf_flags & FB_USERMASK; | | 242 | fb->fb_flags = device_cfdata(&sc->sc_dev)->cf_flags & FB_USERMASK; |
184 | /* | | 243 | /* |
185 | * The onboard framebuffer on the SS4 supports only 8-bit mode; | | 244 | * The onboard framebuffer on the SS4 supports only 8-bit mode; |
186 | * it can be distinguished from the S24 card for the SS5 by the | | 245 | * it can be distinguished from the S24 card for the SS5 by the |
187 | * presence of the "tcx-8-bit" attribute on the SS4 version. | | 246 | * presence of the "tcx-8-bit" attribute on the SS4 version. |
188 | */ | | 247 | */ |
189 | sc->sc_8bit = node_has_property(node, "tcx-8-bit"); | | 248 | sc->sc_8bit = node_has_property(node, "tcx-8-bit"); |
190 | #ifdef TCX_CG8 | | 249 | fb->fb_type.fb_depth = 8; |
191 | if (sc->sc_8bit) { | | 250 | fb_setsize_obp(fb, fb->fb_type.fb_depth, 1152, 900, node); |
192 | #endif | | | |
193 | /* | | | |
194 | * cg8 emulation is either not compiled in or not supported | | | |
195 | * on this hardware. Report values for the 8-bit framebuffer | | | |
196 | * so cg3 emulation works. (If this hardware supports | | | |
197 | * 24-bit mode, the 24-bit framebuffer will also be available) | | | |
198 | */ | | | |
199 | fb->fb_type.fb_depth = 8; | | | |
200 | fb_setsize_obp(fb, fb->fb_type.fb_depth, 1152, 900, node); | | | |
201 | | | 251 | |
202 | ramsize = fb->fb_type.fb_height * fb->fb_linebytes; | | 252 | if (sc->sc_8bit) { |
203 | #ifdef TCX_CG8 | | 253 | printf(" {8bit only TCX)"); |
| | | 254 | ramsize = 1024 * 1024; |
| | | 255 | /* XXX - fix THC and TEC offsets */ |
| | | 256 | sc->sc_physadr[TCX_REG_TEC].oa_base += 0x1000; |
| | | 257 | sc->sc_physadr[TCX_REG_THC].oa_base += 0x1000; |
204 | } else { | | 258 | } else { |
205 | /* | | 259 | printf(" (S24)\n"); |
206 | * for cg8 emulation, unconditionally report the depth as | | 260 | ramsize = 4 * 1024 * 1024; |
207 | * 32 bits, but use the height and width reported by the | | | |
208 | * boot prom. cg8 users want to see the full size of | | | |
209 | * overlay planes plus color planes included in the | | | |
210 | * reported framebuffer size. | | | |
211 | */ | | | |
212 | fb->fb_type.fb_depth = 32; | | | |
213 | fb_setsize_obp(fb, fb->fb_type.fb_depth, 1152, 900, node); | | | |
214 | fb->fb_linebytes = | | | |
215 | (fb->fb_type.fb_width * fb->fb_type.fb_depth) / 8; | | | |
216 | ramsize = TCX_CG8OVERLAY + | | | |
217 | (fb->fb_type.fb_height * fb->fb_linebytes); | | | |
218 | } | | 261 | } |
219 | #endif | | 262 | |
220 | fb->fb_type.fb_cmsize = 256; | | 263 | fb->fb_type.fb_cmsize = 256; |
221 | fb->fb_type.fb_size = ramsize; | | 264 | fb->fb_type.fb_size = ramsize; |
222 | printf(": %s, %d x %d", OBPNAME, | | 265 | printf(": %s, %d x %d", OBPNAME, |
223 | fb->fb_type.fb_width, | | 266 | fb->fb_type.fb_width, |
224 | fb->fb_type.fb_height); | | 267 | fb->fb_type.fb_height); |
225 | #ifdef TCX_CG8 | | | |
226 | /* | | | |
227 | * if cg8 emulation is enabled, say so; but if hardware can't | | | |
228 | * emulate cg8, explain that instead | | | |
229 | */ | | | |
230 | printf( (sc->sc_8bit)? | | | |
231 | " (8-bit only)" : | | | |
232 | " (emulating cg8)"); | | | |
233 | #endif | | | |
234 | | | 268 | |
235 | /* | | 269 | fb->fb_type.fb_type = FBTYPE_SUNTCX; |
236 | * XXX - should be set to FBTYPE_TCX. | | | |
237 | * XXX For CG3 emulation to work in current (96/6) X11 servers, | | | |
238 | * XXX `fbtype' must point to an "unregocnised" entry. | | | |
239 | */ | | | |
240 | #ifdef TCX_CG8 | | | |
241 | if (sc->sc_8bit) { | | | |
242 | fb->fb_type.fb_type = FBTYPE_RESERVED3; | | | |
243 | } else { | | | |
244 | fb->fb_type.fb_type = FBTYPE_MEMCOLOR; | | | |
245 | } | | | |
246 | #else | | | |
247 | fb->fb_type.fb_type = FBTYPE_RESERVED3; | | | |
248 | #endif | | | |
249 | | | 270 | |
250 | | | 271 | |
251 | if (sa->sa_nreg != TCX_NREG) { | | 272 | if (sa->sa_nreg != TCX_NREG) { |
252 | printf("%s: only %d register sets\n", | | 273 | printf("%s: only %d register sets\n", |
253 | device_xname(self), sa->sa_nreg); | | 274 | device_xname(self), sa->sa_nreg); |
254 | return; | | 275 | return; |
255 | } | | 276 | } |
256 | memcpy(sc->sc_physadr, sa->sa_reg, | | 277 | memcpy(sc->sc_physadr, sa->sa_reg, |
257 | sa->sa_nreg * sizeof(struct openprom_addr)); | | 278 | sa->sa_nreg * sizeof(struct openprom_addr)); |
258 | | | 279 | |
259 | /* XXX - fix THC and TEC offsets */ | | | |
260 | sc->sc_physadr[TCX_REG_TEC].oa_base += 0x1000; | | | |
261 | sc->sc_physadr[TCX_REG_THC].oa_base += 0x1000; | | | |
262 | | | | |
263 | /* Map the register banks we care about */ | | 280 | /* Map the register banks we care about */ |
264 | if (sbus_bus_map(sa->sa_bustag, | | 281 | if (sbus_bus_map(sa->sa_bustag, |
265 | sc->sc_physadr[TCX_REG_THC].oa_space, | | 282 | sc->sc_physadr[TCX_REG_THC].oa_space, |
266 | sc->sc_physadr[TCX_REG_THC].oa_base, | | 283 | sc->sc_physadr[TCX_REG_THC].oa_base, |
267 | sizeof (struct tcx_thc), | | 284 | 0x1000, |
268 | BUS_SPACE_MAP_LINEAR, &bh) != 0) { | | 285 | BUS_SPACE_MAP_LINEAR, &sc->sc_thc) != 0) { |
269 | printf("tcxattach: cannot map thc registers\n"); | | 286 | printf("tcxattach: cannot map thc registers\n"); |
270 | return; | | 287 | return; |
271 | } | | 288 | } |
272 | sc->sc_thc = (volatile struct tcx_thc *) | | | |
273 | bus_space_vaddr(sa->sa_bustag, bh); | | | |
274 | | | 289 | |
275 | if (sbus_bus_map(sa->sa_bustag, | | 290 | if (sbus_bus_map(sa->sa_bustag, |
276 | sc->sc_physadr[TCX_REG_CMAP].oa_space, | | 291 | sc->sc_physadr[TCX_REG_CMAP].oa_space, |
277 | sc->sc_physadr[TCX_REG_CMAP].oa_base, | | 292 | sc->sc_physadr[TCX_REG_CMAP].oa_base, |
278 | sizeof (struct bt_regs), | | 293 | 0x1000, |
279 | BUS_SPACE_MAP_LINEAR, &bh) != 0) { | | 294 | BUS_SPACE_MAP_LINEAR, &sc->sc_bt) != 0) { |
280 | printf("tcxattach: cannot map bt registers\n"); | | 295 | printf("tcxattach: cannot map bt registers\n"); |
281 | return; | | 296 | return; |
282 | } | | 297 | } |
283 | sc->sc_bt = bt = (volatile struct bt_regs *) | | | |
284 | bus_space_vaddr(sa->sa_bustag, bh); | | | |
285 | | | 298 | |
286 | #ifdef TCX_CG8 | | 299 | /* map the 8bit dumb FB for the console */ |
287 | if (!sc->sc_8bit) { | | 300 | if (sbus_bus_map(sa->sa_bustag, |
288 | if (sbus_bus_map(sa->sa_bustag, | | 301 | sc->sc_physadr[TCX_REG_DFB8].oa_space, |
289 | sc->sc_physadr[TCX_REG_RDFB32].oa_space, | | 302 | sc->sc_physadr[TCX_REG_DFB8].oa_base, |
290 | sc->sc_physadr[TCX_REG_RDFB32].oa_base, | | 303 | 1024 * 1024, |
291 | TCX_SIZE_DFB32, | | | |
292 | BUS_SPACE_MAP_LINEAR, | | 304 | BUS_SPACE_MAP_LINEAR, |
293 | &bh) != 0) { | | 305 | &bh) != 0) { |
294 | printf("tcxattach: cannot map control planes\n"); | | 306 | printf("tcxattach: cannot map framebuffer\n"); |
295 | return; | | 307 | return; |
296 | } | | | |
297 | sc->sc_cplane = (volatile ulong *)bh; | | | |
298 | } | | 308 | } |
299 | #endif | | 309 | sc->sc_fbaddr = bus_space_vaddr(sa->sa_bustag, bh); |
| | | 310 | |
| | | 311 | /* RBLIT space */ |
| | | 312 | if (sbus_bus_map(sa->sa_bustag, |
| | | 313 | sc->sc_physadr[TCX_REG_RBLIT].oa_space, |
| | | 314 | sc->sc_physadr[TCX_REG_RBLIT].oa_base, |
| | | 315 | 8 * 1024 * 1024, |
| | | 316 | BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, |
| | | 317 | &bh) != 0) { |
| | | 318 | printf("tcxattach: cannot map RBLIT space\n"); |
| | | 319 | return; |
| | | 320 | } |
| | | 321 | sc->sc_rblit = bus_space_vaddr(sa->sa_bustag, bh); |
| | | 322 | |
| | | 323 | /* RSTIP space */ |
| | | 324 | if (sbus_bus_map(sa->sa_bustag, |
| | | 325 | sc->sc_physadr[TCX_REG_RSTIP].oa_space, |
| | | 326 | sc->sc_physadr[TCX_REG_RSTIP].oa_base, |
| | | 327 | 8 * 1024 * 1024, |
| | | 328 | BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, |
| | | 329 | &bh) != 0) { |
| | | 330 | printf("tcxattach: cannot map RSTIP space\n"); |
| | | 331 | return; |
| | | 332 | } |
| | | 333 | sc->sc_rstip = bus_space_vaddr(sa->sa_bustag, bh); |
300 | | | 334 | |
301 | isconsole = fb_is_console(node); | | 335 | isconsole = fb_is_console(node); |
302 | | | 336 | |
| | | 337 | confreg = bus_space_read_4(sa->sa_bustag, sc->sc_thc, THC_CONFIG); |
303 | printf(", id %d, rev %d, sense %d", | | 338 | printf(", id %d, rev %d, sense %d", |
304 | (sc->sc_thc->thc_config & THC_CFG_FBID) >> THC_CFG_FBID_SHIFT, | | 339 | (confreg & THC_CFG_FBID) >> THC_CFG_FBID_SHIFT, |
305 | (sc->sc_thc->thc_config & THC_CFG_REV) >> THC_CFG_REV_SHIFT, | | 340 | (confreg & THC_CFG_REV) >> THC_CFG_REV_SHIFT, |
306 | (sc->sc_thc->thc_config & THC_CFG_SENSE) >> THC_CFG_SENSE_SHIFT | | 341 | (confreg & THC_CFG_SENSE) >> THC_CFG_SENSE_SHIFT |
307 | ); | | 342 | ); |
308 | | | 343 | |
309 | /* reset cursor & frame buffer controls */ | | 344 | /* reset cursor & frame buffer controls */ |
310 | tcx_reset(sc); | | 345 | tcx_reset(sc); |
311 | | | 346 | |
312 | /* Initialize the default color map. */ | | 347 | /* Initialize the default color map. */ |
313 | bt_initcmap(&sc->sc_cmap, 256); | | 348 | j = 0; |
| | | 349 | for (i = 0; i < 256; i++) { |
| | | 350 | |
| | | 351 | sc->sc_cmap_red[i] = rasops_cmap[j]; |
| | | 352 | sc->sc_cmap_green[i] = rasops_cmap[j + 1]; |
| | | 353 | sc->sc_cmap_blue[i] = rasops_cmap[j + 2]; |
| | | 354 | j += 3; |
| | | 355 | } |
314 | tcx_loadcmap(sc, 0, 256); | | 356 | tcx_loadcmap(sc, 0, 256); |
315 | | | 357 | |
316 | /* enable video */ | | 358 | /* enable video */ |
317 | sc->sc_thc->thc_hcmisc |= THC_MISC_VIDEN; | | 359 | confreg = bus_space_read_4(sa->sa_bustag, sc->sc_thc, THC_MISC); |
| | | 360 | confreg |= THC_MISC_VIDEN; |
| | | 361 | bus_space_write_4(sa->sa_bustag, sc->sc_thc, THC_MISC, confreg); |
318 | | | 362 | |
319 | if (isconsole) { | | 363 | if (isconsole) { |
320 | printf(" (console)\n"); | | 364 | printf(" (console)\n"); |
321 | } else | | 365 | } else |
322 | printf("\n"); | | 366 | printf("\n"); |
323 | | | 367 | |
| | | 368 | bus_space_write_4(sa->sa_bustag, sc->sc_bt, DAC_ADDRESS, 0); |
| | | 369 | printf("DAC ID: %02x %02x\n", |
| | | 370 | bus_space_read_1(sa->sa_bustag, sc->sc_bt, DAC_CONTROL_1), |
| | | 371 | bus_space_read_1(sa->sa_bustag, sc->sc_bt, DAC_CONTROL_1)); |
324 | sbus_establish(&sc->sc_sd, &sc->sc_dev); | | 372 | sbus_establish(&sc->sc_sd, &sc->sc_dev); |
325 | fb_attach(&sc->sc_fb, isconsole); | | 373 | fb_attach(&sc->sc_fb, isconsole); |
| | | 374 | |
| | | 375 | sc->sc_mode = WSDISPLAYIO_MODE_EMUL; |
| | | 376 | wsfont_init(); |
| | | 377 | |
| | | 378 | vcons_init(&sc->vd, sc, &tcx_defscreendesc, &tcx_accessops); |
| | | 379 | sc->vd.init_screen = tcx_init_screen; |
| | | 380 | |
| | | 381 | vcons_init_screen(&sc->vd, &tcx_console_screen, 1, &defattr); |
| | | 382 | tcx_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; |
| | | 383 | |
| | | 384 | sc->sc_bg = (defattr >> 16) & 0xff; |
| | | 385 | tcx_clearscreen(sc); |
| | | 386 | |
| | | 387 | ri = &tcx_console_screen.scr_ri; |
| | | 388 | |
| | | 389 | tcx_defscreendesc.nrows = ri->ri_rows; |
| | | 390 | tcx_defscreendesc.ncols = ri->ri_cols; |
| | | 391 | tcx_defscreendesc.textops = &ri->ri_ops; |
| | | 392 | tcx_defscreendesc.capabilities = ri->ri_caps; |
| | | 393 | |
| | | 394 | if(isconsole) { |
| | | 395 | wsdisplay_cnattach(&tcx_defscreendesc, ri, 0, 0, defattr); |
| | | 396 | } |
| | | 397 | |
| | | 398 | aa.console = isconsole; |
| | | 399 | aa.scrdata = &tcx_screenlist; |
| | | 400 | aa.accessops = &tcx_accessops; |
| | | 401 | aa.accesscookie = &sc->vd; |
| | | 402 | |
| | | 403 | config_found(self, &aa, wsemuldisplaydevprint); |
| | | 404 | /* |
| | | 405 | * we need to do this again - something overwrites a handful |
| | | 406 | * palette registers and we end up with white in reg. 0 |
| | | 407 | */ |
| | | 408 | tcx_loadcmap(sc, 0, 256); |
326 | } | | 409 | } |
327 | | | 410 | |
328 | #ifdef TCX_CG8 | | 411 | #ifdef TCX_CG8 |
329 | /* | | 412 | /* |
330 | * keep track of the number of opens, so we can switch to 24-bit mode | | 413 | * keep track of the number of opens, so we can switch to 24-bit mode |
331 | * when the device is first opened, and return to 8-bit mode on the | | 414 | * when the device is first opened, and return to 8-bit mode on the |
332 | * last close. (stolen from cgfourteen driver...) There can only be | | 415 | * last close. (stolen from cgfourteen driver...) There can only be |
333 | * one TCX per system, so we only need one flag. | | 416 | * one TCX per system, so we only need one flag. |
334 | */ | | 417 | */ |
335 | static int tcx_opens = 0; | | 418 | static int tcx_opens = 0; |
336 | #endif | | 419 | #endif |
337 | | | 420 | |
338 | int | | 421 | int |
| @@ -397,146 +480,143 @@ tcxclose(dev_t dev, int flags, int mode, | | | @@ -397,146 +480,143 @@ tcxclose(dev_t dev, int flags, int mode, |
397 | cptr = sc->sc_cplane; | | 480 | cptr = sc->sc_cplane; |
398 | while (--i >= 0) | | 481 | while (--i >= 0) |
399 | *cptr++ &= TCX_CTL_PIXELMASK; | | 482 | *cptr++ &= TCX_CTL_PIXELMASK; |
400 | } | | 483 | } |
401 | } | | 484 | } |
402 | #endif | | 485 | #endif |
403 | return (0); | | 486 | return (0); |
404 | } | | 487 | } |
405 | | | 488 | |
406 | int | | 489 | int |
407 | tcxioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) | | 490 | tcxioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) |
408 | { | | 491 | { |
409 | struct tcx_softc *sc = device_lookup_private(&tcx_cd, minor(dev)); | | 492 | struct tcx_softc *sc = device_lookup_private(&tcx_cd, minor(dev)); |
410 | int error; | | 493 | //int error; |
411 | | | 494 | |
412 | switch (cmd) { | | 495 | switch (cmd) { |
413 | | | 496 | |
414 | case FBIOGTYPE: | | 497 | case FBIOGTYPE: |
415 | *(struct fbtype *)data = sc->sc_fb.fb_type; | | 498 | *(struct fbtype *)data = sc->sc_fb.fb_type; |
416 | break; | | 499 | break; |
417 | | | 500 | |
418 | case FBIOGATTR: | | 501 | case FBIOGATTR: |
419 | #define fba ((struct fbgattr *)data) | | 502 | #define fba ((struct fbgattr *)data) |
420 | fba->real_type = sc->sc_fb.fb_type.fb_type; | | 503 | fba->real_type = sc->sc_fb.fb_type.fb_type; |
421 | fba->owner = 0; /* XXX ??? */ | | 504 | fba->owner = 0; /* XXX ??? */ |
422 | fba->fbtype = sc->sc_fb.fb_type; | | 505 | fba->fbtype = sc->sc_fb.fb_type; |
423 | fba->sattr.flags = 0; | | 506 | fba->sattr.flags = 0; |
424 | fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; | | 507 | fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; |
425 | fba->sattr.dev_specific[0] = -1; | | 508 | fba->sattr.dev_specific[0] = -1; |
426 | fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; | | 509 | fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; |
427 | fba->emu_types[1] = FBTYPE_SUN3COLOR; | | 510 | fba->emu_types[1] = FBTYPE_SUN3COLOR; |
428 | fba->emu_types[2] = -1; | | 511 | fba->emu_types[2] = -1; |
429 | #undef fba | | 512 | #undef fba |
430 | break; | | 513 | break; |
431 | | | 514 | #if 0 |
432 | case FBIOGETCMAP: | | 515 | case FBIOGETCMAP: |
433 | #define p ((struct fbcmap *)data) | | 516 | #define p ((struct fbcmap *)data) |
434 | return (bt_getcmap(p, &sc->sc_cmap, 256, 1)); | | 517 | return (bt_getcmap(p, &sc->sc_cmap, 256, 1)); |
435 | | | 518 | |
436 | case FBIOPUTCMAP: | | 519 | case FBIOPUTCMAP: |
437 | /* copy to software map */ | | 520 | /* copy to software map */ |
438 | #ifdef TCX_CG8 | | 521 | #ifdef TCX_CG8 |
439 | if (!sc->sc_8bit) { | | 522 | if (!sc->sc_8bit) { |
440 | /* | | 523 | /* |
441 | * cg8 has extra bits in high-order byte of the index | | 524 | * cg8 has extra bits in high-order byte of the index |
442 | * that bt_putcmap doesn't recognize | | 525 | * that bt_putcmap doesn't recognize |
443 | */ | | 526 | */ |
444 | p->index &= 0xffffff; | | 527 | p->index &= 0xffffff; |
445 | } | | 528 | } |
446 | #endif | | 529 | #endif |
447 | error = bt_putcmap(p, &sc->sc_cmap, 256, 1); | | 530 | error = bt_putcmap(p, &sc->sc_cmap, 256, 1); |
448 | if (error) | | 531 | if (error) |
449 | return (error); | | 532 | return (error); |
450 | /* now blast them into the chip */ | | 533 | /* now blast them into the chip */ |
451 | /* XXX should use retrace interrupt */ | | 534 | /* XXX should use retrace interrupt */ |
452 | tcx_loadcmap(sc, p->index, p->count); | | 535 | tcx_loadcmap(sc, p->index, p->count); |
453 | #undef p | | 536 | #undef p |
454 | break; | | 537 | break; |
455 | | | 538 | #endif |
456 | case FBIOGVIDEO: | | 539 | case FBIOGVIDEO: |
457 | *(int *)data = sc->sc_blanked; | | 540 | *(int *)data = sc->sc_blanked; |
458 | break; | | 541 | break; |
459 | | | 542 | |
460 | case FBIOSVIDEO: | | 543 | case FBIOSVIDEO: |
461 | if (*(int *)data) | | 544 | if (*(int *)data) |
462 | tcx_unblank(&sc->sc_dev); | | 545 | tcx_unblank(&sc->sc_dev); |
463 | else if (!sc->sc_blanked) { | | 546 | else if (!sc->sc_blanked) { |
464 | sc->sc_blanked = 1; | | 547 | sc->sc_blanked = 1; |
465 | sc->sc_thc->thc_hcmisc &= ~THC_MISC_VIDEN; | | 548 | //sc->sc_thc->thc_hcmisc &= ~THC_MISC_VIDEN; |
466 | /* Put monitor in `power-saving mode' */ | | 549 | /* Put monitor in `power-saving mode' */ |
467 | sc->sc_thc->thc_hcmisc |= THC_MISC_VSYNC_DISABLE; | | 550 | //sc->sc_thc->thc_hcmisc |= THC_MISC_VSYNC_DISABLE; |
468 | sc->sc_thc->thc_hcmisc |= THC_MISC_HSYNC_DISABLE; | | 551 | //sc->sc_thc->thc_hcmisc |= THC_MISC_HSYNC_DISABLE; |
469 | } | | 552 | } |
470 | break; | | 553 | break; |
471 | | | 554 | |
472 | default: | | 555 | default: |
473 | #ifdef DEBUG | | 556 | #ifdef DEBUG |
474 | log(LOG_NOTICE, "tcxioctl(0x%lx) (%s[%d])\n", cmd, | | 557 | log(LOG_NOTICE, "tcxioctl(0x%lx) (%s[%d])\n", cmd, |
475 | l->l_proc->p_comm, l->l_proc->p_pid); | | 558 | l->l_proc->p_comm, l->l_proc->p_pid); |
476 | #endif | | 559 | #endif |
477 | return (ENOTTY); | | 560 | return (ENOTTY); |
478 | } | | 561 | } |
479 | return (0); | | 562 | return (0); |
480 | } | | 563 | } |
481 | | | 564 | |
482 | /* | | 565 | /* |
483 | * Clean up hardware state (e.g., after bootup or after X crashes). | | 566 | * Clean up hardware state (e.g., after bootup or after X crashes). |
484 | */ | | 567 | */ |
485 | static void | | 568 | static void |
486 | tcx_reset(struct tcx_softc *sc) | | 569 | tcx_reset(struct tcx_softc *sc) |
487 | { | | 570 | { |
488 | volatile struct bt_regs *bt; | | | |
489 | | | 571 | |
490 | /* Enable cursor in Brooktree DAC. */ | | 572 | /* Enable cursor in Brooktree DAC. */ |
491 | bt = sc->sc_bt; | | 573 | /* TODO: bus_spacify */ |
492 | bt->bt_addr = 0x06 << 24; | | 574 | // bt->bt_addr = 0x06 << 24; |
493 | bt->bt_ctrl |= 0x03 << 24; | | 575 | // bt->bt_ctrl |= 0x03 << 24; |
494 | } | | 576 | } |
495 | | | 577 | |
496 | /* | | 578 | /* |
497 | * Load a subset of the current (new) colormap into the color DAC. | | 579 | * Load a subset of the current (new) colormap into the color DAC. |
498 | */ | | 580 | */ |
499 | static void | | 581 | static void |
500 | tcx_loadcmap(struct tcx_softc *sc, int start, int ncolors) | | 582 | tcx_loadcmap(struct tcx_softc *sc, int start, int ncolors) |
501 | { | | 583 | { |
502 | volatile struct bt_regs *bt; | | 584 | int i; |
503 | u_int *ip, i; | | 585 | |
504 | int count; | | 586 | for (i = 0; i < ncolors; i++) { |
505 | | | 587 | bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_ADDRESS, |
506 | ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */ | | 588 | (start + i) << 24); |
507 | count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3; | | 589 | bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_FB_LUT, |
508 | bt = sc->sc_bt; | | 590 | sc->sc_cmap_red[i + start] << 24); |
509 | bt->bt_addr = BT_D4M4(start) << 24; | | 591 | bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_FB_LUT, |
510 | while (--count >= 0) { | | 592 | sc->sc_cmap_green[i + start] << 24); |
511 | i = *ip++; | | 593 | bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_FB_LUT, |
512 | /* hardware that makes one want to pound boards with hammers */ | | 594 | sc->sc_cmap_blue[i + start] << 24); |
513 | bt->bt_cmap = i; | | | |
514 | bt->bt_cmap = i << 8; | | | |
515 | bt->bt_cmap = i << 16; | | | |
516 | bt->bt_cmap = i << 24; | | | |
517 | } | | 595 | } |
| | | 596 | bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_ADDRESS, 0); |
518 | } | | 597 | } |
519 | | | 598 | |
520 | static void | | 599 | static void |
521 | tcx_unblank(device_t dev) | | 600 | tcx_unblank(device_t dev) |
522 | { | | 601 | { |
523 | struct tcx_softc *sc = device_private(dev); | | 602 | struct tcx_softc *sc = device_private(dev); |
524 | | | 603 | |
525 | if (sc->sc_blanked) { | | 604 | if (sc->sc_blanked) { |
| | | 605 | |
526 | sc->sc_blanked = 0; | | 606 | sc->sc_blanked = 0; |
527 | sc->sc_thc->thc_hcmisc &= ~THC_MISC_VSYNC_DISABLE; | | 607 | //sc->sc_thc->thc_hcmisc &= ~THC_MISC_VSYNC_DISABLE; |
528 | sc->sc_thc->thc_hcmisc &= ~THC_MISC_HSYNC_DISABLE; | | 608 | //sc->sc_thc->thc_hcmisc &= ~THC_MISC_HSYNC_DISABLE; |
529 | sc->sc_thc->thc_hcmisc |= THC_MISC_VIDEN; | | 609 | //sc->sc_thc->thc_hcmisc |= THC_MISC_VIDEN; |
530 | } | | 610 | } |
531 | } | | 611 | } |
532 | | | 612 | |
533 | /* | | 613 | /* |
534 | * Base addresses at which users can mmap() the various pieces of a tcx. | | 614 | * Base addresses at which users can mmap() the various pieces of a tcx. |
535 | */ | | 615 | */ |
536 | #define TCX_USER_RAM 0x00000000 | | 616 | #define TCX_USER_RAM 0x00000000 |
537 | #define TCX_USER_RAM24 0x01000000 | | 617 | #define TCX_USER_RAM24 0x01000000 |
538 | #define TCX_USER_RAM_COMPAT 0x04000000 /* cg3 emulation */ | | 618 | #define TCX_USER_RAM_COMPAT 0x04000000 /* cg3 emulation */ |
539 | #define TCX_USER_STIP 0x10000000 | | 619 | #define TCX_USER_STIP 0x10000000 |
540 | #define TCX_USER_BLIT 0x20000000 | | 620 | #define TCX_USER_BLIT 0x20000000 |
541 | #define TCX_USER_RDFB32 0x28000000 | | 621 | #define TCX_USER_RDFB32 0x28000000 |
542 | #define TCX_USER_RSTIP 0x30000000 | | 622 | #define TCX_USER_RSTIP 0x30000000 |
| @@ -571,27 +651,27 @@ tcxmmap(dev_t dev, off_t off, int prot) | | | @@ -571,27 +651,27 @@ tcxmmap(dev_t dev, off_t off, int prot) |
571 | u_int u, sz; | | 651 | u_int u, sz; |
572 | static struct mmo mmo[] = { | | 652 | static struct mmo mmo[] = { |
573 | { TCX_USER_RAM, 0, TCX_REG_DFB8 }, | | 653 | { TCX_USER_RAM, 0, TCX_REG_DFB8 }, |
574 | { TCX_USER_RAM24, 0, TCX_REG_DFB24 }, | | 654 | { TCX_USER_RAM24, 0, TCX_REG_DFB24 }, |
575 | { TCX_USER_RAM_COMPAT, 0, TCX_REG_DFB8 }, | | 655 | { TCX_USER_RAM_COMPAT, 0, TCX_REG_DFB8 }, |
576 | | | 656 | |
577 | { TCX_USER_STIP, 1, TCX_REG_STIP }, | | 657 | { TCX_USER_STIP, 1, TCX_REG_STIP }, |
578 | { TCX_USER_BLIT, 1, TCX_REG_BLIT }, | | 658 | { TCX_USER_BLIT, 1, TCX_REG_BLIT }, |
579 | { TCX_USER_RDFB32, 0, TCX_REG_RDFB32 }, | | 659 | { TCX_USER_RDFB32, 0, TCX_REG_RDFB32 }, |
580 | { TCX_USER_RSTIP, 1, TCX_REG_RSTIP }, | | 660 | { TCX_USER_RSTIP, 1, TCX_REG_RSTIP }, |
581 | { TCX_USER_RBLIT, 1, TCX_REG_RBLIT }, | | 661 | { TCX_USER_RBLIT, 1, TCX_REG_RBLIT }, |
582 | { TCX_USER_TEC, 1, TCX_REG_TEC }, | | 662 | { TCX_USER_TEC, 1, TCX_REG_TEC }, |
583 | { TCX_USER_BTREGS, 8192 /* XXX */, TCX_REG_CMAP }, | | 663 | { TCX_USER_BTREGS, 8192 /* XXX */, TCX_REG_CMAP }, |
584 | { TCX_USER_THC, sizeof(struct tcx_thc), TCX_REG_THC }, | | 664 | { TCX_USER_THC, 0x1000, TCX_REG_THC }, |
585 | { TCX_USER_DHC, 1, TCX_REG_DHC }, | | 665 | { TCX_USER_DHC, 1, TCX_REG_DHC }, |
586 | { TCX_USER_ALT, 1, TCX_REG_ALT }, | | 666 | { TCX_USER_ALT, 1, TCX_REG_ALT }, |
587 | { TCX_USER_ROM, 65536, TCX_REG_ROM }, | | 667 | { TCX_USER_ROM, 65536, TCX_REG_ROM }, |
588 | }; | | 668 | }; |
589 | #define NMMO (sizeof mmo / sizeof *mmo) | | 669 | #define NMMO (sizeof mmo / sizeof *mmo) |
590 | #ifdef TCX_CG8 | | 670 | #ifdef TCX_CG8 |
591 | /* | | 671 | /* |
592 | * alternate mapping for CG8 emulation: | | 672 | * alternate mapping for CG8 emulation: |
593 | * map part of the 8-bit-deep framebuffer into the cg8 overlay | | 673 | * map part of the 8-bit-deep framebuffer into the cg8 overlay |
594 | * space, just so there's something there, and map the 32-bit-deep | | 674 | * space, just so there's something there, and map the 32-bit-deep |
595 | * framebuffer where cg8 users expect to find it. | | 675 | * framebuffer where cg8 users expect to find it. |
596 | */ | | 676 | */ |
597 | static struct mmo mmo_cg8[] = { | | 677 | static struct mmo mmo_cg8[] = { |
| @@ -649,13 +729,351 @@ tcxmmap(dev_t dev, off_t off, int prot) | | | @@ -649,13 +729,351 @@ tcxmmap(dev_t dev, off_t off, int prot) |
649 | } | | 729 | } |
650 | } | | 730 | } |
651 | if (u < sz) { | | 731 | if (u < sz) { |
652 | return (bus_space_mmap(sc->sc_bustag, | | 732 | return (bus_space_mmap(sc->sc_bustag, |
653 | BUS_ADDR(rr[mo->mo_bank].oa_space, | | 733 | BUS_ADDR(rr[mo->mo_bank].oa_space, |
654 | rr[mo->mo_bank].oa_base), | | 734 | rr[mo->mo_bank].oa_base), |
655 | u, | | 735 | u, |
656 | prot, | | 736 | prot, |
657 | BUS_SPACE_MAP_LINEAR)); | | 737 | BUS_SPACE_MAP_LINEAR)); |
658 | } | | 738 | } |
659 | } | | 739 | } |
660 | return (-1); | | 740 | return (-1); |
661 | } | | 741 | } |
| | | 742 | |
| | | 743 | int |
| | | 744 | tcx_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, |
| | | 745 | struct lwp *l) |
| | | 746 | { |
| | | 747 | struct vcons_data *vd = v; |
| | | 748 | struct tcx_softc *sc = vd->cookie; |
| | | 749 | struct wsdisplay_fbinfo *wdf; |
| | | 750 | struct vcons_screen *ms = vd->active; |
| | | 751 | |
| | | 752 | switch (cmd) { |
| | | 753 | case WSDISPLAYIO_GTYPE: |
| | | 754 | *(u_int *)data = WSDISPLAY_TYPE_SUNTCX; |
| | | 755 | return 0; |
| | | 756 | |
| | | 757 | #if 0 |
| | | 758 | case FBIOGVIDEO: |
| | | 759 | case WSDISPLAYIO_GVIDEO: |
| | | 760 | *(int *)data = tcx_get_video(sc); |
| | | 761 | return 0; |
| | | 762 | |
| | | 763 | case WSDISPLAYIO_SVIDEO: |
| | | 764 | case FBIOSVIDEO: |
| | | 765 | tcx_set_video(sc, *(int *)data); |
| | | 766 | return 0; |
| | | 767 | #endif |
| | | 768 | case WSDISPLAYIO_GINFO: |
| | | 769 | wdf = (void *)data; |
| | | 770 | wdf->height = ms->scr_ri.ri_height; |
| | | 771 | wdf->width = ms->scr_ri.ri_width; |
| | | 772 | wdf->depth = ms->scr_ri.ri_depth; |
| | | 773 | wdf->cmsize = 256; |
| | | 774 | return 0; |
| | | 775 | #if 0 |
| | | 776 | case WSDISPLAYIO_GETCMAP: |
| | | 777 | return tcx_getcmap(sc, (struct wsdisplay_cmap *)data); |
| | | 778 | |
| | | 779 | case WSDISPLAYIO_PUTCMAP: |
| | | 780 | return tcx_putcmap(sc, (struct wsdisplay_cmap *)data); |
| | | 781 | #endif |
| | | 782 | case WSDISPLAYIO_SMODE: |
| | | 783 | { |
| | | 784 | int new_mode = *(int*)data; |
| | | 785 | if (new_mode != sc->sc_mode) |
| | | 786 | { |
| | | 787 | sc->sc_mode = new_mode; |
| | | 788 | if (new_mode == WSDISPLAYIO_MODE_EMUL) |
| | | 789 | { |
| | | 790 | #if 0 |
| | | 791 | tcxloadcmap(sc, 0, 256); |
| | | 792 | tcx_clearscreen(sc); |
| | | 793 | #endif |
| | | 794 | vcons_redraw_screen(ms); |
| | | 795 | } |
| | | 796 | } |
| | | 797 | } |
| | | 798 | } |
| | | 799 | return EPASSTHROUGH; |
| | | 800 | } |
| | | 801 | |
| | | 802 | static paddr_t |
| | | 803 | tcx_mmap(void *v, void *vs, off_t offset, int prot) |
| | | 804 | { |
| | | 805 | #if 0 |
| | | 806 | struct vcons_data *vd = v; |
| | | 807 | struct tcx_softc *sc = vd->cookie; |
| | | 808 | paddr_t pa; |
| | | 809 | |
| | | 810 | /* 'regular' framebuffer mmap()ing */ |
| | | 811 | if (offset < sc->sc_fb_psize) { |
| | | 812 | pa = bus_space_mmap(sc->sc_bustag, sc->sc_fb_paddr + offset, 0, |
| | | 813 | prot, BUS_SPACE_MAP_LINEAR); |
| | | 814 | return pa; |
| | | 815 | } |
| | | 816 | |
| | | 817 | if ((offset >= sc->sc_fb_paddr) && (offset < (sc->sc_fb_paddr + |
| | | 818 | sc->sc_fb_psize))) { |
| | | 819 | pa = bus_space_mmap(sc->sc_bustag, offset, 0, prot, |
| | | 820 | BUS_SPACE_MAP_LINEAR); |
| | | 821 | return pa; |
| | | 822 | } |
| | | 823 | |
| | | 824 | if ((offset >= sc->sc_ctl_paddr) && (offset < (sc->sc_ctl_paddr + |
| | | 825 | sc->sc_ctl_psize))) { |
| | | 826 | pa = bus_space_mmap(sc->sc_bustag, offset, 0, prot, |
| | | 827 | BUS_SPACE_MAP_LINEAR); |
| | | 828 | return pa; |
| | | 829 | } |
| | | 830 | #endif |
| | | 831 | return -1; |
| | | 832 | } |
| | | 833 | |
| | | 834 | static void |
| | | 835 | tcx_init_screen(void *cookie, struct vcons_screen *scr, |
| | | 836 | int existing, long *defattr) |
| | | 837 | { |
| | | 838 | struct tcx_softc *sc = cookie; |
| | | 839 | struct rasops_info *ri = &scr->scr_ri; |
| | | 840 | |
| | | 841 | ri->ri_depth = 8; |
| | | 842 | ri->ri_width = sc->sc_fb.fb_type.fb_width; |
| | | 843 | ri->ri_height = sc->sc_fb.fb_type.fb_height; |
| | | 844 | ri->ri_stride = sc->sc_fb.fb_linebytes; |
| | | 845 | ri->ri_flg = RI_CENTER | RI_FULLCLEAR; |
| | | 846 | |
| | | 847 | ri->ri_bits = sc->sc_fbaddr; |
| | | 848 | |
| | | 849 | rasops_init(ri, ri->ri_height/8, ri->ri_width/8); |
| | | 850 | ri->ri_caps = WSSCREEN_WSCOLORS; |
| | | 851 | rasops_reconfig(ri, ri->ri_height / ri->ri_font->fontheight, |
| | | 852 | ri->ri_width / ri->ri_font->fontwidth); |
| | | 853 | |
| | | 854 | /* enable acceleration */ |
| | | 855 | ri->ri_ops.copyrows = tcx_copyrows; |
| | | 856 | ri->ri_ops.eraserows = tcx_eraserows; |
| | | 857 | ri->ri_ops.putchar = tcx_putchar; |
| | | 858 | #if 0 |
| | | 859 | ri->ri_ops.cursor = tcx_cursor; |
| | | 860 | ri->ri_ops.copycols = tcx_copycols; |
| | | 861 | ri->ri_ops.erasecols = tcx_erasecols; |
| | | 862 | #endif |
| | | 863 | } |
| | | 864 | |
| | | 865 | static void |
| | | 866 | tcx_clearscreen(struct tcx_softc *sc) |
| | | 867 | { |
| | | 868 | uint64_t bg = ((uint64_t)sc->sc_bg << 32) | 0xffffffffLL; |
| | | 869 | int i; |
| | | 870 | |
| | | 871 | for (i = 0; i < 1024 * 1024; i += 32) |
| | | 872 | sc->sc_rstip[i] = bg; |
| | | 873 | } |
| | | 874 | |
| | | 875 | static void |
| | | 876 | tcx_copyrows(void *cookie, int srcrow, int dstrow, int nrows) |
| | | 877 | { |
| | | 878 | struct rasops_info *ri = cookie; |
| | | 879 | struct vcons_screen *scr = ri->ri_hw; |
| | | 880 | struct tcx_softc *sc = scr->scr_cookie; |
| | | 881 | int i, last, first, len, dest, leftover; |
| | | 882 | |
| | | 883 | i = ri->ri_width * ri->ri_font->fontheight * nrows; |
| | | 884 | len = i & 0xffffe0; |
| | | 885 | leftover = i & 0x1f; |
| | | 886 | if (srcrow < dstrow) { |
| | | 887 | /* we must go bottom to top */ |
| | | 888 | first = ri->ri_width * |
| | | 889 | (ri->ri_font->fontheight * srcrow + ri->ri_yorigin); |
| | | 890 | last = first + len; |
| | | 891 | dest = ri->ri_width * |
| | | 892 | (ri->ri_font->fontheight * dstrow + ri->ri_yorigin) + len; |
| | | 893 | if (leftover > 0) { |
| | | 894 | sc->sc_rblit[dest + 32] = |
| | | 895 | (uint64_t)((leftover - 1) << 24) | |
| | | 896 | (uint64_t)(i + 32); |
| | | 897 | } |
| | | 898 | for (i = last; i >= first; i -= 32) { |
| | | 899 | sc->sc_rblit[dest] = 0x300000001f000000LL | (uint64_t)i; |
| | | 900 | dest -= 32; |
| | | 901 | } |
| | | 902 | } else { |
| | | 903 | /* top to bottom */ |
| | | 904 | first = ri->ri_width * |
| | | 905 | (ri->ri_font->fontheight * srcrow + ri->ri_yorigin); |
| | | 906 | dest = ri->ri_width * |
| | | 907 | (ri->ri_font->fontheight * dstrow + ri->ri_yorigin); |
| | | 908 | last = first + len; |
| | | 909 | for (i = first; i <= last; i+= 32) { |
| | | 910 | sc->sc_rblit[dest] = 0x300000001f000000LL | (uint64_t)i; |
| | | 911 | dest += 32; |
| | | 912 | } |
| | | 913 | if (leftover > 0) { |
| | | 914 | sc->sc_rblit[dest] = |
| | | 915 | (uint64_t)((leftover - 1) << 24) | (uint64_t)i; |
| | | 916 | } |
| | | 917 | } |
| | | 918 | } |
| | | 919 | |
| | | 920 | static void |
| | | 921 | tcx_eraserows(void *cookie, int start, int nrows, long attr) |
| | | 922 | { |
| | | 923 | struct rasops_info *ri = cookie; |
| | | 924 | struct vcons_screen *scr = ri->ri_hw; |
| | | 925 | struct tcx_softc *sc = scr->scr_cookie; |
| | | 926 | uint64_t temp; |
| | | 927 | int i, last, first, len, leftover; |
| | | 928 | |
| | | 929 | i = ri->ri_width * ri->ri_font->fontheight * nrows; |
| | | 930 | len = i & 0xffffe0; |
| | | 931 | leftover = i & 0x1f; |
| | | 932 | first = ri->ri_width * |
| | | 933 | (ri->ri_font->fontheight * start + ri->ri_yorigin); |
| | | 934 | last = first + len; |
| | | 935 | temp = 0x30000000ffffffffLL | |
| | | 936 | ((uint64_t)ri->ri_devcmap[(attr >> 16) & 0xff] << 32); |
| | | 937 | |
| | | 938 | for (i = first; i <= last; i+= 32) |
| | | 939 | sc->sc_rblit[i] = temp; |
| | | 940 | |
| | | 941 | if (leftover > 0) { |
| | | 942 | temp &= 0xffffffffffffffffLL << (32 - leftover); |
| | | 943 | sc->sc_rblit[i] = temp; |
| | | 944 | } |
| | | 945 | } |
| | | 946 | /* |
| | | 947 | * The stipple engine is 100% retarded. All drawing operations have to start |
| | | 948 | * at 32 pixel boundaries so we'll have to deal with characters being split. |
| | | 949 | */ |
| | | 950 | |
| | | 951 | static void |
| | | 952 | tcx_putchar(void *cookie, int row, int col, u_int c, long attr) |
| | | 953 | { |
| | | 954 | struct rasops_info *ri = cookie; |
| | | 955 | struct vcons_screen *scr = ri->ri_hw; |
| | | 956 | struct tcx_softc *sc = scr->scr_cookie; |
| | | 957 | uint64_t bg, fg, temp, mask; |
| | | 958 | int addr, i, uc, shift; |
| | | 959 | uint32_t fmask; |
| | | 960 | uint8_t *cdata; |
| | | 961 | uint16_t *wdata; |
| | | 962 | |
| | | 963 | addr = ri->ri_xorigin + |
| | | 964 | col * ri->ri_font->fontwidth + |
| | | 965 | (ri->ri_yorigin + row * ri->ri_font->fontheight) * ri->ri_width; |
| | | 966 | |
| | | 967 | /* check if the character is crossing a 32 pixel boundary */ |
| | | 968 | if ((addr & 0xffffe0) == |
| | | 969 | ((addr + ri->ri_font->fontwidth - 1) & 0xffffe0)) { |
| | | 970 | /* phew, not split */ |
| | | 971 | shift = addr & 0x1f; |
| | | 972 | addr &= 0xffffe0; |
| | | 973 | fmask = 0xffffffff >> (32 - ri->ri_font->fontwidth); |
| | | 974 | fmask = fmask << (32 - ri->ri_font->fontwidth - shift); |
| | | 975 | mask = fmask; |
| | | 976 | bg = 0x3000000000000000LL | |
| | | 977 | ((uint64_t)ri->ri_devcmap[(attr >> 16) & 0xff] & |
| | | 978 | 0xff) << 32; |
| | | 979 | bg |= mask; |
| | | 980 | temp = 0x3000000000000000LL | |
| | | 981 | ((uint64_t)ri->ri_devcmap[(attr >> 24) & 0xff] & 0xff) << |
| | | 982 | 32; |
| | | 983 | uc = c - ri->ri_font->firstchar; |
| | | 984 | cdata = (uint8_t *)ri->ri_font->data + uc * ri->ri_fontscale; |
| | | 985 | |
| | | 986 | if (ri->ri_font->fontwidth < 9) { |
| | | 987 | /* byte by byte */ |
| | | 988 | for (i = 0; i < ri->ri_font->fontheight; i++) { |
| | | 989 | sc->sc_rstip[addr] = bg; |
| | | 990 | if (*cdata != 0) { |
| | | 991 | if (shift > 24) { |
| | | 992 | fg = (uint64_t)*cdata >> |
| | | 993 | (shift - 24); |
| | | 994 | } else { |
| | | 995 | fg = (uint64_t)*cdata << |
| | | 996 | (24 - shift); |
| | | 997 | } |
| | | 998 | sc->sc_rstip[addr] = fg | temp; |
| | | 999 | } |
| | | 1000 | cdata++; |
| | | 1001 | addr += ri->ri_width; |
| | | 1002 | } |
| | | 1003 | } else if (ri->ri_font->fontwidth < 17) { |
| | | 1004 | /* short by short */ |
| | | 1005 | wdata = (uint16_t *)cdata; |
| | | 1006 | for (i = 0; i < ri->ri_font->fontheight; i++) { |
| | | 1007 | sc->sc_rstip[addr] = bg; |
| | | 1008 | if (*wdata != 0) { |
| | | 1009 | if (shift > 16) { |
| | | 1010 | fg = temp | (uint64_t)*wdata >> |
| | | 1011 | (shift - 16); |
| | | 1012 | } else { |
| | | 1013 | fg = temp | (uint64_t)*wdata << |
| | | 1014 | (16 - shift); |
| | | 1015 | } |
| | | 1016 | sc->sc_rstip[addr] = fg; |
| | | 1017 | } |
| | | 1018 | wdata++; |
| | | 1019 | addr += ri->ri_width; |
| | | 1020 | } |
| | | 1021 | } |
| | | 1022 | } else { |
| | | 1023 | /* and now the split case ( man this hardware is dumb ) */ |
| | | 1024 | uint64_t bgr, maskr, fgr; |
| | | 1025 | uint32_t bork; |
| | | 1026 | |
| | | 1027 | shift = addr & 0x1f; |
| | | 1028 | addr &= 0xffffe0; |
| | | 1029 | mask = 0xffffffff >> shift; |
| | | 1030 | maskr = (uint64_t)(0xffffffffUL << |
| | | 1031 | (32 - (ri->ri_font->fontwidth + shift - 32))); |
| | | 1032 | bg = 0x3000000000000000LL | |
| | | 1033 | ((uint64_t)ri->ri_devcmap[(attr >> 16) & 0xff] & |
| | | 1034 | 0xff) << 32; |
| | | 1035 | bgr = bg | maskr; |
| | | 1036 | bg |= mask; |
| | | 1037 | temp = 0x3000000000000000LL | |
| | | 1038 | ((uint64_t)ri->ri_devcmap[(attr >> 24) & 0xff] & 0xff) << |
| | | 1039 | 32; |
| | | 1040 | |
| | | 1041 | uc = c - ri->ri_font->firstchar; |
| | | 1042 | cdata = (uint8_t *)ri->ri_font->data + uc * ri->ri_fontscale; |
| | | 1043 | |
| | | 1044 | if (ri->ri_font->fontwidth < 9) { |
| | | 1045 | /* byte by byte */ |
| | | 1046 | for (i = 0; i < ri->ri_font->fontheight; i++) { |
| | | 1047 | sc->sc_rstip[addr] = bg; |
| | | 1048 | sc->sc_rstip[addr + 32] = bgr; |
| | | 1049 | bork = *cdata; |
| | | 1050 | if (bork != 0) { |
| | | 1051 | fg = (uint64_t)bork >> (shift - 24); |
| | | 1052 | sc->sc_rstip[addr] = fg | temp; |
| | | 1053 | fgr = (uint64_t)(bork << (52 - shift)); |
| | | 1054 | sc->sc_rstip[addr] = fgr | temp; |
| | | 1055 | } |
| | | 1056 | cdata++; |
| | | 1057 | addr += ri->ri_width; |
| | | 1058 | } |
| | | 1059 | } else if (ri->ri_font->fontwidth < 17) { |
| | | 1060 | /* short by short */ |
| | | 1061 | wdata = (uint16_t *)cdata; |
| | | 1062 | for (i = 0; i < ri->ri_font->fontheight; i++) { |
| | | 1063 | sc->sc_rstip[addr] = bg; |
| | | 1064 | sc->sc_rstip[addr + 32] = bgr; |
| | | 1065 | bork = *wdata; |
| | | 1066 | if (bork != 0) { |
| | | 1067 | fg = (uint64_t)bork >> (shift - 16); |
| | | 1068 | sc->sc_rstip[addr] = fg | temp; |
| | | 1069 | fgr = (uint64_t)(bork << (48 - shift)); |
| | | 1070 | sc->sc_rstip[addr + 32] = fgr | temp; |
| | | 1071 | } |
| | | 1072 | wdata++; |
| | | 1073 | addr += ri->ri_width; |
| | | 1074 | } |
| | | 1075 | } |
| | | 1076 | |
| | | 1077 | } |
| | | 1078 | } |
| | | 1079 | |