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