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