p9100.c revision 1.21 1 /* $NetBSD: p9100.c,v 1.21 2005/05/16 14:43:23 macallan Exp $ */
2
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Thomas.
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 * color display (p9100) driver.
41 *
42 * Does not handle interrupts, even though they can occur.
43 *
44 * XXX should defer colormap updates to vertical retrace interrupts
45 */
46
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD: p9100.c,v 1.21 2005/05/16 14:43:23 macallan Exp $");
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/buf.h>
53 #include <sys/device.h>
54 #include <sys/ioctl.h>
55 #include <sys/malloc.h>
56 #include <sys/mman.h>
57 #include <sys/tty.h>
58 #include <sys/conf.h>
59
60 #include <machine/bus.h>
61 #include <machine/autoconf.h>
62
63 #include <dev/sun/fbio.h>
64 #include <dev/sun/fbvar.h>
65 #include <dev/sun/btreg.h>
66 #include <dev/sun/btvar.h>
67
68 #include <dev/sbus/p9100reg.h>
69
70 #include <dev/sbus/sbusvar.h>
71
72 /*#include <dev/wscons/wsdisplayvar.h>*/
73 #include <dev/wscons/wsconsio.h>
74 #include <dev/wsfont/wsfont.h>
75 #include <dev/rasops/rasops.h>
76
77 #include "opt_wsemul.h"
78
79 #include "tctrl.h"
80 #if NTCTRL > 0
81 #include <machine/tctrl.h>
82 #include <sparc/dev/tctrlvar.h>/*XXX*/
83 #endif
84
85 /* per-display variables */
86 struct p9100_softc {
87 struct device sc_dev; /* base device */
88 struct sbusdev sc_sd; /* sbus device */
89 struct fbdevice sc_fb; /* frame buffer device */
90 bus_space_tag_t sc_bustag;
91
92 bus_addr_t sc_ctl_paddr; /* phys address description */
93 bus_size_t sc_ctl_psize; /* for device mmap() */
94 bus_space_handle_t sc_ctl_memh; /* bus space handle */
95
96 bus_addr_t sc_cmd_paddr; /* phys address description */
97 bus_size_t sc_cmd_psize; /* for device mmap() */
98 bus_space_handle_t sc_cmd_memh; /* bus space handle */
99
100 bus_addr_t sc_fb_paddr; /* phys address description */
101 bus_size_t sc_fb_psize; /* for device mmap() */
102 bus_space_handle_t sc_fb_memh; /* bus space handle */
103
104 uint32_t sc_junk;
105 uint32_t sc_mono_width; /* for setup_mono */
106
107 uint32_t sc_width;
108 uint32_t sc_height; /* panel width / height */
109 uint32_t sc_stride;
110 uint32_t sc_depth;
111 union bt_cmap sc_cmap; /* Brooktree color map */
112
113 #ifdef PNOZZ_SOFT_PUTCHAR
114 void (*putchar)(void *c, int row, int col, u_int uc, long attr);
115 #endif
116 int sc_mode;
117 uint32_t sc_bg;
118 void (*switchcb)(void *, int, int);
119 void *switchcbarg;
120 struct callout switch_callout;
121 LIST_HEAD(, p9100_screen) screens;
122 struct p9100_screen *active, *wanted;
123 const struct wsscreen_descr *currenttype;
124
125 };
126
127 struct p9100_screen {
128 struct rasops_info ri;
129 LIST_ENTRY(p9100_screen) next;
130 struct p9100_softc *sc;
131 const struct wsscreen_descr *type;
132 int active;
133 u_int16_t *chars;
134 long *attrs;
135 int dispoffset;
136 int mindispoffset;
137 int maxdispoffset;
138
139 int cursoron;
140 int cursorcol;
141 int cursorrow;
142 int cursordrawn;
143 };
144
145 static struct p9100_screen p9100_console_screen;
146
147 extern const u_char rasops_cmap[768];
148
149 struct wsscreen_descr p9100_defscreendesc = {
150 "default",
151 0, 0,
152 NULL,
153 8, 16,
154 WSSCREEN_WSCOLORS,
155 };
156
157 const struct wsscreen_descr *_p9100_scrlist[] = {
158 &p9100_defscreendesc,
159 /* XXX other formats, graphics screen? */
160 };
161
162 struct wsscreen_list p9100_screenlist = {
163 sizeof(_p9100_scrlist) / sizeof(struct wsscreen_descr *), _p9100_scrlist
164 };
165
166 /* autoconfiguration driver */
167 static int p9100_sbus_match(struct device *, struct cfdata *, void *);
168 static void p9100_sbus_attach(struct device *, struct device *, void *);
169
170 static void p9100unblank(struct device *);
171 static void p9100_shutdown(void *);
172
173 CFATTACH_DECL(pnozz, sizeof(struct p9100_softc),
174 p9100_sbus_match, p9100_sbus_attach, NULL, NULL);
175
176 extern struct cfdriver pnozz_cd;
177
178 dev_type_open(p9100open);
179 dev_type_ioctl(p9100ioctl);
180 dev_type_mmap(p9100mmap);
181
182 const struct cdevsw pnozz_cdevsw = {
183 p9100open, nullclose, noread, nowrite, p9100ioctl,
184 nostop, notty, nopoll, p9100mmap, nokqfilter,
185 };
186
187 /* frame buffer generic driver */
188 static struct fbdriver p9100fbdriver = {
189 p9100unblank, p9100open, nullclose, p9100ioctl, nopoll,
190 p9100mmap, nokqfilter
191 };
192
193 static void p9100loadcmap(struct p9100_softc *, int, int);
194 static void p9100_set_video(struct p9100_softc *, int);
195 static int p9100_get_video(struct p9100_softc *);
196 static uint32_t p9100_ctl_read_4(struct p9100_softc *, bus_size_t);
197 static void p9100_ctl_write_4(struct p9100_softc *, bus_size_t, uint32_t);
198 uint8_t p9100_ramdac_read(struct p9100_softc *, bus_size_t);
199 void p9100_ramdac_write(struct p9100_softc *, bus_size_t, uint8_t);
200
201 static void p9100_sync(struct p9100_softc *);
202 void p9100_bitblt(struct p9100_softc *, int, int, int, int, int, int, uint32_t); /* coordinates, rasop */
203 void p9100_rectfill(struct p9100_softc *, int, int, int, int,
204 uint32_t); /* coordinates, colour */
205 static void p9100_init_engine(struct p9100_softc *);
206 void p9100_setup_mono(struct p9100_softc *, int, int, int, int,
207 uint32_t, uint32_t);
208 void p9100_feed_line(struct p9100_softc *, int, uint8_t *);
209 static void p9100_set_color_reg(struct p9100_softc *, int, int32_t);
210
211 void p9100_cursor(void *, int, int, int);
212 int p9100_mapchar(void *, int, u_int *);
213 void p9100_putchar(void *, int, int, u_int, long);
214 void p9100_copycols(void *, int, int, int, int);
215 void p9100_erasecols(void *, int, int, int, long);
216 void p9100_copyrows(void *, int, int, int);
217 void p9100_eraserows(void *, int, int, long);
218 int p9100_allocattr(void *, int, int, int, long *);
219
220 void p9100_scroll(void *, void *, int);
221
222 int p9100_putcmap(struct p9100_softc *, struct wsdisplay_cmap *);
223 int p9100_getcmap(struct p9100_softc *, struct wsdisplay_cmap *);
224 int p9100_ioctl(void *, u_long, caddr_t, int, struct proc *);
225 paddr_t p9100_mmap(void *, off_t, int);
226 int p9100_alloc_screen(void *, const struct wsscreen_descr *, void **,
227 int *, int *, long *);
228 void p9100_free_screen(void *, void *);
229 int p9100_show_screen(void *, void *, int, void (*)(void *, int, int),
230 void *);
231 void p9100_switch_screen(struct p9100_softc *);
232 void p9100_restore_screen(struct p9100_screen *,
233 const struct wsscreen_descr *, u_int16_t *);
234 void p9100_clearscreen(struct p9100_softc *);
235
236 int p9100_load_font(void *, void *, struct wsdisplay_font *);
237
238 void p9100_init_screen(struct p9100_softc *, struct p9100_screen *, int,
239 long *);
240
241 int p9100_intr(void *);
242
243 struct wsdisplay_accessops p9100_accessops = {
244 p9100_ioctl,
245 p9100_mmap,
246 p9100_alloc_screen,
247 p9100_free_screen,
248 p9100_show_screen,
249 NULL, /* load_font */
250 NULL, /* polls */
251 NULL, /* getwschar */
252 NULL, /* putwschar */
253 NULL, /* scroll */
254 NULL, /* getborder */
255 NULL /* setborder */
256 };
257
258 /*
259 * Match a p9100.
260 */
261 static int
262 p9100_sbus_match(struct device *parent, struct cfdata *cf, void *aux)
263 {
264 struct sbus_attach_args *sa = aux;
265
266 return (strcmp("p9100", sa->sa_name) == 0);
267 }
268
269
270 /*
271 * Attach a display. We need to notice if it is the console, too.
272 */
273 static void
274 p9100_sbus_attach(struct device *parent, struct device *self, void *args)
275 {
276 struct p9100_softc *sc = (struct p9100_softc *)self;
277 struct sbus_attach_args *sa = args;
278 struct fbdevice *fb = &sc->sc_fb;
279 int isconsole;
280 int node;
281 int i, j;
282
283 #if NWSDISPLAY > 0
284 struct wsemuldisplaydev_attach_args aa;
285 struct rasops_info *ri;
286 unsigned long defattr;
287 #endif
288
289 /* Remember cookies for p9100_mmap() */
290 sc->sc_bustag = sa->sa_bustag;
291 sc->sc_ctl_paddr = sbus_bus_addr(sa->sa_bustag,
292 sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base);
293 sc->sc_ctl_psize = 0x8000;/*(bus_size_t)sa->sa_reg[0].oa_size;*/
294
295 sc->sc_cmd_paddr = sbus_bus_addr(sa->sa_bustag,
296 sa->sa_reg[1].oa_space, sa->sa_reg[1].oa_base);
297 sc->sc_cmd_psize = (bus_size_t)sa->sa_reg[1].oa_size;
298
299 sc->sc_fb_paddr = sbus_bus_addr(sa->sa_bustag,
300 sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base);
301 sc->sc_fb_psize = (bus_size_t)sa->sa_reg[2].oa_size;
302
303 fb->fb_driver = &p9100fbdriver;
304 fb->fb_device = &sc->sc_dev;
305 fb->fb_flags = sc->sc_dev.dv_cfdata->cf_flags & FB_USERMASK;
306 #ifdef PNOZZ_EMUL_CG3
307 fb->fb_type.fb_type = FBTYPE_SUN3COLOR;
308 #else
309 fb->fb_type.fb_type = FBTYPE_P9100;
310 #endif
311 fb->fb_pixels = NULL;
312
313 sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
314 #ifdef PNOZZ_SOFT_PUTCHAR
315 sc->putchar = NULL;
316 #endif
317
318 LIST_INIT(&sc->screens);
319 sc->active = NULL;
320 sc->currenttype = &p9100_defscreendesc;
321 callout_init(&sc->switch_callout);
322
323 node = sa->sa_node;
324 isconsole = fb_is_console(node);
325 if (!isconsole) {
326 printf("\n%s: fatal error: PROM didn't configure device\n",
327 self->dv_xname);
328 return;
329 }
330
331 /*
332 * When the ROM has mapped in a p9100 display, the address
333 * maps only the video RAM, so in any case we have to map the
334 * registers ourselves. We only need the video RAM if we are
335 * going to print characters via rconsole.
336 */
337 if (sbus_bus_map(sc->sc_bustag,
338 sa->sa_reg[0].oa_space,
339 sa->sa_reg[0].oa_base,
340 /*
341 * XXX for some reason the SBus resources don't cover
342 * all registers, so we just map what we need
343 */
344 /*sc->sc_ctl_psize*/ 0x8000,
345 BUS_SPACE_MAP_LINEAR, &sc->sc_ctl_memh) != 0) {
346 printf("%s: cannot map control registers\n", self->dv_xname);
347 return;
348 }
349
350 if (sa->sa_npromvaddrs != 0)
351 fb->fb_pixels = (caddr_t)sa->sa_promvaddrs[0];
352
353 if (fb->fb_pixels == NULL) {
354 if (sbus_bus_map(sc->sc_bustag,
355 sa->sa_reg[2].oa_space,
356 sa->sa_reg[2].oa_base,
357 sc->sc_fb_psize,
358 BUS_SPACE_MAP_LINEAR, &sc->sc_fb_memh) != 0) {
359 printf("%s: cannot map framebuffer\n", self->dv_xname);
360 return;
361 }
362 fb->fb_pixels = (char *)sc->sc_fb_memh;
363 } else {
364 sc->sc_fb_memh = (bus_space_handle_t) fb->fb_pixels;
365 }
366
367 i = p9100_ctl_read_4(sc, 0x0004);
368 switch ((i >> 26) & 7) {
369 case 5: fb->fb_type.fb_depth = 32; break;
370 case 7: fb->fb_type.fb_depth = 24; break;
371 case 3: fb->fb_type.fb_depth = 16; break;
372 case 2: fb->fb_type.fb_depth = 8; break;
373 default: {
374 panic("pnozz: can't determine screen depth (0x%02x)", i);
375 }
376 }
377 sc->sc_depth = (fb->fb_type.fb_depth >> 3);
378
379 /* XXX for some reason I get a kernel trap with this */
380 sc->sc_width = prom_getpropint(node, "width", 800);
381 sc->sc_height = prom_getpropint(node, "height", 600);
382
383 sc->sc_stride = prom_getpropint(node, "linebytes", sc->sc_width *
384 (fb->fb_type.fb_depth >> 3));
385
386 p9100_init_engine(sc);
387
388 fb_setsize_obp(fb, fb->fb_type.fb_depth, sc->sc_width, sc->sc_height,
389 node);
390
391 sbus_establish(&sc->sc_sd, &sc->sc_dev);
392
393 fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes;
394 printf(": rev %d, %dx%d, depth %d mem %x",
395 (i & 7), fb->fb_type.fb_width, fb->fb_type.fb_height,
396 fb->fb_type.fb_depth, (unsigned int)sc->sc_fb_psize);
397
398 fb->fb_type.fb_cmsize = prom_getpropint(node, "cmsize", 256);
399 if ((1 << fb->fb_type.fb_depth) != fb->fb_type.fb_cmsize)
400 printf(", %d entry colormap", fb->fb_type.fb_cmsize);
401
402 /* Initialize the default color map. */
403 /*bt_initcmap(&sc->sc_cmap, 256);*/
404 j = 0;
405 for (i = 0; i < 256; i++) {
406 sc->sc_cmap.cm_map[i][0] = rasops_cmap[j];
407 j++;
408 sc->sc_cmap.cm_map[i][1] = rasops_cmap[j];
409 j++;
410 sc->sc_cmap.cm_map[i][2] = rasops_cmap[j];
411 j++;
412 }
413 p9100loadcmap(sc, 0, 256);
414
415 /* make sure we are not blanked */
416 if (isconsole)
417 p9100_set_video(sc, 1);
418
419 if (shutdownhook_establish(p9100_shutdown, sc) == NULL) {
420 panic("%s: could not establish shutdown hook",
421 sc->sc_dev.dv_xname);
422 }
423
424 if (isconsole) {
425 printf(" (console)\n");
426 #ifdef RASTERCONSOLE
427 /*p9100loadcmap(sc, 255, 1);*/
428 fbrcons_init(fb);
429 #endif
430 } else
431 printf("\n");
432
433 #if NWSDISPLAY > 0
434 wsfont_init();
435
436 p9100_init_screen(sc, &p9100_console_screen, 1, &defattr);
437 p9100_console_screen.active = 1;
438 sc->active = &p9100_console_screen;
439 ri = &p9100_console_screen.ri;
440
441 p9100_defscreendesc.nrows = ri->ri_rows;
442 p9100_defscreendesc.ncols = ri->ri_cols;
443 p9100_defscreendesc.textops = &ri->ri_ops;
444 p9100_defscreendesc.capabilities = ri->ri_caps;
445
446 if(isconsole) {
447 wsdisplay_cnattach(&p9100_defscreendesc, ri, 0, 0, defattr);
448 }
449
450 sc->sc_bg = (defattr >> 16) & 0xff;
451
452 p9100_clearscreen(sc);
453
454 aa.console = isconsole;
455 aa.scrdata = &p9100_screenlist;
456 aa.accessops = &p9100_accessops;
457 aa.accesscookie = sc;
458
459 config_found(self, &aa, wsemuldisplaydevprint);
460 #endif
461 /* attach the fb */
462 fb_attach(fb, isconsole);
463
464 #if 0
465 p9100_rectfill(sc, 10, 10, 200, 200, 0x01);
466 p9100_rectfill(sc, 210, 10, 200, 200, 0xff);
467 p9100_bitblt(sc, 10, 10, 110, 110, 400, 200, ROP_SRC);
468 #endif
469 #if 0
470 p9100_setup_mono(sc, 750, 500, 32, 1, 1, 6);
471 {
472 uint32_t ev = 0xc3000000, odd = 0x3c000000;
473 for (i = 0; i < 16; i++) {
474 p9100_feed_line(sc, 1, (uint8_t*)&ev);
475 p9100_feed_line(sc, 1, (uint8_t*)&odd);
476 }
477 }
478 delay(4000000);
479 #endif
480 }
481
482 static void
483 p9100_shutdown(arg)
484 void *arg;
485 {
486 struct p9100_softc *sc = arg;
487
488 #ifdef RASTERCONSOLE
489 sc->sc_cmap.cm_map[0][0] = 0xff;
490 sc->sc_cmap.cm_map[0][1] = 0xff;
491 sc->sc_cmap.cm_map[0][2] = 0xff;
492 sc->sc_cmap.cm_map[1][0] = 0;
493 sc->sc_cmap.cm_map[1][1] = 0;
494 sc->sc_cmap.cm_map[1][2] = 0x00;
495 p9100loadcmap(sc, 0, 2);
496 sc->sc_cmap.cm_map[255][0] = 0;
497 sc->sc_cmap.cm_map[255][1] = 0;
498 sc->sc_cmap.cm_map[255][2] = 0;
499 p9100loadcmap(sc, 255, 1);
500 #endif
501 p9100_set_video(sc, 1);
502 }
503
504 int
505 p9100open(dev_t dev, int flags, int mode, struct proc *p)
506 {
507 int unit = minor(dev);
508
509 if (unit >= pnozz_cd.cd_ndevs || pnozz_cd.cd_devs[unit] == NULL)
510 return (ENXIO);
511 return (0);
512 }
513
514 int
515 p9100ioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
516 {
517 struct p9100_softc *sc = pnozz_cd.cd_devs[minor(dev)];
518 struct fbgattr *fba;
519 int error;
520
521 switch (cmd) {
522
523 case FBIOGTYPE:
524 *(struct fbtype *)data = sc->sc_fb.fb_type;
525 break;
526
527 case FBIOGATTR:
528 fba = (struct fbgattr *)data;
529 fba->real_type = sc->sc_fb.fb_type.fb_type;
530 fba->owner = 0; /* XXX ??? */
531 fba->fbtype = sc->sc_fb.fb_type;
532 fba->sattr.flags = 0;
533 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
534 fba->sattr.dev_specific[0] = -1;
535 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
536 fba->emu_types[1] = -1;
537 break;
538
539 case FBIOGETCMAP:
540 #define p ((struct fbcmap *)data)
541 return (bt_getcmap(p, &sc->sc_cmap, 256, 1));
542
543 case FBIOPUTCMAP:
544 /* copy to software map */
545 error = bt_putcmap(p, &sc->sc_cmap, 256, 1);
546 if (error)
547 return (error);
548 /* now blast them into the chip */
549 /* XXX should use retrace interrupt */
550 p9100loadcmap(sc, p->index, p->count);
551 #undef p
552 break;
553
554 case FBIOGVIDEO:
555 *(int *)data = p9100_get_video(sc);
556 break;
557
558 case FBIOSVIDEO:
559 p9100_set_video(sc, *(int *)data);
560 break;
561
562 default:
563 return (ENOTTY);
564 }
565 return (0);
566 }
567
568 static uint32_t
569 p9100_ctl_read_4(struct p9100_softc *sc, bus_size_t off)
570 {
571 sc->sc_junk = bus_space_read_4(sc->sc_bustag, sc->sc_fb_memh, off);
572 return bus_space_read_4(sc->sc_bustag, sc->sc_ctl_memh, off);
573 }
574
575 static void
576 p9100_ctl_write_4(struct p9100_softc *sc, bus_size_t off, uint32_t v)
577 {
578 sc->sc_junk = bus_space_read_4(sc->sc_bustag, sc->sc_fb_memh, off);
579 bus_space_write_4(sc->sc_bustag, sc->sc_ctl_memh, off, v);
580 }
581
582 /* wait until the engine is idle */
583 static void
584 p9100_sync(struct p9100_softc *sc)
585 {
586 while((p9100_ctl_read_4(sc, ENGINE_STATUS) &
587 (ENGINE_BUSY | BLITTER_BUSY)) != 0);
588 }
589
590 static void
591 p9100_set_color_reg(struct p9100_softc *sc, int reg, int32_t col)
592 {
593 uint32_t out;
594
595 switch(sc->sc_depth)
596 {
597 case 1: /* 8 bit */
598 out = (col << 8) | col;
599 out |= out << 16;
600 break;
601 case 2: /* 16 bit */
602 out = col | (col << 16);
603 break;
604 default:
605 out = col;
606 }
607 p9100_ctl_write_4(sc, reg, out);
608 }
609
610 /* initialize the drawing engine */
611 static void
612 p9100_init_engine(struct p9100_softc *sc)
613 {
614 /* reset clipping rectangles */
615 uint32_t max = ((sc->sc_width & 0x3fff) << 16) |
616 (sc->sc_height & 0x3fff);
617
618 p9100_ctl_write_4(sc, WINDOW_OFFSET, 0);
619 p9100_ctl_write_4(sc, WINDOW_MIN, 0);
620 p9100_ctl_write_4(sc, WINDOW_MAX, max);
621 p9100_ctl_write_4(sc, BYTE_CLIP_MIN, 0);
622 p9100_ctl_write_4(sc, BYTE_CLIP_MAX, max);
623 p9100_ctl_write_4(sc, DRAW_MODE, 0);
624 p9100_ctl_write_4(sc, PLANE_MASK, 0xffffffff);
625 p9100_ctl_write_4(sc, PATTERN0, 0xffffffff);
626 p9100_ctl_write_4(sc, PATTERN1, 0xffffffff);
627 p9100_ctl_write_4(sc, PATTERN2, 0xffffffff);
628 p9100_ctl_write_4(sc, PATTERN3, 0xffffffff);
629 }
630
631 /* screen-to-screen blit */
632 void
633 p9100_bitblt(struct p9100_softc *sc, int xs, int ys, int xd, int yd, int wi,
634 int he, uint32_t rop)
635 {
636 uint32_t src, dst, srcw, dstw, junk;
637
638 src = ((xs & 0x3fff) << 16) | (ys & 0x3fff);
639 dst = ((xd & 0x3fff) << 16) | (yd & 0x3fff);
640 srcw = (((xs + wi - 1) & 0x3fff) << 16) | ((ys + he - 1) & 0x3fff);
641 dstw = (((xd + wi - 1) & 0x3fff) << 16) | ((yd + he - 1) & 0x3fff);
642 p9100_sync(sc);
643 p9100_ctl_write_4(sc, RASTER_OP, rop);
644
645 p9100_ctl_write_4(sc, ABS_XY0, src);
646
647 p9100_ctl_write_4(sc, ABS_XY1, srcw);
648 p9100_ctl_write_4(sc, ABS_XY2, dst);
649 p9100_ctl_write_4(sc, ABS_XY3, dstw);
650 junk = p9100_ctl_read_4(sc, COMMAND_BLIT);
651 }
652
653 /* solid rectangle fill */
654 void
655 p9100_rectfill(struct p9100_softc *sc, int xs, int ys, int wi, int he, uint32_t col)
656 {
657 uint32_t src, srcw, junk;
658
659 src = ((xs & 0x3fff) << 16) | (ys & 0x3fff);
660 srcw = (((xs + wi) & 0x3fff) << 16) | ((ys + he) & 0x3fff);
661 p9100_sync(sc);
662 p9100_set_color_reg(sc, FOREGROUND_COLOR, col);
663 p9100_set_color_reg(sc, BACKGROUND_COLOR, col);
664 p9100_ctl_write_4(sc, RASTER_OP, ROP_PAT);
665 p9100_ctl_write_4(sc, COORD_INDEX, 0);
666 p9100_ctl_write_4(sc, RECT_RTW_XY, src);
667 p9100_ctl_write_4(sc, RECT_RTW_XY, srcw);
668 junk=p9100_ctl_read_4(sc, COMMAND_QUAD);
669 }
670
671 /* setup for mono->colour expansion */
672 void
673 p9100_setup_mono(struct p9100_softc *sc, int x, int y, int wi, int he,
674 uint32_t fg, uint32_t bg)
675 {
676 p9100_sync(sc);
677 /*
678 * this doesn't make any sense to me either, but for some reason the
679 * chip applies the foreground colour to 0 pixels
680 */
681
682 p9100_set_color_reg(sc,FOREGROUND_COLOR,bg);
683 p9100_set_color_reg(sc,BACKGROUND_COLOR,fg);
684
685 p9100_ctl_write_4(sc, RASTER_OP, ROP_SRC);
686 p9100_ctl_write_4(sc, ABS_X0, x);
687 p9100_ctl_write_4(sc, ABS_XY1, (x << 16) | (y & 0xFFFFL));
688 p9100_ctl_write_4(sc, ABS_X2, (x + wi));
689 p9100_ctl_write_4(sc, ABS_Y3, he);
690 /* now feed the data into the chip */
691 sc->sc_mono_width = wi;
692 }
693
694 /* write monochrome data to the screen through the blitter */
695 void
696 p9100_feed_line(struct p9100_softc *sc, int count, uint8_t *data)
697 {
698 int i;
699 uint32_t latch = 0, bork;
700 int shift = 24;
701 int to_go = sc->sc_mono_width;
702
703 for (i = 0; i < count; i++) {
704 bork = data[i];
705 latch |= (bork << shift);
706 if (shift == 0) {
707 /* check how many bits are significant */
708 if (to_go > 31) {
709 p9100_ctl_write_4(sc, (PIXEL_1 +
710 (31 << 2)), latch);
711 to_go -= 32;
712 } else
713 {
714 p9100_ctl_write_4(sc, (PIXEL_1 +
715 ((to_go - 1) << 2)), latch);
716 to_go = 0;
717 }
718 latch = 0;
719 shift = 24;
720 } else
721 shift -= 8;
722 }
723 if (shift != 24)
724 p9100_ctl_write_4(sc, (PIXEL_1 + ((to_go - 1) << 2)), latch);
725 }
726
727 void
728 p9100_clearscreen(struct p9100_softc *sc)
729 {
730 p9100_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, sc->sc_bg);
731 }
732
733 uint8_t
734 p9100_ramdac_read(struct p9100_softc *sc, bus_size_t off)
735 {
736 sc->sc_junk = p9100_ctl_read_4(sc, PWRUP_CNFG);
737 sc->sc_junk = bus_space_read_4(sc->sc_bustag, sc->sc_fb_memh, off);
738 return ((bus_space_read_4(sc->sc_bustag,
739 sc->sc_ctl_memh, off) >> 16) & 0xff);
740 }
741
742 void
743 p9100_ramdac_write(struct p9100_softc *sc, bus_size_t off, uint8_t v)
744 {
745 sc->sc_junk = p9100_ctl_read_4(sc, PWRUP_CNFG);
746 sc->sc_junk = bus_space_read_4(sc->sc_bustag, sc->sc_fb_memh, off);
747 bus_space_write_4(sc->sc_bustag, sc->sc_ctl_memh, off,
748 ((uint32_t)v) << 16);
749 }
750
751 /*
752 * Undo the effect of an FBIOSVIDEO that turns the video off.
753 */
754 static void
755 p9100unblank(struct device *dev)
756 {
757 p9100_set_video((struct p9100_softc *)dev, 1);
758 }
759
760 static void
761 p9100_set_video(struct p9100_softc *sc, int enable)
762 {
763 u_int32_t v = p9100_ctl_read_4(sc, SCRN_RPNT_CTL_1);
764
765 if (enable)
766 v |= VIDEO_ENABLED;
767 else
768 v &= ~VIDEO_ENABLED;
769 p9100_ctl_write_4(sc, SCRN_RPNT_CTL_1, v);
770 #if NTCTRL > 0
771 /* Turn On/Off the TFT if we know how.
772 */
773 tadpole_set_video(enable);
774 #endif
775 }
776
777 static int
778 p9100_get_video(struct p9100_softc *sc)
779 {
780 return (p9100_ctl_read_4(sc, SCRN_RPNT_CTL_1) & VIDEO_ENABLED) != 0;
781 }
782
783 /*
784 * Load a subset of the current (new) colormap into the IBM RAMDAC.
785 */
786 static void
787 p9100loadcmap(struct p9100_softc *sc, int start, int ncolors)
788 {
789 int i;
790 p9100_ramdac_write(sc, DAC_CMAP_WRIDX, start);
791
792 for (i=0;i<ncolors;i++) {
793 p9100_ramdac_write(sc, DAC_CMAP_DATA,
794 sc->sc_cmap.cm_map[i + start][0]);
795 p9100_ramdac_write(sc, DAC_CMAP_DATA,
796 sc->sc_cmap.cm_map[i + start][1]);
797 p9100_ramdac_write(sc, DAC_CMAP_DATA,
798 sc->sc_cmap.cm_map[i + start][2]);
799 }
800 }
801
802 /*
803 * Return the address that would map the given device at the given
804 * offset, allowing for the given protection, or return -1 for error.
805 */
806 paddr_t
807 p9100mmap(dev_t dev, off_t off, int prot)
808 {
809 struct p9100_softc *sc = pnozz_cd.cd_devs[minor(dev)];
810
811 if (off & PGOFSET)
812 panic("p9100mmap");
813 if (off < 0)
814 return (-1);
815
816 #ifdef PNOZZ_EMUL_CG3
817 #define CG3_MMAP_OFFSET 0x04000000
818 /* Make Xsun think we are a CG3 (SUN3COLOR)
819 */
820 if (off >= CG3_MMAP_OFFSET && off < CG3_MMAP_OFFSET + sc->sc_fb_psize) {
821 off -= CG3_MMAP_OFFSET;
822 return (bus_space_mmap(sc->sc_bustag,
823 sc->sc_fb_paddr,
824 off,
825 prot,
826 BUS_SPACE_MAP_LINEAR));
827 }
828 #endif
829
830 if (off >= sc->sc_fb_psize + sc->sc_ctl_psize + sc->sc_cmd_psize)
831 return (-1);
832
833 if (off < sc->sc_fb_psize) {
834 return (bus_space_mmap(sc->sc_bustag,
835 sc->sc_fb_paddr,
836 off,
837 prot,
838 BUS_SPACE_MAP_LINEAR));
839 }
840 off -= sc->sc_fb_psize;
841 if (off < sc->sc_ctl_psize) {
842 return (bus_space_mmap(sc->sc_bustag,
843 sc->sc_ctl_paddr,
844 off,
845 prot,
846 BUS_SPACE_MAP_LINEAR));
847 }
848 off -= sc->sc_ctl_psize;
849
850 return (bus_space_mmap(sc->sc_bustag,
851 sc->sc_cmd_paddr,
852 off,
853 prot,
854 BUS_SPACE_MAP_LINEAR));
855 }
856
857 /* wscons stuff */
858
859 void
860 p9100_switch_screen(struct p9100_softc *sc)
861 {
862 struct p9100_screen *scr, *oldscr;
863
864 scr = sc->wanted;
865 if (!scr) {
866 printf("p9100_switch_screen: disappeared\n");
867 (*sc->switchcb)(sc->switchcbarg, EIO, 0);
868 return;
869 }
870 oldscr = sc->active; /* can be NULL! */
871 #ifdef DIAGNOSTIC
872 if (oldscr) {
873 if (!oldscr->active)
874 panic("p9100_switch_screen: not active");
875 }
876 #endif
877 if (scr == oldscr)
878 return;
879
880 #ifdef DIAGNOSTIC
881 if (scr->active)
882 panic("p9100_switch_screen: active");
883 #endif
884
885 if (oldscr)
886 oldscr->active = 0;
887 #ifdef notyet
888 if (sc->currenttype != type) {
889 p9100_set_screentype(sc, type);
890 sc->currenttype = type;
891 }
892 #endif
893
894 /* Clear the entire screen. */
895
896 scr->active = 1;
897 p9100_restore_screen(scr, &p9100_defscreendesc, scr->chars);
898
899 sc->active = scr;
900
901 scr->ri.ri_ops.cursor(scr, scr->cursoron, scr->cursorrow,
902 scr->cursorcol);
903
904 sc->wanted = 0;
905 if (sc->switchcb)
906 (*sc->switchcb)(sc->switchcbarg, 0, 0);
907 }
908
909 void
910 p9100_restore_screen(struct p9100_screen *scr,
911 const struct wsscreen_descr *type, u_int16_t *mem)
912 {
913 int i, j, offset = 0;
914 uint16_t *charptr = scr->chars;
915 long *attrptr = scr->attrs;
916
917 p9100_clearscreen(scr->sc);
918 for (i = 0; i < scr->ri.ri_rows; i++) {
919 for (j = 0; j < scr->ri.ri_cols; j++) {
920 p9100_putchar(scr, i, j, charptr[offset],
921 attrptr[offset]);
922 offset++;
923 }
924 }
925 scr->cursordrawn = 0;
926 }
927
928 void
929 p9100_cursor(void *cookie, int on, int row, int col)
930 {
931 struct rasops_info *ri = cookie;
932 struct p9100_screen *scr = ri->ri_hw;
933 struct p9100_softc *sc = scr->sc;
934 int x, y, wi,he;
935
936 wi = ri->ri_font->fontwidth;
937 he = ri->ri_font->fontheight;
938
939 if ((scr->active) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
940 x = scr->cursorcol * wi + ri->ri_xorigin;
941 y = scr->cursorrow * he + ri->ri_yorigin;
942 if (scr->cursordrawn) {
943 p9100_bitblt(sc, x, y, x, y, wi, he, (ROP_SRC ^ 0xff));
944 scr->cursordrawn = 0;
945 }
946 scr->cursorrow = row;
947 scr->cursorcol = col;
948 if ((scr->cursoron = on) != 0)
949 {
950 x = scr->cursorcol * wi + ri->ri_xorigin;
951 y = scr->cursorrow * he + ri->ri_yorigin;
952 p9100_bitblt(sc, x, y, x, y, wi, he, (ROP_SRC ^ 0xff));
953 scr->cursordrawn = 1;
954 }
955 } else {
956 scr->cursoron = on;
957 scr->cursorrow = row;
958 scr->cursorcol = col;
959 scr->cursordrawn = 0;
960 }
961 }
962
963 #if 0
964 int
965 p9100_mapchar(void *cookie, int uni, u_int *index)
966 {
967 return 0;
968 }
969 #endif
970
971 void
972 p9100_putchar(void *cookie, int row, int col, u_int c, long attr)
973 {
974 struct rasops_info *ri = cookie;
975 struct p9100_screen *scr = ri->ri_hw;
976 struct p9100_softc *sc = scr->sc;
977 int pos;
978
979 if ((row >= 0) && (row < ri->ri_rows) && (col >= 0) &&
980 (col < ri->ri_cols)) {
981 pos = col + row * ri->ri_cols;
982 scr->attrs[pos] = attr;
983 scr->chars[pos] = c;
984
985 #ifdef PNOZZ_SOFT_PUTCHAR
986 if ((sc->putchar != NULL) && ( scr->active) &&
987 (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
988 p9100_sync(sc);
989 sc->putchar(cookie, row, col, c, attr);
990 }
991 #else
992 if ((scr->active) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
993 int fg, bg, uc, i;
994 uint8_t *data;
995 int x, y, wi,he;
996
997 wi = ri->ri_font->fontwidth;
998 he = ri->ri_font->fontheight;
999
1000 if (!CHAR_IN_FONT(c, ri->ri_font))
1001 return;
1002 bg = (u_char)ri->ri_devcmap[(attr >> 16) & 0xff];
1003 fg = (u_char)ri->ri_devcmap[(attr >> 24) & 0xff];
1004 x = ri->ri_xorigin + col * wi;
1005 y = ri->ri_yorigin + row * he;
1006 if (c == 0x20) {
1007 p9100_rectfill(sc, x, y, wi, he, bg);
1008 } else {
1009 uc = c-ri->ri_font->firstchar;
1010 data = (uint8_t *)ri->ri_font->data + uc *
1011 ri->ri_fontscale;
1012
1013 p9100_setup_mono(sc, x, y, wi, 1, fg, bg);
1014 for (i = 0; i < he; i++) {
1015 p9100_feed_line(sc, ri->ri_font->stride,
1016 data);
1017 data += ri->ri_font->stride;
1018 }
1019 /*p9100_sync(sc);*/
1020 }
1021 }
1022 #endif
1023 }
1024 }
1025
1026 void
1027 p9100_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
1028 {
1029 struct rasops_info *ri = cookie;
1030 struct p9100_screen *scr = ri->ri_hw;
1031 struct p9100_softc *sc = scr->sc;
1032 int32_t xs, xd, y, width, height;
1033 int from = srccol + row * ri->ri_cols;
1034 int to = dstcol + row * ri->ri_cols;
1035
1036 memmove(&scr->attrs[to], &scr->attrs[from], ncols * sizeof(long));
1037 memmove(&scr->chars[to], &scr->chars[from], ncols * sizeof(uint16_t));
1038
1039 if ((scr->active) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1040 xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
1041 xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
1042 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1043 width = ri->ri_font->fontwidth * ncols;
1044 height = ri->ri_font->fontheight;
1045 p9100_bitblt(sc, xs, y, xd, y, width, height, ROP_SRC);
1046 }
1047 }
1048
1049 void
1050 p9100_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
1051 {
1052 struct rasops_info *ri = cookie;
1053 struct p9100_screen *scr = ri->ri_hw;
1054 struct p9100_softc *sc = scr->sc;
1055 int32_t x, y, width, height, bg;
1056 int start = startcol + row * ri->ri_cols;
1057 int end = start + ncols, i;
1058
1059 for (i = start; i < end; i++) {
1060 scr->attrs[i] = fillattr;
1061 scr->chars[i] = 0x20;
1062 }
1063 if ((scr->active) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1064 x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
1065 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1066 width = ri->ri_font->fontwidth * ncols;
1067 height = ri->ri_font->fontheight;
1068 bg = (fillattr >> 16) & 0xff;
1069 p9100_rectfill(sc, x, y, width, height, bg);
1070 }
1071 }
1072
1073 void
1074 p9100_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
1075 {
1076 struct rasops_info *ri = cookie;
1077 struct p9100_screen *scr = ri->ri_hw;
1078 struct p9100_softc *sc = scr->sc;
1079 int32_t x, ys, yd, width, height;
1080 int from, to, len;
1081
1082 from = ri->ri_cols * srcrow;
1083 to = ri->ri_cols * dstrow;
1084 len = ri->ri_cols * nrows;
1085
1086 memmove(&scr->attrs[to], &scr->attrs[from], len * sizeof(long));
1087 memmove(&scr->chars[to], &scr->chars[from], len * sizeof(uint16_t));
1088
1089 if ((scr->active) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1090 x = ri->ri_xorigin;
1091 ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
1092 yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
1093 width = ri->ri_emuwidth;
1094 height = ri->ri_font->fontheight * nrows;
1095 p9100_bitblt(sc, x, ys, x, yd, width, height, ROP_SRC);
1096 }
1097 }
1098
1099 void
1100 p9100_eraserows(void *cookie, int row, int nrows, long fillattr)
1101 {
1102 struct rasops_info *ri = cookie;
1103 struct p9100_screen *scr = ri->ri_hw;
1104 struct p9100_softc *sc = scr->sc;
1105 int32_t x,y,width,height,bg;
1106 int start, end, i;
1107
1108 start = ri->ri_cols * row;
1109 end = ri->ri_cols * (row + nrows);
1110
1111 for (i = start; i < end; i++) {
1112 scr->attrs[i] = fillattr;
1113 scr->chars[i] = 0x20;
1114 }
1115
1116 if ((scr->active) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1117 x = ri->ri_xorigin;
1118 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1119 width = ri->ri_emuwidth;
1120 height = ri->ri_font->fontheight * nrows;
1121 bg = (fillattr >> 16) & 0xff;
1122 p9100_rectfill(sc, x, y, width, height, bg);
1123 }
1124 }
1125
1126 int
1127 p9100_allocattr(void *cookie, int fg, int bg, int flags, long *attrp)
1128 {
1129 if ((fg == 0) && (bg == 0))
1130 {
1131 fg = WS_DEFAULT_FG;
1132 bg = WS_DEFAULT_BG;
1133 }
1134 if (flags & WSATTR_REVERSE) {
1135 *attrp = (bg & 0xff) << 24 | (fg & 0xff) << 16 |
1136 (flags & 0xff) << 8;
1137 } else
1138 *attrp = (fg & 0xff) << 24 | (bg & 0xff) << 16 |
1139 (flags & 0xff) << 8;
1140 return 0;
1141 }
1142
1143 /*
1144 * wsdisplay_accessops
1145 */
1146
1147 int
1148 p9100_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
1149 {
1150 struct p9100_softc *sc = v;
1151 struct wsdisplay_fbinfo *wdf;
1152 struct p9100_screen *ms = sc->active;
1153
1154 switch (cmd) {
1155 case WSDISPLAYIO_GTYPE:
1156 *(u_int *)data = WSDISPLAY_TYPE_SB_P9100;
1157 return 0;
1158
1159 case FBIOGVIDEO:
1160 case WSDISPLAYIO_GVIDEO:
1161 *(int *)data = p9100_get_video(sc);
1162 return 0;
1163
1164 case WSDISPLAYIO_SVIDEO:
1165 case FBIOSVIDEO:
1166 p9100_set_video(sc, *(int *)data);
1167 return 0;
1168
1169 case WSDISPLAYIO_GINFO:
1170 wdf = (void *)data;
1171 wdf->height = ms->ri.ri_height;
1172 wdf->width = ms->ri.ri_width;
1173 wdf->depth = ms->ri.ri_depth;
1174 wdf->cmsize = 256;
1175 return 0;
1176
1177 case WSDISPLAYIO_GETCMAP:
1178 return p9100_getcmap(sc, (struct wsdisplay_cmap *)data);
1179
1180 case WSDISPLAYIO_PUTCMAP:
1181 return p9100_putcmap(sc, (struct wsdisplay_cmap *)data);
1182
1183 case WSDISPLAYIO_SMODE:
1184 {
1185 int new_mode = *(int*)data;
1186 if (new_mode != sc->sc_mode)
1187 {
1188 sc->sc_mode = new_mode;
1189 if (new_mode == WSDISPLAYIO_MODE_EMUL)
1190 {
1191 p9100_init_engine(sc);
1192 p9100loadcmap(sc,0,256);
1193 p9100_restore_screen(ms,
1194 ms->type, ms->chars);
1195 p9100_cursor(ms, ms->cursoron,
1196 ms->cursorrow,
1197 ms->cursorcol);
1198 }
1199 }
1200 }
1201 }
1202 return EPASSTHROUGH;
1203 }
1204
1205 paddr_t
1206 p9100_mmap(void *v, off_t offset, int prot)
1207 {
1208 struct p9100_softc *sc = v;
1209 paddr_t pa;
1210
1211 /* 'regular' framebuffer mmap()ing */
1212 if (offset < sc->sc_fb_psize) {
1213 pa = bus_space_mmap(sc->sc_bustag, sc->sc_fb_paddr + offset, 0,
1214 prot, BUS_SPACE_MAP_LINEAR);
1215 return pa;
1216 }
1217
1218 if ((offset >= sc->sc_fb_paddr) && (offset < (sc->sc_fb_paddr +
1219 sc->sc_fb_psize))) {
1220 pa = bus_space_mmap(sc->sc_bustag, offset, 0, prot,
1221 BUS_SPACE_MAP_LINEAR);
1222 return pa;
1223 }
1224
1225 if ((offset >= sc->sc_ctl_paddr) && (offset < (sc->sc_ctl_paddr +
1226 sc->sc_ctl_psize))) {
1227 pa = bus_space_mmap(sc->sc_bustag, offset, 0, prot,
1228 BUS_SPACE_MAP_LINEAR);
1229 return pa;
1230 }
1231
1232 return -1;
1233 }
1234
1235 void
1236 p9100_init_screen(struct p9100_softc *sc, struct p9100_screen *scr,
1237 int existing, long *defattr)
1238 {
1239 struct rasops_info *ri = &scr->ri;
1240 int cnt;
1241
1242 scr->sc = sc;
1243 /*scr->type = type;*/
1244 scr->dispoffset = 0;
1245 scr->cursorcol = 0;
1246 scr->cursorrow = 0;
1247 scr->cursordrawn=0;
1248
1249 ri->ri_depth = sc->sc_depth << 3;
1250 ri->ri_width = sc->sc_width;
1251 ri->ri_height = sc->sc_height;
1252 ri->ri_stride = sc->sc_stride;
1253 ri->ri_flg = RI_CENTER;
1254
1255 ri->ri_bits = bus_space_vaddr(sc->sc_bustag, sc->sc_fb_memh);
1256
1257 #ifdef DEBUG_P9100
1258 printf("addr: %08lx\n",(ulong)ri->ri_bits);
1259 #endif
1260 rasops_init(ri, sc->sc_height/8, sc->sc_width/8);
1261 ri->ri_caps = WSSCREEN_WSCOLORS;
1262 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
1263 sc->sc_width / ri->ri_font->fontwidth);
1264
1265 p9100_allocattr(ri, WS_DEFAULT_FG, WS_DEFAULT_BG, 0, defattr);
1266
1267 /*
1268 * we allocate both chars and attributes in one chunk, attributes first
1269 * because they have the (potentially) bigger alignment
1270 */
1271 cnt=ri->ri_rows * ri->ri_cols;
1272 scr->attrs = (long *)malloc(cnt * (sizeof(long) + sizeof(uint16_t)),
1273 M_DEVBUF, M_WAITOK);
1274 scr->chars = (uint16_t *)&scr->attrs[cnt];
1275
1276 /* enable acceleration */
1277 ri->ri_hw = scr;
1278 ri->ri_ops.copyrows = p9100_copyrows;
1279 ri->ri_ops.copycols = p9100_copycols;
1280 ri->ri_ops.eraserows = p9100_eraserows;
1281 ri->ri_ops.erasecols = p9100_erasecols;
1282 ri->ri_ops.cursor = p9100_cursor;
1283 ri->ri_ops.allocattr = p9100_allocattr;
1284 #ifdef PNOZZ_SOFT_PUTCHAR
1285 if (sc->putchar == NULL)
1286 sc->putchar=ri->ri_ops.putchar;
1287 #endif
1288 ri->ri_ops.putchar = p9100_putchar;
1289
1290 if (existing) {
1291 scr->active = 1;
1292 } else {
1293 scr->active = 0;
1294 }
1295
1296 p9100_eraserows(&scr->ri, 0, ri->ri_rows, *defattr);
1297
1298 LIST_INSERT_HEAD(&sc->screens, scr, next);
1299 }
1300
1301 int
1302 p9100_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
1303 int *curxp, int *curyp, long *defattrp)
1304 {
1305 struct p9100_softc *sc = v;
1306 struct p9100_screen *scr;
1307
1308 scr = malloc(sizeof(struct p9100_screen), M_DEVBUF, M_WAITOK | M_ZERO);
1309 p9100_init_screen(sc, scr, 0, defattrp);
1310
1311 if (sc->active == NULL) {
1312 scr->active = 1;
1313 sc->active = scr;
1314 sc->currenttype = type;
1315 }
1316
1317 *cookiep = scr;
1318 *curxp = scr->cursorcol;
1319 *curyp = scr->cursorrow;
1320 return 0;
1321 }
1322
1323 void
1324 p9100_free_screen(void *v, void *cookie)
1325 {
1326 struct p9100_softc *sc = v;
1327 struct p9100_screen *scr = cookie;
1328
1329 LIST_REMOVE(scr, next);
1330 if (scr != &p9100_console_screen) {
1331 free(scr->attrs, M_DEVBUF);
1332 free(scr, M_DEVBUF);
1333 } else
1334 panic("p9100_free_screen: console");
1335
1336 if (sc->active == scr)
1337 sc->active = 0;
1338 }
1339
1340 int
1341 p9100_show_screen(void *v, void *cookie, int waitok,
1342 void (*cb)(void *, int, int), void *cbarg)
1343 {
1344 struct p9100_softc *sc = v;
1345 struct p9100_screen *scr, *oldscr;
1346
1347 scr = cookie;
1348 oldscr = sc->active;
1349 if (scr == oldscr)
1350 return 0;
1351
1352 sc->wanted = scr;
1353 sc->switchcb = cb;
1354 sc->switchcbarg = cbarg;
1355 if (cb) {
1356 callout_reset(&sc->switch_callout, 0,
1357 (void(*)(void *))p9100_switch_screen, sc);
1358 return EAGAIN;
1359 }
1360
1361 p9100_switch_screen(sc);
1362 return 0;
1363 }
1364
1365 int
1366 p9100_putcmap(struct p9100_softc *sc, struct wsdisplay_cmap *cm)
1367 {
1368 u_int index = cm->index;
1369 u_int count = cm->count;
1370 int i, error;
1371 u_char rbuf[256], gbuf[256], bbuf[256];
1372 u_char *r, *g, *b;
1373
1374 printf("putcmap: %d %d\n",index, count);
1375 if (cm->index >= 256 || cm->count > 256 ||
1376 (cm->index + cm->count) > 256)
1377 return EINVAL;
1378 error = copyin(cm->red, &rbuf[index], count);
1379 if (error)
1380 return error;
1381 error = copyin(cm->green, &gbuf[index], count);
1382 if (error)
1383 return error;
1384 error = copyin(cm->blue, &bbuf[index], count);
1385 if (error)
1386 return error;
1387
1388 r = &rbuf[index];
1389 g = &gbuf[index];
1390 b = &bbuf[index];
1391
1392 for (i = 0; i < count; i++) {
1393 sc->sc_cmap.cm_map[index][0] = *r;
1394 sc->sc_cmap.cm_map[index][1] = *g;
1395 sc->sc_cmap.cm_map[index][2] = *b;
1396 index++;
1397 r++, g++, b++;
1398 }
1399 p9100loadcmap(sc, 0, 256);
1400 return 0;
1401 }
1402
1403 int
1404 p9100_getcmap(struct p9100_softc *sc, struct wsdisplay_cmap *cm)
1405 {
1406 u_int index = cm->index;
1407 u_int count = cm->count;
1408 int error, i;
1409 uint8_t red[256],green[256],blue[256];
1410
1411 if (index >= 255 || count > 256 || index + count > 256)
1412 return EINVAL;
1413
1414 i = index;
1415 while (i < (index + count)) {
1416 red[i] = sc->sc_cmap.cm_map[i][0];
1417 green[i] = sc->sc_cmap.cm_map[i][1];
1418 blue[i] = sc->sc_cmap.cm_map[i][2];
1419 i++;
1420 }
1421 error = copyout(&red[index], cm->red, count);
1422 if (error)
1423 return error;
1424 error = copyout(&green[index], cm->green, count);
1425 if (error)
1426 return error;
1427 error = copyout(&blue[index], cm->blue, count);
1428 if (error)
1429 return error;
1430
1431 return 0;
1432 }
1433
1434 #if 0
1435 int
1436 p9100_load_font(void *v, void *cookie, struct wsdisplay_font *data)
1437 {
1438
1439 return 0;
1440 }
1441 #endif
1442
1443 int
1444 p9100_intr(void *arg)
1445 {
1446 /*p9100_softc *sc=arg;
1447 printf(".");*/
1448 return 1;
1449 }
1450