sfbplus.c revision 1.2 1 /* $NetBSD: sfbplus.c,v 1.2 1999/12/06 19:26:01 drochner Exp $ */
2
3 /*
4 * Copyright (c) 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> /* RCS ID & Copyright macro defns */
34
35 __KERNEL_RCSID(0, "$NetBSD: sfbplus.c,v 1.2 1999/12/06 19:26:01 drochner 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/bt459reg.h>
56 #include <dev/ic/bt463reg.h>
57 #include <dev/tc/sfbreg.h>
58 #include <dev/pci/tgareg.h>
59
60 #include <uvm/uvm_extern.h>
61
62 #if defined(pmax)
63 #define machine_btop(x) mips_btop(x)
64 #define MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG1_TO_PHYS(x)
65 #endif
66
67 #if defined(__alpha__) || defined(alpha)
68 #define machine_btop(x) alpha_btop(x)
69 #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x)
70 #endif
71
72 /* Bt459/Bt463 hardware registers */
73 #define bt_lo 0
74 #define bt_hi 1
75 #define bt_reg 2
76 #define bt_cmap 3
77
78 #define REG(base, index) *((u_int32_t *)(base) + (index))
79 #define SELECT(vdac, regno) do { \
80 REG(vdac, bt_lo) = ((regno) & 0x00ff); \
81 REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8; \
82 tc_wmb(); \
83 } while (0)
84
85 struct fb_devconfig {
86 vaddr_t dc_vaddr; /* memory space virtual base address */
87 paddr_t dc_paddr; /* memory space physical base address */
88 vsize_t dc_size; /* size of slot memory */
89 int dc_wid; /* width of frame buffer */
90 int dc_ht; /* height of frame buffer */
91 int dc_depth; /* depth, bits per pixel */
92 int dc_rowbytes; /* bytes in a FB scan line */
93 vaddr_t dc_videobase; /* base of flat frame buffer */
94 struct raster dc_raster; /* raster description */
95 struct rcons dc_rcons; /* raster blitter control info */
96 int dc_blanked; /* currently has video disabled */
97 };
98
99 struct hwcmap256 {
100 #define CMAP_SIZE 256 /* 256 R/G/B entries */
101 u_int8_t r[CMAP_SIZE];
102 u_int8_t g[CMAP_SIZE];
103 u_int8_t b[CMAP_SIZE];
104 };
105
106 struct hwcursor64 {
107 struct wsdisplay_curpos cc_pos;
108 struct wsdisplay_curpos cc_hot;
109 struct wsdisplay_curpos cc_size;
110 struct wsdisplay_curpos cc_magic;
111 #define CURSOR_MAX_SIZE 64
112 u_int8_t cc_color[6];
113 u_int64_t cc_image[64 + 64];
114 };
115
116 struct hwops {
117 void (*setlut) __P((void *, struct hwcmap256 *));
118 void (*getlut) __P((void *, struct hwcmap256 *));
119 void (*visible) __P((void *, int));
120 void (*locate) __P((void *, int, int));
121 void (*shape) __P((void *, struct wsdisplay_curpos *, u_int64_t *));
122 void (*color) __P((void *, u_int8_t *));
123 };
124
125 struct sfb_softc {
126 struct device sc_dev;
127 struct fb_devconfig *sc_dc; /* device configuration */
128 struct hwcmap256 sc_cmap; /* software copy of colormap */
129 struct hwcursor64 sc_cursor; /* software copy of cursor */
130 int sc_curenb; /* cursor sprite enabled */
131 int sc_changed; /* need update of colormap */
132 #define DATA_ENB_CHANGED 0x01 /* cursor enable changed */
133 #define DATA_CURCMAP_CHANGED 0x02 /* cursor colormap changed */
134 #define DATA_CURSHAPE_CHANGED 0x04 /* cursor size, image, mask changed */
135 #define DATA_CMAP_CHANGED 0x08 /* colormap changed */
136 #define DATA_ALL_CHANGED 0x0f
137 int nscreens;
138 struct hwops sc_hwops;
139 void *sc_hw0, *sc_hw1;
140 };
141
142 #define HX_MAGIC_X 368
143 #define HX_MAGIC_Y 38
144
145 static int sfbpmatch __P((struct device *, struct cfdata *, void *));
146 static void sfbpattach __P((struct device *, struct device *, void *));
147
148 struct cfattach sfbp_ca = {
149 sizeof(struct sfb_softc), sfbpmatch, sfbpattach,
150 };
151
152 static void sfbp_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
153 static struct fb_devconfig sfbp_console_dc;
154 static tc_addr_t sfbp_consaddr;
155
156 extern const struct wsdisplay_emulops sfbp_emulops, sfbp_emulops32;
157
158 static struct wsscreen_descr sfb_stdscreen = {
159 "std", 0, 0,
160 NULL, /* textops */
161 0, 0,
162 WSSCREEN_REVERSE
163 };
164
165 static const struct wsscreen_descr *_sfb_scrlist[] = {
166 &sfb_stdscreen,
167 };
168
169 static const struct wsscreen_list sfb_screenlist = {
170 sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
171 };
172
173 static int sfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
174 static int sfbmmap __P((void *, off_t, int));
175
176 static int sfb_alloc_screen __P((void *, const struct wsscreen_descr *,
177 void **, int *, int *, long *));
178 static void sfb_free_screen __P((void *, void *));
179 static int sfb_show_screen __P((void *, void *, int,
180 void (*) (void *, int, int), void *));
181 /* EXPORT */ int sfb_alloc_attr __P((void *, int, int, int, long *));
182
183 static const struct wsdisplay_accessops sfb_accessops = {
184 sfbioctl,
185 sfbmmap,
186 sfb_alloc_screen,
187 sfb_free_screen,
188 sfb_show_screen,
189 0 /* load_font */
190 };
191
192 static void bt459visible __P((void *, int));
193 static void bt459locate __P((void *, int, int));
194 static void bt459shape __P((void *, struct wsdisplay_curpos *, u_int64_t *));
195 static void bt459color __P((void *, u_int8_t *));
196 static void bt459setlut __P((void *, struct hwcmap256 *));
197
198 static void sfbpvisible __P((void *, int));
199 static void sfbplocate __P((void *, int, int));
200 static void sfbpshape __P((void *, struct wsdisplay_curpos *, u_int64_t *));
201 static void bt463color __P((void *, u_int8_t *));
202 static void noplut __P((void *, struct hwcmap256 *));
203
204
205 /* EXPORT */ int sfbp_cnattach __P((tc_addr_t));
206 static int sfbpintr __P((void *));
207 static void sfbpinit __P((struct fb_devconfig *));
208
209 static int get_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *));
210 static int set_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *));
211 static int set_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *));
212 static int get_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *));
213
214
215 /*
216 * Compose 2 bit/pixel cursor image. Bit order will be reversed.
217 * M M M M I I I I M I M I M I M I
218 * [ before ] [ after ]
219 * 3 2 1 0 3 2 1 0 0 0 1 1 2 2 3 3
220 * 7 6 5 4 7 6 5 4 4 4 5 5 6 6 7 7
221 */
222 static const u_int8_t shuffle[256] = {
223 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
224 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55,
225 0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4,
226 0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5,
227 0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74,
228 0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75,
229 0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4,
230 0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5,
231 0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c,
232 0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d,
233 0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc,
234 0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd,
235 0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c,
236 0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d,
237 0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc,
238 0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd,
239 0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56,
240 0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57,
241 0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6,
242 0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7,
243 0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76,
244 0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77,
245 0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6,
246 0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7,
247 0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e,
248 0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f,
249 0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde,
250 0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf,
251 0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e,
252 0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f,
253 0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe,
254 0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff,
255 };
256
257 static int
258 sfbpmatch(parent, match, aux)
259 struct device *parent;
260 struct cfdata *match;
261 void *aux;
262 {
263 struct tc_attach_args *ta = aux;
264
265 if (strncmp("PMAGD", ta->ta_modname, 5) != 0)
266 return (0);
267
268 return (1);
269 }
270
271 static void
272 sfbp_getdevconfig(dense_addr, dc)
273 tc_addr_t dense_addr;
274 struct fb_devconfig *dc;
275 {
276 struct raster *rap;
277 struct rcons *rcp;
278 caddr_t sfbasic;
279 int i, hsetup, vsetup, vbase;
280
281 dc->dc_vaddr = dense_addr;
282 dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr);
283
284 sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
285 hsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_HSETUP);
286 vsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VSETUP);
287 i = *(u_int32_t *)(sfbasic + SFB_ASIC_DEEP);
288 *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) = vbase = 1;
289
290 dc->dc_wid = (hsetup & 0x1ff) << 2;
291 dc->dc_ht = (vsetup & 0x7ff);
292 dc->dc_depth = (i & 1) ? 32 : 8;
293 dc->dc_rowbytes = dc->dc_wid * (dc->dc_depth / 8);
294 dc->dc_videobase = dc->dc_vaddr + 0x800000 + vbase * 4096; /* XXX */
295 dc->dc_blanked = 0;
296
297 /* initialize colormap and cursor resource */
298 sfbpinit(dc);
299
300 /* clear the screen */
301 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
302 *(u_int32_t *)(dc->dc_videobase + i) = 0x0;
303
304 /* initialize the raster */
305 rap = &dc->dc_raster;
306 rap->width = dc->dc_wid;
307 rap->height = dc->dc_ht;
308 rap->depth = dc->dc_depth;
309 rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
310 rap->pixels = (u_int32_t *)dc->dc_videobase;
311 rap->data = sfbasic;
312
313 /* initialize the raster console blitter */
314 rcp = &dc->dc_rcons;
315 rcp->rc_sp = rap;
316 rcp->rc_crow = rcp->rc_ccol = -1;
317 rcp->rc_crowp = &rcp->rc_crow;
318 rcp->rc_ccolp = &rcp->rc_ccol;
319 rcons_init(rcp, 34, 80);
320
321 sfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
322 sfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
323 sfb_stdscreen.textops
324 = (dc->dc_depth == 8) ? &sfbp_emulops : &sfbp_emulops32;
325 }
326
327 static void
328 sfbpattach(parent, self, aux)
329 struct device *parent, *self;
330 void *aux;
331 {
332 struct sfb_softc *sc = (struct sfb_softc *)self;
333 struct tc_attach_args *ta = aux;
334 struct wsemuldisplaydev_attach_args waa;
335 struct hwcmap256 *cm;
336 caddr_t sfbasic;
337 int console;
338
339 console = (ta->ta_addr == sfbp_consaddr);
340 if (console) {
341 sc->sc_dc = &sfbp_console_dc;
342 sc->nscreens = 1;
343 }
344 else {
345 sc->sc_dc = (struct fb_devconfig *)
346 malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
347 sfbp_getdevconfig(ta->ta_addr, sc->sc_dc);
348 }
349 printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
350 sc->sc_dc->dc_depth);
351
352 cm = &sc->sc_cmap;
353 memset(cm, 255, sizeof(struct hwcmap256)); /* XXX */
354 cm->r[0] = cm->g[0] = cm->b[0] = 0; /* XXX */
355
356 sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
357 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
358
359 if (sc->sc_dc->dc_depth == 8) {
360 sc->sc_hw0 = (caddr_t)ta->ta_addr + SFB_RAMDAC_OFFSET;
361 sc->sc_hw1 = sc->sc_hw0;
362 sc->sc_hwops.visible = bt459visible;
363 sc->sc_hwops.locate = bt459locate;
364 sc->sc_hwops.shape = bt459shape;
365 sc->sc_hwops.color = bt459color;
366 sc->sc_hwops.setlut = bt459setlut;
367 sc->sc_hwops.getlut = noplut;
368 }
369 else {
370 sc->sc_hw0 = (caddr_t)ta->ta_addr + SFB_ASIC_OFFSET;
371 sc->sc_hw1 = (caddr_t)ta->ta_addr + SFB_RAMDAC_OFFSET;
372 sc->sc_hwops.visible = sfbpvisible;
373 sc->sc_hwops.locate = sfbplocate;
374 sc->sc_hwops.shape = sfbpshape;
375 sc->sc_hwops.color = bt463color;
376 sc->sc_hwops.setlut = noplut;
377 sc->sc_hwops.getlut = noplut;
378 }
379
380 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbpintr, sc);
381
382 sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
383 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0; tc_wmb();
384 *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; tc_wmb();
385
386 waa.console = console;
387 waa.scrdata = &sfb_screenlist;
388 waa.accessops = &sfb_accessops;
389 waa.accesscookie = sc;
390
391 config_found(self, &waa, wsemuldisplaydevprint);
392 }
393
394 static int
395 sfbioctl(v, cmd, data, flag, p)
396 void *v;
397 u_long cmd;
398 caddr_t data;
399 int flag;
400 struct proc *p;
401 {
402 struct sfb_softc *sc = v;
403 struct fb_devconfig *dc = sc->sc_dc;
404 int turnoff;
405
406 switch (cmd) {
407 case WSDISPLAYIO_GTYPE:
408 *(u_int *)data = WSDISPLAY_TYPE_SFB; /* XXX SFBP XXX */
409 return (0);
410
411 case WSDISPLAYIO_GINFO:
412 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
413 wsd_fbip->height = sc->sc_dc->dc_ht;
414 wsd_fbip->width = sc->sc_dc->dc_wid;
415 wsd_fbip->depth = sc->sc_dc->dc_depth;
416 wsd_fbip->cmsize = CMAP_SIZE;
417 #undef fbt
418 return (0);
419
420 case WSDISPLAYIO_GETCMAP:
421 return get_cmap(sc, (struct wsdisplay_cmap *)data);
422
423 case WSDISPLAYIO_PUTCMAP:
424 return set_cmap(sc, (struct wsdisplay_cmap *)data);
425
426 case WSDISPLAYIO_SVIDEO:
427 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
428 if ((dc->dc_blanked == 0) ^ turnoff) {
429 dc->dc_blanked = turnoff;
430 #if 0 /* XXX later XXX */
431 Low order 3bit control visibilities of screen and builtin cursor.
432 #endif /* XXX XXX XXX */
433 }
434 return (0);
435
436 case WSDISPLAYIO_GVIDEO:
437 *(u_int *)data = dc->dc_blanked ?
438 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
439 return (0);
440
441 case WSDISPLAYIO_GCURPOS:
442 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
443 return (0);
444
445 case WSDISPLAYIO_SCURPOS: {
446 struct wsdisplay_curpos *pos = (void *)data;
447 int x, y;
448
449 x = pos->x;
450 y = pos->y;
451 if (y < 0)
452 y = 0;
453 else if (y > dc->dc_ht)
454 y = dc->dc_ht;
455 if (x < 0)
456 x = 0;
457 else if (x > dc->dc_wid)
458 x = dc->dc_wid;
459 sc->sc_cursor.cc_pos.x = x;
460 sc->sc_cursor.cc_pos.y = y;
461 x -= sc->sc_cursor.cc_hot.x;
462 y -= sc->sc_cursor.cc_hot.y;
463 x += sc->sc_cursor.cc_magic.x;
464 y += sc->sc_cursor.cc_magic.y;
465 (*sc->sc_hwops.locate)(sc->sc_hw0, x, y);
466 return (0);
467 }
468
469 case WSDISPLAYIO_GCURMAX:
470 ((struct wsdisplay_curpos *)data)->x =
471 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
472 return (0);
473
474 case WSDISPLAYIO_GCURSOR:
475 return get_cursor(sc, (struct wsdisplay_cursor *)data);
476
477 case WSDISPLAYIO_SCURSOR:
478 return set_cursor(sc, (struct wsdisplay_cursor *)data);
479 }
480 return ENOTTY;
481 }
482
483 int
484 sfbmmap(v, offset, prot)
485 void *v;
486 off_t offset;
487 int prot;
488 {
489 struct sfb_softc *sc = v;
490
491 if (offset >= 0x1000000 || offset < 0) /* XXX 16MB XXX */
492 return (-1);
493 return machine_btop(sc->sc_dc->dc_paddr + offset);
494 }
495
496 static int
497 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
498 void *v;
499 const struct wsscreen_descr *type;
500 void **cookiep;
501 int *curxp, *curyp;
502 long *attrp;
503 {
504 struct sfb_softc *sc = v;
505 long defattr;
506
507 if (sc->nscreens > 0)
508 return (ENOMEM);
509
510 *cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
511 *curxp = 0;
512 *curyp = 0;
513 sfb_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
514 *attrp = defattr;
515 sc->nscreens++;
516 return (0);
517 }
518
519 void
520 sfb_free_screen(v, cookie)
521 void *v;
522 void *cookie;
523 {
524 struct sfb_softc *sc = v;
525
526 if (sc->sc_dc == &sfbp_console_dc)
527 panic("sfb_free_screen: console");
528
529 sc->nscreens--;
530 }
531
532 static int
533 sfb_show_screen(v, cookie, waitok, cb, cbarg)
534 void *v;
535 void *cookie;
536 int waitok;
537 void (*cb) __P((void *, int, int));
538 void *cbarg;
539 {
540
541 return (0);
542 }
543
544 int
545 sfbp_cnattach(addr)
546 tc_addr_t addr;
547 {
548 struct fb_devconfig *dcp = &sfbp_console_dc;
549 long defattr;
550
551 sfbp_getdevconfig(addr, dcp);
552
553 sfb_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
554
555 wsdisplay_cnattach(&sfb_stdscreen, &dcp->dc_rcons,
556 0, 0, defattr);
557 sfbp_consaddr = addr;
558 return(0);
559 }
560
561 static int
562 sfbpintr(arg)
563 void *arg;
564 {
565 struct sfb_softc *sc = arg;
566 caddr_t sfbasic = (caddr_t)sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET;
567 int v;
568 u_int32_t sisr;
569
570 #define cc (&sc->sc_cursor)
571 sisr = *((u_int32_t *)sfbasic + TGA_REG_SISR);
572
573 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
574
575 if (sc->sc_changed == 0)
576 goto finish;
577
578 v = sc->sc_changed;
579 sc->sc_changed = 0;
580
581 if (v & DATA_ENB_CHANGED)
582 (*sc->sc_hwops.visible)(sc->sc_hw0, sc->sc_curenb);
583 if (v & DATA_CURCMAP_CHANGED)
584 (*sc->sc_hwops.color)(sc->sc_hw1, cc->cc_color);
585 if (v & DATA_CURSHAPE_CHANGED)
586 (*sc->sc_hwops.shape)(sc->sc_hw0, &cc->cc_size, cc->cc_image);
587 if (v & DATA_CMAP_CHANGED)
588 (*sc->sc_hwops.setlut)(sc->sc_hw1, &sc->sc_cmap);
589
590 finish:
591 *((u_int32_t *)sfbasic + TGA_REG_SISR) = sisr = 0x00000001; tc_wmb();
592 return (1);
593 #undef cc
594 }
595
596 static void
597 sfbpinit(dc)
598 struct fb_devconfig *dc;
599 {
600 caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
601 caddr_t vdac = (caddr_t)(dc->dc_vaddr + SFB_RAMDAC_OFFSET);
602 int i;
603
604 *(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
605 *(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
606 *(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */
607 *(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3; /* ROP_COPY */
608
609 if (dc->dc_depth == 8) {
610 *(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */
611
612 SELECT(vdac, BT459_REG_COMMAND_0);
613 REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb();
614 REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb();
615 REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb();
616 REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb();
617 REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb();
618 REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb();
619 REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb();
620 REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb();
621 REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb();
622 REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb();
623 REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb();
624
625 SELECT(vdac, BT459_REG_CCR);
626 REG(vdac, bt_reg) = 0x0; tc_wmb();
627 REG(vdac, bt_reg) = 0x0; tc_wmb();
628 REG(vdac, bt_reg) = 0x0; tc_wmb();
629 REG(vdac, bt_reg) = 0x0; tc_wmb();
630 REG(vdac, bt_reg) = 0x0; tc_wmb();
631 REG(vdac, bt_reg) = 0x0; tc_wmb();
632 REG(vdac, bt_reg) = 0x0; tc_wmb();
633 REG(vdac, bt_reg) = 0x0; tc_wmb();
634 REG(vdac, bt_reg) = 0x0; tc_wmb();
635 REG(vdac, bt_reg) = 0x0; tc_wmb();
636 REG(vdac, bt_reg) = 0x0; tc_wmb();
637 REG(vdac, bt_reg) = 0x0; tc_wmb();
638 REG(vdac, bt_reg) = 0x0; tc_wmb();
639
640 /* build sane colormap */
641 SELECT(vdac, 0);
642 REG(vdac, bt_cmap) = 0; tc_wmb();
643 REG(vdac, bt_cmap) = 0; tc_wmb();
644 REG(vdac, bt_cmap) = 0; tc_wmb();
645 for (i = 1; i < CMAP_SIZE; i++) {
646 REG(vdac, bt_cmap) = 0xff; tc_wmb();
647 REG(vdac, bt_cmap) = 0xff; tc_wmb();
648 REG(vdac, bt_cmap) = 0xff; tc_wmb();
649 }
650
651 /* clear out cursor image */
652 SELECT(vdac, BT459_REG_CRAM_BASE);
653 for (i = 0; i < 1024; i++)
654 REG(vdac, bt_reg) = 0xff; tc_wmb();
655
656 /*
657 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for
658 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for
659 * image color. CCOLOR_1 will be never used.
660 */
661 SELECT(vdac, BT459_REG_CCOLOR_1);
662 REG(vdac, bt_reg) = 0xff; tc_wmb();
663 REG(vdac, bt_reg) = 0xff; tc_wmb();
664 REG(vdac, bt_reg) = 0xff; tc_wmb();
665
666 REG(vdac, bt_reg) = 0; tc_wmb();
667 REG(vdac, bt_reg) = 0; tc_wmb();
668 REG(vdac, bt_reg) = 0; tc_wmb();
669
670 REG(vdac, bt_reg) = 0xff; tc_wmb();
671 REG(vdac, bt_reg) = 0xff; tc_wmb();
672 REG(vdac, bt_reg) = 0xff; tc_wmb();
673 } else {
674 SELECT(vdac, BT463_IREG_COMMAND_0);
675 REG(vdac, bt_reg) = 0x40; tc_wmb(); /* CMD 0 */
676 REG(vdac, bt_reg) = 0x46; tc_wmb(); /* CMD 1 */
677 REG(vdac, bt_reg) = 0xc0; tc_wmb(); /* CMD 2 */
678 REG(vdac, bt_reg) = 0; tc_wmb(); /* !? 204 !? */
679 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 0:7 */
680 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 8:15 */
681 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 16:23 */
682 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 24:27 */
683 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 0:7 */
684 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 8:15 */
685 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 16:23 */
686 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 24:27 */
687 REG(vdac, bt_reg) = 0x00; tc_wmb();
688
689 #if 0 /* XXX ULTRIX does initialize 16 entry window type here XXX */
690 {
691 static u_int32_t windowtype[BT463_IREG_WINDOW_TYPE_TABLE] = {
692 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
693 };
694
695 SELECT(vdac, BT463_IREG_WINDOW_TYPE_TABLE);
696 for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
697 REG(vdac, bt_reg) = windowtype[i]; /* 0:7 */
698 REG(vdac, bt_reg) = windowtype[i] >> 8; /* 8:15 */
699 REG(vdac, bt_reg) = windowtype[i] >> 16; /* 16:23 */
700 }
701 }
702 #endif
703
704 SELECT(vdac, BT463_IREG_CPALETTE_RAM);
705 REG(vdac, bt_cmap) = 0; tc_wmb();
706 REG(vdac, bt_cmap) = 0; tc_wmb();
707 REG(vdac, bt_cmap) = 0; tc_wmb();
708 for (i = 1; i < 256; i++) {
709 REG(vdac, bt_cmap) = 0xff; tc_wmb();
710 REG(vdac, bt_cmap) = 0xff; tc_wmb();
711 REG(vdac, bt_cmap) = 0xff; tc_wmb();
712 }
713
714 /* !? Eeeh !? */
715 SELECT(vdac, 0x0100 /* BT463_IREG_CURSOR_COLOR_0 */);
716 for (i = 0; i < 256; i++) {
717 REG(vdac, bt_cmap) = i; tc_wmb();
718 REG(vdac, bt_cmap) = i; tc_wmb();
719 REG(vdac, bt_cmap) = i; tc_wmb();
720 }
721 }
722 }
723
724 static int
725 get_cmap(sc, p)
726 struct sfb_softc *sc;
727 struct wsdisplay_cmap *p;
728 {
729 u_int index = p->index, count = p->count;
730
731 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
732 return (EINVAL);
733
734 if (!uvm_useracc(p->red, count, B_WRITE) ||
735 !uvm_useracc(p->green, count, B_WRITE) ||
736 !uvm_useracc(p->blue, count, B_WRITE))
737 return (EFAULT);
738
739 copyout(&sc->sc_cmap.r[index], p->red, count);
740 copyout(&sc->sc_cmap.g[index], p->green, count);
741 copyout(&sc->sc_cmap.b[index], p->blue, count);
742
743 return (0);
744 }
745
746 static int
747 set_cmap(sc, p)
748 struct sfb_softc *sc;
749 struct wsdisplay_cmap *p;
750 {
751 u_int index = p->index, count = p->count;
752
753 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
754 return (EINVAL);
755
756 if (!uvm_useracc(p->red, count, B_READ) ||
757 !uvm_useracc(p->green, count, B_READ) ||
758 !uvm_useracc(p->blue, count, B_READ))
759 return (EFAULT);
760
761 copyin(p->red, &sc->sc_cmap.r[index], count);
762 copyin(p->green, &sc->sc_cmap.g[index], count);
763 copyin(p->blue, &sc->sc_cmap.b[index], count);
764
765 sc->sc_changed |= DATA_CMAP_CHANGED;
766
767 return (0);
768 }
769
770
771 static int
772 set_cursor(sc, p)
773 struct sfb_softc *sc;
774 struct wsdisplay_cursor *p;
775 {
776 #define cc (&sc->sc_cursor)
777 int v, index, count, icount, x, y;
778
779 v = p->which;
780 if (v & WSDISPLAY_CURSOR_DOCMAP) {
781 index = p->cmap.index;
782 count = p->cmap.count;
783 if (index >= 2 || (index + count) > 2)
784 return (EINVAL);
785 if (!uvm_useracc(p->cmap.red, count, B_READ) ||
786 !uvm_useracc(p->cmap.green, count, B_READ) ||
787 !uvm_useracc(p->cmap.blue, count, B_READ))
788 return (EFAULT);
789 }
790 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
791 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
792 return (EINVAL);
793 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
794 if (!uvm_useracc(p->image, icount, B_READ) ||
795 !uvm_useracc(p->mask, icount, B_READ))
796 return (EFAULT);
797 }
798 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
799 if (v & WSDISPLAY_CURSOR_DOCUR)
800 cc->cc_hot = p->hot;
801 if (v & WSDISPLAY_CURSOR_DOPOS) {
802 struct fb_devconfig *dc = sc->sc_dc;
803
804 x = p->pos.x;
805 y = p->pos.y;
806 if (y < 0)
807 y = 0;
808 else if (y > dc->dc_ht)
809 y = dc->dc_ht;
810 if (x < 0)
811 x = 0;
812 else if (x > dc->dc_wid)
813 x = dc->dc_wid;
814 sc->sc_cursor.cc_pos.x = x;
815 sc->sc_cursor.cc_pos.y = y;
816 }
817 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
818 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
819 x += sc->sc_cursor.cc_magic.x;
820 y += sc->sc_cursor.cc_magic.y;
821 (*sc->sc_hwops.locate)(sc->sc_hw0, x, y);
822 }
823
824 sc->sc_changed = 0;
825 if (v & WSDISPLAY_CURSOR_DOCUR) {
826 sc->sc_curenb = p->enable;
827 sc->sc_changed |= DATA_ENB_CHANGED;
828 }
829 if (v & WSDISPLAY_CURSOR_DOCMAP) {
830 copyin(p->cmap.red, &cc->cc_color[index], count);
831 copyin(p->cmap.green, &cc->cc_color[index + 2], count);
832 copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
833 sc->sc_changed |= DATA_CURCMAP_CHANGED;
834 }
835 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
836 cc->cc_size = p->size;
837 memset(cc->cc_image, 0, sizeof cc->cc_image);
838 copyin(p->image, cc->cc_image, icount);
839 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
840 sc->sc_changed |= DATA_CURSHAPE_CHANGED;
841 }
842
843 return (0);
844 #undef cc
845 }
846
847 static int
848 get_cursor(sc, p)
849 struct sfb_softc *sc;
850 struct wsdisplay_cursor *p;
851 {
852 return (ENOTTY); /* XXX */
853 }
854
855 int
856 sfb_alloc_attr(id, fg, bg, flags, attrp)
857 void *id;
858 int fg, bg, flags;
859 long *attrp;
860 {
861 if (flags & (WSATTR_HILIT | WSATTR_BLINK |
862 WSATTR_UNDERLINE | WSATTR_WSCOLORS))
863 return (EINVAL);
864 if (flags & WSATTR_REVERSE)
865 *attrp = 1;
866 else
867 *attrp = 0;
868 return (0);
869 }
870
871 static void
872 bt459visible(hw, on)
873 void *hw;
874 int on;
875 {
876 SELECT(hw, BT459_REG_CCR);
877 REG(hw, bt_reg) = (on) ? 0xc0 : 0x00;
878 tc_wmb();
879 }
880
881 static void
882 sfbpvisible(hw, on)
883 void *hw;
884 int on;
885 {
886 }
887
888 static void
889 bt459locate(hw, x, y)
890 void *hw;
891 int x, y;
892 {
893 int s;
894
895 s = spltty();
896 SELECT(hw, BT459_REG_CURSOR_X_LOW);
897 REG(hw, bt_reg) = x; tc_wmb();
898 REG(hw, bt_reg) = x >> 8; tc_wmb();
899 REG(hw, bt_reg) = y; tc_wmb();
900 REG(hw, bt_reg) = y >> 8; tc_wmb();
901 splx(s);
902 }
903
904 static void
905 sfbplocate(hw, x, y)
906 void *hw;
907 int x, y;
908 {
909 *((u_int32_t *)hw + TGA_REG_CXYR) = ((y & 0xfff) << 12) | (x & 0xfff);
910 tc_wmb();
911 }
912
913 static void
914 bt459color(hw, cp)
915 void *hw;
916 u_int8_t *cp;
917 {
918 SELECT(hw, BT459_REG_CCOLOR_2);
919 REG(hw, bt_reg) = cp[1]; tc_wmb();
920 REG(hw, bt_reg) = cp[3]; tc_wmb();
921 REG(hw, bt_reg) = cp[5]; tc_wmb();
922
923 REG(hw, bt_reg) = cp[0]; tc_wmb();
924 REG(hw, bt_reg) = cp[2]; tc_wmb();
925 REG(hw, bt_reg) = cp[4]; tc_wmb();
926 }
927
928 static void
929 bt463color(hw, cp)
930 void *hw;
931 u_int8_t *cp;
932 {
933 }
934
935 static void
936 bt459shape(hw, size, image)
937 void *hw;
938 struct wsdisplay_curpos *size;
939 u_int64_t *image;
940 {
941 u_int8_t *ip, *mp, img, msk;
942 u_int8_t u;
943 int bcnt;
944
945 ip = (u_int8_t *)image;
946 mp = (u_int8_t *)(image + CURSOR_MAX_SIZE);
947
948 bcnt = 0;
949 SELECT(hw, BT459_REG_CRAM_BASE+0);
950 /* 64 pixel scan line is consisted with 16 byte cursor ram */
951 while (bcnt < size->y * 16) {
952 /* pad right half 32 pixel when smaller than 33 */
953 if ((bcnt & 0x8) && size->x < 33) {
954 REG(hw, bt_reg) = 0; tc_wmb();
955 REG(hw, bt_reg) = 0; tc_wmb();
956 }
957 else {
958 img = *ip++;
959 msk = *mp++;
960 img &= msk; /* cookie off image */
961 u = (msk & 0x0f) << 4 | (img & 0x0f);
962 REG(hw, bt_reg) = shuffle[u]; tc_wmb();
963 u = (msk & 0xf0) | (img & 0xf0) >> 4;
964 REG(hw, bt_reg) = shuffle[u]; tc_wmb();
965 }
966 bcnt += 2;
967 }
968 /* pad unoccupied scan lines */
969 while (bcnt < CURSOR_MAX_SIZE * 16) {
970 REG(hw, bt_reg) = 0; tc_wmb();
971 REG(hw, bt_reg) = 0; tc_wmb();
972 bcnt += 2;
973 }
974 }
975
976 static void
977 sfbpshape(hw, size, image)
978 void *hw;
979 struct wsdisplay_curpos *size;
980 u_int64_t *image;
981 {
982 }
983
984 static void
985 bt459setlut(hw, cm)
986 void *hw;
987 struct hwcmap256 *cm;
988 {
989 int index;
990
991 SELECT(hw, 0);
992 for (index = 0; index < CMAP_SIZE; index++) {
993 REG(hw, bt_cmap) = cm->r[index]; tc_wmb();
994 REG(hw, bt_cmap) = cm->g[index]; tc_wmb();
995 REG(hw, bt_cmap) = cm->b[index]; tc_wmb();
996 }
997 }
998
999 static void
1000 noplut(hw, cm)
1001 void *hw;
1002 struct hwcmap256 *cm;
1003 {
1004 }
1005