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