topcat.c revision 1.11 1 /* $NetBSD: topcat.c,v 1.11 2024/05/01 19:28:33 tsutsui 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.
355 *
356 * It looks these boards have VRAM with sparse address layout,
357 * i.e. 1 bit or 4 bits per pixel but 2 bytes per pixel, so
358 * we have to handle 512 pixels per line with 1024 bytes per line.
359 */
360 if (fb->planes <= 4 && fb->dwidth == 1024 && fb->dheight == 400) {
361 fb->dwidth = 512;
362 sparse = true;
363 }
364
365 fb->bmv = topcat_windowmove;
366 topcat_restore(fb);
367 diofb_fbsetup(fb);
368 if (!sparse) {
369 /* save original rasops putchar op */
370 fb->wsputchar = ri->ri_ops.putchar;
371 ri->ri_ops.putchar = topcat_putchar8;
372 } else {
373 ri->ri_ops.putchar = topcat_putchar1_4;
374 /* copycols and erasecols ops require byte size of fontwidth */
375 fb->wsd.fontwidth *= 2;
376 /* copyrows and eraserows ops require byte size per line */
377 ri->ri_emuwidth *= 2;
378 }
379 for (i = 0; i <= fb->planemask; i++)
380 topcat_setcolor(fb, i);
381
382 return 0;
383 }
384
385 void
386 topcat_restore(struct diofb *fb)
387 {
388 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva;
389
390 /*
391 * Catseye looks a lot like a topcat, but not completely.
392 * So, we set some bits to make it work.
393 */
394 if (tc->regs.fbid != GID_TOPCAT) {
395 while ((tc->catseye_status & 1))
396 ;
397 tc->catseye_status = 0x0;
398 tc->vb_select = 0x0;
399 tc->tcntrl = 0x0;
400 tc->acntrl = 0x0;
401 tc->pncntrl = 0x0;
402 tc->rug_cmdstat = 0x90;
403 }
404
405 /*
406 * Enable reading/writing of all the planes.
407 */
408 tc->fben = fb->planemask;
409 tc->wen = fb->planemask;
410 tc->ren = fb->planemask;
411 tc->prr = RR_COPY;
412
413 /* Enable display */
414 tc->nblank = fb->planemask;
415 }
416
417 int
418 topcat_ioctl(void *v, void *vs, u_long cmd, void *data, int flags,
419 struct lwp *l)
420 {
421 struct diofb *fb = v;
422 struct wsdisplay_fbinfo *wdf;
423 u_int i;
424
425 switch (cmd) {
426 case WSDISPLAYIO_GTYPE:
427 *(u_int *)data = WSDISPLAY_TYPE_TOPCAT;
428 return 0;
429 case WSDISPLAYIO_SMODE:
430 fb->mapmode = *(u_int *)data;
431 if (fb->mapmode == WSDISPLAYIO_MODE_EMUL) {
432 topcat_restore(fb);
433 for (i = 0; i <= fb->planemask; i++)
434 topcat_setcolor(fb, i);
435 }
436 return 0;
437 case WSDISPLAYIO_GINFO:
438 wdf = (void *)data;
439 wdf->width = fb->ri.ri_width;
440 wdf->height = fb->ri.ri_height;
441 wdf->depth = fb->ri.ri_depth;
442 wdf->cmsize = 1 << fb->planes;
443 return 0;
444 case WSDISPLAYIO_LINEBYTES:
445 *(u_int *)data = fb->ri.ri_stride;
446 return 0;
447 case WSDISPLAYIO_GETCMAP:
448 if (fb->planemask == 1)
449 return EPASSTHROUGH;
450 return diofb_getcmap(fb, (struct wsdisplay_cmap *)data);
451 case WSDISPLAYIO_PUTCMAP:
452 if (fb->planemask == 1)
453 return EPASSTHROUGH;
454 return topcat_setcmap(fb, (struct wsdisplay_cmap *)data);
455 case WSDISPLAYIO_GVIDEO:
456 case WSDISPLAYIO_SVIDEO:
457 return EPASSTHROUGH;
458 }
459
460 return EPASSTHROUGH;
461 }
462
463 void
464 topcat_setcolor(struct diofb *fb, u_int index)
465 {
466 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva;
467
468 /* No color map registers on monochrome framebuffers. */
469 if (fb->planemask == 1)
470 return;
471
472 tc_waitbusy(tc, fb->planemask);
473
474 if (tc->regs.fbid != GID_TOPCAT) {
475 tccm_waitbusy(tc);
476 tc->plane_mask = fb->planemask;
477 tc->cindex = ~index;
478 tc->rdata = fb->cmap.r[index];
479 tc->gdata = fb->cmap.g[index];
480 tc->bdata = fb->cmap.b[index];
481 tc->strobe = 0xff;
482 /* XXX delay required on 68020/30 to avoid bus error */
483 DELAY(100);
484
485 tccm_waitbusy(tc);
486 tc->cindex = 0;
487 } else {
488 tccm_waitbusy(tc);
489 tc->plane_mask = fb->planemask;
490 tc->rdata = fb->cmap.r[index];
491 tc->gdata = fb->cmap.g[index];
492 tc->bdata = fb->cmap.b[index];
493 DELAY(1); /* necessary for at least old HP98543 */
494 tc->cindex = ~index;
495 DELAY(1); /* necessary for at least old HP98543 */
496 tc->strobe = 0xff;
497 /* XXX delay required on 68020/30 to avoid bus error */
498 DELAY(100);
499
500 tccm_waitbusy(tc);
501 tc->rdata = 0;
502 tc->gdata = 0;
503 tc->bdata = 0;
504 tc->cindex = 0;
505 }
506 }
507
508 int
509 topcat_setcmap(struct diofb *fb, struct wsdisplay_cmap *cm)
510 {
511 uint8_t r[256], g[256], b[256];
512 u_int index = cm->index, count = cm->count;
513 u_int colcount = 1 << fb->planes;
514 int error;
515
516 if (index >= colcount || count > colcount - index)
517 return EINVAL;
518
519 if ((error = copyin(cm->red, r, count)) != 0)
520 return error;
521 if ((error = copyin(cm->green, g, count)) != 0)
522 return error;
523 if ((error = copyin(cm->blue, b, count)) != 0)
524 return error;
525
526 memcpy(fb->cmap.r + index, r, count);
527 memcpy(fb->cmap.g + index, g, count);
528 memcpy(fb->cmap.b + index, b, count);
529
530 while (count-- != 0)
531 topcat_setcolor(fb, index++);
532
533 return 0;
534 }
535
536 /*
537 * Accelerated routines
538 */
539
540 int
541 topcat_windowmove(struct diofb *fb, uint16_t sx, uint16_t sy,
542 uint16_t dx, uint16_t dy, uint16_t cx, uint16_t cy, int16_t rop,
543 int16_t planemask)
544 {
545 volatile struct tcboxfb *tc = (struct tcboxfb *)fb->regkva;
546
547 tc_waitbusy(tc, fb->planemask);
548
549 if (planemask != 0xff) {
550 tc->wen = planemask ^ 0xff;
551 tc->wmrr = rop ^ 0x0f;
552 tc->wen = fb->planemask;
553 } else {
554 tc->wen = planemask;
555 tc->wmrr = rop;
556 }
557 tc->source_y = sy;
558 tc->source_x = sx;
559 tc->dest_y = dy;
560 tc->dest_x = dx;
561 tc->wheight = cy;
562 tc->wwidth = cx;
563 tc->wmove = fb->planemask;
564
565 return 0;
566 }
567
568 static void
569 topcat_putchar8(void *cookie, int row, int col, u_int uc, long attr)
570 {
571 struct rasops_info *ri = (struct rasops_info *)cookie;
572 struct diofb *diofb = ri->ri_hw;
573 volatile struct tcboxfb *tc = (struct tcboxfb *)diofb->regkva;
574
575 /* Wait windowmove ops complete before drawing a glyph */
576 tc_waitbusy(tc, diofb->planemask);
577
578 /* Call the original rasops putchar */
579 (*diofb->wsputchar)(cookie, row, col, uc, attr);
580 }
581
582 /*
583 * Put a single character on 1 bpp or 4 bpp variants with sparse VRAM addresses
584 */
585 static void
586 topcat_putchar1_4(void *cookie, int row, int col, u_int uc, long attr)
587 {
588 int width, height, cnt, fs;
589 uint32_t fb;
590 uint8_t *fr, clr[2];
591 uint8_t *dp, *rp;
592 struct rasops_info *ri;
593 struct diofb *diofb;
594 volatile struct tcboxfb *tc;
595
596 ri = (struct rasops_info *)cookie;
597
598 if (!CHAR_IN_FONT(uc, ri->ri_font))
599 return;
600
601 rp = ri->ri_bits + (row * ri->ri_yscale) +
602 (col * ri->ri_xscale * 2);
603
604 height = ri->ri_font->fontheight;
605 width = ri->ri_font->fontwidth;
606 clr[0] = (uint8_t)ri->ri_devcmap[(attr >> 16) & 0xf];
607 clr[1] = (uint8_t)ri->ri_devcmap[(attr >> 24) & 0xf];
608
609 /* Wait windowmove ops complete before drawing a glyph */
610 diofb = ri->ri_hw;
611 tc = (struct tcboxfb *)diofb->regkva;
612 tc_waitbusy(tc, diofb->planemask);
613
614 /*
615 * At least HP98543 requires to write 4 bpp data onto
616 * both odd and even addresses.
617 */
618 if (uc == ' ') {
619 uint16_t c = clr[0];
620
621 c = c << 8 | c;
622 while (height--) {
623 dp = rp;
624 rp += ri->ri_stride;
625
626 for (cnt = width; cnt; cnt--) {
627 *(uint16_t *)dp = c;
628 dp += 2;
629 }
630 }
631 } else {
632 uc -= ri->ri_font->firstchar;
633 fr = (uint8_t *)ri->ri_font->data + uc * ri->ri_fontscale;
634 fs = ri->ri_font->stride;
635
636 while (height--) {
637 dp = rp;
638 fb = be32dec(fr);
639 fr += fs;
640 rp += ri->ri_stride;
641
642 for (cnt = width; cnt; cnt--) {
643 uint16_t c = clr[(fb >> 31) & 1];
644
645 c = c << 8 | c;
646 *(uint16_t *)dp = c;
647 dp += 2;
648 fb <<= 1;
649 }
650 }
651 }
652
653 /* Do underline */
654 if ((attr & WSATTR_UNDERLINE) != 0) {
655 uint16_t c = clr[1];
656
657 c = c << 8 | c;
658 rp -= ri->ri_stride * ri->ri_ul.off;
659
660 while (width--) {
661 *(uint16_t *)rp = c;
662 rp += 2;
663 }
664 }
665 }
666
667 /*
668 * Topcat/catseye console attachment
669 */
670
671 int
672 topcatcnattach(bus_space_tag_t bst, bus_addr_t addr, int scode)
673 {
674 bus_space_handle_t bsh;
675 void *va;
676 struct diofbreg *fbr;
677 struct diofb *fb = &diofb_cn;
678 int size;
679
680 if (bus_space_map(bst, addr, PAGE_SIZE, 0, &bsh))
681 return 1;
682 va = bus_space_vaddr(bst, bsh);
683 fbr = va;
684
685 if (badaddr(va) || fbr->id != GRFHWID) {
686 bus_space_unmap(bst, bsh, PAGE_SIZE);
687 return 1;
688 }
689
690 switch (fbr->fbid) {
691 case GID_TOPCAT:
692 case GID_LRCATSEYE:
693 case GID_HRCCATSEYE:
694 case GID_HRMCATSEYE:
695 break;
696
697 default:
698 bus_space_unmap(bst, bsh, PAGE_SIZE);
699 return 1;
700 }
701
702 size = DIO_SIZE(scode, va);
703
704 bus_space_unmap(bst, bsh, PAGE_SIZE);
705 if (bus_space_map(bst, addr, size, 0, &bsh))
706 return 1;
707 va = bus_space_vaddr(bst, bsh);
708
709 /*
710 * Initialize the framebuffer hardware.
711 */
712 conscode = scode;
713 conaddr = va;
714 topcat_reset(fb, conscode, (struct diofbreg *)conaddr);
715
716 /*
717 * Initialize the terminal emulator.
718 */
719 diofb_cnattach(fb);
720 return 0;
721 }
722