1 /*        $NetBSD: tcx.c,v 1.61 2022/09/25 18:03:04 thorpej Exp $ */
2 
3 /*
4  *  Copyright (c) 1996, 1998, 2009 The NetBSD Foundation, Inc.
5  *  All rights reserved.
6  *
7  *  This code is derived from software contributed to The NetBSD Foundation
8  *  by Paul Kranenburg and Michael Lorenz.
9  *
10  *  Redistribution and use in source and binary forms, with or without
11  *  modification, are permitted provided that the following conditions
12  *  are met:
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.
18  *
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.
30  */
31 
32 /*
33  * color display (TCX) driver.
34  *
35  * Does not handle interrupts, even though they can occur.
36  *
37  * XXX should defer colormap updates to vertical retrace interrupts
38  */
39 
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: tcx.c,v 1.61 2022/09/25 18:03:04 thorpej Exp $");
42 
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/buf.h>
46 #include <sys/device.h>
47 #include <sys/ioctl.h>
48 #include <sys/mman.h>
49 #include <sys/tty.h>
50 #include <sys/conf.h>
51 
52 #ifdef DEBUG
53 #include <sys/proc.h>
54 #include <sys/syslog.h>
55 #endif
56 
57 #include <sys/bus.h>
58 #include <machine/autoconf.h>
59 
60 #include <dev/sun/fbio.h>
61 #include <dev/sun/fbvar.h>
62 #include <dev/sun/btreg.h>
63 #include <dev/sun/btvar.h>
64 
65 #include <dev/sbus/sbusvar.h>
66 #include <dev/sbus/tcxreg.h>
67 
68 #include <dev/wscons/wsdisplayvar.h>
69 #include <dev/wscons/wsconsio.h>
70 #include <dev/wsfont/wsfont.h>
71 #include <dev/rasops/rasops.h>
72 
73 #include <dev/wscons/wsdisplay_vconsvar.h>
74 
75 #include "opt_wsemul.h"
76 
77 #include "ioconf.h"
78 
79 /* per-display variables */
80 struct tcx_softc {
81           device_t  sc_dev;             /* base device */
82           struct fbdevice     sc_fb;              /* frame buffer device */
83           bus_space_tag_t     sc_bustag;
84           struct openprom_addr sc_physaddr[TCX_NREG];/* phys addr of h/w */
85 
86           bus_space_handle_t sc_bt;     /* Brooktree registers */
87           bus_space_handle_t sc_thc;    /* THC registers */
88           uint8_t   *sc_fbaddr;         /* framebuffer */
89           volatile uint64_t   *sc_rblit;          /* blitspace */
90           volatile uint64_t   *sc_rstip;          /* stipple space */
91 
92           short               sc_8bit;  /* true if 8-bit hardware */
93           short               sc_blanked;         /* true if blanked */
94           uint32_t  sc_fbsize;          /* size of the 8bit fb */
95           u_char              sc_cmap_red[256];
96           u_char              sc_cmap_green[256];
97           u_char              sc_cmap_blue[256];
98           int                 sc_mode, sc_bg;
99           int                 sc_cursor_x, sc_cursor_y;
100           int                 sc_hotspot_x, sc_hotspot_y;
101           struct vcons_data vd;
102 };
103 
104 static struct vcons_screen tcx_console_screen;
105 
106 extern const u_char rasops_cmap[768];
107 
108 struct wsscreen_descr tcx_defscreendesc = {
109           "default",
110           0, 0,
111           NULL,
112           8, 16,
113           WSSCREEN_WSCOLORS,
114 };
115 
116 const struct wsscreen_descr *_tcx_scrlist[] = {
117           &tcx_defscreendesc,
118           /* XXX other formats, graphics screen? */
119 };
120 
121 struct wsscreen_list tcx_screenlist = {
122           sizeof(_tcx_scrlist) / sizeof(struct wsscreen_descr *),
123           _tcx_scrlist
124 };
125 
126 /* autoconfiguration driver */
127 static void         tcxattach(device_t, device_t, void *);
128 static int          tcxmatch(device_t, cfdata_t, void *);
129 static void         tcx_unblank(device_t);
130 
131 CFATTACH_DECL_NEW(tcx, sizeof(struct tcx_softc),
132     tcxmatch, tcxattach, NULL, NULL);
133 
134 dev_type_open(tcxopen);
135 dev_type_close(tcxclose);
136 dev_type_ioctl(tcxioctl);
137 dev_type_mmap(tcxmmap);
138 
139 const struct cdevsw tcx_cdevsw = {
140           .d_open = tcxopen,
141           .d_close = tcxclose,
142           .d_read = noread,
143           .d_write = nowrite,
144           .d_ioctl = tcxioctl,
145           .d_stop = nostop,
146           .d_tty = notty,
147           .d_poll = nopoll,
148           .d_mmap = tcxmmap,
149           .d_kqfilter = nokqfilter,
150           .d_discard = nodiscard,
151           .d_flag = 0
152 };
153 
154 /* frame buffer generic driver */
155 static struct fbdriver tcx_fbdriver = {
156           tcx_unblank, tcxopen, tcxclose, tcxioctl, nopoll, tcxmmap,
157           nokqfilter
158 };
159 
160 static void tcx_reset(struct tcx_softc *);
161 static void tcx_loadcmap(struct tcx_softc *, int, int);
162 
163 static int          tcx_ioctl(void *, void *, u_long, void *, int, struct lwp *);
164 static paddr_t      tcx_mmap(void *, void *, off_t, int);
165 
166 static void         tcx_init_cmap(struct tcx_softc *);
167 static void         tcx_init_screen(void *, struct vcons_screen *, int, long *);
168 static void         tcx_clearscreen(struct tcx_softc *, int);
169 static void         tcx_copyrows(void *, int, int, int);
170 static void         tcx_eraserows(void *, int, int, long);
171 static void         tcx_putchar(void *, int, int, u_int, long);
172 static void         tcx_set_video(struct tcx_softc *, int);
173 static int          tcx_do_cursor(struct tcx_softc *, struct wsdisplay_cursor *);
174 static void         tcx_set_cursor(struct tcx_softc *);
175 
176 struct wsdisplay_accessops tcx_accessops = {
177           tcx_ioctl,
178           tcx_mmap,
179           NULL,     /* vcons_alloc_screen */
180           NULL,     /* vcons_free_screen */
181           NULL,     /* vcons_show_screen */
182           NULL,     /* load_font */
183           NULL,     /* polls */
184           NULL,     /* scroll */
185 };
186 
187 #define OBPNAME     "SUNW,tcx"
188 
189 /*
190  * Match a tcx.
191  */
192 int
tcxmatch(device_t parent,cfdata_t cf,void * aux)193 tcxmatch(device_t parent, cfdata_t cf, void *aux)
194 {
195           struct sbus_attach_args *sa = aux;
196 
197           if (strcmp(sa->sa_name, OBPNAME) == 0)
198                     return 100;         /* beat genfb */
199           return 0;
200 }
201 
202 /*
203  * Attach a display.
204  */
205 void
tcxattach(device_t parent,device_t self,void * args)206 tcxattach(device_t parent, device_t self, void *args)
207 {
208           struct tcx_softc *sc = device_private(self);
209           struct sbus_attach_args *sa = args;
210           struct wsemuldisplaydev_attach_args aa;
211           struct rasops_info *ri;
212           unsigned long defattr;
213           int node;
214           struct fbdevice *fb = &sc->sc_fb;
215           bus_space_handle_t bh;
216           int isconsole;
217           uint32_t confreg;
218 
219           sc->sc_dev = self;
220           sc->sc_bustag = sa->sa_bustag;
221           node = sa->sa_node;
222 
223           sc->sc_cursor_x = 0x7fff;
224           sc->sc_cursor_y = 0x7fff;
225           sc->sc_hotspot_x = 0;
226           sc->sc_hotspot_y = 0;
227 
228           fb->fb_driver = &tcx_fbdriver;
229           fb->fb_device = sc->sc_dev;
230           /* Mask out invalid flags from the user. */
231           fb->fb_flags = device_cfdata(sc->sc_dev)->cf_flags & FB_USERMASK;
232           /*
233            * The onboard framebuffer on the SS4 supports only 8-bit mode;
234            * it can be distinguished from the S24 card for the SS5 by the
235            * presence of the "tcx-8-bit" attribute on the SS4 version.
236            */
237           sc->sc_8bit = node_has_property(node, "tcx-8-bit");
238           fb->fb_type.fb_depth = 8;
239           fb_setsize_obp(fb, fb->fb_type.fb_depth, 1152, 900, node);
240 
241           /*
242            * actual FB size ( of the 8bit region )
243            * no reason to restrict userland mappings to the visible VRAM
244            */
245           if (sc->sc_8bit) {
246                     aprint_normal(" (8-bit only TCX)\n");
247                     /* at least the SS4 can have 2MB with a VSIMM */
248                     sc->sc_fbsize = 0x100000 * prom_getpropint(node, "vram", 1);
249           } else {
250                     aprint_normal(" (S24)\n");
251                     /* all S24 I know of have 4MB, non-expandable */
252                     sc->sc_fbsize = 0x100000;
253           }
254 
255           fb->fb_type.fb_cmsize = 256;
256           fb->fb_type.fb_size = sc->sc_fbsize;    /* later code assumes 8bit */
257           aprint_normal_dev(self, "%s, %d x %d\n", OBPNAME,
258                     fb->fb_type.fb_width,
259                     fb->fb_type.fb_height);
260 
261           fb->fb_type.fb_type = FBTYPE_TCXCOLOR;
262 
263           if (sa->sa_nreg != TCX_NREG) {
264                     aprint_error("\n");
265                     aprint_error_dev(self, "only %d register sets\n",
266                               sa->sa_nreg);
267                     return;
268           }
269           if (sa->sa_reg[TCX_REG_STIP].oa_size < 0x1000) {
270                     aprint_error("\n");
271                     aprint_error_dev(self, "STIP register too small (0x%x)\n",
272                         sa->sa_reg[TCX_REG_STIP].oa_size);
273                     return;
274           }
275 
276           memcpy(sc->sc_physaddr, sa->sa_reg,
277                 sa->sa_nreg * sizeof(struct openprom_addr));
278 
279           /* Map the register banks we care about */
280           if (sbus_bus_map(sa->sa_bustag,
281                                sc->sc_physaddr[TCX_REG_THC].oa_space,
282                                sc->sc_physaddr[TCX_REG_THC].oa_base,
283                                0x1000,
284                                BUS_SPACE_MAP_LINEAR, &sc->sc_thc) != 0) {
285                     aprint_error_dev(self,
286                         "tcxattach: cannot map thc registers\n");
287                     return;
288           }
289 
290           if (sbus_bus_map(sa->sa_bustag,
291                                sc->sc_physaddr[TCX_REG_CMAP].oa_space,
292                                sc->sc_physaddr[TCX_REG_CMAP].oa_base,
293                                0x1000,
294                                BUS_SPACE_MAP_LINEAR, &sc->sc_bt) != 0) {
295                     aprint_error_dev(self, "tcxattach: cannot map DAC registers\n");
296                     return;
297           }
298 
299           /* map the 8bit dumb FB for the console */
300           if (sbus_bus_map(sa->sa_bustag,
301                      sc->sc_physaddr[TCX_REG_DFB8].oa_space,
302                      sc->sc_physaddr[TCX_REG_DFB8].oa_base,
303                                sc->sc_fbsize,
304                                BUS_SPACE_MAP_LINEAR,
305                                &bh) != 0) {
306                     aprint_error_dev(self, "tcxattach: cannot map framebuffer\n");
307                     return;
308           }
309           sc->sc_fbaddr = bus_space_vaddr(sa->sa_bustag, bh);
310 
311           /*
312            * 8bit tcx has the RSTIP and RBLIT ranges set to size 0.
313            * On Real Hardware they work anyway ( on my SS4 at least ) but
314            * emulators may not be so forgiving.
315            */
316           if (sc->sc_8bit) {
317                     /* BLIT space */
318                     if (sbus_bus_map(sa->sa_bustag,
319                                sc->sc_physaddr[TCX_REG_BLIT].oa_space,
320                                sc->sc_physaddr[TCX_REG_BLIT].oa_base,
321                                          sc->sc_fbsize << 3,
322                                          BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE,
323                                          &bh) != 0) {
324                               aprint_error_dev(self,
325                                   "tcxattach: cannot map BLIT space\n");
326                               return;
327                     }
328                     sc->sc_rblit = bus_space_vaddr(sa->sa_bustag, bh);
329 
330                     /* STIP space */
331                     if (sbus_bus_map(sa->sa_bustag,
332                                sc->sc_physaddr[TCX_REG_STIP].oa_space,
333                                sc->sc_physaddr[TCX_REG_STIP].oa_base,
334                                          sc->sc_fbsize << 3,
335                                          BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE,
336                                          &bh) != 0) {
337                               aprint_error_dev(self,
338                                   "tcxattach: cannot map STIP space\n");
339                               return;
340                     }
341                     sc->sc_rstip = bus_space_vaddr(sa->sa_bustag, bh);
342           } else {
343                     /* RBLIT space */
344                     if (sbus_bus_map(sa->sa_bustag,
345                                sc->sc_physaddr[TCX_REG_RBLIT].oa_space,
346                                sc->sc_physaddr[TCX_REG_RBLIT].oa_base,
347                                          sc->sc_fbsize << 3,
348                                          BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE,
349                                          &bh) != 0) {
350                               aprint_error_dev(self,
351                                   "tcxattach: cannot map RBLIT space\n");
352                               return;
353                     }
354                     sc->sc_rblit = bus_space_vaddr(sa->sa_bustag, bh);
355 
356                     /* RSTIP space */
357                     if (sbus_bus_map(sa->sa_bustag,
358                                sc->sc_physaddr[TCX_REG_RSTIP].oa_space,
359                                sc->sc_physaddr[TCX_REG_RSTIP].oa_base,
360                                          sc->sc_fbsize << 3,
361                                          BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE,
362                                          &bh) != 0) {
363                               aprint_error_dev(self,
364                                   "tcxattach: cannot map RSTIP space\n");
365                               return;
366                     }
367                     sc->sc_rstip = bus_space_vaddr(sa->sa_bustag, bh);
368           }
369           isconsole = fb_is_console(node);
370 
371           confreg = bus_space_read_4(sa->sa_bustag, sc->sc_thc, THC_CONFIG);
372           aprint_normal_dev(self, "id %d, rev %d, sense %d\n",
373                     (confreg & THC_CFG_FBID) >> THC_CFG_FBID_SHIFT,
374                     (confreg & THC_CFG_REV) >> THC_CFG_REV_SHIFT,
375                     (confreg & THC_CFG_SENSE) >> THC_CFG_SENSE_SHIFT
376           );
377 
378           /* reset cursor & frame buffer controls */
379           tcx_reset(sc);
380 
381           if (!sc->sc_8bit)
382               tcx_set_cursor(sc);
383 
384           /* enable video */
385           confreg = bus_space_read_4(sa->sa_bustag, sc->sc_thc, THC_MISC);
386           confreg |= THC_MISC_VIDEN;
387           bus_space_write_4(sa->sa_bustag, sc->sc_thc, THC_MISC, confreg);
388 
389           if (isconsole) {
390                     aprint_error_dev(self, "(console)\n");
391           }
392 
393           fb_attach(&sc->sc_fb, isconsole);
394 
395           sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
396           wsfont_init();
397 
398           vcons_init(&sc->vd, sc, &tcx_defscreendesc, &tcx_accessops);
399           sc->vd.init_screen = tcx_init_screen;
400 
401           vcons_init_screen(&sc->vd, &tcx_console_screen, 1, &defattr);
402           tcx_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
403 
404           ri = &tcx_console_screen.scr_ri;
405 
406           sc->sc_bg = ri->ri_devcmap[(defattr >> 16) & 0xff];
407           tcx_clearscreen(sc, 0);
408           tcx_init_cmap(sc);
409 
410           tcx_defscreendesc.nrows = ri->ri_rows;
411           tcx_defscreendesc.ncols = ri->ri_cols;
412           tcx_defscreendesc.textops = &ri->ri_ops;
413           tcx_defscreendesc.capabilities = ri->ri_caps;
414 
415           if(isconsole) {
416                     wsdisplay_cnattach(&tcx_defscreendesc, ri, 0, 0, defattr);
417                     vcons_replay_msgbuf(&tcx_console_screen);
418           }
419 
420           aa.console = isconsole;
421           aa.scrdata = &tcx_screenlist;
422           aa.accessops = &tcx_accessops;
423           aa.accesscookie = &sc->vd;
424 
425           config_found(self, &aa, wsemuldisplaydevprint, CFARGS_NONE);
426           /*
427            * we need to do this again - something overwrites a handful
428            * palette registers and we end up with white in reg. 0
429            */
430           tcx_loadcmap(sc, 0, 256);
431 }
432 
433 int
tcxopen(dev_t dev,int flags,int mode,struct lwp * l)434 tcxopen(dev_t dev, int flags, int mode, struct lwp *l)
435 {
436           return (0);
437 }
438 
439 int
tcxclose(dev_t dev,int flags,int mode,struct lwp * l)440 tcxclose(dev_t dev, int flags, int mode, struct lwp *l)
441 {
442           struct tcx_softc *sc = device_lookup_private(&tcx_cd, minor(dev));
443 
444           tcx_reset(sc);
445           /* we may want to clear and redraw the console here */
446           return (0);
447 }
448 
449 int
tcxioctl(dev_t dev,u_long cmd,void * data,int flags,struct lwp * l)450 tcxioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
451 {
452           struct tcx_softc *sc = device_lookup_private(&tcx_cd, minor(dev));
453 
454           switch (cmd) {
455 
456           case FBIOGTYPE:
457                     *(struct fbtype *)data = sc->sc_fb.fb_type;
458                     break;
459 
460           case FBIOGATTR:
461 #define fba ((struct fbgattr *)data)
462                     fba->real_type = sc->sc_fb.fb_type.fb_type;
463                     fba->owner = 0;               /* XXX ??? */
464                     fba->fbtype = sc->sc_fb.fb_type;
465                     fba->sattr.flags = 0;
466                     fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
467                     fba->sattr.dev_specific[0] = -1;
468                     fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
469                     fba->emu_types[1] = FBTYPE_SUN3COLOR;
470                     fba->emu_types[2] = -1;
471 #undef fba
472                     break;
473 
474           case FBIOGETCMAP:
475 #define   p ((struct fbcmap *)data)
476                     if (p->index > 256 || p->count > 256 - p->index)
477                               return EINVAL;
478                     if (copyout(&sc->sc_cmap_red[p->index], p->red, p->count) != 0)
479                               return EINVAL;
480                     if (copyout(&sc->sc_cmap_green[p->index], p->green, p->count)
481                         != 0)
482                               return EINVAL;
483                     if (copyout(&sc->sc_cmap_blue[p->index], p->blue, p->count)
484                         != 0)
485                               return EINVAL;
486                     return 0;
487 
488           case FBIOPUTCMAP:
489                     /* copy to software map */
490                     if (p->index > 256 || p->count > 256 - p->index)
491                               return EINVAL;
492                     if (copyin(p->red, &sc->sc_cmap_red[p->index], p->count) != 0)
493                               return EINVAL;
494                     if (copyin(p->green, &sc->sc_cmap_green[p->index], p->count)
495                         != 0)
496                               return EINVAL;
497                     if (copyin(p->blue, &sc->sc_cmap_blue[p->index], p->count) != 0)
498                               return EINVAL;
499                     tcx_loadcmap(sc, p->index, p->count);
500 #undef p
501                     break;
502           case FBIOGVIDEO:
503                     *(int *)data = sc->sc_blanked;
504                     break;
505 
506           case FBIOSVIDEO:
507                     tcx_set_video(sc, *(int *)data);
508                     break;
509 
510           default:
511 #ifdef DEBUG
512                     log(LOG_NOTICE, "tcxioctl(0x%lx) (%s[%d])\n", cmd,
513                         l->l_proc->p_comm, l->l_proc->p_pid);
514 #endif
515                     return (ENOTTY);
516           }
517           return (0);
518 }
519 
520 /*
521  * Clean up hardware state (e.g., after bootup or after X crashes).
522  */
523 static void
tcx_reset(struct tcx_softc * sc)524 tcx_reset(struct tcx_softc *sc)
525 {
526           uint32_t reg;
527 
528           reg = bus_space_read_4(sc->sc_bustag, sc->sc_thc, THC_MISC);
529           reg |= THC_MISC_CURSRES;
530           bus_space_write_4(sc->sc_bustag, sc->sc_thc, THC_MISC, reg);
531 }
532 
533 static void
tcx_init_cmap(struct tcx_softc * sc)534 tcx_init_cmap(struct tcx_softc *sc)
535 {
536           int i, j;
537 
538           /* Initialize the default color map. */
539           j = 0;
540           for (i = 0; i < 256; i++) {
541 
542                     sc->sc_cmap_red[i] = rasops_cmap[j];
543                     sc->sc_cmap_green[i] = rasops_cmap[j + 1];
544                     sc->sc_cmap_blue[i] = rasops_cmap[j + 2];
545                     j += 3;
546           }
547           tcx_loadcmap(sc, 0, 256);
548 }
549 
550 static void
tcx_loadcmap(struct tcx_softc * sc,int start,int ncolors)551 tcx_loadcmap(struct tcx_softc *sc, int start, int ncolors)
552 {
553           int i;
554 
555           for (i = 0; i < ncolors; i++) {
556                     bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_ADDRESS,
557                         (start + i) << 24);
558                     bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_FB_LUT,
559                         sc->sc_cmap_red[i + start] << 24);
560                     bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_FB_LUT,
561                         sc->sc_cmap_green[i + start] << 24);
562                     bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_FB_LUT,
563                         sc->sc_cmap_blue[i + start] << 24);
564           }
565           bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_ADDRESS, 0);
566 }
567 
568 static void
tcx_unblank(device_t dev)569 tcx_unblank(device_t dev)
570 {
571           struct tcx_softc *sc = device_private(dev);
572 
573           if (sc->sc_blanked) {
574                     uint32_t reg;
575                     sc->sc_blanked = 0;
576                     reg = bus_space_read_4(sc->sc_bustag, sc->sc_thc, THC_MISC);
577                     reg &= ~THC_MISC_VSYNC_DISABLE;
578                     reg &= ~THC_MISC_HSYNC_DISABLE;
579                     reg |= THC_MISC_VIDEN;
580                     bus_space_write_4(sc->sc_bustag, sc->sc_thc, THC_MISC, reg);
581           }
582 }
583 
584 static void
tcx_set_video(struct tcx_softc * sc,int unblank)585 tcx_set_video(struct tcx_softc *sc, int unblank)
586 {
587           uint32_t reg;
588           if (unblank) {
589                     sc->sc_blanked = 0;
590                     reg = bus_space_read_4(sc->sc_bustag, sc->sc_thc, THC_MISC);
591                     reg &= ~THC_MISC_VSYNC_DISABLE;
592                     reg &= ~THC_MISC_HSYNC_DISABLE;
593                     reg |= THC_MISC_VIDEN;
594                     bus_space_write_4(sc->sc_bustag, sc->sc_thc, THC_MISC, reg);
595           } else {
596                     sc->sc_blanked = 1;
597                     reg = bus_space_read_4(sc->sc_bustag, sc->sc_thc, THC_MISC);
598                     reg |= THC_MISC_VSYNC_DISABLE;
599                     reg |= THC_MISC_HSYNC_DISABLE;
600                     reg &= ~THC_MISC_VIDEN;
601                     bus_space_write_4(sc->sc_bustag, sc->sc_thc, THC_MISC, reg);
602           }
603 }
604 
605 /*
606  * Base addresses at which users can mmap() the various pieces of a tcx.
607  */
608 #define   TCX_USER_RAM        0x00000000
609 #define   TCX_USER_RAM24      0x01000000
610 #define   TCX_USER_RAM_COMPAT 0x04000000          /* cg3 emulation */
611 #define   TCX_USER_STIP       0x10000000
612 #define   TCX_USER_BLIT       0x20000000
613 #define   TCX_USER_RDFB32     0x28000000
614 #define   TCX_USER_RSTIP      0x30000000
615 #define   TCX_USER_RBLIT      0x38000000
616 #define   TCX_USER_TEC        0x70001000
617 #define   TCX_USER_BTREGS     0x70002000
618 #define   TCX_USER_THC        0x70004000
619 #define   TCX_USER_DHC        0x70008000
620 #define   TCX_USER_ALT        0x7000a000
621 #define   TCX_USER_UART       0x7000c000
622 #define   TCX_USER_VRT        0x7000e000
623 #define   TCX_USER_ROM        0x70010000
624 
625 struct mmo {
626           u_int     mo_uaddr; /* user (virtual) address */
627           u_int     mo_size;  /* size, or 0 for video ram size */
628           u_int     mo_bank;  /* register bank number */
629 };
630 
631 /*
632  * Return the address that would map the given device at the given
633  * offset, allowing for the given protection, or return -1 for error.
634  *
635  * XXX    needs testing against `demanding' applications (e.g., aviator)
636  */
637 paddr_t
tcxmmap(dev_t dev,off_t off,int prot)638 tcxmmap(dev_t dev, off_t off, int prot)
639 {
640           struct tcx_softc *sc = device_lookup_private(&tcx_cd, minor(dev));
641           struct openprom_addr *rr = sc->sc_physaddr;
642           struct mmo *mo, *mo_end;
643           u_int u, sz;
644           static struct mmo mmo[] = {
645                     { TCX_USER_RAM, 0, TCX_REG_DFB8 },
646                     { TCX_USER_RAM24, 0, TCX_REG_DFB24 },
647                     { TCX_USER_RAM_COMPAT, 0, TCX_REG_DFB8 },
648 
649                     { TCX_USER_STIP, 1, TCX_REG_STIP },
650                     { TCX_USER_BLIT, 1, TCX_REG_BLIT },
651                     { TCX_USER_RDFB32, 0, TCX_REG_RDFB32 },
652                     { TCX_USER_RSTIP, 1, TCX_REG_RSTIP },
653                     { TCX_USER_RBLIT, 1, TCX_REG_RBLIT },
654                     { TCX_USER_TEC, 1, TCX_REG_TEC },
655                     { TCX_USER_BTREGS, 8192 /* XXX */, TCX_REG_CMAP },
656                     { TCX_USER_THC, 0x2000, TCX_REG_THC },
657                     { TCX_USER_DHC, 1, TCX_REG_DHC },
658                     { TCX_USER_ALT, 1, TCX_REG_ALT },
659                     { TCX_USER_ROM, 65536, TCX_REG_ROM },
660           };
661 #define NMMO (sizeof mmo / sizeof *mmo)
662 
663           if (off & PGOFSET)
664                     panic("tcxmmap");
665 
666           /*
667            * Entries with size 0 map video RAM (i.e., the size in fb data).
668            * Entries that map 32-bit deep regions are adjusted for their
669            * depth (fb_size gives the size of the 8-bit-deep region).
670            *
671            * Since we work in pages, the fact that the map offset table's
672            * sizes are sometimes bizarre (e.g., 1) is effectively ignored:
673            * one byte is as good as one page.
674            */
675 
676           mo = mmo;
677           mo_end = &mmo[NMMO];
678 
679           for (; mo < mo_end; mo++) {
680                     if ((u_int)off < mo->mo_uaddr)
681                               continue;
682 
683                     u = off - mo->mo_uaddr;
684                     sz = mo->mo_size;
685 
686                     if (sz == 0) {
687                               sz = sc->sc_fb.fb_type.fb_size;
688                               /*
689                                * check for the 32-bit-deep regions and adjust
690                                * accordingly
691                                */
692                               if (mo->mo_uaddr == TCX_USER_RAM24 ||
693                                   mo->mo_uaddr == TCX_USER_RDFB32) {
694                                         if (sc->sc_8bit) {
695                                                   /*
696                                                    * not present on 8-bit hardware
697                                                    */
698                                                   continue;
699                                         }
700                                         sz *= 4;
701                               }
702                     }
703                     if (sz == 1)
704                               sz = rr[mo->mo_bank].oa_size;
705 
706                     if (u < sz) {
707                               return (bus_space_mmap(sc->sc_bustag,
708                                         BUS_ADDR(rr[mo->mo_bank].oa_space,
709                                                    rr[mo->mo_bank].oa_base),
710                                         u,
711                                         prot,
712                                         BUS_SPACE_MAP_LINEAR));
713                     }
714           }
715           return (-1);
716 }
717 
718 int
tcx_ioctl(void * v,void * vs,u_long cmd,void * data,int flag,struct lwp * l)719 tcx_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
720           struct lwp *l)
721 {
722           struct vcons_data *vd = v;
723           struct tcx_softc *sc = vd->cookie;
724           struct wsdisplay_fbinfo *wdf;
725           struct vcons_screen *ms = vd->active;
726 
727           switch (cmd) {
728                     case WSDISPLAYIO_GTYPE:
729                               *(u_int *)data = WSDISPLAY_TYPE_SUNTCX;
730                               return 0;
731 
732                     case FBIOGVIDEO:
733                     case WSDISPLAYIO_GVIDEO:
734                               *(int *)data = !sc->sc_blanked;
735                               return 0;
736 
737                     case WSDISPLAYIO_SVIDEO:
738                     case FBIOSVIDEO:
739                               tcx_set_video(sc, *(int *)data);
740                               return 0;
741 
742                     case WSDISPLAYIO_GINFO:
743                               wdf = (void *)data;
744                               wdf->height = ms->scr_ri.ri_height;
745                               wdf->width = ms->scr_ri.ri_width;
746                               if (sc->sc_8bit) {
747                                         wdf->depth = 8;
748                               } else {
749                                         wdf->depth = 32;
750                               }
751                               wdf->cmsize = 256;
752                               return 0;
753                     case WSDISPLAYIO_LINEBYTES:
754                               {
755                                         int *ret = (int *)data;
756                                         *ret = sc->sc_8bit ? ms->scr_ri.ri_width :
757                                             ms->scr_ri.ri_width << 2;
758                               }
759                               return 0;
760 #if 0
761                     case WSDISPLAYIO_GETCMAP:
762                               return tcx_getcmap(sc, (struct wsdisplay_cmap *)data);
763 
764                     case WSDISPLAYIO_PUTCMAP:
765                               return tcx_putcmap(sc, (struct wsdisplay_cmap *)data);
766 #endif
767                     case WSDISPLAYIO_SMODE:
768                               {
769                                         int new_mode = *(int*)data;
770                                         if (new_mode != sc->sc_mode)
771                                         {
772                                                   sc->sc_mode = new_mode;
773                                                   if (new_mode == WSDISPLAYIO_MODE_EMUL)
774                                                   {
775                                                             tcx_init_cmap(sc);
776                                                             tcx_clearscreen(sc, 0);
777                                                             vcons_redraw_screen(ms);
778                                                   } else if (!sc->sc_8bit)
779                                                             tcx_clearscreen(sc, 3);
780                                         }
781                               }
782                               return 0;
783 
784                     case WSDISPLAYIO_GCURPOS:
785                               if (sc->sc_8bit) {
786                                         return EOPNOTSUPP;
787                               } else {
788                                         struct wsdisplay_curpos *cp = (void *)data;
789 
790                                         cp->x = sc->sc_cursor_x;
791                                         cp->y = sc->sc_cursor_y;
792                               }
793                               return 0;
794 
795                     case WSDISPLAYIO_SCURPOS:
796                               if (sc->sc_8bit) {
797                                         return EOPNOTSUPP;
798                               } else {
799                                         struct wsdisplay_curpos *cp = (void *)data;
800 
801                                         sc->sc_cursor_x = cp->x;
802                                         sc->sc_cursor_y = cp->y;
803                                         tcx_set_cursor(sc);
804                               }
805                               return 0;
806 
807                     case WSDISPLAYIO_GCURMAX:
808                               if (sc->sc_8bit) {
809                                         return EOPNOTSUPP;
810                               } else {
811                                         struct wsdisplay_curpos *cp = (void *)data;
812 
813                                         cp->x = 32;
814                                         cp->y = 32;
815                               }
816                               return 0;
817 
818                     case WSDISPLAYIO_SCURSOR:
819                               if (sc->sc_8bit) {
820                                         return EOPNOTSUPP;
821                               } else {
822                                         struct wsdisplay_cursor *cursor = (void *)data;
823 
824                                         return tcx_do_cursor(sc, cursor);
825                               }
826           }
827           return EPASSTHROUGH;
828 }
829 
830 static paddr_t
tcx_mmap(void * v,void * vs,off_t offset,int prot)831 tcx_mmap(void *v, void *vs, off_t offset, int prot)
832 {
833           struct vcons_data *vd = v;
834           struct tcx_softc *sc = vd->cookie;
835 
836           /* 'regular' framebuffer mmap()ing */
837           if (sc->sc_8bit) {
838                     /* on 8Bit boards hand over the 8 bit aperture */
839                     if (offset > sc->sc_fbsize)
840                               return -1;
841                     return bus_space_mmap(sc->sc_bustag,
842                         sc->sc_physaddr[TCX_REG_DFB8].oa_base + offset, 0, prot,
843                         BUS_SPACE_MAP_LINEAR);
844           } else {
845                     /* ... but if we have a 24bit aperture we use it */
846                     if (offset > sc->sc_fbsize * 4)
847                               return -1;
848                     return bus_space_mmap(sc->sc_bustag,
849                         sc->sc_physaddr[TCX_REG_DFB24].oa_base + offset, 0, prot,
850                         BUS_SPACE_MAP_LINEAR);
851           }
852           return -1;
853 }
854 
855 static void
tcx_init_screen(void * cookie,struct vcons_screen * scr,int existing,long * defattr)856 tcx_init_screen(void *cookie, struct vcons_screen *scr,
857     int existing, long *defattr)
858 {
859           struct tcx_softc *sc = cookie;
860           struct rasops_info *ri = &scr->scr_ri;
861 
862           ri->ri_depth = 8;
863           ri->ri_width = sc->sc_fb.fb_type.fb_width;
864           ri->ri_height = sc->sc_fb.fb_type.fb_height;
865           ri->ri_stride = sc->sc_fb.fb_linebytes;
866           ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
867 
868           ri->ri_bits = sc->sc_fbaddr;
869 
870           rasops_init(ri, 0, 0);
871           ri->ri_caps = WSSCREEN_WSCOLORS;
872           rasops_reconfig(ri, ri->ri_height / ri->ri_font->fontheight,
873                         ri->ri_width / ri->ri_font->fontwidth);
874 
875           /* enable acceleration */
876           ri->ri_ops.copyrows  = tcx_copyrows;
877           ri->ri_ops.eraserows = tcx_eraserows;
878           ri->ri_ops.putchar   = tcx_putchar;
879 #if 0
880           ri->ri_ops.cursor    = tcx_cursor;
881           ri->ri_ops.copycols  = tcx_copycols;
882           ri->ri_ops.erasecols = tcx_erasecols;
883 #endif
884 }
885 
886 static void
tcx_clearscreen(struct tcx_softc * sc,int spc)887 tcx_clearscreen(struct tcx_softc *sc, int spc)
888 {
889           /* ROP in the upper 4bit is necessary, tcx actually uses it */
890           volatile uint64_t bg = 0x30000000ffffffffLL;
891           volatile uint64_t spc64;
892           int i, len;
893 
894           spc64 = ((spc & 3) << 24);
895           bg |= (spc64 << 32);
896 
897           len = sc->sc_fb.fb_type.fb_width * sc->sc_fb.fb_type.fb_height;
898           for (i = 0; i < len; i += 32)
899                     sc->sc_rstip[i] = bg;
900 }
901 
902 static void
tcx_copyrows(void * cookie,int srcrow,int dstrow,int nrows)903 tcx_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
904 {
905           struct rasops_info *ri = cookie;
906           struct vcons_screen *scr = ri->ri_hw;
907           struct tcx_softc *sc = scr->scr_cookie;
908           int i, last, first, len, dest, leftover;
909 
910           i = ri->ri_width * ri->ri_font->fontheight * nrows;
911           len = i & 0xffffe0;
912           leftover = i & 0x1f;
913           if (srcrow < dstrow) {
914                     /* we must go bottom to top */
915                     first = ri->ri_width *
916                         (ri->ri_font->fontheight * srcrow + ri->ri_yorigin);
917                     last = first + len;
918                     dest = ri->ri_width *
919                         (ri->ri_font->fontheight * dstrow + ri->ri_yorigin) + len;
920                     if (leftover > 0) {
921                               sc->sc_rblit[dest + 32] =
922                                   (uint64_t)((leftover - 1) << 24) |
923                                   (uint64_t)(i + 32);
924                     }
925                     for (i = last; i >= first; i -= 32) {
926                               sc->sc_rblit[dest] = 0x300000001f000000LL | (uint64_t)i;
927                               dest -= 32;
928                     }
929           } else {
930                     /* top to bottom */
931                     first = ri->ri_width *
932                         (ri->ri_font->fontheight * srcrow + ri->ri_yorigin);
933                     dest = ri->ri_width *
934                         (ri->ri_font->fontheight * dstrow + ri->ri_yorigin);
935                     last = first + len;
936                     for (i = first; i <= last; i+= 32) {
937                               sc->sc_rblit[dest] = 0x300000001f000000LL | (uint64_t)i;
938                               dest += 32;
939                     }
940                     if (leftover > 0) {
941                               sc->sc_rblit[dest] =
942                                   (uint64_t)((leftover - 1) << 24) | (uint64_t)i;
943                     }
944           }
945 }
946 
947 static void
tcx_eraserows(void * cookie,int start,int nrows,long attr)948 tcx_eraserows(void *cookie, int start, int nrows, long attr)
949 {
950           struct rasops_info *ri = cookie;
951           struct vcons_screen *scr = ri->ri_hw;
952           struct tcx_softc *sc = scr->scr_cookie;
953           volatile uint64_t temp;
954           int i, last, first, len, leftover;
955 
956           i = ri->ri_width * ri->ri_font->fontheight * nrows;
957           len = i & 0xffffe0;
958           leftover = i & 0x1f;
959           first = ri->ri_width *
960               (ri->ri_font->fontheight * start + ri->ri_yorigin);
961           last = first + len;
962           temp = 0x30000000ffffffffLL |
963               ((uint64_t)((ri->ri_devcmap[(attr >> 16) & 0xff]) & 0xff) << 32);
964 
965           for (i = first; i < last; i+= 32)
966                     sc->sc_rstip[i] = temp;
967 
968           if (leftover > 0) {
969                     temp &= 0xffffffffffffffffLL << (32 - leftover);
970                     sc->sc_rstip[i] = temp;
971           }
972 }
973 /*
974  * The stipple engine is 100% retarded. All drawing operations have to start
975  * at 32 pixel boundaries so we'll have to deal with characters being split.
976  */
977 
978 static void
tcx_putchar(void * cookie,int row,int col,u_int c,long attr)979 tcx_putchar(void *cookie, int row, int col, u_int c, long attr)
980 {
981           struct rasops_info *ri = cookie;
982           struct wsdisplay_font *font = PICK_FONT(ri, c);
983           struct vcons_screen *scr = ri->ri_hw;
984           struct tcx_softc *sc = scr->scr_cookie;
985           volatile uint64_t bg, fg, temp, mask;
986           int addr, i, uc, shift;
987           uint32_t fmask;
988           uint8_t *cdata;
989           uint16_t *wdata;
990 
991           addr = ri->ri_xorigin + col * font->fontwidth +
992               (ri->ri_yorigin + row * font->fontheight) * ri->ri_width;
993 
994           /* check if the character is crossing a 32 pixel boundary */
995           if ((addr & 0xffffe0) ==
996               ((addr + font->fontwidth - 1) & 0xffffe0)) {
997                     /* phew, not split */
998                     shift = addr & 0x1f;
999                     addr &= 0xffffe0;
1000                     fmask = 0xffffffff >> (32 - font->fontwidth);
1001                     fmask = fmask << (32 - font->fontwidth - shift);
1002                     mask = fmask;
1003                     bg = 0x3000000000000000LL |
1004                         ((uint64_t)ri->ri_devcmap[(attr >> 16) & 0xff] &
1005                           0xff) << 32;
1006                     bg |= mask;
1007                     temp = 0x3000000000000000LL |
1008                         ((uint64_t)ri->ri_devcmap[(attr >> 24) & 0xff] & 0xff) <<
1009                               32;
1010                     uc = c - font->firstchar;
1011                     cdata = (uint8_t *)font->data + uc * ri->ri_fontscale;
1012 
1013                     if (font->fontwidth < 9) {
1014                               /* byte by byte */
1015                               for (i = 0; i < font->fontheight; i++) {
1016                                         sc->sc_rstip[addr] = bg;
1017                                         if (*cdata != 0) {
1018                                                   if (shift > 24) {
1019                                                             fg = (uint64_t)*cdata >>
1020                                                               (shift - 24);
1021                                                   } else {
1022                                                             fg = (uint64_t)*cdata <<
1023                                                               (24 - shift);
1024                                                   }
1025                                                   sc->sc_rstip[addr] = fg | temp;
1026                                         }
1027                                         cdata++;
1028                                         addr += ri->ri_width;
1029                               }
1030                     } else if (font->fontwidth < 17) {
1031                               /* short by short */
1032                               wdata = (uint16_t *)cdata;
1033                               for (i = 0; i < font->fontheight; i++) {
1034                                         sc->sc_rstip[addr] = bg;
1035                                         if (*wdata != 0) {
1036                                                   if (shift > 16) {
1037                                                             fg = temp | (uint64_t)*wdata >>
1038                                                               (shift - 16);
1039                                                   } else {
1040                                                             fg = temp | (uint64_t)*wdata <<
1041                                                               (16 - shift);
1042                                                   }
1043                                                   sc->sc_rstip[addr] = fg;
1044                                         }
1045                                         wdata++;
1046                                         addr += ri->ri_width;
1047                               }
1048                     }
1049           } else {
1050                     /* and now the split case ( man this hardware is dumb ) */
1051                     volatile uint64_t bgr, maskr, fgr;
1052                     uint32_t bork;
1053 
1054                     shift = addr & 0x1f;
1055                     addr &= 0xffffe0;
1056                     mask = 0xffffffff >> shift;
1057                     maskr = (uint64_t)(0xffffffffUL <<
1058                         (32 - (font->fontwidth + shift - 32)));
1059                     bg = 0x3000000000000000LL |
1060                         ((uint64_t)ri->ri_devcmap[(attr >> 16) & 0xff] &
1061                           0xff) << 32;
1062                     bgr = bg | maskr;
1063                     bg |= mask;
1064                     temp = 0x3000000000000000LL |
1065                         ((uint64_t)ri->ri_devcmap[(attr >> 24) & 0xff] & 0xff) <<
1066                           32;
1067 
1068                     uc = c - font->firstchar;
1069                     cdata = (uint8_t *)font->data + uc * ri->ri_fontscale;
1070 
1071                     if (font->fontwidth < 9) {
1072                               /* byte by byte */
1073                               for (i = 0; i < font->fontheight; i++) {
1074                                         sc->sc_rstip[addr] = bg;
1075                                         sc->sc_rstip[addr + 32] = bgr;
1076                                         bork = *cdata;
1077                                         if (bork != 0) {
1078                                                   fg = (uint64_t)bork >> (shift - 24);
1079                                                   sc->sc_rstip[addr] = fg | temp;
1080                                                   fgr = (uint64_t)(bork << (52 - shift));
1081                                                   sc->sc_rstip[addr] = fgr | temp;
1082                                         }
1083                                         cdata++;
1084                                         addr += ri->ri_width;
1085                               }
1086                     } else if (font->fontwidth < 17) {
1087                               /* short by short */
1088                               wdata = (uint16_t *)cdata;
1089                               for (i = 0; i < font->fontheight; i++) {
1090                                         sc->sc_rstip[addr] = bg;
1091                                         sc->sc_rstip[addr + 32] = bgr;
1092                                         bork = *wdata;
1093                                         if (bork != 0) {
1094                                                   fg = (uint64_t)bork >> (shift - 16);
1095                                                   sc->sc_rstip[addr] = fg | temp;
1096                                                   fgr = (uint64_t)(bork << (48 - shift));
1097                                                   sc->sc_rstip[addr + 32] = fgr | temp;
1098                                         }
1099                                         wdata++;
1100                                         addr += ri->ri_width;
1101                               }
1102                     }
1103 
1104           }
1105 }
1106 
1107 static int
tcx_do_cursor(struct tcx_softc * sc,struct wsdisplay_cursor * cur)1108 tcx_do_cursor(struct tcx_softc *sc, struct wsdisplay_cursor *cur)
1109 {
1110           if (sc->sc_8bit) {
1111                     /* hw cursor is not implemented on tcx */
1112                     return -1;
1113           }
1114           if (cur->which & WSDISPLAY_CURSOR_DOCUR) {
1115 
1116                     if (cur->enable) {
1117                               tcx_set_cursor(sc);
1118                     } else {
1119                               /* move the cursor out of sight */
1120                               bus_space_write_4(sc->sc_bustag, sc->sc_thc,
1121                                   THC_CURSOR_POS, 0x7fff7fff);
1122                     }
1123           }
1124           if (cur->which & WSDISPLAY_CURSOR_DOHOT) {
1125 
1126                     sc->sc_hotspot_x = cur->hot.x;
1127                     sc->sc_hotspot_y = cur->hot.y;
1128                     tcx_set_cursor(sc);
1129           }
1130           if (cur->which & WSDISPLAY_CURSOR_DOPOS) {
1131 
1132                     sc->sc_cursor_x = cur->pos.x;
1133                     sc->sc_cursor_y = cur->pos.y;
1134                     tcx_set_cursor(sc);
1135           }
1136           if (cur->which & WSDISPLAY_CURSOR_DOCMAP) {
1137 #if 0
1138           /*
1139            * apparently we're not writing in the right register here - if we do
1140            * this the screen goes all funky
1141            */
1142                     int i;
1143 
1144                     for (i = 0; i < cur->cmap.count; i++) {
1145                               bus_space_write_4(sc->sc_bustag, sc->sc_bt, DAC_ADDRESS,
1146                                   (cur->cmap.index + i + 2) << 24);
1147                               bus_space_write_4(sc->sc_bustag, sc->sc_bt,
1148                                   DAC_CURSOR_LUT, cur->cmap.red[i] << 24);
1149                               bus_space_write_4(sc->sc_bustag, sc->sc_bt,
1150                                   DAC_CURSOR_LUT, cur->cmap.green[i] << 24);
1151                               bus_space_write_4(sc->sc_bustag, sc->sc_bt,
1152                                   DAC_CURSOR_LUT, cur->cmap.blue[i] << 24);
1153                     }
1154 #endif
1155           }
1156           if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) {
1157                     int i;
1158                     uint32_t temp, poof;
1159 
1160                     for (i = 0; i < 128; i += 4) {
1161                               memcpy(&temp, &cur->mask[i], 4);
1162                               printf("%08x -> ", temp);
1163                               poof = ((temp & 0x80808080) >> 7) |
1164                                      ((temp & 0x40404040) >> 5) |
1165                                      ((temp & 0x20202020) >> 3) |
1166                                      ((temp & 0x10101010) >> 1) |
1167                                      ((temp & 0x08080808) << 1) |
1168                                      ((temp & 0x04040404) << 3) |
1169                                      ((temp & 0x02020202) << 5) |
1170                                      ((temp & 0x01010101) << 7);
1171                               printf("%08x\n", poof);
1172                               bus_space_write_4(sc->sc_bustag, sc->sc_thc,
1173                                   THC_CURSOR_1 + i, poof);
1174                               memcpy(&temp, &cur->image[i], 4);
1175                               poof = ((temp & 0x80808080) >> 7) |
1176                                      ((temp & 0x40404040) >> 5) |
1177                                      ((temp & 0x20202020) >> 3) |
1178                                      ((temp & 0x10101010) >> 1) |
1179                                      ((temp & 0x08080808) << 1) |
1180                                      ((temp & 0x04040404) << 3) |
1181                                      ((temp & 0x02020202) << 5) |
1182                                      ((temp & 0x01010101) << 7);
1183                               bus_space_write_4(sc->sc_bustag, sc->sc_thc,
1184                                   THC_CURSOR_0 + i, poof);
1185                     }
1186           }
1187           return 0;
1188 }
1189 
1190 static void
tcx_set_cursor(struct tcx_softc * sc)1191 tcx_set_cursor(struct tcx_softc *sc)
1192 {
1193           uint32_t reg;
1194 
1195           reg = (sc->sc_cursor_x - sc->sc_hotspot_x) << 16 |
1196                ((sc->sc_cursor_y - sc->sc_hotspot_y) & 0xffff);
1197           bus_space_write_4(sc->sc_bustag, sc->sc_thc, THC_CURSOR_POS, reg);
1198 }
1199 
1200