pm.c revision 1.5.44.1 1 /* $NetBSD: pm.c,v 1.5.44.1 2008/05/16 02:22:59 yamt Exp $ */
2
3 /*-
4 * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright (c) 1998, 1999 Tohru Nishimura. All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 * must display the following acknowledgement:
45 * This product includes software developed by Tohru Nishimura
46 * for the NetBSD Project.
47 * 4. The name of the author may not be used to endorse or promote products
48 * derived from this software without specific prior written permission
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
51 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
52 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
53 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
54 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
55 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
56 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
57 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
59 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60 */
61
62 #include <sys/cdefs.h>
63 __KERNEL_RCSID(0, "$NetBSD: pm.c,v 1.5.44.1 2008/05/16 02:22:59 yamt Exp $");
64
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/kernel.h>
68 #include <sys/device.h>
69 #include <sys/buf.h>
70 #include <sys/ioctl.h>
71
72 #include <machine/bus.h>
73 #include <machine/intr.h>
74
75 #include <dev/wscons/wsconsio.h>
76 #include <dev/wscons/wsdisplayvar.h>
77 #include <dev/rasops/rasops.h>
78 #include <dev/wsfont/wsfont.h>
79
80 #include <pmax/pmax/kn01.h>
81
82 #include <pmax/ibus/ibusvar.h>
83 #include <pmax/ibus/pmreg.h>
84
85 #include <uvm/uvm_extern.h>
86
87 #define CURSOR_MAX_SIZE 16
88
89 struct hwcmap256 {
90 uint8_t r[256];
91 uint8_t g[256];
92 uint8_t b[256];
93 };
94
95 struct hwcursor64 {
96 struct wsdisplay_curpos cc_pos;
97 struct wsdisplay_curpos cc_hot;
98 struct wsdisplay_curpos cc_size;
99 uint8_t cc_color[6];
100
101 /*
102 * Max cursor size is 16x16. The X server pads bitmap scanlines to
103 * a word boundary. We take the easy route and waste some space.
104 */
105 u_short cc_image[32 + 32];
106 };
107
108 struct pm_softc {
109 struct device sc_dev;
110 size_t sc_cmap_size;
111 size_t sc_fb_size;
112 int sc_type;
113 int sc_blanked;
114 int sc_curenb;
115 int sc_changed;
116 int sc_nscreens;
117 struct hwcursor64 sc_cursor;
118 struct hwcmap256 sc_cmap;
119 };
120 #define WSDISPLAY_CMAP_DOLUT 0x20
121
122 int pm_match(struct device *, struct cfdata *, void *);
123 void pm_attach(struct device *, struct device *, void *);
124 int pm_ioctl(void *, void *, u_long, void *, int, struct lwp *);
125 paddr_t pm_mmap(void *, void *, off_t, int);
126 int pm_alloc_screen(void *, const struct wsscreen_descr *,
127 void **, int *, int *, long *);
128 void pm_free_screen(void *, void *);
129 int pm_show_screen(void *, void *, int,
130 void (*) (void *, int, int), void *);
131 void pm_cursor_off(void);
132 void pm_cursor_on(struct pm_softc *);
133 int pm_cnattach(void);
134 void pm_common_init(void);
135 int pm_flush(struct pm_softc *);
136 int pm_get_cmap(struct pm_softc *, struct wsdisplay_cmap *);
137 int pm_set_cmap(struct pm_softc *, struct wsdisplay_cmap *);
138 int pm_set_cursor(struct pm_softc *, struct wsdisplay_cursor *);
139 int pm_get_cursor(struct pm_softc *, struct wsdisplay_cursor *);
140 void pm_set_curpos(struct pm_softc *, struct wsdisplay_curpos *);
141 void pm_init_cmap(struct pm_softc *);
142
143 CFATTACH_DECL(pm, sizeof(struct pm_softc),
144 pm_match, pm_attach, NULL, NULL);
145
146 struct rasops_info pm_ri;
147
148 struct wsscreen_descr pm_stdscreen = {
149 "std", 0, 0,
150 0, /* textops */
151 0, 0,
152 WSSCREEN_REVERSE
153 };
154
155 const struct wsscreen_descr *_pm_scrlist[] = {
156 &pm_stdscreen,
157 };
158
159 const struct wsscreen_list pm_screenlist = {
160 sizeof(_pm_scrlist) / sizeof(struct wsscreen_descr *), _pm_scrlist
161 };
162
163 const struct wsdisplay_accessops pm_accessops = {
164 pm_ioctl,
165 pm_mmap,
166 pm_alloc_screen,
167 pm_free_screen,
168 pm_show_screen,
169 0 /* load_font */
170 };
171
172 u_int pm_creg;
173
174 int
175 pm_match(struct device *parent, struct cfdata *match, void *aux)
176 {
177 struct ibus_attach_args *ia;
178 void *pmaddr;
179
180 ia = aux;
181 pmaddr = (void *)ia->ia_addr;
182
183 if (strcmp(ia->ia_name, "pm") != 0)
184 return (0);
185
186 if (badaddr(pmaddr, 4))
187 return (0);
188
189 return (1);
190 }
191
192 void
193 pm_attach(struct device *parent, struct device *self, void *aux)
194 {
195 struct pm_softc *sc;
196 struct rasops_info *ri;
197 struct wsemuldisplaydev_attach_args waa;
198 int console;
199
200 sc = (struct pm_softc *)self;
201 ri = &pm_ri;
202 console = (ri->ri_bits != NULL);
203
204 if (console)
205 sc->sc_nscreens = 1;
206 else
207 pm_common_init();
208
209 printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height, ri->ri_depth);
210
211 pm_init_cmap(sc);
212
213 sc->sc_blanked = 0;
214 sc->sc_curenb = 0;
215
216 waa.console = console;
217 waa.scrdata = &pm_screenlist;
218 waa.accessops = &pm_accessops;
219 waa.accesscookie = sc;
220
221 config_found(self, &waa, wsemuldisplaydevprint);
222 }
223
224 void
225 pm_init_cmap(struct pm_softc *sc)
226 {
227 struct hwcmap256 *cm;
228 struct rasops_info *ri;
229 const uint8_t *p;
230 int index;
231
232 cm = &sc->sc_cmap;
233 ri = &pm_ri;
234
235 if (ri->ri_depth == 8) {
236 p = rasops_cmap;
237 for (index = 0; index < 256; index++, p += 3) {
238 cm->r[index] = p[0];
239 cm->g[index] = p[1];
240 cm->b[index] = p[2];
241 }
242
243 sc->sc_type = WSDISPLAY_TYPE_PM_COLOR;
244 sc->sc_cmap_size = 256;
245 sc->sc_fb_size = 0x100000;
246 } else {
247 cm->r[0] = 0x00;
248 cm->g[0] = 0x00;
249 cm->b[0] = 0x00;
250
251 cm->r[1] = 0x00;
252 cm->g[1] = 0xff;
253 cm->b[1] = 0x00;
254
255 sc->sc_type = WSDISPLAY_TYPE_PM_MONO;
256 sc->sc_cmap_size = 2;
257 sc->sc_fb_size = 0x40000;
258 }
259 }
260
261 void
262 pm_common_init(void)
263 {
264 struct rasops_info *ri;
265 int cookie, bior, i;
266 PCCRegs *pcc;
267 VDACRegs *vdac;
268 uint16_t kn01csr;
269
270 kn01csr = *(volatile uint16_t *)MIPS_PHYS_TO_KSEG1(KN01_SYS_CSR);
271 pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
272 vdac = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_VDAC);
273 ri = &pm_ri;
274
275 ri->ri_flg = RI_CENTER;
276 ri->ri_depth = ((kn01csr & KN01_CSR_MONO) != 0 ? 1 : 8);
277 ri->ri_width = 1024;
278 ri->ri_height = 864;
279 ri->ri_stride = (ri->ri_depth == 8 ? 1024 : 2048 / 8);
280 ri->ri_bits = (void *)MIPS_PHYS_TO_KSEG1(KN01_PHYS_FBUF_START);
281
282 /*
283 * Clear the screen.
284 */
285 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
286
287 /*
288 * Get a font to use.
289 */
290 bior = (ri->ri_depth == 8 ? WSDISPLAY_FONTORDER_L2R :
291 WSDISPLAY_FONTORDER_R2L);
292
293 wsfont_init();
294 if (ri->ri_depth == 8)
295 cookie = wsfont_find(NULL, 12, 0, 0, bior,
296 WSDISPLAY_FONTORDER_L2R);
297 else
298 cookie = wsfont_find(NULL, 8, 0, 0, bior,
299 WSDISPLAY_FONTORDER_L2R);
300 if (cookie <= 0)
301 cookie = wsfont_find(NULL, 0, 0, 0, bior,
302 WSDISPLAY_FONTORDER_L2R);
303 if (cookie <= 0) {
304 printf("pm: font table is empty\n");
305 return;
306 }
307
308 if (wsfont_lock(cookie, &ri->ri_font)) {
309 printf("pm: couldn't lock font\n");
310 return;
311 }
312 ri->ri_wsfcookie = cookie;
313
314 /*
315 * Set up the raster operations set.
316 */
317 rasops_init(ri, 1000, 1000);
318
319 pm_stdscreen.nrows = ri->ri_rows;
320 pm_stdscreen.ncols = ri->ri_cols;
321 pm_stdscreen.textops = &ri->ri_ops;
322 pm_stdscreen.capabilities = ri->ri_caps;
323
324 /*
325 * Initalize the VDAC.
326 */
327 *(uint8_t *)MIPS_PHYS_TO_KSEG1(KN01_PHYS_COLMASK_START) = 0xff;
328 wbflush();
329
330 vdac->overWA = 0x04; wbflush();
331 vdac->over = 0x00; wbflush();
332 vdac->over = 0x00; wbflush();
333 vdac->over = 0x00; wbflush();
334 vdac->overWA = 0x08; wbflush();
335 vdac->over = 0x00; wbflush();
336 vdac->over = 0x00; wbflush();
337 vdac->over = 0x7f; wbflush();
338 vdac->overWA = 0x0c; wbflush();
339 vdac->over = 0xff; wbflush();
340 vdac->over = 0xff; wbflush();
341 vdac->over = 0xff; wbflush();
342
343 /*
344 * Set in the initial colormap.
345 */
346 if (ri->ri_depth == 8) {
347 vdac->mapWA = 0;
348 wbflush();
349
350 for (i = 0; i < 256 * 3; i += 3) {
351 vdac->map = rasops_cmap[i];
352 wbflush();
353 vdac->map = rasops_cmap[i + 1];
354 wbflush();
355 vdac->map = rasops_cmap[i + 2];
356 wbflush();
357 }
358 } else {
359 vdac->mapWA = 0;
360 wbflush();
361
362 for (i = 0; i < 256; i++) {
363 vdac->map = 0x00;
364 wbflush();
365 vdac->map = (i < 128 ? 0x00 : 0xff);
366 wbflush();
367 vdac->map = 0x00;
368 wbflush();
369 }
370 }
371
372 /*
373 * Turn off the hardware cursor sprite for text mode.
374 */
375 pcc->cmdr = PCC_FOPB | PCC_VBHI;
376 wbflush();
377 pm_creg = 0;
378 pm_cursor_off();
379 }
380
381 void
382 pm_cursor_off(void)
383 {
384 PCCRegs *pcc;
385
386 pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
387 pcc->cmdr = (pm_creg &= ~(PCC_ENPA | PCC_ENPB));
388 wbflush();
389 }
390
391 void
392 pm_cursor_on(struct pm_softc *sc)
393 {
394 PCCRegs *pcc;
395
396 if (sc->sc_curenb) {
397 pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
398 pcc->cmdr = (pm_creg |= (PCC_ENPA | PCC_ENPB));
399 wbflush();
400 }
401 }
402
403 int
404 pm_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
405 {
406 struct pm_softc *sc;
407 struct rasops_info *ri;
408 int turnoff, rv, i;
409 PCCRegs *pcc;
410 VDACRegs *vdac;
411
412 sc = v;
413 ri = &pm_ri;
414 rv = 0;
415 pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
416 vdac = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_VDAC);
417
418 switch (cmd) {
419 case WSDISPLAYIO_GTYPE:
420 *(u_int *)data = sc->sc_type;
421 break;
422
423 case WSDISPLAYIO_SMODE:
424 if (*(u_int *)data == WSDISPLAYIO_MODE_EMUL) {
425 pm_cursor_off();
426 pm_init_cmap(sc);
427 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
428 sc->sc_curenb = 0;
429 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
430 }
431 break;
432
433 case WSDISPLAYIO_GINFO:
434 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
435 wsd_fbip->height = ri->ri_height;
436 wsd_fbip->width = ri->ri_width;
437 wsd_fbip->depth = ri->ri_depth;
438 wsd_fbip->cmsize = sc->sc_cmap_size;
439 #undef fbt
440 break;
441
442 case WSDISPLAYIO_GETCMAP:
443 rv = pm_get_cmap(sc, (struct wsdisplay_cmap *)data);
444 break;
445
446 case WSDISPLAYIO_PUTCMAP:
447 rv = pm_set_cmap(sc, (struct wsdisplay_cmap *)data);
448 break;
449
450 case WSDISPLAYIO_SVIDEO:
451 turnoff = (*(int *)data == WSDISPLAYIO_VIDEO_OFF);
452 if ((sc->sc_blanked == 0) ^ turnoff) {
453 sc->sc_blanked = turnoff;
454 if (turnoff == 0) {
455 pcc->cmdr =
456 (pm_creg &= ~(PCC_FOPA | PCC_FOPB));
457 wbflush();
458 pm_cursor_on(sc);
459 sc->sc_changed |= WSDISPLAY_CURSOR_DOCMAP;
460 } else {
461 pm_cursor_off();
462 pcc->cmdr =
463 (pm_creg |= (PCC_FOPA | PCC_FOPB));
464 wbflush();
465 vdac->overWA = 0x0c;
466 wbflush();
467 for (i = 0; i < 3; i++) {
468 vdac->over = 0;
469 wbflush();
470 }
471 }
472 }
473 break;
474
475 case WSDISPLAYIO_GVIDEO:
476 *(u_int *)data = (sc->sc_blanked ?
477 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON);
478 break;
479
480 case WSDISPLAYIO_GCURPOS:
481 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
482 break;
483
484 case WSDISPLAYIO_SCURPOS:
485 pm_set_curpos(sc, (struct wsdisplay_curpos *)data);
486 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS;
487 break;
488
489 case WSDISPLAYIO_GCURMAX:
490 ((struct wsdisplay_curpos *)data)->x =
491 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
492 break;
493
494 case WSDISPLAYIO_GCURSOR:
495 rv = pm_get_cursor(sc, (struct wsdisplay_cursor *)data);
496 break;
497
498 case WSDISPLAYIO_SCURSOR:
499 rv = pm_set_cursor(sc, (struct wsdisplay_cursor *)data);
500 break;
501
502 default:
503 rv = ENOTTY;
504 break;
505 }
506
507 pm_flush(sc);
508 return (rv);
509 }
510
511 paddr_t
512 pm_mmap(void *v, void *vs, off_t offset, int prot)
513 {
514 struct pm_softc *sc;
515
516 sc = v;
517
518 if (offset >= sc->sc_fb_size || offset < 0)
519 return (-1);
520
521 return (mips_btop(KN01_PHYS_FBUF_START + offset));
522 }
523
524 int
525 pm_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
526 int *curxp, int *curyp, long *attrp)
527 {
528 struct pm_softc *sc;
529 struct rasops_info *ri;
530 long defattr;
531
532 sc = v;
533 ri = &pm_ri;
534
535 if (sc->sc_nscreens > 0)
536 return (ENOMEM);
537
538 *cookiep = ri; /* one and only for now */
539 *curxp = 0;
540 *curyp = 0;
541 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
542 *attrp = defattr;
543 sc->sc_nscreens++;
544 return (0);
545 }
546
547 void
548 pm_free_screen(void *v, void *cookie)
549 {
550
551 panic("pm_free_screen: console");
552 }
553
554 int
555 pm_show_screen(void *v, void *cookie, int waitok,
556 void (*cb)(void *, int, int), void *cbarg)
557 {
558
559 return (0);
560 }
561
562 /* EXPORT */ int
563 pm_cnattach(void)
564 {
565 struct rasops_info *ri;
566 long defattr;
567
568 ri = &pm_ri;
569
570 pm_common_init();
571 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
572 wsdisplay_cnattach(&pm_stdscreen, ri, 0, 0, defattr);
573 return (1);
574 }
575
576 int
577 pm_flush(struct pm_softc *sc)
578 {
579 VDACRegs *vdac;
580 PCCRegs *pcc;
581 uint8_t *cp;
582 int v, i, x, y;
583 u_short *p, *pe;
584 struct hwcmap256 *cm;
585 struct rasops_info *ri;
586
587 if (sc->sc_changed == 0)
588 return (1);
589
590 vdac = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_VDAC);
591 pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
592 ri = &pm_ri;
593 v = sc->sc_changed;
594
595 if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) {
596 if (sc->sc_curenb)
597 pm_cursor_on(sc);
598 else
599 pm_cursor_off();
600 }
601
602 if ((v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) != 0) {
603 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
604 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
605 pcc->xpos = x + PCC_X_OFFSET;
606 pcc->ypos = y + PCC_Y_OFFSET;
607 wbflush();
608 }
609 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
610 cp = sc->sc_cursor.cc_color;
611
612 vdac->overWA = 0x04;
613 wbflush();
614 for (i = 1; i < 6; i += 2) {
615 vdac->over = cp[i];
616 wbflush();
617 }
618
619 vdac->overWA = 0x08;
620 wbflush();
621 vdac->over = 0x00;
622 wbflush();
623 vdac->over = 0x00;
624 wbflush();
625 vdac->over = 0x7f;
626 wbflush();
627
628 vdac->overWA = 0x0c;
629 wbflush();
630 for (i = 0; i < 6; i += 2) {
631 vdac->over = cp[i];
632 wbflush();
633 }
634 }
635 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
636 pcc->cmdr = (pm_creg | PCC_LODSA);
637 wbflush();
638
639 p = sc->sc_cursor.cc_image;
640 x = 0xffff >> (16 - sc->sc_cursor.cc_size.x);
641 for (pe = p + 64; p < pe; p += 2) {
642 pcc->memory = *p & x;
643 wbflush();
644 }
645
646 pcc->cmdr = (pm_creg &= ~PCC_LODSA);
647 wbflush();
648 }
649
650 if ((v & WSDISPLAY_CMAP_DOLUT) != 0) {
651 cm = &sc->sc_cmap;
652
653 vdac->mapWA = 0;
654 wbflush();
655
656 if (sc->sc_cmap_size == 2) {
657 for (i = 0; i < 128; i++) {
658 vdac->map = 0;
659 wbflush();
660 vdac->map = cm->g[0];
661 wbflush();
662 vdac->map = 0;
663 wbflush();
664 }
665 for (; i < 256; i++) {
666 vdac->map = 0;
667 wbflush();
668 vdac->map = cm->g[1];
669 wbflush();
670 vdac->map = 0;
671 wbflush();
672 }
673 } else {
674 for (i = 0; i < sc->sc_cmap_size; i++) {
675 vdac->map = cm->r[i];
676 wbflush();
677 vdac->map = cm->g[i];
678 wbflush();
679 vdac->map = cm->b[i];
680 wbflush();
681 }
682 }
683 }
684
685 sc->sc_changed = 0;
686 return (1);
687 }
688
689 int
690 pm_get_cmap(struct pm_softc *sc, struct wsdisplay_cmap *p)
691 {
692 u_int index, count;
693 int rv;
694
695 index = p->index;
696 count = p->count;
697
698 if (index >= sc->sc_cmap_size || (index + count) > sc->sc_cmap_size)
699 return (EINVAL);
700
701 if ((rv = copyout(&sc->sc_cmap.r[index], p->red, count)) != 0)
702 return (rv);
703 if ((rv = copyout(&sc->sc_cmap.g[index], p->green, count)) != 0)
704 return (rv);
705 return (copyout(&sc->sc_cmap.b[index], p->blue, count));
706 }
707
708 int
709 pm_set_cmap(struct pm_softc *sc, struct wsdisplay_cmap *p)
710 {
711 u_int index, count;
712 int rv;
713
714 index = p->index;
715 count = p->count;
716
717 if (index >= sc->sc_cmap_size || (index + count) > sc->sc_cmap_size)
718 return (EINVAL);
719
720 if ((rv = copyin(p->red, &sc->sc_cmap.r[index], count)) != 0)
721 return (rv);
722 if ((rv = copyin(p->green, &sc->sc_cmap.g[index], count)) != 0)
723 return (rv);
724 if ((rv = copyin(p->blue, &sc->sc_cmap.b[index], count)) != 0)
725 return (rv);
726 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
727 return (0);
728 }
729
730 int
731 pm_set_cursor(struct pm_softc *sc, struct wsdisplay_cursor *p)
732 {
733 u_int v, index, count;
734 struct hwcursor64 *cc;
735 int rv;
736
737 v = p->which;
738 cc = &sc->sc_cursor;
739
740 if ((v & WSDISPLAY_CURSOR_DOCUR) != 0)
741 sc->sc_curenb = p->enable;
742 if ((v & WSDISPLAY_CURSOR_DOPOS) != 0)
743 pm_set_curpos(sc, &p->pos);
744 if ((v & WSDISPLAY_CURSOR_DOHOT) != 0)
745 cc->cc_hot = p->hot;
746 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
747 index = p->cmap.index;
748 count = p->cmap.count;
749 if (index >= 2 || (index + count) > 2)
750 return (EINVAL);
751
752 rv = copyin(p->cmap.red, &cc->cc_color[index], count);
753 if (rv != 0)
754 return (rv);
755 rv = copyin(p->cmap.green, &cc->cc_color[index + 2], count);
756 if (rv != 0)
757 return (rv);
758 rv = copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
759 if (rv != 0)
760 return (rv);
761 }
762 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
763 if (p->size.x > CURSOR_MAX_SIZE ||
764 p->size.y > CURSOR_MAX_SIZE)
765 return (EINVAL);
766
767 cc->cc_size = p->size;
768 memset(cc->cc_image, 0, sizeof(cc->cc_image));
769 rv = copyin(p->image, cc->cc_image, p->size.y * 4);
770 if (rv != 0)
771 return (rv);
772 rv = copyin(p->mask, cc->cc_image+32, p->size.y * 4);
773 if (rv != 0)
774 return (rv);
775 }
776
777 sc->sc_changed |= v;
778 return (0);
779 }
780
781 int
782 pm_get_cursor(struct pm_softc *sc, struct wsdisplay_cursor *p)
783 {
784
785 return (ENOTTY); /* XXX */
786 }
787
788 void
789 pm_set_curpos(struct pm_softc *sc, struct wsdisplay_curpos *curpos)
790 {
791 struct rasops_info *ri;
792 int x, y;
793
794 ri = &pm_ri;
795 x = curpos->x;
796 y = curpos->y;
797
798 if (y < 0)
799 y = 0;
800 else if (y > ri->ri_height)
801 y = ri->ri_height;
802 if (x < 0)
803 x = 0;
804 else if (x > ri->ri_width)
805 x = ri->ri_width;
806 sc->sc_cursor.cc_pos.x = x;
807 sc->sc_cursor.cc_pos.y = y;
808 }
809