sfb.c revision 1.2 1 /* $NetBSD: sfb.c,v 1.2 1998/10/30 00:53:12 nisimura Exp $ */
2
3 /*
4 * Copyright (c) 1996, 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: sfb.c,v 1.2 1998/10/30 00:53:12 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 #include <machine/autoconf.h>
54
55 #include <dev/tc/tcvar.h>
56 #include <dev/ic/bt459reg.h>
57 #include <machine/sfbreg.h>
58
59 #include "opt_uvm.h"
60 #if defined(UVM)
61 #include <uvm/uvm_extern.h>
62 #define useracc uvm_useracc
63 #endif
64
65 /* XXX BUS'IFYING XXX */
66
67 #if defined(__pmax__)
68 #define machine_btop(x) mips_btop(x)
69 #define MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG1_TO_PHYS(x)
70 #endif
71
72 #if defined(__alpha__) || defined(alpha)
73 #define machine_btop(x) alpha_btop(x)
74 #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x)
75 #endif
76
77 /*
78 * N.B., Bt459 registers are 8bit width. Some of TC framebuffers have
79 * weird register layout such as each of 2nd and 3rd Bt459 registers
80 * is adjacent each other in a word, i.e.,
81 *
82 * struct bt459triplet {
83 * struct {
84 * u_int8_t u0;
85 * u_int8_t u1;
86 * u_int8_t u2;
87 * unsigned :8;
88 * } bt_lo;
89 * ...
90 *
91 * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
92 */
93 struct bt459reg {
94 u_int32_t bt_lo;
95 u_int32_t bt_hi;
96 u_int32_t bt_reg;
97 u_int32_t bt_cmap;
98 };
99
100 /* XXX XXX XXX */
101
102 struct fb_devconfig {
103 vaddr_t dc_vaddr; /* memory space virtual base address */
104 paddr_t dc_paddr; /* memory space physical base address */
105 vsize_t dc_size; /* size of slot memory */
106 int dc_wid; /* width of frame buffer */
107 int dc_ht; /* height of frame buffer */
108 int dc_depth; /* depth, bits per pixel */
109 int dc_rowbytes; /* bytes in a FB scan line */
110 vaddr_t dc_videobase; /* base of flat frame buffer */
111 struct raster dc_raster; /* raster description */
112 struct rcons dc_rcons; /* raster blitter control info */
113 int dc_blanked; /* currently has video disabled */
114 };
115
116 struct hwcmap {
117 #define CMAP_SIZE 256 /* 256 R/G/B entries */
118 u_int8_t r[CMAP_SIZE];
119 u_int8_t g[CMAP_SIZE];
120 u_int8_t b[CMAP_SIZE];
121 };
122
123 struct hwcursor {
124 struct wsdisplay_curpos cc_pos;
125 struct wsdisplay_curpos cc_hot;
126 struct wsdisplay_curpos cc_size;
127 #define CURSOR_MAX_SIZE 64
128 u_int8_t cc_color[6];
129 u_int64_t cc_image[64 + 64];
130 };
131
132 struct sfb_softc {
133 struct device sc_dev;
134 struct fb_devconfig *sc_dc; /* device configuration */
135 struct hwcmap sc_cmap; /* software copy of colormap */
136 struct hwcursor sc_cursor; /* software copy of cursor */
137 int sc_curenb; /* cursor sprite enabled */
138 int sc_changed; /* need update of colormap */
139 #define DATA_ENB_CHANGED 0x01 /* cursor enable changed */
140 #define DATA_CURCMAP_CHANGED 0x02 /* cursor colormap changed */
141 #define DATA_CURSHAPE_CHANGED 0x04 /* cursor size, image, mask changed */
142 #define DATA_CMAP_CHANGED 0x08 /* colormap changed */
143 #define DATA_ALL_CHANGED 0x0f
144 int nscreens;
145 };
146
147 int sfbmatch __P((struct device *, struct cfdata *, void *));
148 void sfbattach __P((struct device *, struct device *, void *));
149
150 struct cfattach sfb_ca = {
151 sizeof(struct sfb_softc), sfbmatch, sfbattach,
152 };
153
154 void sfb_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
155 struct fb_devconfig sfb_console_dc;
156 tc_addr_t sfb_consaddr;
157
158 struct wsdisplay_emulops sfb_emulops = {
159 rcons_cursor, /* could use hardware cursor; punt */
160 rcons_mapchar,
161 rcons_putchar,
162 rcons_copycols,
163 rcons_erasecols,
164 rcons_copyrows,
165 rcons_eraserows,
166 rcons_alloc_attr
167 };
168
169 struct wsscreen_descr sfb_stdscreen = {
170 "std", 0, 0,
171 &sfb_emulops,
172 0, 0,
173 0
174 };
175
176 const struct wsscreen_descr *_sfb_scrlist[] = {
177 &sfb_stdscreen,
178 };
179
180 struct wsscreen_list sfb_screenlist = {
181 sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
182 };
183
184 int sfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
185 int sfbmmap __P((void *, off_t, int));
186
187 int sfb_alloc_screen __P((void *, const struct wsscreen_descr *,
188 void **, int *, int *, long *));
189 void sfb_free_screen __P((void *, void *));
190 void sfb_show_screen __P((void *, void *));
191 int sfb_load_font __P((void *, void *, int, int, int, void *));
192
193 struct wsdisplay_accessops sfb_accessops = {
194 sfbioctl,
195 sfbmmap,
196 sfb_alloc_screen,
197 sfb_free_screen,
198 sfb_show_screen,
199 sfb_load_font
200 };
201
202 int sfb_cnattach __P((tc_addr_t));
203 int sfbintr __P((void *));
204 void sfbinit __P((struct fb_devconfig *));
205
206 static int get_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *));
207 static int set_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *));
208 static int set_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *));
209 static int get_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *));
210 static void set_curpos __P((struct sfb_softc *, struct wsdisplay_curpos *));
211 static void bt459_set_curpos __P((struct sfb_softc *));
212
213 /* XXX XXX XXX */
214 #define BT459_SELECT(vdac, regno) do { \
215 vdac->bt_lo = (regno) & 0x00ff; \
216 vdac->bt_hi = ((regno)& 0xff00) >> 8 ; \
217 tc_wmb(); \
218 } while (0)
219 /* XXX XXX XXX */
220
221 int
222 sfbmatch(parent, match, aux)
223 struct device *parent;
224 struct cfdata *match;
225 void *aux;
226 {
227 struct tc_attach_args *ta = aux;
228
229 if (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0)
230 return (0);
231
232 return (1);
233 }
234
235 void
236 sfb_getdevconfig(dense_addr, dc)
237 tc_addr_t dense_addr;
238 struct fb_devconfig *dc;
239 {
240 struct raster *rap;
241 struct rcons *rcp;
242 caddr_t sfbasic;
243 int i, hsetup, vsetup, vbase;
244
245 dc->dc_vaddr = dense_addr;
246 dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr);
247
248 sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
249 hsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_HSETUP);
250 vsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VSETUP);
251 vbase = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) & 0x1ff;
252
253 dc->dc_wid = (hsetup & 0x1ff) << 2;
254 dc->dc_ht = (vsetup & 0x7ff);
255 dc->dc_depth = 8;
256 dc->dc_rowbytes = dc->dc_wid * (dc->dc_depth / 8);
257 dc->dc_videobase = dc->dc_vaddr + SFB_FB_OFFSET + vbase * 4096;
258 dc->dc_blanked = 0;
259
260 /* initialize colormap and cursor resource */
261 sfbinit(dc);
262
263 /* clear the screen */
264 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
265 *(u_int32_t *)(dc->dc_videobase + i) = 0x0;
266
267 /* initialize the raster */
268 rap = &dc->dc_raster;
269 rap->width = dc->dc_wid;
270 rap->height = dc->dc_ht;
271 rap->depth = dc->dc_depth;
272 rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
273 rap->pixels = (u_int32_t *)dc->dc_videobase;
274
275 /* initialize the raster console blitter */
276 rcp = &dc->dc_rcons;
277 rcp->rc_sp = rap;
278 rcp->rc_crow = rcp->rc_ccol = -1;
279 rcp->rc_crowp = &rcp->rc_crow;
280 rcp->rc_ccolp = &rcp->rc_ccol;
281 rcons_init(rcp, 34, 80);
282
283 sfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
284 sfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
285 }
286
287 void
288 sfbattach(parent, self, aux)
289 struct device *parent, *self;
290 void *aux;
291 {
292 struct sfb_softc *sc = (struct sfb_softc *)self;
293 struct tc_attach_args *ta = aux;
294 struct wsemuldisplaydev_attach_args waa;
295 struct hwcmap *cm;
296 caddr_t sfbasic;
297 int console, i;
298
299 console = (ta->ta_addr == sfb_consaddr);
300 if (console) {
301 sc->sc_dc = &sfb_console_dc;
302 sc->nscreens = 1;
303 }
304 else {
305 sc->sc_dc = (struct fb_devconfig *)
306 malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
307 sfb_getdevconfig(ta->ta_addr, sc->sc_dc);
308 }
309 printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
310 sc->sc_dc->dc_depth);
311
312 cm = &sc->sc_cmap;
313 cm->r[0] = cm->g[0] = cm->b[0] = 0;
314 for (i = 1; i < CMAP_SIZE; i++) {
315 cm->r[i] = cm->g[i] = cm->b[i] = 0xff;
316 }
317
318 tc_intr_establish(parent, ta->ta_cookie, TC_IPL_TTY, sfbintr, sc);
319
320 sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
321 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
322 *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1;
323
324 waa.console = console;
325 waa.scrdata = &sfb_screenlist;
326 waa.accessops = &sfb_accessops;
327 waa.accesscookie = sc;
328
329 config_found(self, &waa, wsemuldisplaydevprint);
330 }
331
332 int
333 sfbioctl(v, cmd, data, flag, p)
334 void *v;
335 u_long cmd;
336 caddr_t data;
337 int flag;
338 struct proc *p;
339 {
340 struct sfb_softc *sc = v;
341 struct fb_devconfig *dc = sc->sc_dc;
342 int turnoff;
343
344 switch (cmd) {
345 case WSDISPLAYIO_GTYPE:
346 *(u_int *)data = WSDISPLAY_TYPE_SFB;
347 return (0);
348
349 case WSDISPLAYIO_GINFO:
350 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
351 wsd_fbip->height = sc->sc_dc->dc_ht;
352 wsd_fbip->width = sc->sc_dc->dc_wid;
353 wsd_fbip->depth = sc->sc_dc->dc_depth;
354 wsd_fbip->cmsize = CMAP_SIZE;
355 #undef fbt
356 return (0);
357
358 case WSDISPLAYIO_GETCMAP:
359 return get_cmap(sc, (struct wsdisplay_cmap *)data);
360
361 case WSDISPLAYIO_PUTCMAP:
362 return set_cmap(sc, (struct wsdisplay_cmap *)data);
363
364 case WSDISPLAYIO_SVIDEO:
365 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
366 if ((dc->dc_blanked == 0) ^ turnoff) {
367 /* sc->sc_changed |= DATA_ALL_CHANGED; */
368 dc->dc_blanked = turnoff;
369 }
370 return (0);
371
372 case WSDISPLAYIO_GVIDEO:
373 *(u_int *)data = dc->dc_blanked ?
374 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
375 return (0);
376
377 case WSDISPLAYIO_GCURPOS:
378 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
379 return (0);
380
381 case WSDISPLAYIO_SCURPOS:
382 set_curpos(sc, (struct wsdisplay_curpos *)data);
383 bt459_set_curpos(sc);
384 return (0);
385
386 case WSDISPLAYIO_GCURMAX:
387 ((struct wsdisplay_curpos *)data)->x =
388 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
389 return (0);
390
391 case WSDISPLAYIO_GCURSOR:
392 return get_cursor(sc, (struct wsdisplay_cursor *)data);
393
394 case WSDISPLAYIO_SCURSOR:
395 return set_cursor(sc, (struct wsdisplay_cursor *)data);
396 }
397 return ENOTTY;
398 }
399
400 int
401 sfbmmap(v, offset, prot)
402 void *v;
403 off_t offset;
404 int prot;
405 {
406 struct sfb_softc *sc = v;
407
408 if (offset > 0x1000000) /* XXX */
409 return (-1);
410 return machine_btop(sc->sc_dc->dc_paddr + offset);
411 }
412
413 int
414 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
415 void *v;
416 const struct wsscreen_descr *type;
417 void **cookiep;
418 int *curxp, *curyp;
419 long *attrp;
420 {
421 struct sfb_softc *sc = v;
422 long defattr;
423
424 if (sc->nscreens > 0)
425 return (ENOMEM);
426
427 *cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
428 *curxp = 0;
429 *curyp = 0;
430 rcons_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
431 *attrp = defattr;
432 sc->nscreens++;
433 return (0);
434 }
435
436 void
437 sfb_free_screen(v, cookie)
438 void *v;
439 void *cookie;
440 {
441 struct sfb_softc *sc = v;
442
443 if (sc->sc_dc == &sfb_console_dc)
444 panic("sfb_free_screen: console");
445
446 sc->nscreens--;
447 }
448
449 void
450 sfb_show_screen(v, cookie)
451 void *v;
452 void *cookie;
453 {
454 }
455
456 int
457 sfb_load_font(v, cookie, first, num, stride, data)
458 void *v;
459 void *cookie;
460 int first, num, stride;
461 void *data;
462 {
463 return (EINVAL);
464 }
465
466 int
467 sfb_cnattach(addr)
468 tc_addr_t addr;
469 {
470 struct fb_devconfig *dcp = &sfb_console_dc;
471 long defattr;
472
473 sfb_getdevconfig(addr, dcp);
474
475 rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
476
477 wsdisplay_cnattach(&sfb_stdscreen, &dcp->dc_rcons,
478 0, 0, defattr);
479 sfb_consaddr = addr;
480 return(0);
481 }
482
483
484 int
485 sfbintr(arg)
486 void *arg;
487 {
488 struct sfb_softc *sc = arg;
489 caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
490 caddr_t sfbasic = sfbbase + SFB_ASIC_OFFSET;
491 struct bt459reg *vdac;
492 int v;
493
494 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
495 /* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
496
497 if (sc->sc_changed == 0)
498 return (1);
499
500 vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
501 v = sc->sc_changed;
502 sc->sc_changed = 0;
503
504 if (v & DATA_ENB_CHANGED) {
505 BT459_SELECT(vdac, BT459_REG_CCR);
506 vdac->bt_reg = (sc->sc_curenb) ? 0xc0 : 0x00; tc_wmb();
507 }
508 if (v & DATA_CURCMAP_CHANGED) {
509 u_int8_t *cp = sc->sc_cursor.cc_color;
510
511 BT459_SELECT(vdac, BT459_REG_CCOLOR_2);
512 vdac->bt_reg = cp[1]; tc_wmb();
513 vdac->bt_reg = cp[3]; tc_wmb();
514 vdac->bt_reg = cp[5]; tc_wmb();
515
516 BT459_SELECT(vdac, BT459_REG_CCOLOR_3);
517 vdac->bt_reg = cp[0]; tc_wmb();
518 vdac->bt_reg = cp[2]; tc_wmb();
519 vdac->bt_reg = cp[4]; tc_wmb();
520 }
521 if (v & DATA_CURSHAPE_CHANGED) {
522 u_int8_t *bp;
523 int i;
524
525 bp = (u_int8_t *)&sc->sc_cursor.cc_image;
526 BT459_SELECT(vdac, BT459_REG_CRAM_BASE);
527 for (i = 0; i < sizeof(sc->sc_cursor.cc_image); i++) {
528 vdac->bt_reg = *bp++;
529 tc_wmb();
530 }
531 }
532 if (v & DATA_CMAP_CHANGED) {
533 struct hwcmap *cm = &sc->sc_cmap;
534 int index;
535
536 BT459_SELECT(vdac, 0);
537 for (index = 0; index < CMAP_SIZE; index++) {
538 vdac->bt_cmap = cm->r[index]; tc_wmb();
539 vdac->bt_cmap = cm->g[index]; tc_wmb();
540 vdac->bt_cmap = cm->b[index]; tc_wmb();
541 }
542 }
543 return (1);
544 }
545
546 void
547 sfbinit(dc)
548 struct fb_devconfig *dc;
549 {
550 caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
551 struct bt459reg *vdac = (void *)(dc->dc_vaddr + SFB_RAMDAC_OFFSET);
552 int i;
553
554 *(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0;
555 *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VALID) = 1;
556 *(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
557 *(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
558
559 *(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */
560
561 BT459_SELECT(vdac, 0);
562 vdac->bt_cmap = 0; tc_wmb();
563 vdac->bt_cmap = 0; tc_wmb();
564 vdac->bt_cmap = 0; tc_wmb();
565 for (i = 1; i < CMAP_SIZE; i++) {
566 vdac->bt_cmap = 0xff; tc_wmb();
567 vdac->bt_cmap = 0xff; tc_wmb();
568 vdac->bt_cmap = 0xff; tc_wmb();
569 }
570
571 BT459_SELECT(vdac, BT459_REG_COMMAND_0);
572 vdac->bt_reg = 0x40; /* CMD0 */ tc_wmb();
573 vdac->bt_reg = 0x0; /* CMD1 */ tc_wmb();
574 vdac->bt_reg = 0xc0; /* CMD2 */ tc_wmb();
575 vdac->bt_reg = 0xff; /* PRM */ tc_wmb();
576 vdac->bt_reg = 0; /* 205 */ tc_wmb();
577 vdac->bt_reg = 0x0; /* PBM */ tc_wmb();
578 vdac->bt_reg = 0; /* 207 */ tc_wmb();
579 vdac->bt_reg = 0x0; /* ORM */ tc_wmb();
580 vdac->bt_reg = 0x0; /* OBM */ tc_wmb();
581 vdac->bt_reg = 0x0; /* ILV */ tc_wmb();
582 vdac->bt_reg = 0x0; /* TEST */ tc_wmb();
583
584 BT459_SELECT(vdac, BT459_REG_CCR);
585 vdac->bt_reg = 0x0; tc_wmb();
586 vdac->bt_reg = 0x0; tc_wmb();
587 vdac->bt_reg = 0x0; tc_wmb();
588 vdac->bt_reg = 0x0; tc_wmb();
589 vdac->bt_reg = 0x0; tc_wmb();
590 vdac->bt_reg = 0x0; tc_wmb();
591 vdac->bt_reg = 0x0; tc_wmb();
592 vdac->bt_reg = 0x0; tc_wmb();
593 vdac->bt_reg = 0x0; tc_wmb();
594 vdac->bt_reg = 0x0; tc_wmb();
595 vdac->bt_reg = 0x0; tc_wmb();
596 vdac->bt_reg = 0x0; tc_wmb();
597 vdac->bt_reg = 0x0; tc_wmb();
598 }
599
600 static int
601 get_cmap(sc, p)
602 struct sfb_softc *sc;
603 struct wsdisplay_cmap *p;
604 {
605 u_int index = p->index, count = p->count;
606
607 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
608 return (EINVAL);
609
610 if (!useracc(p->red, count, B_WRITE) ||
611 !useracc(p->green, count, B_WRITE) ||
612 !useracc(p->blue, count, B_WRITE))
613 return (EFAULT);
614
615 copyout(&sc->sc_cmap.r[index], p->red, count);
616 copyout(&sc->sc_cmap.g[index], p->green, count);
617 copyout(&sc->sc_cmap.b[index], p->blue, count);
618
619 return (0);
620 }
621
622 static int
623 set_cmap(sc, p)
624 struct sfb_softc *sc;
625 struct wsdisplay_cmap *p;
626 {
627 u_int index = p->index, count = p->count;
628
629 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
630 return (EINVAL);
631
632 if (!useracc(p->red, count, B_READ) ||
633 !useracc(p->green, count, B_READ) ||
634 !useracc(p->blue, count, B_READ))
635 return (EFAULT);
636
637 copyin(p->red, &sc->sc_cmap.r[index], count);
638 copyin(p->green, &sc->sc_cmap.g[index], count);
639 copyin(p->blue, &sc->sc_cmap.b[index], count);
640
641 sc->sc_changed |= DATA_CMAP_CHANGED;
642
643 return (0);
644 }
645
646 static int
647 set_cursor(sc, p)
648 struct sfb_softc *sc;
649 struct wsdisplay_cursor *p;
650 {
651 #define cc (&sc->sc_cursor)
652 int v, index, count;
653
654 v = p->which;
655 if (v & WSDISPLAY_CURSOR_DOCMAP) {
656 index = p->cmap.index;
657 count = p->cmap.count;
658
659 if (index >= 2 || (index + count) > 2)
660 return (EINVAL);
661 if (!useracc(p->cmap.red, count, B_READ) ||
662 !useracc(p->cmap.green, count, B_READ) ||
663 !useracc(p->cmap.blue, count, B_READ))
664 return (EFAULT);
665 }
666 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
667 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
668 return (EINVAL);
669 count = (CURSOR_MAX_SIZE / NBBY) * p->size.y;
670 if (!useracc(p->image, count, B_READ) ||
671 !useracc(p->mask, count, B_READ))
672 return (EFAULT);
673 }
674 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
675 if (v & WSDISPLAY_CURSOR_DOCUR)
676 cc->cc_hot = p->hot;
677 if (v & WSDISPLAY_CURSOR_DOPOS)
678 set_curpos(sc, &p->pos);
679 bt459_set_curpos(sc);
680 }
681
682 sc->sc_changed = 0;
683 if (v & WSDISPLAY_CURSOR_DOCUR) {
684 sc->sc_curenb = p->enable;
685 sc->sc_changed |= DATA_ENB_CHANGED;
686 }
687 if (v & WSDISPLAY_CURSOR_DOCMAP) {
688 count = p->cmap.count;
689 copyin(p->cmap.red, &cc->cc_color[index], count);
690 copyin(p->cmap.green, &cc->cc_color[index + 2], count);
691 copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
692 sc->sc_changed |= DATA_CURCMAP_CHANGED;
693 }
694 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
695 cc->cc_size = p->size;
696 memset(cc->cc_image, 0, sizeof cc->cc_image);
697 copyin(p->image, cc->cc_image, count);
698 copyin(p->mask, &cc->cc_image[CURSOR_MAX_SIZE], count);
699 sc->sc_changed |= DATA_CURSHAPE_CHANGED;
700 }
701
702 return (0);
703 #undef cc
704 }
705
706 static int
707 get_cursor(sc, p)
708 struct sfb_softc *sc;
709 struct wsdisplay_cursor *p;
710 {
711 return (ENOTTY); /* XXX */
712 }
713
714 static void
715 set_curpos(sc, curpos)
716 struct sfb_softc *sc;
717 struct wsdisplay_curpos *curpos;
718 {
719 struct fb_devconfig *dc = sc->sc_dc;
720 int x = curpos->x, y = curpos->y;
721
722 if (y < 0)
723 y = 0;
724 else if (y > dc->dc_ht - sc->sc_cursor.cc_size.y - 1)
725 y = dc->dc_ht - sc->sc_cursor.cc_size.y - 1;
726 if (x < 0)
727 x = 0;
728 else if (x > dc->dc_wid - sc->sc_cursor.cc_size.x - 1)
729 x = dc->dc_wid - sc->sc_cursor.cc_size.x - 1;
730 sc->sc_cursor.cc_pos.x = x;
731 sc->sc_cursor.cc_pos.y = y;
732 }
733
734 static void
735 bt459_set_curpos(sc)
736 struct sfb_softc *sc;
737 {
738 caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
739 struct bt459reg *vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
740 int x = 219, y = 34; /* magic offset of HX coordinate */
741 int s;
742
743 x += sc->sc_cursor.cc_pos.x;
744 y += sc->sc_cursor.cc_pos.y;
745
746 s = spltty();
747
748 BT459_SELECT(vdac, BT459_REG_CURSOR_X_LOW);
749 vdac->bt_reg = x; tc_wmb();
750 vdac->bt_reg = x >> 8; tc_wmb();
751 vdac->bt_reg = y; tc_wmb();
752 vdac->bt_reg = y >> 8; tc_wmb();
753
754 splx(s);
755 }
756