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