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