Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / tc / tfb.c
blob5a96c65ef06d9f40c6a2324f48624ca811f0adee
1 /* $NetBSD: tfb.c,v 1.56 2008/12/17 20:51:35 cegger Exp $ */
3 /*-
4 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tohru Nishimura.
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.
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.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: tfb.c,v 1.56 2008/12/17 20:51:35 cegger Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/device.h>
39 #include <sys/malloc.h>
40 #include <sys/buf.h>
41 #include <sys/ioctl.h>
43 #include <sys/bus.h>
44 #include <sys/intr.h>
46 #include <dev/wscons/wsconsio.h>
47 #include <dev/wscons/wsdisplayvar.h>
49 #include <dev/rasops/rasops.h>
50 #include <dev/wsfont/wsfont.h>
52 #include <dev/tc/tcvar.h>
53 #include <dev/ic/bt463reg.h>
54 #include <dev/ic/bt431reg.h>
56 #include <uvm/uvm_extern.h>
58 #if defined(pmax)
59 #define machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x))
60 #endif
62 #if defined(alpha)
63 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x))
64 #endif
67 * struct bt463reg {
68 * uint8_t bt_lo;
69 * unsigned : 24;
70 * uint8_t bt_hi;
71 * unsigned : 24;
72 * uint8_t bt_reg;
73 * unsigned : 24;
74 * uint8_t bt_cmap;
75 * };
77 * N.B. a pair of Bt431s are located adjascently.
78 * struct bt431twin {
79 * struct {
80 * uint8_t u0; for sprite mask
81 * uint8_t u1; for sprite image
82 * unsigned :16;
83 * } bt_lo;
84 * ...
86 * struct bt431reg {
87 * uint16_t bt_lo;
88 * unsigned : 16;
89 * uint16_t bt_hi;
90 * unsigned : 16;
91 * uint16_t bt_ram;
92 * unsigned : 16;
93 * uint16_t bt_ctl;
94 * };
97 /* Bt463 hardware registers, memory-mapped in 32bit stride */
98 #define bt_lo 0x0
99 #define bt_hi 0x4
100 #define bt_reg 0x8
101 #define bt_cmap 0xc
103 /* Bt431 hardware registers, memory-mapped in 32bit stride */
104 #define bt_ram 0x8
105 #define bt_ctl 0xc
107 #define REGWRITE32(p,i,v) do { \
108 *(volatile uint32_t *)((p) + (i)) = (v); tc_wmb(); \
109 } while (0)
111 #define SELECT463(p,r) do { \
112 REGWRITE32((p), bt_lo, 0xff & (r)); \
113 REGWRITE32((p), bt_hi, 0xff & ((r)>>8)); \
114 } while (0)
116 #define TWIN(x) ((x) | ((x) << 8))
117 #define TWIN_LO(x) (twin = (x) & 0x00ff, (twin << 8) | twin)
118 #define TWIN_HI(x) (twin = (x) & 0xff00, twin | (twin >> 8))
120 #define SELECT431(p,r) do { \
121 REGWRITE32((p), bt_lo, TWIN(r)); \
122 REGWRITE32((p), bt_hi, 0); \
123 } while (0)
125 struct hwcmap256 {
126 #define CMAP_SIZE 256 /* R/G/B entries */
127 uint8_t r[CMAP_SIZE];
128 uint8_t g[CMAP_SIZE];
129 uint8_t b[CMAP_SIZE];
132 struct hwcursor64 {
133 struct wsdisplay_curpos cc_pos;
134 struct wsdisplay_curpos cc_hot;
135 struct wsdisplay_curpos cc_size;
136 struct wsdisplay_curpos cc_magic;
137 #define CURSOR_MAX_SIZE 64
138 uint8_t cc_color[6];
139 uint64_t cc_image[CURSOR_MAX_SIZE];
140 uint64_t cc_mask[CURSOR_MAX_SIZE];
143 struct tfb_softc {
144 vaddr_t sc_vaddr;
145 size_t sc_size;
146 struct rasops_info *sc_ri;
147 struct hwcmap256 sc_cmap; /* software copy of colormap */
148 struct hwcursor64 sc_cursor; /* software copy of cursor */
149 int sc_blanked; /* video visibility disabled */
150 int sc_curenb; /* cursor sprite enabled */
151 int sc_changed; /* need update of hardware */
152 #define WSDISPLAY_CMAP_DOLUT 0x20
153 int nscreens;
156 #define TX_MAGIC_X 360
157 #define TX_MAGIC_Y 36
159 #define TX_BT463_OFFSET 0x040000
160 #define TX_BT431_OFFSET 0x040010
161 #define TX_CONTROL 0x040030
162 #define TX_MAP_REGISTER 0x040030
163 #define TX_PIP_OFFSET 0x0800c0
164 #define TX_SELECTION 0x100000
165 #define TX_8BPP_OFFSET 0x200000
166 #define TX_8BPP_SIZE 0x200000
167 #define TX_24BPP_OFFSET 0x400000
168 #define TX_24BPP_SIZE 0x600000
169 #define TX_VIDEO_ENABLE 0xa00000
171 #define TX_CTL_VIDEO_ON 0x80
172 #define TX_CTL_INT_ENA 0x40
173 #define TX_CTL_INT_PEND 0x20
174 #define TX_CTL_SEG_ENA 0x10
175 #define TX_CTL_SEG 0x0f
177 static int tfbmatch(device_t, cfdata_t, void *);
178 static void tfbattach(device_t, device_t, void *);
180 CFATTACH_DECL_NEW(tfb, sizeof(struct tfb_softc),
181 tfbmatch, tfbattach, NULL, NULL);
183 static void tfb_common_init(struct rasops_info *);
184 static void tfb_cmap_init(struct tfb_softc *);
185 static struct rasops_info tfb_console_ri;
186 static tc_addr_t tfb_consaddr;
188 static struct wsscreen_descr tfb_stdscreen = {
189 "std", 0, 0,
190 0, /* textops */
191 0, 0,
192 WSSCREEN_REVERSE
195 static const struct wsscreen_descr *_tfb_scrlist[] = {
196 &tfb_stdscreen,
199 static const struct wsscreen_list tfb_screenlist = {
200 sizeof(_tfb_scrlist) / sizeof(struct wsscreen_descr *), _tfb_scrlist
203 static int tfbioctl(void *, void *, u_long, void *, int, struct lwp *);
204 static paddr_t tfbmmap(void *, void *, off_t, int);
206 static int tfb_alloc_screen(void *, const struct wsscreen_descr *,
207 void **, int *, int *, long *);
208 static void tfb_free_screen(void *, void *);
209 static int tfb_show_screen(void *, void *, int,
210 void (*) (void *, int, int), void *);
212 static const struct wsdisplay_accessops tfb_accessops = {
213 tfbioctl,
214 tfbmmap,
215 tfb_alloc_screen,
216 tfb_free_screen,
217 tfb_show_screen,
218 0 /* load_font */
221 int tfb_cnattach(tc_addr_t);
222 static int tfbintr(void *);
223 static void tfbhwinit(void *);
225 static int get_cmap(struct tfb_softc *, struct wsdisplay_cmap *);
226 static int set_cmap(struct tfb_softc *, struct wsdisplay_cmap *);
227 static int set_cursor(struct tfb_softc *, struct wsdisplay_cursor *);
228 static int get_cursor(struct tfb_softc *, struct wsdisplay_cursor *);
229 static void set_curpos(struct tfb_softc *, struct wsdisplay_curpos *);
231 /* bit order reverse */
232 static const uint8_t flip[256] = {
233 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
234 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
235 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
236 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
237 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
238 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
239 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
240 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
241 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
242 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
243 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
244 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
245 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
246 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
247 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
248 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
249 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
250 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
251 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
252 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
253 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
254 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
255 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
256 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
257 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
258 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
259 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
260 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
261 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
262 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
263 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
264 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
267 static int
268 tfbmatch(device_t parent, cfdata_t match, void *aux)
270 struct tc_attach_args *ta = aux;
272 if (strncmp("PMAG-RO ", ta->ta_modname, TC_ROM_LLEN) != 0
273 && strncmp("PMAG-JA ", ta->ta_modname, TC_ROM_LLEN) != 0)
274 return (0);
276 return (1);
280 static void
281 tfbattach(device_t parent, device_t self, void *aux)
283 struct tfb_softc *sc = device_private(self);
284 struct tc_attach_args *ta = aux;
285 struct rasops_info *ri;
286 struct wsemuldisplaydev_attach_args waa;
287 int console;
289 console = (ta->ta_addr == tfb_consaddr);
290 if (console) {
291 sc->sc_ri = ri = &tfb_console_ri;
292 sc->nscreens = 1;
294 else {
295 ri = malloc(sizeof(struct rasops_info),
296 M_DEVBUF, M_NOWAIT|M_ZERO);
297 if (ri == NULL) {
298 printf(": can't alloc memory\n");
299 return;
302 ri->ri_hw = (void *)ta->ta_addr;
303 tfb_common_init(ri);
304 sc->sc_ri = ri;
306 printf(": %dx%d, 8,24bpp\n", ri->ri_width, ri->ri_height);
308 tfb_cmap_init(sc);
310 sc->sc_vaddr = ta->ta_addr;
311 sc->sc_cursor.cc_magic.x = TX_MAGIC_X;
312 sc->sc_cursor.cc_magic.y = TX_MAGIC_Y;
313 sc->sc_blanked = sc->sc_curenb = 0;
315 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, tfbintr, sc);
317 *(uint8_t *)((char *)ri->ri_hw + TX_CONTROL) &= ~0x40;
318 *(uint8_t *)((char *)ri->ri_hw + TX_CONTROL) |= 0x40;
320 waa.console = console;
321 waa.scrdata = &tfb_screenlist;
322 waa.accessops = &tfb_accessops;
323 waa.accesscookie = sc;
325 config_found(self, &waa, wsemuldisplaydevprint);
328 static void
329 tfb_common_init(struct rasops_info *ri)
331 char *base;
332 int cookie;
334 base = (void *)ri->ri_hw;
336 /* initialize colormap and cursor hardware */
337 tfbhwinit(base);
339 ri->ri_flg = RI_CENTER;
340 ri->ri_depth = 8;
341 ri->ri_width = 1280;
342 ri->ri_height = 1024;
343 ri->ri_stride = 1280;
344 ri->ri_bits = base + TX_8BPP_OFFSET;
346 /* clear the screen */
347 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
349 wsfont_init();
350 /* prefer 12 pixel wide font */
351 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_L2R,
352 WSDISPLAY_FONTORDER_L2R);
353 if (cookie <= 0)
354 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R,
355 WSDISPLAY_FONTORDER_L2R);
356 if (cookie <= 0) {
357 printf("tfb: font table is empty\n");
358 return;
361 if (wsfont_lock(cookie, &ri->ri_font)) {
362 printf("tfb: couldn't lock font\n");
363 return;
365 ri->ri_wsfcookie = cookie;
367 rasops_init(ri, 34, 80);
369 /* XXX shouldn't be global */
370 tfb_stdscreen.nrows = ri->ri_rows;
371 tfb_stdscreen.ncols = ri->ri_cols;
372 tfb_stdscreen.textops = &ri->ri_ops;
373 tfb_stdscreen.capabilities = ri->ri_caps;
376 static void
377 tfb_cmap_init(struct tfb_softc *sc)
379 struct hwcmap256 *cm;
380 const uint8_t *p;
381 int index;
383 cm = &sc->sc_cmap;
384 p = rasops_cmap;
385 for (index = 0; index < CMAP_SIZE; index++, p += 3) {
386 cm->r[index] = p[0];
387 cm->g[index] = p[1];
388 cm->b[index] = p[2];
392 static int
393 tfbioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
395 struct tfb_softc *sc = v;
396 struct rasops_info *ri = sc->sc_ri;
397 int turnoff, s;
399 switch (cmd) {
400 case WSDISPLAYIO_GTYPE:
401 *(u_int *)data = WSDISPLAY_TYPE_TX;
402 return (0);
404 case WSDISPLAYIO_GINFO:
405 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
406 wsd_fbip->height = ri->ri_height;
407 wsd_fbip->width = ri->ri_width;
408 wsd_fbip->depth = ri->ri_depth;
409 wsd_fbip->cmsize = CMAP_SIZE;
410 #undef fbt
411 return (0);
413 case WSDISPLAYIO_GETCMAP:
414 return get_cmap(sc, (struct wsdisplay_cmap *)data);
416 case WSDISPLAYIO_PUTCMAP:
417 return set_cmap(sc, (struct wsdisplay_cmap *)data);
419 case WSDISPLAYIO_SVIDEO:
420 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
421 if (sc->sc_blanked != turnoff) {
422 sc->sc_blanked = turnoff;
423 #if 0 /* XXX later XXX */
424 To turn off;
425 - clear the MSB of TX control register; &= ~0x80,
426 - assign Bt431 register #0 with value 0x4 to hide sprite cursor.
427 #endif /* XXX XXX XXX */
429 return (0);
431 case WSDISPLAYIO_GVIDEO:
432 *(u_int *)data = sc->sc_blanked ?
433 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
434 return (0);
436 case WSDISPLAYIO_GCURPOS:
437 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
438 return (0);
440 case WSDISPLAYIO_SCURPOS:
441 s = spltty();
442 set_curpos(sc, (struct wsdisplay_curpos *)data);
443 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS;
444 splx(s);
445 return (0);
447 case WSDISPLAYIO_GCURMAX:
448 ((struct wsdisplay_curpos *)data)->x =
449 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
450 return (0);
452 case WSDISPLAYIO_GCURSOR:
453 return get_cursor(sc, (struct wsdisplay_cursor *)data);
455 case WSDISPLAYIO_SCURSOR:
456 return set_cursor(sc, (struct wsdisplay_cursor *)data);
458 case WSDISPLAYIO_SMODE:
459 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
460 s = spltty();
461 tfb_cmap_init(sc);
462 sc->sc_curenb = 0;
463 sc->sc_blanked = 0;
464 sc->sc_changed |= (WSDISPLAY_CURSOR_DOCUR |
465 WSDISPLAY_CMAP_DOLUT);
466 splx(s);
468 return (0);
470 return (EPASSTHROUGH);
473 static paddr_t
474 tfbmmap(void *v, void *vs, off_t offset, int prot)
476 struct tfb_softc *sc = v;
478 if (offset >= TX_8BPP_SIZE || offset < 0) /* XXX 24bpp XXX */
479 return (-1);
480 return machine_btop(sc->sc_vaddr + TX_8BPP_OFFSET + offset);
483 static int
484 tfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
485 int *curxp, int *curyp, long *attrp)
487 struct tfb_softc *sc = v;
488 struct rasops_info *ri = sc->sc_ri;
489 long defattr;
491 if (sc->nscreens > 0)
492 return (ENOMEM);
494 *cookiep = ri; /* one and only for now */
495 *curxp = 0;
496 *curyp = 0;
497 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
498 *attrp = defattr;
499 sc->nscreens++;
500 return (0);
503 static void
504 tfb_free_screen(void *v, void *cookie)
506 struct tfb_softc *sc = v;
508 if (sc->sc_ri == &tfb_console_ri)
509 panic("tfb_free_screen: console");
511 sc->nscreens--;
514 static int
515 tfb_show_screen(void *v, void *cookie, int waitok,
516 void (*cb)(void *, int, int), void *cbarg)
519 return (0);
522 /* EXPORT */ int
523 tfb_cnattach(tc_addr_t addr)
525 struct rasops_info *ri;
526 long defattr;
528 ri = &tfb_console_ri;
529 ri->ri_hw = (void *)addr;
530 tfb_common_init(ri);
531 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
532 wsdisplay_cnattach(&tfb_stdscreen, ri, 0, 0, defattr);
533 tfb_consaddr = addr;
534 return (0);
537 static int
538 tfbintr(void *arg)
540 struct tfb_softc *sc = arg;
541 char *base, *vdac, *curs;
542 int v;
544 base = (void *)sc->sc_ri->ri_hw;
545 *(uint8_t *)(base + TX_CONTROL) &= ~0x40;
546 if (sc->sc_changed == 0)
547 goto done;
549 vdac = base + TX_BT463_OFFSET;
550 curs = base + TX_BT431_OFFSET;
551 v = sc->sc_changed;
552 if (v & WSDISPLAY_CURSOR_DOCUR) {
553 int onoff;
555 onoff = (sc->sc_curenb) ? 0x4444 : 0x0404;
556 SELECT431(curs, BT431_REG_COMMAND);
557 REGWRITE32(curs, bt_ctl, onoff);
559 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
560 int x, y;
561 uint32_t twin;
563 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
564 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
566 x += sc->sc_cursor.cc_magic.x;
567 y += sc->sc_cursor.cc_magic.y;
569 SELECT431(curs, BT431_REG_CURSOR_X_LOW);
570 REGWRITE32(curs, bt_ctl, TWIN_LO(x));
571 REGWRITE32(curs, bt_ctl, TWIN_HI(x));
572 REGWRITE32(curs, bt_ctl, TWIN_LO(y));
573 REGWRITE32(curs, bt_ctl, TWIN_HI(y));
575 if (v & WSDISPLAY_CURSOR_DOCMAP) {
576 uint8_t *cp = sc->sc_cursor.cc_color;
578 SELECT463(vdac, BT463_IREG_CURSOR_COLOR_0);
579 REGWRITE32(vdac, bt_reg, cp[1]);
580 REGWRITE32(vdac, bt_reg, cp[3]);
581 REGWRITE32(vdac, bt_reg, cp[5]);
583 REGWRITE32(vdac, bt_reg, cp[0]);
584 REGWRITE32(vdac, bt_reg, cp[2]);
585 REGWRITE32(vdac, bt_reg, cp[4]);
587 REGWRITE32(vdac, bt_reg, cp[1]);
588 REGWRITE32(vdac, bt_reg, cp[3]);
589 REGWRITE32(vdac, bt_reg, cp[5]);
591 REGWRITE32(vdac, bt_reg, cp[1]);
592 REGWRITE32(vdac, bt_reg, cp[3]);
593 REGWRITE32(vdac, bt_reg, cp[5]);
595 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
596 uint8_t *ip, *mp, img, msk;
597 int bcnt;
599 ip = (uint8_t *)sc->sc_cursor.cc_image;
600 mp = (uint8_t *)sc->sc_cursor.cc_mask;
601 bcnt = 0;
602 SELECT431(curs, BT431_REG_CRAM_BASE);
604 /* 64 pixel scan line is consisted with 16 byte cursor ram */
605 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
606 /* pad right half 32 pixel when smaller than 33 */
607 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
608 REGWRITE32(curs, bt_ram, 0);
610 else {
611 int half;
612 img = *ip++;
613 msk = *mp++;
614 img &= msk; /* cookie off image */
615 half = (flip[img] << 8) | flip[msk];
616 REGWRITE32(curs, bt_ram, half);
618 bcnt += 2;
620 /* pad unoccupied scan lines */
621 while (bcnt < CURSOR_MAX_SIZE * 16) {
622 REGWRITE32(curs, bt_ram, 0);
623 bcnt += 2;
626 if (v & WSDISPLAY_CMAP_DOLUT) {
627 struct hwcmap256 *cm = &sc->sc_cmap;
628 int index;
630 SELECT463(vdac, BT463_IREG_CPALETTE_RAM);
631 for (index = 0; index < CMAP_SIZE; index++) {
632 REGWRITE32(vdac, bt_cmap, cm->r[index]);
633 REGWRITE32(vdac, bt_cmap, cm->g[index]);
634 REGWRITE32(vdac, bt_cmap, cm->b[index]);
637 sc->sc_changed = 0;
638 done:
639 *(uint8_t *)(base + TX_CONTROL) &= ~0x40; /* !? Eeeh !? */
640 *(uint8_t *)(base + TX_CONTROL) |= 0x40;
641 return (1);
644 static void
645 tfbhwinit(void *tfbbase)
647 char *vdac, *curs;
648 const uint8_t *p;
649 int i;
651 vdac = (char *)tfbbase + TX_BT463_OFFSET;
652 curs = (char *)tfbbase + TX_BT431_OFFSET;
653 SELECT463(vdac, BT463_IREG_COMMAND_0);
654 REGWRITE32(vdac, bt_reg, 0x40); /* CMD 0 */
655 REGWRITE32(vdac, bt_reg, 0x46); /* CMD 1 */
656 REGWRITE32(vdac, bt_reg, 0xc0); /* CMD 2 */
657 REGWRITE32(vdac, bt_reg, 0); /* !? 204 !? */
658 REGWRITE32(vdac, bt_reg, 0xff); /* plane 0:7 */
659 REGWRITE32(vdac, bt_reg, 0xff); /* plane 8:15 */
660 REGWRITE32(vdac, bt_reg, 0xff); /* plane 16:23 */
661 REGWRITE32(vdac, bt_reg, 0xff); /* plane 24:27 */
662 REGWRITE32(vdac, bt_reg, 0x00); /* blink 0:7 */
663 REGWRITE32(vdac, bt_reg, 0x00); /* blink 8:15 */
664 REGWRITE32(vdac, bt_reg, 0x00); /* blink 16:23 */
665 REGWRITE32(vdac, bt_reg, 0x00); /* blink 24:27 */
666 REGWRITE32(vdac, bt_reg, 0x00);
668 #if 0 /* XXX ULTRIX does initialize 16 entry window type here XXX */
670 static uint32_t windowtype[BT463_IREG_WINDOW_TYPE_TABLE] = {
671 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
674 SELECT463(vdac, BT463_IREG_WINDOW_TYPE_TABLE);
675 for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
676 BYTE(vdac, bt_reg) = windowtype[i]; /* 0:7 */
677 BYTE(vdac, bt_reg) = windowtype[i] >> 8; /* 8:15 */
678 BYTE(vdac, bt_reg) = windowtype[i] >> 16; /* 16:23 */
681 #endif
683 SELECT463(vdac, BT463_IREG_CPALETTE_RAM);
684 p = rasops_cmap;
685 for (i = 0; i < 256; i++, p += 3) {
686 REGWRITE32(vdac, bt_cmap, p[0]);
687 REGWRITE32(vdac, bt_cmap, p[1]);
688 REGWRITE32(vdac, bt_cmap, p[2]);
691 /* !? Eeeh !? */
692 SELECT463(vdac, 0x0100 /* BT463_IREG_CURSOR_COLOR_0 */);
693 for (i = 0; i < 256; i++) {
694 REGWRITE32(vdac, bt_cmap, i);
695 REGWRITE32(vdac, bt_cmap, i);
696 REGWRITE32(vdac, bt_cmap, i);
699 SELECT431(curs, BT431_REG_COMMAND);
700 REGWRITE32(curs, bt_ctl, 0x0404);
701 REGWRITE32(curs, bt_ctl, 0); /* XLO */
702 REGWRITE32(curs, bt_ctl, 0); /* XHI */
703 REGWRITE32(curs, bt_ctl, 0); /* YLO */
704 REGWRITE32(curs, bt_ctl, 0); /* YHI */
705 REGWRITE32(curs, bt_ctl, 0); /* XWLO */
706 REGWRITE32(curs, bt_ctl, 0); /* XWHI */
707 REGWRITE32(curs, bt_ctl, 0); /* WYLO */
708 REGWRITE32(curs, bt_ctl, 0); /* WYLO */
709 REGWRITE32(curs, bt_ctl, 0); /* WWLO */
710 REGWRITE32(curs, bt_ctl, 0); /* WWHI */
711 REGWRITE32(curs, bt_ctl, 0); /* WHLO */
712 REGWRITE32(curs, bt_ctl, 0); /* WHHI */
714 SELECT431(curs, BT431_REG_CRAM_BASE);
715 for (i = 0; i < 512; i++) {
716 REGWRITE32(curs, bt_ram, 0);
720 static int
721 get_cmap(struct tfb_softc *sc, struct wsdisplay_cmap *p)
723 u_int index = p->index, count = p->count;
724 int error;
726 if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
727 return (EINVAL);
729 error = copyout(&sc->sc_cmap.r[index], p->red, count);
730 if (error)
731 return error;
732 error = copyout(&sc->sc_cmap.g[index], p->green, count);
733 if (error)
734 return error;
735 error = copyout(&sc->sc_cmap.b[index], p->blue, count);
736 return error;
739 static int
740 set_cmap(struct tfb_softc *sc, struct wsdisplay_cmap *p)
742 struct hwcmap256 cmap;
743 u_int index = p->index, count = p->count;
744 int error, s;
746 if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
747 return (EINVAL);
749 error = copyin(p->red, &cmap.r[index], count);
750 if (error)
751 return error;
752 error = copyin(p->green, &cmap.g[index], count);
753 if (error)
754 return error;
755 error = copyin(p->blue, &cmap.b[index], count);
756 if (error)
757 return error;
758 s = spltty();
759 memcpy(&sc->sc_cmap.r[index], &cmap.r[index], count);
760 memcpy(&sc->sc_cmap.g[index], &cmap.g[index], count);
761 memcpy(&sc->sc_cmap.b[index], &cmap.b[index], count);
762 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
763 splx(s);
764 return (0);
767 static int
768 set_cursor(struct tfb_softc *sc, struct wsdisplay_cursor *p)
770 #define cc (&sc->sc_cursor)
771 u_int v, index = 0, count = 0, icount = 0;
772 uint8_t r[2], g[2], b[2], image[512], mask[512];
773 int error, s;
775 v = p->which;
776 if (v & WSDISPLAY_CURSOR_DOCMAP) {
777 index = p->cmap.index;
778 count = p->cmap.count;
779 if (index >= 2 || (index + count) > 2)
780 return (EINVAL);
781 error = copyin(p->cmap.red, &r[index], count);
782 if (error)
783 return error;
784 error = copyin(p->cmap.green, &g[index], count);
785 if (error)
786 return error;
787 error = copyin(p->cmap.blue, &b[index], count);
788 if (error)
789 return error;
791 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
792 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
793 return (EINVAL);
794 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
795 error = copyin(p->image, image, icount);
796 if (error)
797 return error;
798 error = copyin(p->mask, mask, icount);
799 if (error)
800 return error;
803 s = spltty();
804 if (v & WSDISPLAY_CURSOR_DOCUR)
805 sc->sc_curenb = p->enable;
806 if (v & WSDISPLAY_CURSOR_DOPOS)
807 set_curpos(sc, &p->pos);
808 if (v & WSDISPLAY_CURSOR_DOHOT)
809 cc->cc_hot = p->hot;
810 if (v & WSDISPLAY_CURSOR_DOCMAP) {
811 memcpy(&cc->cc_color[index], &r[index], count);
812 memcpy(&cc->cc_color[index + 2], &g[index], count);
813 memcpy(&cc->cc_color[index + 4], &b[index], count);
815 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
816 cc->cc_size = p->size;
817 memset(cc->cc_image, 0, sizeof cc->cc_image);
818 memcpy(cc->cc_image, image, icount);
819 memset(cc->cc_mask, 0, sizeof cc->cc_mask);
820 memcpy(cc->cc_mask, mask, icount);
822 sc->sc_changed |= v;
823 splx(s);
825 return (0);
826 #undef cc
829 static int
830 get_cursor(struct tfb_softc *sc, struct wsdisplay_cursor *p)
832 return (EPASSTHROUGH); /* XXX */
835 static void
836 set_curpos(struct tfb_softc *sc, struct wsdisplay_curpos *curpos)
838 struct rasops_info *ri = sc->sc_ri;
839 int x = curpos->x, y = curpos->y;
841 if (y < 0)
842 y = 0;
843 else if (y > ri->ri_height)
844 y = ri->ri_height;
845 if (x < 0)
846 x = 0;
847 else if (x > ri->ri_width)
848 x = ri->ri_width;
849 sc->sc_cursor.cc_pos.x = x;
850 sc->sc_cursor.cc_pos.y = y;