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