topcat.c revision 1.14 1 /* $NetBSD: topcat.c,v 1.14 2025/02/26 04:49:46 andvar Exp $ */
2 /* $OpenBSD: topcat.c,v 1.15 2006/08/11 18:33:13 miod Exp $ */
3
4 /*
5 * Copyright (c) 2005, Miodrag Vallat.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30 /*-
31 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
32 * All rights reserved.
33 *
34 * This code is derived from software contributed to The NetBSD Foundation
35 * by Jason R. Thorpe.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
47 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
48 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
50 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
56 * POSSIBILITY OF SUCH DAMAGE.
57 */
58
59 /*
60 * Copyright (c) 1988 University of Utah.
61 * Copyright (c) 1990, 1993
62 * The Regents of the University of California. All rights reserved.
63 *
64 * This code is derived from software contributed to Berkeley by
65 * the Systems Programming Group of the University of Utah Computer
66 * Science Department.
67 *
68 * Redistribution and use in source and binary forms, with or without
69 * modification, are permitted provided that the following conditions
70 * are met:
71 * 1. Redistributions of source code must retain the above copyright
72 * notice, this list of conditions and the following disclaimer.
73 * 2. Redistributions in binary form must reproduce the above copyright
74 * notice, this list of conditions and the following disclaimer in the
75 * documentation and/or other materials provided with the distribution.
76 * 3. Neither the name of the University nor the names of its contributors
77 * may be used to endorse or promote products derived from this software
78 * without specific prior written permission.
79 *
80 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
81 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
82 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
83 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
84 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
85 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
86 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
87 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
88 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
89 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
90 * SUCH DAMAGE.
91 *
92 * from: Utah $Hdr: grf_tc.c 1.20 93/08/13$
93 *
94 * @(#)grf_tc.c 8.4 (Berkeley) 1/12/94
95 */
96
97 /*
98 * Graphics routines for TOPCAT, CATSEYE and KATHMANDU frame buffers
99 */
100
101 #include <sys/param.h>
102 #include <sys/systm.h>
103 #include <sys/conf.h>
104 #include <sys/device.h>
105 #include <sys/proc.h>
106 #include <sys/ioctl.h>
107 #include <sys/bus.h>
108 #include <sys/cpu.h>
109
110 #include <machine/autoconf.h>
111
112 #include <hp300/dev/dioreg.h>
113 #include <hp300/dev/diovar.h>
114 #include <hp300/dev/diodevs.h>
115 #include <hp300/dev/intiovar.h>
116
117 #include <dev/wscons/wsconsio.h>
118 #include <dev/wscons/wsdisplayvar.h>
119 #include <dev/rasops/rasops.h>
120
121 #include <hp300/dev/diofbreg.h>
122 #include <hp300/dev/diofbvar.h>
123 #include <hp300/dev/topcatreg.h>
124
125 struct topcat_softc {
126 device_t sc_dev;
127 struct diofb *sc_fb;
128 struct diofb sc_fb_store;
129 int sc_scode;
130 };
131
132 static int topcat_dio_match(device_t, cfdata_t, void *);
133 static void topcat_dio_attach(device_t, device_t, void *);
134 static int topcat_intio_match(device_t, cfdata_t, void *);
135 static void topcat_intio_attach(device_t, device_t, void *);
136
137 CFATTACH_DECL_NEW(topcat_dio, sizeof(struct topcat_softc),
138 topcat_dio_match, topcat_dio_attach, NULL, NULL);
139
140 CFATTACH_DECL_NEW(topcat_intio, sizeof(struct topcat_softc),
141 topcat_intio_match, topcat_intio_attach, NULL, NULL);
142
143 static void topcat_end_attach(struct topcat_softc *, uint8_t);
144 static int topcat_reset(struct diofb *, int, struct diofbreg *);
145 static void topcat_restore(struct diofb *);
146 static int topcat_setcmap(struct diofb *, struct wsdisplay_cmap *);
147 static void topcat_setcolor(struct diofb *, u_int);
148 static int topcat_windowmove(struct diofb *, uint16_t, uint16_t, uint16_t,
149 uint16_t, uint16_t, uint16_t, int16_t, int16_t);
150
151 static int topcat_ioctl(void *, void *, u_long, void *, int, struct lwp *);
152 static void topcat_putchar8(void *, int, int, u_int, long);
153 static void topcat_putchar1_4(void *, int, int, u_int, long);
154
155 static struct wsdisplay_accessops topcat_accessops = {
156 topcat_ioctl,
157 diofb_mmap,
158 diofb_alloc_screen,
159 diofb_free_screen,
160 diofb_show_screen,
161 NULL, /* load_font */
162 };
163
164 /*
165 * Attachment glue
166 */
167
168 int
169 topcat_intio_match(device_t parent, cfdata_t cf, void *aux)
170 {
171 struct intio_attach_args *ia = aux;
172 struct diofbreg *fbr;
173
174 if (strcmp("fb", ia->ia_modname) != 0)
175 return 0;
176
177 fbr = (struct diofbreg *)ia->ia_addr;
178
179 if (badaddr((void *)fbr))
180 return 0;
181
182 if (fbr->id == GRFHWID) {
183 switch (fbr->fbid) {
184 case GID_TOPCAT:
185 case GID_LRCATSEYE:
186 case GID_HRCCATSEYE:
187 case GID_HRMCATSEYE:
188 #if 0
189 case GID_XXXCATSEYE:
190 #endif
191 return 1;
192 }
193 }
194
195 return 0;
196 }
197
198 void
199 topcat_intio_attach(device_t parent, device_t self, void *aux)
200 {
201 struct topcat_softc *sc = device_private(self);
202 struct intio_attach_args *ia = aux;
203 struct diofbreg *fbr;
204
205 sc->sc_dev = self;
206 fbr = (struct diofbreg *)ia->ia_addr;
207 sc->sc_scode = CONSCODE_INTERNAL;
208
209 if (sc->sc_scode == conscode) {
210 sc->sc_fb = &diofb_cn;
211 } else {
212 sc->sc_fb = &sc->sc_fb_store;
213 topcat_reset(sc->sc_fb, sc->sc_scode, fbr);
214 }
215
216 topcat_end_attach(sc, fbr->fbid);
217 }
218
219 int
220 topcat_dio_match(device_t parent, cfdata_t cf, void *aux)
221 {
222 struct dio_attach_args *da = aux;
223
224 if (da->da_id == DIO_DEVICE_ID_FRAMEBUFFER) {
225 switch (da->da_secid) {
226 case DIO_DEVICE_SECID_TOPCAT:
227 case DIO_DEVICE_SECID_LRCATSEYE:
228 case DIO_DEVICE_SECID_HRCCATSEYE:
229 case DIO_DEVICE_SECID_HRMCATSEYE:
230 #if 0
231 case DIO_DEVICE_SECID_XXXCATSEYE:
232 #endif
233 return 1;
234 }
235 }
236
237 return 0;
238 }
239
240 void
241 topcat_dio_attach(device_t parent, device_t self, void *aux)
242 {
243 struct topcat_softc *sc = device_private(self);
244 struct dio_attach_args *da = aux;
245 bus_space_handle_t bsh;
246 struct diofbreg *fbr;
247
248 sc->sc_dev = self;
249 sc->sc_scode = da->da_scode;
250 if (sc->sc_scode == conscode) {
251 fbr = (struct diofbreg *)conaddr; /* already mapped */
252 sc->sc_fb = &diofb_cn;
253 } else {
254 sc->sc_fb = &sc->sc_fb_store;
255 if (bus_space_map(da->da_bst, da->da_addr, da->da_size, 0,
256 &bsh)) {
257 aprint_error(": can't map framebuffer\n");
258 return;
259 }
260 fbr = bus_space_vaddr(da->da_bst, bsh);
261 if (topcat_reset(sc->sc_fb, sc->sc_scode, fbr) != 0) {
262 aprint_error(": can't reset framebuffer\n");
263 return;
264 }
265 }
266
267 topcat_end_attach(sc, fbr->fbid);
268 }
269
270 void
271 topcat_end_attach(struct topcat_softc *sc, uint8_t id)
272 {
273 const char *fbname = "unknown";
274
275 switch (id) {
276 case GID_TOPCAT:
277 switch (sc->sc_fb->planes) {
278 case 1:
279 if (sc->sc_fb->dheight == 400)
280 fbname = "HP98542 topcat";
281 else
282 fbname = "HP98544 topcat";
283 break;
284 case 4:
285 if (sc->sc_fb->dheight == 400)
286 fbname = "HP98543 topcat";
287 else
288 fbname = "HP98545 topcat";
289 break;
290 case 6:
291 fbname = "HP98547 topcat";
292 break;
293 }
294 break;
295 case GID_HRCCATSEYE:
296 fbname = "HP98550 catseye"; /* also A1416 kathmandu */
297 break;
298 case GID_LRCATSEYE:
299 fbname = "HP98549 catseye";
300 break;
301 case GID_HRMCATSEYE:
302 fbname = "HP98548 catseye";
303 break;
304 }
305
306 diofb_end_attach(sc->sc_dev, &topcat_accessops, sc->sc_fb,
307 sc->sc_scode == conscode, fbname);
308 }
309
310 /*
311 * Initialize hardware and display routines.
312 */
313 int
314 topcat_reset(struct diofb *fb, int scode, struct diofbreg *fbr)
315 {
316 volatile struct tcboxfb *tc = (struct tcboxfb *)fbr;
317 struct rasops_info *ri = &fb->ri;
318 int rc;
319 u_int i;
320 bool sparse = false;
321
322 if ((rc = diofb_fbinquire(fb, scode, fbr)) != 0)
323 return rc;
324
325 /*
326 * If we could not get a valid number of planes, determine it
327 * by writing to the first frame buffer display location,
328 * then reading it back.
329 */
330 if (fb->planes == 0) {
331 volatile uint8_t *fbp;
332 uint8_t save;
333
334 fbp = (uint8_t *)fb->fbkva;
335 tc->fben = ~0;
336 tc->wen = ~0;
337 tc->ren = ~0;
338 tc->prr = RR_COPY;
339 save = *fbp;
340 *fbp = 0xff;
341 fb->planemask = *fbp;
342 *fbp = save;
343
344 for (fb->planes = 1; fb->planemask >= (1 << fb->planes);
345 fb->planes++);
346 if (fb->planes > 8)
347 fb->planes = 8;
348 fb->planemask = (1 << fb->planes) - 1;
349 }
350
351 /*
352 * Some displays, such as the HP332 and HP340 internal video
353 * and HP98542/98543 appear to return a display width of 1024
354 * instead of 512. It looks these boards have actually have
355 * enough 64KB (1bpp) or 256KB (4bpp) VRAM and RAMDAC capabilities
356 * to display 1024x400 pixels.
357 *
358 * However HP's official "Service Information Manual" for
359 * "HP 900 Series 300 Computers Models 330/350" says:
360 * "The medium-resolution board uses eight memory chips per plane.
361 * This is enough to display 512 doubled pixels by 400 scan lines."
362 *
363 * This "512 doubled pixels" implies that the native HP-UX treated
364 * these 1024x400 framebuffers as pseudo 512x400 ones because
365 * ancient 1980s CRTs (such as 35741) didn't display such higher
366 * resolution. Furthermore, even modern LCDs can only handle
367 * upto 720 pixels in the "400 line" as VGA compatible mode.
368 *
369 * As mentioned above, we treat these 1024x400 1 bit or 4 bit
370 * framebuffers as "2 bytes per pixel" ones, so we have to handle
371 * 512 pixels per line with 1024 bytes per line.
372 */
373 if (fb->planes <= 4 && fb->dwidth == 1024 && fb->dheight == 400) {
374 fb->dwidth = 512;
375 sparse = true;
376 }
377
378 fb->bmv = topcat_windowmove;
379 topcat_restore(fb);
380 diofb_fbsetup(fb);
381 if (!sparse) {
382 /* save original rasops putchar op */
383 fb->wsputchar = ri->ri_ops.putchar;
384 ri->ri_ops.putchar = topcat_putchar8;
385 } else {
386 ri->ri_ops.putchar = topcat_putchar1_4;
387 /* copycols and erasecols ops require byte size of fontwidth */
388 fb->wsd.fontwidth *= 2;
389 /* copyrows and eraserows ops require byte size per line */
390 ri->ri_emuwidth *= 2;
391 }
392 for (i = 0; i <= fb->planemask; i++)
393 topcat_setcolor(fb, i);
394
395 return 0;
396 }
397
398 void
399 topcat_restore(struct diofb *fb)
400 {
401 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva;
402
403 /*
404 * Catseye looks a lot like a topcat, but not completely.
405 * So, we set some bits to make it work.
406 */
407 if (tc->regs.fbid != GID_TOPCAT) {
408 while ((tc->catseye_status & 1))
409 ;
410 tc->catseye_status = 0x0;
411 tc->vb_select = 0x0;
412 tc->tcntrl = 0x0;
413 tc->acntrl = 0x0;
414 tc->pncntrl = 0x0;
415 tc->rug_cmdstat = 0x90;
416 }
417
418 /*
419 * Enable reading/writing of all the planes.
420 */
421 tc->fben = fb->planemask;
422 tc->wen = fb->planemask;
423 tc->ren = fb->planemask;
424 tc->prr = RR_COPY;
425
426 /* Enable display */
427 tc->nblank = fb->planemask;
428 }
429
430 int
431 topcat_ioctl(void *v, void *vs, u_long cmd, void *data, int flags,
432 struct lwp *l)
433 {
434 struct diofb *fb = v;
435 struct wsdisplay_fbinfo *wdf;
436 u_int i;
437
438 switch (cmd) {
439 case WSDISPLAYIO_GTYPE:
440 *(u_int *)data = WSDISPLAY_TYPE_TOPCAT;
441 return 0;
442 case WSDISPLAYIO_SMODE:
443 fb->mapmode = *(u_int *)data;
444 if (fb->mapmode == WSDISPLAYIO_MODE_EMUL) {
445 topcat_restore(fb);
446 for (i = 0; i <= fb->planemask; i++)
447 topcat_setcolor(fb, i);
448 }
449 return 0;
450 case WSDISPLAYIO_GINFO:
451 wdf = (void *)data;
452 wdf->width = fb->ri.ri_width;
453 wdf->height = fb->ri.ri_height;
454 wdf->depth = fb->ri.ri_depth;
455 wdf->cmsize = 1 << fb->planes;
456 return 0;
457 case WSDISPLAYIO_LINEBYTES:
458 *(u_int *)data = fb->ri.ri_stride;
459 return 0;
460 case WSDISPLAYIO_GETCMAP:
461 if (fb->planemask == 1)
462 return EPASSTHROUGH;
463 return diofb_getcmap(fb, (struct wsdisplay_cmap *)data);
464 case WSDISPLAYIO_PUTCMAP:
465 if (fb->planemask == 1)
466 return EPASSTHROUGH;
467 return topcat_setcmap(fb, (struct wsdisplay_cmap *)data);
468 case WSDISPLAYIO_GVIDEO:
469 case WSDISPLAYIO_SVIDEO:
470 return EPASSTHROUGH;
471 }
472
473 return EPASSTHROUGH;
474 }
475
476 void
477 topcat_setcolor(struct diofb *fb, u_int index)
478 {
479 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva;
480
481 /* No color map registers on monochrome framebuffers. */
482 if (fb->planemask == 1)
483 return;
484
485 tc_waitbusy(tc, fb->planemask);
486
487 if (tc->regs.fbid != GID_TOPCAT) {
488 tccm_waitbusy(tc);
489 tc->plane_mask = fb->planemask;
490 tc->cindex = ~index;
491 tc->rdata = fb->cmap.r[index];
492 tc->gdata = fb->cmap.g[index];
493 tc->bdata = fb->cmap.b[index];
494 tc->strobe = 0xff;
495 /* XXX delay required on 68020/30 to avoid bus error */
496 DELAY(100);
497
498 tccm_waitbusy(tc);
499 tc->cindex = 0;
500 } else {
501 tccm_waitbusy(tc);
502 tc->plane_mask = fb->planemask;
503 tc->rdata = fb->cmap.r[index];
504 tc->gdata = fb->cmap.g[index];
505 tc->bdata = fb->cmap.b[index];
506 DELAY(1); /* necessary for at least old HP98543 */
507 tc->cindex = ~index;
508 DELAY(1); /* necessary for at least old HP98543 */
509 tc->strobe = 0xff;
510 /* XXX delay required on 68020/30 to avoid bus error */
511 DELAY(100);
512
513 tccm_waitbusy(tc);
514 tc->rdata = 0;
515 tc->gdata = 0;
516 tc->bdata = 0;
517 tc->cindex = 0;
518 }
519 }
520
521 int
522 topcat_setcmap(struct diofb *fb, struct wsdisplay_cmap *cm)
523 {
524 uint8_t r[256], g[256], b[256];
525 u_int index = cm->index, count = cm->count;
526 u_int colcount = 1 << fb->planes;
527 int error;
528
529 if (index >= colcount || count > colcount - index)
530 return EINVAL;
531
532 if ((error = copyin(cm->red, r, count)) != 0)
533 return error;
534 if ((error = copyin(cm->green, g, count)) != 0)
535 return error;
536 if ((error = copyin(cm->blue, b, count)) != 0)
537 return error;
538
539 memcpy(fb->cmap.r + index, r, count);
540 memcpy(fb->cmap.g + index, g, count);
541 memcpy(fb->cmap.b + index, b, count);
542
543 while (count-- != 0)
544 topcat_setcolor(fb, index++);
545
546 return 0;
547 }
548
549 /*
550 * Accelerated routines
551 */
552
553 int
554 topcat_windowmove(struct diofb *fb, uint16_t sx, uint16_t sy,
555 uint16_t dx, uint16_t dy, uint16_t cx, uint16_t cy, int16_t rop,
556 int16_t planemask)
557 {
558 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva;
559
560 tc_waitbusy(tc, fb->planemask);
561
562 if (planemask != 0xff) {
563 tc->wen = planemask ^ 0xff;
564 tc->wmrr = rop ^ 0x0f;
565 tc->wen = fb->planemask;
566 } else {
567 tc->wen = planemask;
568 tc->wmrr = rop;
569 }
570 tc->source_y = sy;
571 tc->source_x = sx;
572 tc->dest_y = dy;
573 tc->dest_x = dx;
574 tc->wheight = cy;
575 tc->wwidth = cx;
576 tc->wmove = fb->planemask;
577
578 return 0;
579 }
580
581 static void
582 topcat_putchar8(void *cookie, int row, int col, u_int uc, long attr)
583 {
584 struct rasops_info *ri = (struct rasops_info *)cookie;
585 struct diofb *diofb = ri->ri_hw;
586 volatile struct tcboxfb *tc = (struct tcboxfb *)diofb->regkva;
587
588 /* Wait windowmove ops complete before drawing a glyph */
589 tc_waitbusy(tc, diofb->planemask);
590
591 /* Call the original rasops putchar */
592 (*diofb->wsputchar)(cookie, row, col, uc, attr);
593 }
594
595 /*
596 * Put a single character on 1 bpp (98542) or 4 bpp (98543) variants
597 * with 1024x400 VRAM to treat them as a pseudo 512x400 bitmap.
598 */
599 static void
600 topcat_putchar1_4(void *cookie, int row, int col, u_int uc, long attr)
601 {
602 int width, height, cnt, fs;
603 uint32_t fb;
604 uint8_t *fr, clr[2];
605 uint8_t *dp, *rp;
606 struct rasops_info *ri;
607 struct diofb *diofb;
608 volatile struct tcboxfb *tc;
609
610 ri = (struct rasops_info *)cookie;
611
612 if (!CHAR_IN_FONT(uc, ri->ri_font))
613 return;
614
615 rp = ri->ri_bits + (row * ri->ri_yscale) +
616 (col * ri->ri_xscale * 2);
617
618 height = ri->ri_font->fontheight;
619 width = ri->ri_font->fontwidth;
620 clr[0] = (uint8_t)ri->ri_devcmap[(attr >> 16) & 0xf];
621 clr[1] = (uint8_t)ri->ri_devcmap[(attr >> 24) & 0xf];
622
623 /* Wait windowmove ops complete before drawing a glyph */
624 diofb = ri->ri_hw;
625 tc = (struct tcboxfb *)diofb->regkva;
626 tc_waitbusy(tc, diofb->planemask);
627
628 /*
629 * We have to put pixel data to both odd and even addresses
630 * to handle "doubled pixels" as noted above.
631 */
632 if (uc == ' ') {
633 uint16_t c = clr[0];
634
635 c = c << 8 | c;
636 while (height--) {
637 dp = rp;
638 rp += ri->ri_stride;
639
640 for (cnt = width; cnt; cnt--) {
641 *(uint16_t *)dp = c;
642 dp += 2;
643 }
644 }
645 } else {
646 uc -= ri->ri_font->firstchar;
647 fr = (uint8_t *)ri->ri_font->data + uc * ri->ri_fontscale;
648 fs = ri->ri_font->stride;
649
650 while (height--) {
651 dp = rp;
652 fb = be32dec(fr);
653 fr += fs;
654 rp += ri->ri_stride;
655
656 for (cnt = width; cnt; cnt--) {
657 uint16_t c = clr[(fb >> 31) & 1];
658
659 c = c << 8 | c;
660 *(uint16_t *)dp = c;
661 dp += 2;
662 fb <<= 1;
663 }
664 }
665 }
666
667 /* Do underline */
668 if ((attr & WSATTR_UNDERLINE) != 0) {
669 uint16_t c = clr[1];
670
671 c = c << 8 | c;
672 rp -= ri->ri_stride * ri->ri_ul.off;
673
674 while (width--) {
675 *(uint16_t *)rp = c;
676 rp += 2;
677 }
678 }
679 }
680
681 /*
682 * Topcat/catseye console attachment
683 */
684
685 int
686 topcatcnattach(bus_space_tag_t bst, bus_addr_t addr, int scode)
687 {
688 bus_space_handle_t bsh;
689 void *va;
690 struct diofbreg *fbr;
691 struct diofb *fb = &diofb_cn;
692 int size;
693
694 if (bus_space_map(bst, addr, PAGE_SIZE, 0, &bsh))
695 return 1;
696 va = bus_space_vaddr(bst, bsh);
697 fbr = va;
698
699 if (badaddr(va) || fbr->id != GRFHWID) {
700 bus_space_unmap(bst, bsh, PAGE_SIZE);
701 return 1;
702 }
703
704 switch (fbr->fbid) {
705 case GID_TOPCAT:
706 case GID_LRCATSEYE:
707 case GID_HRCCATSEYE:
708 case GID_HRMCATSEYE:
709 break;
710
711 default:
712 bus_space_unmap(bst, bsh, PAGE_SIZE);
713 return 1;
714 }
715
716 size = DIO_SIZE(scode, va);
717
718 bus_space_unmap(bst, bsh, PAGE_SIZE);
719 if (bus_space_map(bst, addr, size, 0, &bsh))
720 return 1;
721 va = bus_space_vaddr(bst, bsh);
722
723 /*
724 * Initialize the framebuffer hardware.
725 */
726 conscode = scode;
727 conaddr = va;
728 topcat_reset(fb, conscode, (struct diofbreg *)conaddr);
729
730 /*
731 * Initialize the terminal emulator.
732 */
733 diofb_cnattach(fb);
734 return 0;
735 }
736