| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: tcx.c,v 1.54 2014/07/16 17:58:35 macallan Exp $ */ | | 1 | /* $NetBSD: tcx.c,v 1.55 2014/07/22 04:55:51 macallan Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1996, 1998, 2009 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1996, 1998, 2009 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 and Michael Lorenz. | | 8 | * by Paul Kranenburg and Michael Lorenz. |
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.54 2014/07/16 17:58:35 macallan Exp $"); | | 41 | __KERNEL_RCSID(0, "$NetBSD: tcx.c,v 1.55 2014/07/22 04:55:51 macallan Exp $"); |
42 | | | 42 | |
43 | #include <sys/param.h> | | 43 | #include <sys/param.h> |
44 | #include <sys/systm.h> | | 44 | #include <sys/systm.h> |
45 | #include <sys/buf.h> | | 45 | #include <sys/buf.h> |
46 | #include <sys/device.h> | | 46 | #include <sys/device.h> |
47 | #include <sys/ioctl.h> | | 47 | #include <sys/ioctl.h> |
48 | #include <sys/malloc.h> | | 48 | #include <sys/malloc.h> |
49 | #include <sys/mman.h> | | 49 | #include <sys/mman.h> |
50 | #include <sys/tty.h> | | 50 | #include <sys/tty.h> |
51 | #include <sys/conf.h> | | 51 | #include <sys/conf.h> |
52 | | | 52 | |
53 | #ifdef DEBUG | | 53 | #ifdef DEBUG |
54 | #include <sys/proc.h> | | 54 | #include <sys/proc.h> |
| @@ -153,26 +153,27 @@ const struct cdevsw tcx_cdevsw = { | | | @@ -153,26 +153,27 @@ const struct cdevsw tcx_cdevsw = { |
153 | | | 153 | |
154 | /* frame buffer generic driver */ | | 154 | /* frame buffer generic driver */ |
155 | static struct fbdriver tcx_fbdriver = { | | 155 | static struct fbdriver tcx_fbdriver = { |
156 | tcx_unblank, tcxopen, tcxclose, tcxioctl, nopoll, tcxmmap, | | 156 | tcx_unblank, tcxopen, tcxclose, tcxioctl, nopoll, tcxmmap, |
157 | nokqfilter | | 157 | nokqfilter |
158 | }; | | 158 | }; |
159 | | | 159 | |
160 | static void tcx_reset(struct tcx_softc *); | | 160 | static void tcx_reset(struct tcx_softc *); |
161 | static void tcx_loadcmap(struct tcx_softc *, int, int); | | 161 | static void tcx_loadcmap(struct tcx_softc *, int, int); |
162 | | | 162 | |
163 | static int tcx_ioctl(void *, void *, u_long, void *, int, struct lwp *); | | 163 | static int tcx_ioctl(void *, void *, u_long, void *, int, struct lwp *); |
164 | static paddr_t tcx_mmap(void *, void *, off_t, int); | | 164 | static paddr_t tcx_mmap(void *, void *, off_t, int); |
165 | | | 165 | |
| | | 166 | static void tcx_init_cmap(struct tcx_softc *); |
166 | static void tcx_init_screen(void *, struct vcons_screen *, int, long *); | | 167 | static void tcx_init_screen(void *, struct vcons_screen *, int, long *); |
167 | static void tcx_clearscreen(struct tcx_softc *, int); | | 168 | static void tcx_clearscreen(struct tcx_softc *, int); |
168 | static void tcx_copyrows(void *, int, int, int); | | 169 | static void tcx_copyrows(void *, int, int, int); |
169 | static void tcx_eraserows(void *, int, int, long); | | 170 | static void tcx_eraserows(void *, int, int, long); |
170 | static void tcx_putchar(void *, int, int, u_int, long); | | 171 | static void tcx_putchar(void *, int, int, u_int, long); |
171 | static void tcx_set_video(struct tcx_softc *, int); | | 172 | static void tcx_set_video(struct tcx_softc *, int); |
172 | static int tcx_do_cursor(struct tcx_softc *, struct wsdisplay_cursor *); | | 173 | static int tcx_do_cursor(struct tcx_softc *, struct wsdisplay_cursor *); |
173 | static void tcx_set_cursor(struct tcx_softc *); | | 174 | static void tcx_set_cursor(struct tcx_softc *); |
174 | | | 175 | |
175 | struct wsdisplay_accessops tcx_accessops = { | | 176 | struct wsdisplay_accessops tcx_accessops = { |
176 | tcx_ioctl, | | 177 | tcx_ioctl, |
177 | tcx_mmap, | | 178 | tcx_mmap, |
178 | NULL, /* vcons_alloc_screen */ | | 179 | NULL, /* vcons_alloc_screen */ |
| @@ -202,27 +203,27 @@ tcxmatch(device_t parent, cfdata_t cf, v | | | @@ -202,27 +203,27 @@ tcxmatch(device_t parent, cfdata_t cf, v |
202 | * Attach a display. | | 203 | * Attach a display. |
203 | */ | | 204 | */ |
204 | void | | 205 | void |
205 | tcxattach(device_t parent, device_t self, void *args) | | 206 | tcxattach(device_t parent, device_t self, void *args) |
206 | { | | 207 | { |
207 | struct tcx_softc *sc = device_private(self); | | 208 | struct tcx_softc *sc = device_private(self); |
208 | struct sbus_attach_args *sa = args; | | 209 | struct sbus_attach_args *sa = args; |
209 | struct wsemuldisplaydev_attach_args aa; | | 210 | struct wsemuldisplaydev_attach_args aa; |
210 | struct rasops_info *ri; | | 211 | struct rasops_info *ri; |
211 | unsigned long defattr; | | 212 | unsigned long defattr; |
212 | int node; | | 213 | int node; |
213 | struct fbdevice *fb = &sc->sc_fb; | | 214 | struct fbdevice *fb = &sc->sc_fb; |
214 | bus_space_handle_t bh; | | 215 | bus_space_handle_t bh; |
215 | int isconsole, i, j; | | 216 | int isconsole; |
216 | uint32_t confreg; | | 217 | uint32_t confreg; |
217 | | | 218 | |
218 | sc->sc_dev = self; | | 219 | sc->sc_dev = self; |
219 | sc->sc_bustag = sa->sa_bustag; | | 220 | sc->sc_bustag = sa->sa_bustag; |
220 | node = sa->sa_node; | | 221 | node = sa->sa_node; |
221 | | | 222 | |
222 | sc->sc_cursor_x = 0x7fff; | | 223 | sc->sc_cursor_x = 0x7fff; |
223 | sc->sc_cursor_y = 0x7fff; | | 224 | sc->sc_cursor_y = 0x7fff; |
224 | sc->sc_hotspot_x = 0; | | 225 | sc->sc_hotspot_x = 0; |
225 | sc->sc_hotspot_y = 0; | | 226 | sc->sc_hotspot_y = 0; |
226 | | | 227 | |
227 | fb->fb_driver = &tcx_fbdriver; | | 228 | fb->fb_driver = &tcx_fbdriver; |
228 | fb->fb_device = sc->sc_dev; | | 229 | fb->fb_device = sc->sc_dev; |
| @@ -367,37 +368,26 @@ tcxattach(device_t parent, device_t self | | | @@ -367,37 +368,26 @@ tcxattach(device_t parent, device_t self |
367 | } | | 368 | } |
368 | isconsole = fb_is_console(node); | | 369 | isconsole = fb_is_console(node); |
369 | | | 370 | |
370 | confreg = bus_space_read_4(sa->sa_bustag, sc->sc_thc, THC_CONFIG); | | 371 | confreg = bus_space_read_4(sa->sa_bustag, sc->sc_thc, THC_CONFIG); |
371 | aprint_normal_dev(self, "id %d, rev %d, sense %d\n", | | 372 | aprint_normal_dev(self, "id %d, rev %d, sense %d\n", |
372 | (confreg & THC_CFG_FBID) >> THC_CFG_FBID_SHIFT, | | 373 | (confreg & THC_CFG_FBID) >> THC_CFG_FBID_SHIFT, |
373 | (confreg & THC_CFG_REV) >> THC_CFG_REV_SHIFT, | | 374 | (confreg & THC_CFG_REV) >> THC_CFG_REV_SHIFT, |
374 | (confreg & THC_CFG_SENSE) >> THC_CFG_SENSE_SHIFT | | 375 | (confreg & THC_CFG_SENSE) >> THC_CFG_SENSE_SHIFT |
375 | ); | | 376 | ); |
376 | | | 377 | |
377 | /* reset cursor & frame buffer controls */ | | 378 | /* reset cursor & frame buffer controls */ |
378 | tcx_reset(sc); | | 379 | tcx_reset(sc); |
379 | | | 380 | |
380 | /* Initialize the default color map. */ | | | |
381 | j = 0; | | | |
382 | for (i = 0; i < 256; i++) { | | | |
383 | | | | |
384 | sc->sc_cmap_red[i] = rasops_cmap[j]; | | | |
385 | sc->sc_cmap_green[i] = rasops_cmap[j + 1]; | | | |
386 | sc->sc_cmap_blue[i] = rasops_cmap[j + 2]; | | | |
387 | j += 3; | | | |
388 | } | | | |
389 | tcx_loadcmap(sc, 0, 256); | | | |
390 | | | | |
391 | if (!sc->sc_8bit) | | 381 | if (!sc->sc_8bit) |
392 | tcx_set_cursor(sc); | | 382 | tcx_set_cursor(sc); |
393 | | | 383 | |
394 | /* enable video */ | | 384 | /* enable video */ |
395 | confreg = bus_space_read_4(sa->sa_bustag, sc->sc_thc, THC_MISC); | | 385 | confreg = bus_space_read_4(sa->sa_bustag, sc->sc_thc, THC_MISC); |
396 | confreg |= THC_MISC_VIDEN; | | 386 | confreg |= THC_MISC_VIDEN; |
397 | bus_space_write_4(sa->sa_bustag, sc->sc_thc, THC_MISC, confreg); | | 387 | bus_space_write_4(sa->sa_bustag, sc->sc_thc, THC_MISC, confreg); |
398 | | | 388 | |
399 | if (isconsole) { | | 389 | if (isconsole) { |
400 | aprint_error_dev(self, "(console)\n"); | | 390 | aprint_error_dev(self, "(console)\n"); |
401 | } | | 391 | } |
402 | | | 392 | |
403 | fb_attach(&sc->sc_fb, isconsole); | | 393 | fb_attach(&sc->sc_fb, isconsole); |
| @@ -405,26 +395,27 @@ tcxattach(device_t parent, device_t self | | | @@ -405,26 +395,27 @@ tcxattach(device_t parent, device_t self |
405 | sc->sc_mode = WSDISPLAYIO_MODE_EMUL; | | 395 | sc->sc_mode = WSDISPLAYIO_MODE_EMUL; |
406 | wsfont_init(); | | 396 | wsfont_init(); |
407 | | | 397 | |
408 | vcons_init(&sc->vd, sc, &tcx_defscreendesc, &tcx_accessops); | | 398 | vcons_init(&sc->vd, sc, &tcx_defscreendesc, &tcx_accessops); |
409 | sc->vd.init_screen = tcx_init_screen; | | 399 | sc->vd.init_screen = tcx_init_screen; |
410 | | | 400 | |
411 | vcons_init_screen(&sc->vd, &tcx_console_screen, 1, &defattr); | | 401 | vcons_init_screen(&sc->vd, &tcx_console_screen, 1, &defattr); |
412 | tcx_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; | | 402 | tcx_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; |
413 | | | 403 | |
414 | ri = &tcx_console_screen.scr_ri; | | 404 | ri = &tcx_console_screen.scr_ri; |
415 | | | 405 | |
416 | sc->sc_bg = ri->ri_devcmap[(defattr >> 16) & 0xff]; | | 406 | sc->sc_bg = ri->ri_devcmap[(defattr >> 16) & 0xff]; |
417 | tcx_clearscreen(sc, 0); | | 407 | tcx_clearscreen(sc, 0); |
| | | 408 | tcx_init_cmap(sc); |
418 | | | 409 | |
419 | tcx_defscreendesc.nrows = ri->ri_rows; | | 410 | tcx_defscreendesc.nrows = ri->ri_rows; |
420 | tcx_defscreendesc.ncols = ri->ri_cols; | | 411 | tcx_defscreendesc.ncols = ri->ri_cols; |
421 | tcx_defscreendesc.textops = &ri->ri_ops; | | 412 | tcx_defscreendesc.textops = &ri->ri_ops; |
422 | tcx_defscreendesc.capabilities = ri->ri_caps; | | 413 | tcx_defscreendesc.capabilities = ri->ri_caps; |
423 | | | 414 | |
424 | if(isconsole) { | | 415 | if(isconsole) { |
425 | wsdisplay_cnattach(&tcx_defscreendesc, ri, 0, 0, defattr); | | 416 | wsdisplay_cnattach(&tcx_defscreendesc, ri, 0, 0, defattr); |
426 | vcons_replay_msgbuf(&tcx_console_screen); | | 417 | vcons_replay_msgbuf(&tcx_console_screen); |
427 | } | | 418 | } |
428 | | | 419 | |
429 | aa.console = isconsole; | | 420 | aa.console = isconsole; |
430 | aa.scrdata = &tcx_screenlist; | | 421 | aa.scrdata = &tcx_screenlist; |
| @@ -526,26 +517,43 @@ tcxioctl(dev_t dev, u_long cmd, void *da | | | @@ -526,26 +517,43 @@ tcxioctl(dev_t dev, u_long cmd, void *da |
526 | * Clean up hardware state (e.g., after bootup or after X crashes). | | 517 | * Clean up hardware state (e.g., after bootup or after X crashes). |
527 | */ | | 518 | */ |
528 | static void | | 519 | static void |
529 | tcx_reset(struct tcx_softc *sc) | | 520 | tcx_reset(struct tcx_softc *sc) |
530 | { | | 521 | { |
531 | uint32_t reg; | | 522 | uint32_t reg; |
532 | | | 523 | |
533 | reg = bus_space_read_4(sc->sc_bustag, sc->sc_thc, THC_MISC); | | 524 | reg = bus_space_read_4(sc->sc_bustag, sc->sc_thc, THC_MISC); |
534 | reg |= THC_MISC_CURSRES; | | 525 | reg |= THC_MISC_CURSRES; |
535 | bus_space_write_4(sc->sc_bustag, sc->sc_thc, THC_MISC, reg); | | 526 | bus_space_write_4(sc->sc_bustag, sc->sc_thc, THC_MISC, reg); |
536 | } | | 527 | } |
537 | | | 528 | |
538 | static void | | 529 | static void |
| | | 530 | tcx_init_cmap(struct tcx_softc *sc) |
| | | 531 | { |
| | | 532 | int i, j; |
| | | 533 | |
| | | 534 | /* Initialize the default color map. */ |
| | | 535 | j = 0; |
| | | 536 | for (i = 0; i < 256; i++) { |
| | | 537 | |
| | | 538 | sc->sc_cmap_red[i] = rasops_cmap[j]; |
| | | 539 | sc->sc_cmap_green[i] = rasops_cmap[j + 1]; |
| | | 540 | sc->sc_cmap_blue[i] = rasops_cmap[j + 2]; |
| | | 541 | j += 3; |
| | | 542 | } |
| | | 543 | tcx_loadcmap(sc, 0, 256); |
| | | 544 | } |
| | | 545 | |
| | | 546 | static void |
539 | tcx_loadcmap(struct tcx_softc *sc, int start, int ncolors) | | 547 | tcx_loadcmap(struct tcx_softc *sc, int start, int ncolors) |
540 | { | | 548 | { |
541 | int i; | | 549 | int i; |
542 | | | 550 | |
543 | for (i = 0; i < ncolors; i++) { | | 551 | for (i = 0; i < ncolors; i++) { |
544 | bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_ADDRESS, | | 552 | bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_ADDRESS, |
545 | (start + i) << 24); | | 553 | (start + i) << 24); |
546 | bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_FB_LUT, | | 554 | bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_FB_LUT, |
547 | sc->sc_cmap_red[i + start] << 24); | | 555 | sc->sc_cmap_red[i + start] << 24); |
548 | bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_FB_LUT, | | 556 | bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_FB_LUT, |
549 | sc->sc_cmap_green[i + start] << 24); | | 557 | sc->sc_cmap_green[i + start] << 24); |
550 | bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_FB_LUT, | | 558 | bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_FB_LUT, |
551 | sc->sc_cmap_blue[i + start] << 24); | | 559 | sc->sc_cmap_blue[i + start] << 24); |
| @@ -750,27 +758,27 @@ tcx_ioctl(void *v, void *vs, u_long cmd, | | | @@ -750,27 +758,27 @@ tcx_ioctl(void *v, void *vs, u_long cmd, |
750 | return tcx_getcmap(sc, (struct wsdisplay_cmap *)data); | | 758 | return tcx_getcmap(sc, (struct wsdisplay_cmap *)data); |
751 | | | 759 | |
752 | case WSDISPLAYIO_PUTCMAP: | | 760 | case WSDISPLAYIO_PUTCMAP: |
753 | return tcx_putcmap(sc, (struct wsdisplay_cmap *)data); | | 761 | return tcx_putcmap(sc, (struct wsdisplay_cmap *)data); |
754 | #endif | | 762 | #endif |
755 | case WSDISPLAYIO_SMODE: | | 763 | case WSDISPLAYIO_SMODE: |
756 | { | | 764 | { |
757 | int new_mode = *(int*)data; | | 765 | int new_mode = *(int*)data; |
758 | if (new_mode != sc->sc_mode) | | 766 | if (new_mode != sc->sc_mode) |
759 | { | | 767 | { |
760 | sc->sc_mode = new_mode; | | 768 | sc->sc_mode = new_mode; |
761 | if (new_mode == WSDISPLAYIO_MODE_EMUL) | | 769 | if (new_mode == WSDISPLAYIO_MODE_EMUL) |
762 | { | | 770 | { |
763 | tcx_loadcmap(sc, 0, 256); | | 771 | tcx_init_cmap(sc); |
764 | tcx_clearscreen(sc, 0); | | 772 | tcx_clearscreen(sc, 0); |
765 | vcons_redraw_screen(ms); | | 773 | vcons_redraw_screen(ms); |
766 | } else if (!sc->sc_8bit) | | 774 | } else if (!sc->sc_8bit) |
767 | tcx_clearscreen(sc, 3); | | 775 | tcx_clearscreen(sc, 3); |
768 | } | | 776 | } |
769 | } | | 777 | } |
770 | return 0; | | 778 | return 0; |
771 | | | 779 | |
772 | case WSDISPLAYIO_GCURPOS: | | 780 | case WSDISPLAYIO_GCURPOS: |
773 | if (sc->sc_8bit) { | | 781 | if (sc->sc_8bit) { |
774 | return EOPNOTSUPP; | | 782 | return EOPNOTSUPP; |
775 | } else { | | 783 | } else { |
776 | struct wsdisplay_curpos *cp = (void *)data; | | 784 | struct wsdisplay_curpos *cp = (void *)data; |