pm.c revision 1.1.2.5 1 /* $NetBSD: pm.c,v 1.1.2.5 1999/01/07 06:44:22 nisimura Exp $ */
2
3 /*
4 * Copyright (c) 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, "$Id: pm.c,v 1.1.2.5 1999/01/07 06:44:22 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 <pmax/ibus/ibusvar.h>
56
57 #include "opt_uvm.h"
58 #if defined(UVM)
59 #include <uvm/uvm_extern.h>
60 #define useracc uvm_useracc
61 #endif
62
63 extern void kn01_wbflush __P((void));
64
65 struct pccreg {
66 #define _WORD_(_x_) u_int16_t _x_; unsigned : 16
67 _WORD_(pcc_cmdr); /* cursor command register */
68 _WORD_(pcc_xpos); /* cursor X position */
69 _WORD_(pcc_ypos); /* cursor Y position */
70 _WORD_(pcc_xmin1); /* region 1 top edge */
71 _WORD_(pcc_xmax1); /* region 1 bottom edge */
72 _WORD_(pcc_ymin1); /* region 1 top edge */
73 _WORD_(pcc_ymax1); /* region 1 bottom edge */
74 unsigned : 32; /* unused */
75 unsigned : 32; /* unused */
76 unsigned : 32; /* unused */
77 unsigned : 32; /* unused */
78 _WORD_(pcc_xmin2); /* region 2 top edge */
79 _WORD_(pcc_xmax2); /* region 2 bottom edge */
80 _WORD_(pcc_ymin2); /* region 2 top edge */
81 _WORD_(pcc_ymax2); /* region 2 bottom edge */
82 _WORD_(pcc_memory); /* cursor sprite pattern load */
83 #undef _WORD_
84 };
85
86 #define PCC_ENPA 0000001
87 #define PCC_FOPA 0000002
88 #define PCC_ENPB 0000004
89 #define PCC_FOPB 0000010
90 #define PCC_XHAIR 0000020
91 #define PCC_XHCLP 0000040
92 #define PCC_XHCL1 0000100
93 #define PCC_XHWID 0000200
94 #define PCC_ENRG1 0000400
95 #define PCC_FORG1 0001000
96 #define PCC_ENRG2 0002000
97 #define PCC_FORG2 0004000
98 #define PCC_LODSA 0010000
99 #define PCC_VBHI 0020000
100 #define PCC_HSHI 0040000
101 #define PCC_TEST 0100000
102
103 struct bt478reg {
104 #define _BYTE_(_y_) u_int8_t _y_; unsigned : 24
105 _BYTE_(bt_mapWA); /* address register (color map write) */
106 _BYTE_(bt_map); /* color map */
107 _BYTE_(bt_mask); /* pixel read mask */
108 _BYTE_(bt_mapRA); /* address register (color map read) */
109 _BYTE_(bt_overWA); /* address register (overlay map write) */
110 _BYTE_(bt_over); /* overlay map */
111 unsigned : 32; /* unused */
112 _BYTE_(bt_overRA); /* address register (overlay map read) */
113 #undef _BYTE_
114 };
115
116 struct fb_devconfig {
117 vaddr_t dc_vaddr; /* memory space virtual base address */
118 paddr_t dc_paddr; /* memory space physical base address */
119 vsize_t dc_size; /* size of slot memory */
120 int dc_wid; /* width of frame buffer */
121 int dc_ht; /* height of frame buffer */
122 int dc_depth; /* depth, bits per pixel */
123 int dc_rowbytes; /* bytes in a FB scan line */
124 vaddr_t dc_videobase; /* base of flat frame buffer */
125 struct raster dc_raster; /* raster description */
126 struct rcons dc_rcons; /* raster blitter control info */
127 int dc_blanked; /* currently has video disabled */
128 };
129
130 struct hwcmap {
131 #define CMAP_SIZE 256 /* 256 R/G/B entries */
132 u_int8_t r[CMAP_SIZE];
133 u_int8_t g[CMAP_SIZE];
134 u_int8_t b[CMAP_SIZE];
135 };
136
137 struct hwcursor {
138 struct wsdisplay_curpos cc_pos;
139 struct wsdisplay_curpos cc_hot;
140 struct wsdisplay_curpos cc_size;
141 #define CURSOR_MAX_SIZE 16
142 u_int8_t cc_color[6];
143 u_int16_t cc_image[16 + 16];
144 };
145
146 struct pm_softc {
147 struct device sc_dev;
148 struct fb_devconfig *sc_dc; /* device configuration */
149 struct hwcmap sc_cmap; /* software copy of colormap */
150 struct hwcursor sc_cursor; /* software copy of cursor */
151 /* no sc_change field because pm does not emit interrupt */
152 int nscreens;
153 short magic_x, magic_y; /* cursor location offset */
154 #define PCC_MAGIC_X 212
155 #define PCC_MAGIC_Y 34
156
157 struct pccreg *sc_pcc;
158 struct bt478reg *sc_vdac;
159 u_int16_t sc_pcccmdr; /* software copy of PCC cmdr */
160 };
161
162 int pmmatch __P((struct device *, struct cfdata *, void *));
163 void pmattach __P((struct device *, struct device *, void *));
164
165 struct cfattach pm_ca = {
166 sizeof(struct pm_softc), pmmatch, pmattach,
167 };
168
169 void pm_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
170 struct fb_devconfig pm_console_dc;
171 tc_addr_t pm_consaddr;
172
173 struct wsdisplay_emulops pm_emulops = {
174 rcons_cursor,
175 rcons_mapchar,
176 rcons_putchar,
177 rcons_copycols,
178 rcons_erasecols,
179 rcons_copyrows,
180 rcons_eraserows,
181 rcons_alloc_attr
182 };
183
184 struct wsscreen_descr pm_stdscreen = {
185 "std",
186 0, 0, /* will be filled in -- XXX shouldn't, it's global */
187 &pm_emulops,
188 0, 0,
189 0
190 };
191
192 const struct wsscreen_descr *_pm_scrlist[] = {
193 &pm_stdscreen,
194 };
195
196 struct wsscreen_list pm_screenlist = {
197 sizeof(_pm_scrlist) / sizeof(struct wsscreen_descr *), _pm_scrlist
198 };
199
200 int pmioctl __P((void *, u_long, caddr_t, int, struct proc *));
201 int pmmmap __P((void *, off_t, int));
202
203 int pm_alloc_screen __P((void *, const struct wsscreen_descr *,
204 void **, int *, int *, long *));
205 void pm_free_screen __P((void *, void *));
206 void pm_show_screen __P((void *, void *));
207 int pm_load_font __P((void *, void *, int, int, int, void *));
208
209 struct wsdisplay_accessops pm_accessops = {
210 pmioctl,
211 pmmmap,
212 pm_alloc_screen,
213 pm_free_screen,
214 pm_show_screen,
215 pm_load_font
216 };
217
218 int pm_cnattach __P((tc_addr_t));
219 void pminit __P((struct fb_devconfig *));
220 void pm_screenblank __P((struct pm_softc *));
221
222 static int set_cmap __P((struct pm_softc *, struct wsdisplay_cmap *));
223 static int get_cmap __P((struct pm_softc *, struct wsdisplay_cmap *));
224 static int set_cursor __P((struct pm_softc *, struct wsdisplay_cursor *));
225 static int get_cursor __P((struct pm_softc *, struct wsdisplay_cursor *));
226 static void set_curpos __P((struct pm_softc *, struct wsdisplay_curpos *));
227 void bt478_loadcmap __P((struct pm_softc *));
228 void bt478_load_curcmap __P((struct pm_softc *));
229 void pcc_load_curshape __P((struct pm_softc *));
230 void pcc_set_curpos __P((struct pm_softc *));
231 void pcc_show_cursor __P((struct pm_softc *, int));
232
233 #define KN01_SYS_PCC 0x11100000
234 #define KN01_SYS_BT478 0x11200000
235 #define KN01_SYS_PMASK 0x10000000
236 #define KN01_SYS_CSR 0x1e000000
237 #define KN01_CSR_MONO 0x0800
238
239 int
240 pmmatch(parent, match, aux)
241 struct device *parent;
242 struct cfdata *match;
243 void *aux;
244 {
245 struct ibus_attach_args *ia = aux;
246
247 if (strcmp("pm", ia->ia_name))
248 return (0);
249 if (badaddr((char *)ia->ia_addr, 4))
250 return (0);
251 return (1);
252 }
253
254 void
255 pm_getdevconfig(dense_addr, dc)
256 tc_addr_t dense_addr;
257 struct fb_devconfig *dc;
258 {
259 struct raster *rap;
260 struct rcons *rcp;
261 u_int16_t *p = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_CSR);
262 int i;
263
264 dc->dc_wid = 1024;
265 dc->dc_ht = 864;
266 dc->dc_depth = (*p & KN01_CSR_MONO) ? 1 : 8;
267 dc->dc_rowbytes = (dc->dc_depth == 8) ? 1024 : 1024 / 8;
268 dc->dc_videobase = dense_addr;
269 dc->dc_blanked = 0;
270
271 dc->dc_vaddr = dense_addr;
272 dc->dc_paddr = MIPS_KSEG1_TO_PHYS(dc->dc_vaddr);
273 dc->dc_size = (dc->dc_depth == 8) ? 0x100000 : 0x40000;
274
275 /* initialize colormap and cursor resource */
276 pminit(dc);
277
278 /* clear the screen */
279 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
280 *(u_int32_t *)(dc->dc_videobase + i) = 0;
281
282 /* initialize the raster */
283 rap = &dc->dc_raster;
284 rap->width = dc->dc_wid;
285 rap->height = dc->dc_ht;
286 rap->depth = dc->dc_depth;
287 rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
288 rap->pixels = (u_int32_t *)dc->dc_videobase;
289
290 /* initialize the raster console blitter */
291 rcp = &dc->dc_rcons;
292 rcp->rc_sp = rap;
293 rcp->rc_crow = rcp->rc_ccol = -1;
294 rcp->rc_crowp = &rcp->rc_crow;
295 rcp->rc_ccolp = &rcp->rc_ccol;
296 rcons_init(rcp, 34, 80);
297
298 pm_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
299 pm_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
300 }
301
302 void
303 pmattach(parent, self, aux)
304 struct device *parent, *self;
305 void *aux;
306 {
307 struct pm_softc *sc = (struct pm_softc *)self;
308 struct ibus_attach_args *ia = aux;
309 struct wsemuldisplaydev_attach_args waa;
310 struct hwcmap *cm;
311 int console, i;
312
313 console = (ia->ia_addr == pm_consaddr);
314 if (console) {
315 sc->sc_dc = &pm_console_dc;
316 sc->nscreens = 1;
317 }
318 else {
319 sc->sc_dc = (struct fb_devconfig *)
320 malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
321 pm_getdevconfig(ia->ia_addr, sc->sc_dc);
322 }
323 printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
324 sc->sc_dc->dc_depth);
325
326 cm = &sc->sc_cmap;
327 cm->r[0] = cm->g[0] = cm->b[0] = 0;
328 for (i = 1; i < CMAP_SIZE; i++) {
329 cm->r[i] = cm->g[i] = cm->b[i] = 0xff;
330 }
331 sc->magic_x = PCC_MAGIC_X;
332 sc->magic_y = PCC_MAGIC_Y;
333 sc->sc_pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
334 sc->sc_vdac = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_BT478);
335 sc->sc_pcccmdr = 0;
336
337 /* pm emits no interrupt */
338
339 waa.console = console;
340 waa.scrdata = &pm_screenlist;
341 waa.accessops = &pm_accessops;
342 waa.accesscookie = sc;
343
344 config_found(self, &waa, wsemuldisplaydevprint);
345 }
346
347 int
348 pmioctl(v, cmd, data, flag, p)
349 void *v;
350 u_long cmd;
351 caddr_t data;
352 int flag;
353 struct proc *p;
354 {
355 struct pm_softc *sc = v;
356 struct fb_devconfig *dc = sc->sc_dc;
357 int turnoff, error;
358
359 switch (cmd) {
360 case WSDISPLAYIO_GTYPE:
361 *(u_int *)data = (dc->dc_depth == 8)
362 ? WSDISPLAY_TYPE_PM_COLOR : WSDISPLAY_TYPE_PM_MONO;
363 return (0);
364
365 case WSDISPLAYIO_GINFO:
366 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
367 wsd_fbip->height = sc->sc_dc->dc_ht;
368 wsd_fbip->width = sc->sc_dc->dc_wid;
369 wsd_fbip->depth = sc->sc_dc->dc_depth;
370 wsd_fbip->cmsize = CMAP_SIZE;
371 #undef fbt
372 return (0);
373
374 case WSDISPLAYIO_GETCMAP:
375 return get_cmap(sc, (struct wsdisplay_cmap *)data);
376
377 case WSDISPLAYIO_PUTCMAP:
378 error = set_cmap(sc, (struct wsdisplay_cmap *)data);
379 if (error == 0)
380 bt478_loadcmap(sc);
381 return (error);
382
383 case WSDISPLAYIO_SVIDEO:
384 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
385 if ((dc->dc_blanked == 0) ^ turnoff) {
386 dc->dc_blanked = turnoff;
387 pm_screenblank(sc);
388 }
389 return (0);
390
391 case WSDISPLAYIO_GVIDEO:
392 *(u_int *)data = dc->dc_blanked ?
393 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
394 return (0);
395
396 case WSDISPLAYIO_GCURPOS:
397 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
398 return (0);
399
400 case WSDISPLAYIO_SCURPOS:
401 set_curpos(sc, (struct wsdisplay_curpos *)data);
402 pcc_set_curpos(sc);
403 return (0);
404
405 case WSDISPLAYIO_GCURMAX:
406 ((struct wsdisplay_curpos *)data)->x =
407 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
408 return (0);
409
410 case WSDISPLAYIO_GCURSOR:
411 return get_cursor(sc, (struct wsdisplay_cursor *)data);
412
413 case WSDISPLAYIO_SCURSOR:
414 return set_cursor(sc, (struct wsdisplay_cursor *)data);
415 }
416 return ENOTTY;
417 }
418
419 int
420 pmmmap(v, offset, prot)
421 void *v;
422 off_t offset;
423 int prot;
424 {
425 struct pm_softc *sc = v;
426
427 if (offset >= sc->sc_dc->dc_size)
428 return -1;
429 return mips_btop(sc->sc_dc->dc_paddr + offset);
430 }
431
432 int
433 pm_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
434 void *v;
435 const struct wsscreen_descr *type;
436 void **cookiep;
437 int *curxp, *curyp;
438 long *attrp;
439 {
440 struct pm_softc *sc = v;
441 long defattr;
442
443 if (sc->nscreens > 0)
444 return (ENOMEM);
445
446 *cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
447 *curxp = 0;
448 *curyp = 0;
449 rcons_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
450 *attrp = defattr;
451 sc->nscreens++;
452 return (0);
453 }
454
455 void
456 pm_free_screen(v, cookie)
457 void *v;
458 void *cookie;
459 {
460 struct pm_softc *sc = v;
461
462 if (sc->sc_dc == &pm_console_dc)
463 panic("pm_free_screen: console");
464
465 sc->nscreens--;
466 }
467
468 void
469 pm_show_screen(v, cookie)
470 void *v;
471 void *cookie;
472 {
473 }
474
475 int
476 pm_load_font(v, cookie, first, num, stride, data)
477 void *v;
478 void *cookie;
479 int first, num, stride;
480 void *data;
481 {
482 return (EINVAL);
483 }
484
485 int
486 pm_cnattach(addr)
487 tc_addr_t addr;
488 {
489 struct fb_devconfig *dcp = &pm_console_dc;
490 long defattr;
491
492 pm_getdevconfig(addr, dcp);
493
494 rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
495
496 wsdisplay_cnattach(&pm_stdscreen, &dcp->dc_rcons,
497 0, 0, defattr);
498 pm_consaddr = addr;
499 return (0);
500 }
501
502 void
503 pminit(dc)
504 struct fb_devconfig *dc;
505 {
506 int i;
507 volatile struct bt478reg *vdac =
508 (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_BT478);
509 volatile struct pccreg *pcc =
510 (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC);
511
512 pcc->pcc_cmdr = PCC_FOPB | PCC_VBHI;
513
514 *(volatile u_int8_t *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PMASK) = 0xff;
515
516 vdac->bt_mapWA = 0; kn01_wbflush();
517 vdac->bt_map = 0; kn01_wbflush();
518 vdac->bt_map = 0; kn01_wbflush();
519 vdac->bt_map = 0; kn01_wbflush();
520 for (i = 1; i < CMAP_SIZE; i++) {
521 vdac->bt_mapWA = i; kn01_wbflush();
522 vdac->bt_map = 0xff; kn01_wbflush();
523 vdac->bt_map = 0xff; kn01_wbflush();
524 vdac->bt_map = 0xff; kn01_wbflush();
525 }
526 }
527
528 void
529 pm_screenblank(sc)
530 struct pm_softc *sc;
531 {
532 #if 0 /* XXX later XXX */
533 struct fb_devconfig *dc = sc->sc_dc;
534
535 if (dc->dc_blanked) {
536 /* blank screen */
537 /* turnoff hardware cursor */
538 }
539 else {
540 /* restore current colormap */
541 /* turnon hardware cursor */
542 }
543 #endif
544 }
545
546 static int
547 get_cmap(sc, p)
548 struct pm_softc *sc;
549 struct wsdisplay_cmap *p;
550 {
551 u_int index = p->index, count = p->count;
552
553 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
554 return (EINVAL);
555
556 if (!useracc(p->red, count, B_WRITE) ||
557 !useracc(p->green, count, B_WRITE) ||
558 !useracc(p->blue, count, B_WRITE))
559 return (EFAULT);
560
561 copyout(&sc->sc_cmap.r[index], p->red, count);
562 copyout(&sc->sc_cmap.r[index], p->green, count);
563 copyout(&sc->sc_cmap.r[index], p->blue, count);
564
565 return (0);
566 }
567
568 static int
569 set_cmap(sc, p)
570 struct pm_softc *sc;
571 struct wsdisplay_cmap *p;
572 {
573 u_int index = p->index, count = p->count;
574
575 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
576 return (EINVAL);
577
578 if (!useracc(p->red, count, B_READ) ||
579 !useracc(p->green, count, B_READ) ||
580 !useracc(p->blue, count, B_READ))
581 return (EFAULT);
582
583 copyin(p->red, &sc->sc_cmap.r[index], count);
584 copyin(p->green, &sc->sc_cmap.g[index], count);
585 copyin(p->blue, &sc->sc_cmap.b[index], count);
586
587 return (0);
588 }
589
590 static int
591 set_cursor(sc, p)
592 struct pm_softc *sc;
593 struct wsdisplay_cursor *p;
594 {
595 #define cc (&sc->sc_cursor)
596 int v, index, count;
597
598 v = p->which;
599 if (v & WSDISPLAY_CURSOR_DOCMAP) {
600 index = p->cmap.index;
601 count = p->cmap.count;
602 if (index >= 2 || (index + count) > 2)
603 return (EINVAL);
604 if (!useracc(p->cmap.red, count, B_READ) ||
605 !useracc(p->cmap.green, count, B_READ) ||
606 !useracc(p->cmap.blue, count, B_READ))
607 return (EFAULT);
608
609 count = p->cmap.count;
610 copyin(p->cmap.red, &cc->cc_color[index], count);
611 copyin(p->cmap.green, &cc->cc_color[index + 2], count);
612 copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
613
614 bt478_load_curcmap(sc);
615 }
616 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
617 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
618 return (EINVAL);
619 count = (CURSOR_MAX_SIZE / NBBY) * p->size.y;
620 if (!useracc(p->image, count, B_READ) ||
621 !useracc(p->mask, count, B_READ))
622 return (EFAULT);
623 cc->cc_size = p->size;
624 memset(cc->cc_image, 0, sizeof cc->cc_image);
625 copyin(p->image, (caddr_t)cc->cc_image, count);
626 copyin(p->mask, (caddr_t)(cc->cc_image+CURSOR_MAX_SIZE), count);
627
628 pcc_load_curshape(sc);
629 }
630 if (v & WSDISPLAY_CURSOR_DOCUR) {
631 cc->cc_hot = p->hot;
632 pcc_show_cursor(sc, p->enable);
633 }
634 if (v & WSDISPLAY_CURSOR_DOPOS) {
635 set_curpos(sc, &p->pos);
636 pcc_set_curpos(sc);
637 }
638
639 return (0);
640 #undef cc
641 }
642
643 static int
644 get_cursor(sc, p)
645 struct pm_softc *sc;
646 struct wsdisplay_cursor *p;
647 {
648 return (ENOTTY); /* XXX */
649 }
650
651 void
652 set_curpos(sc, curpos)
653 struct pm_softc *sc;
654 struct wsdisplay_curpos *curpos;
655 {
656 struct fb_devconfig *dc = sc->sc_dc;
657 int x = curpos->x, y = curpos->y;
658
659 if (y < 0)
660 y = 0;
661 else if (y > dc->dc_ht)
662 y = dc->dc_ht;
663 if (x < 0)
664 x = 0;
665 else if (x > dc->dc_wid)
666 x = dc->dc_wid;
667 sc->sc_cursor.cc_pos.x = x;
668 sc->sc_cursor.cc_pos.y = y;
669 }
670
671 void
672 bt478_loadcmap(sc)
673 struct pm_softc *sc;
674 {
675 int i;
676 struct hwcmap *cm = &sc->sc_cmap;
677 volatile struct bt478reg *vdac = sc->sc_vdac;
678
679 for (i = 0; i < CMAP_SIZE; i++) {
680 vdac->bt_mapWA = i; kn01_wbflush();
681 vdac->bt_map = cm->r[i]; kn01_wbflush();
682 vdac->bt_map = cm->g[i]; kn01_wbflush();
683 vdac->bt_map = cm->b[i]; kn01_wbflush();
684 }
685 }
686
687 void
688 bt478_load_curcmap(sc)
689 struct pm_softc *sc;
690 {
691 u_int8_t *cp = sc->sc_cursor.cc_color;
692 volatile struct bt478reg *vdac = sc->sc_vdac;
693
694 vdac->bt_overWA = 0x04; kn01_wbflush();
695 vdac->bt_over = cp[1]; kn01_wbflush();
696 vdac->bt_over = cp[3]; kn01_wbflush();
697 vdac->bt_over = cp[5]; kn01_wbflush();
698
699 vdac->bt_overWA = 0x08; kn01_wbflush();
700 vdac->bt_over = 0x00; kn01_wbflush();
701 vdac->bt_over = 0x00; kn01_wbflush();
702 vdac->bt_over = 0x7f; kn01_wbflush();
703
704 vdac->bt_overWA = 0x0c; kn01_wbflush();
705 vdac->bt_over = cp[0]; kn01_wbflush();
706 vdac->bt_over = cp[2]; kn01_wbflush();
707 vdac->bt_over = cp[4]; kn01_wbflush();
708 }
709
710 void
711 pcc_load_curshape(sc)
712 struct pm_softc *sc;
713 {
714 volatile struct pccreg *pcc = sc->sc_pcc;
715 u_int16_t *bp;
716 int i;
717
718 pcc->pcc_cmdr = sc->sc_pcccmdr | PCC_LODSA;
719 bp = sc->sc_cursor.cc_image;
720 for (i = 0; i < sizeof(sc->sc_cursor.cc_image); i++) {
721 pcc->pcc_memory = *bp++;
722 }
723 pcc->pcc_cmdr = sc->sc_pcccmdr;
724 }
725
726 void
727 pcc_set_curpos(sc)
728 struct pm_softc *sc;
729 {
730 volatile struct pccreg *pcc = sc->sc_pcc;
731
732 pcc->pcc_xpos = sc->sc_cursor.cc_pos.x + sc->magic_x;
733 pcc->pcc_ypos = sc->sc_cursor.cc_pos.y + sc->magic_y;
734 }
735
736 void
737 pcc_show_cursor(sc, enable)
738 struct pm_softc *sc;
739 int enable;
740 {
741 volatile struct pccreg *pcc = sc->sc_pcc;
742
743 if (enable)
744 sc->sc_pcccmdr |= (PCC_ENPA | PCC_ENPB);
745 else
746 sc->sc_pcccmdr &= ~(PCC_ENPA | PCC_ENPB);
747 pcc->pcc_cmdr = sc->sc_pcccmdr;
748 }
749