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