hyperfb.c revision 1.2 1 /* $NetBSD: hyperfb.c,v 1.2 2024/07/15 10:26:09 macallan Exp $ */
2
3 /*
4 * Copyright (c) 2024 Michael Lorenz
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 * THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * a native driver for HCRX / hyperdrive cards
31 */
32
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: hyperfb.c,v 1.2 2024/07/15 10:26:09 macallan Exp $");
35
36 #include "opt_cputype.h"
37 #include "opt_hyperfb.h"
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/device.h>
42
43 #include <sys/bus.h>
44 #include <machine/cpu.h>
45 #include <machine/iomod.h>
46 #include <machine/autoconf.h>
47
48 #include <dev/wscons/wsdisplayvar.h>
49 #include <dev/wscons/wsconsio.h>
50 #include <dev/wsfont/wsfont.h>
51 #include <dev/rasops/rasops.h>
52 #include <dev/wscons/wsdisplay_vconsvar.h>
53 #include <dev/wscons/wsdisplay_glyphcachevar.h>
54
55 #include <dev/ic/stireg.h>
56 #include <dev/ic/stivar.h>
57
58 #include <hppa/dev/cpudevs.h>
59 #include <hppa/hppa/machdep.h>
60
61 #ifdef HYPERFB_DEBUG
62 #define DPRINTF printf
63 #else
64 #define DPRINTF if (0) printf
65 #endif
66
67 #define STI_ROMSIZE (sizeof(struct sti_dd) * 4)
68
69 #define HCRX_FBOFFSET 0x01000000
70 #define HCRX_FBLEN 0x01000000
71 #define HCRX_REGOFFSET 0x00100000
72 #define HCRX_REGLEN 0x00280000
73
74 #define HCRX_CONFIG_24BIT 0x100
75
76 #define HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES 4
77 #define HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE 8
78 #define HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE 10
79 #define HYPERBOWL_MODE2_8_24 15
80
81 int hyperfb_match(device_t, cfdata_t, void *);
82 void hyperfb_attach(device_t, device_t, void *);
83
84 struct hyperfb_softc {
85 device_t sc_dev;
86 bus_space_tag_t sc_iot;
87 bus_addr_t sc_base;
88 bus_space_handle_t sc_hfb, sc_hreg;
89 void *sc_fb;
90
91 int sc_width, sc_height;
92 int sc_locked, sc_is_console, sc_24bit;
93 struct vcons_screen sc_console_screen;
94 struct wsscreen_descr sc_defaultscreen_descr;
95 const struct wsscreen_descr *sc_screens[1];
96 struct wsscreen_list sc_screenlist;
97 struct vcons_data vd;
98 int sc_mode;
99 void (*sc_putchar)(void *, int, int, u_int, long);
100 u_char sc_cmap_red[256];
101 u_char sc_cmap_green[256];
102 u_char sc_cmap_blue[256];
103 kmutex_t sc_hwlock;
104 uint32_t sc_hwmode;
105 #define HW_FB 0
106 #define HW_FILL 1
107 #define HW_BLIT 2
108 uint32_t sc_rect_colour, sc_rect_height;
109 /* cursor stuff */
110 int sc_cursor_x, sc_cursor_y;
111 int sc_hot_x, sc_hot_y, sc_enabled;
112 int sc_video_on;
113 glyphcache sc_gc;
114 };
115
116 extern struct cfdriver hyperfb_cd;
117
118 CFATTACH_DECL_NEW(hyperfb, sizeof(struct hyperfb_softc), hyperfb_match,
119 hyperfb_attach, NULL, NULL);
120
121 void hyperfb_setup_fb(struct hyperfb_softc *);
122 static void hyperfb_init_screen(void *, struct vcons_screen *,
123 int, long *);
124 static int hyperfb_ioctl(void *, void *, u_long, void *, int,
125 struct lwp *);
126 static paddr_t hyperfb_mmap(void *, void *, off_t, int);
127
128 static int hyperfb_putcmap(struct hyperfb_softc *, struct wsdisplay_cmap *);
129 static int hyperfb_getcmap(struct hyperfb_softc *, struct wsdisplay_cmap *);
130 static void hyperfb_restore_palette(struct hyperfb_softc *);
131 static int hyperfb_putpalreg(struct hyperfb_softc *, uint8_t, uint8_t,
132 uint8_t, uint8_t);
133 void hyperfb_setup(struct hyperfb_softc *);
134 static void hyperfb_set_video(struct hyperfb_softc *, int);
135
136 static void hyperfb_rectfill(struct hyperfb_softc *, int, int, int, int,
137 uint32_t);
138 static void hyperfb_bitblt(void *, int, int, int, int, int,
139 int, int);
140
141 static void hyperfb_cursor(void *, int, int, int);
142 static void hyperfb_putchar(void *, int, int, u_int, long);
143 static void hyperfb_copycols(void *, int, int, int, int);
144 static void hyperfb_erasecols(void *, int, int, int, long);
145 static void hyperfb_copyrows(void *, int, int, int);
146 static void hyperfb_eraserows(void *, int, int, long);
147
148 #if 0
149 static void hyperfb_move_cursor(struct hyperfb_softc *, int, int);
150 static int hyperfb_do_cursor(struct hyperfb_softc *, struct wsdisplay_cursor *);
151 #endif
152
153 #define BA(F,C,S,A,J,B,I) \
154 (((F)<<31)|((C)<<27)|((S)<<24)|((A)<<21)|((J)<<16)|((B)<<12)|(I))
155 /* FCCCCSSSAAAJJJJJBBBBIIIIIIIIIIII */
156
157 #define IBOvals(R,M,X,S,D,L,B,F) \
158 (((R)<<8)|((M)<<16)|((X)<<24)|((S)<<29)|((D)<<28)|((L)<<31)|((B)<<1)|(F))
159 /* LSSDXXXXMMMMMMMMRRRRRRRRBBBBBBBF */
160
161 #define IndexedDcd 0 /* Pixel data is indexed (pseudo) color */
162 #define Otc04 2 /* Pixels in each longword transfer (4) */
163 #define Otc32 5 /* Pixels in each longword transfer (32) */
164 #define Ots08 3 /* Each pixel is size (8)d transfer (1) */
165 #define OtsIndirect 6 /* Each bit goes through FG/BG color(8) */
166 #define AddrLong 5 /* FB address is Long aligned (pixel) */
167 #define BINovly 0x2 /* 8 bit overlay */
168 #define BINapp0I 0x0 /* Application Buffer 0, Indexed */
169 #define BINapp1I 0x1 /* Application Buffer 1, Indexed */
170 #define BINapp0F8 0xa /* Application Buffer 0, Fractional 8-8-8 */
171 #define BINattr 0xd /* Attribute Bitmap */
172 #define RopSrc 0x3
173 #define RopInv 0xc
174 #define BitmapExtent08 3 /* Each write hits ( 8) bits in depth */
175 #define BitmapExtent32 5 /* Each write hits (32) bits in depth */
176 #define DataDynamic 0 /* Data register reloaded by direct access */
177 #define MaskDynamic 1 /* Mask register reloaded by direct access */
178 #define MaskOtc 0 /* Mask contains Object Count valid bits */
179
180 static inline void hyperfb_wait_fifo(struct hyperfb_softc *, uint32_t);
181
182 #define ngle_bt458_write(sc, r, v) \
183 hyperfb_write4(sc, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24)
184
185 struct wsdisplay_accessops hyperfb_accessops = {
186 hyperfb_ioctl,
187 hyperfb_mmap,
188 NULL, /* alloc_screen */
189 NULL, /* free_screen */
190 NULL, /* show_screen */
191 NULL, /* load_font */
192 NULL, /* pollc */
193 NULL /* scroll */
194 };
195
196 static inline uint32_t
197 hyperfb_read4(struct hyperfb_softc *sc, uint32_t offset)
198 {
199 return bus_space_read_4(sc->sc_iot, sc->sc_hreg, offset);
200 }
201
202 static inline uint8_t
203 hyperfb_read1(struct hyperfb_softc *sc, uint32_t offset)
204 {
205 return bus_space_read_1(sc->sc_iot, sc->sc_hreg, offset);
206 }
207
208 static inline void
209 hyperfb_write4(struct hyperfb_softc *sc, uint32_t offset, uint32_t val)
210 {
211 bus_space_write_4(sc->sc_iot, sc->sc_hreg, offset, val);
212 }
213
214 static inline void
215 hyperfb_write1(struct hyperfb_softc *sc, uint32_t offset, uint8_t val)
216 {
217 bus_space_write_1(sc->sc_iot, sc->sc_hreg, offset, val);
218 }
219
220 static inline void
221 hyperfb_wait(struct hyperfb_softc *sc)
222 {
223 uint8_t stat;
224
225 do {
226 stat = hyperfb_read1(sc, NGLE_REG_15b0);
227 if (stat == 0)
228 stat = hyperfb_read1(sc, NGLE_REG_15b0);
229 } while (stat != 0);
230 }
231
232 static inline void
233 hyperfb_wait_fifo(struct hyperfb_softc *sc, uint32_t slots)
234 {
235 uint32_t reg;
236
237 do {
238 reg = hyperfb_read4(sc, NGLE_REG_34);
239 } while (reg < slots);
240 }
241
242 void
243 hyperfb_setup_fb(struct hyperfb_softc *sc)
244 {
245
246 hyperfb_wait(sc);
247 hyperfb_write4(sc, NGLE_REG_10, 0x13602000); /* 8bit */
248 hyperfb_write4(sc, NGLE_REG_14, 0x83000300);
249 hyperfb_wait(sc);
250 hyperfb_write1(sc, NGLE_REG_16b1, 1);
251 sc->sc_hwmode = HW_FB;
252 }
253
254 int
255 hyperfb_match(device_t parent, cfdata_t cf, void *aux)
256 {
257 struct confargs *ca = aux;
258 bus_space_handle_t romh;
259 paddr_t rom;
260 uint32_t id = 0;
261 u_char devtype;
262 int rv = 0, romunmapped = 0;
263
264 if (ca->ca_type.iodc_type != HPPA_TYPE_FIO)
265 return 0;
266
267 /* these need further checking for the graphics id */
268 if (ca->ca_type.iodc_sv_model != HPPA_FIO_GSGC &&
269 ca->ca_type.iodc_sv_model != HPPA_FIO_SGC)
270 return 0;
271
272 if (ca->ca_naddrs > 0)
273 rom = ca->ca_addrs[0].addr;
274 else
275 rom = ca->ca_hpa;
276
277 DPRINTF("%s: hpa=%x, rom=%x\n", __func__, (uint)ca->ca_hpa,
278 (uint)rom);
279
280 /* if it does not map, probably part of the lasi space */
281 if (bus_space_map(ca->ca_iot, rom, STI_ROMSIZE, 0, &romh)) {
282 DPRINTF("%s: can't map rom space (%d)\n", __func__, rv);
283
284 if ((rom & HPPA_IOBEGIN) == HPPA_IOBEGIN) {
285 romh = rom;
286 romunmapped++;
287 } else {
288 /* in this case nobody has no freaking idea */
289 return 0;
290 }
291 }
292
293 devtype = bus_space_read_1(ca->ca_iot, romh, 3);
294 DPRINTF("%s: devtype=%d\n", __func__, devtype);
295 rv = 1;
296 switch (devtype) {
297 case STI_DEVTYPE4:
298 id = bus_space_read_4(ca->ca_iot, romh, STI_DEV4_DD_GRID);
299 break;
300 case STI_DEVTYPE1:
301 id = (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID
302 + 3) << 24) |
303 (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID
304 + 7) << 16) |
305 (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID
306 + 11) << 8) |
307 (bus_space_read_1(ca->ca_iot, romh, STI_DEV1_DD_GRID
308 + 15));
309 break;
310 default:
311 DPRINTF("%s: unknown type (%x)\n", __func__, devtype);
312 rv = 0;
313 }
314
315 if (id == STI_DD_HCRX)
316 rv = 100; /* beat out sti */
317
318 ca->ca_addrs[ca->ca_naddrs].addr = rom;
319 ca->ca_addrs[ca->ca_naddrs].size = sti_rom_size(ca->ca_iot, romh);
320 ca->ca_naddrs++;
321
322 if (!romunmapped)
323 bus_space_unmap(ca->ca_iot, romh, STI_ROMSIZE);
324 return rv;
325 }
326
327 void
328 hyperfb_attach(device_t parent, device_t self, void *aux)
329 {
330 struct hyperfb_softc *sc = device_private(self);
331 struct confargs *ca = aux;
332 struct rasops_info *ri;
333 struct wsemuldisplaydev_attach_args aa;
334 bus_space_handle_t hrom;
335 hppa_hpa_t consaddr;
336 long defattr;
337 int pagezero_cookie;
338 paddr_t rom;
339 uint32_t config;
340
341 pagezero_cookie = hppa_pagezero_map();
342 consaddr = (hppa_hpa_t)PAGE0->mem_cons.pz_hpa;
343 hppa_pagezero_unmap(pagezero_cookie);
344
345 sc->sc_dev = self;
346 sc->sc_base = ca->ca_hpa;
347 sc->sc_iot = ca->ca_iot;
348 sc->sc_is_console =(ca->ca_hpa == consaddr);
349 sc->sc_width = 1280;
350 sc->sc_height = 1024;
351
352 /* we can *not* be interrupted when doing colour map accesses */
353 mutex_init(&sc->sc_hwlock, MUTEX_DEFAULT, IPL_HIGH);
354
355 /* we stashed rom addr/len into the last slot during probe */
356 rom = ca->ca_addrs[ca->ca_naddrs - 1].addr;
357
358 if (bus_space_map(sc->sc_iot,
359 sc->sc_base + HCRX_FBOFFSET, HCRX_FBLEN,
360 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE,
361 &sc->sc_hfb)) {
362 aprint_error_dev(sc->sc_dev, "failed to map the framebuffer\n");
363 return;
364 }
365 sc->sc_fb = bus_space_vaddr(sc->sc_iot, sc->sc_hfb);
366
367 if (bus_space_map(sc->sc_iot,
368 sc->sc_base + HCRX_REGOFFSET, HCRX_REGLEN, 0, &sc->sc_hreg)) {
369 aprint_error_dev(sc->sc_dev, "failed to map registers\n");
370 return;
371 }
372
373 /*
374 * we really only need the first word so we can grab the config bits
375 * between the bytes
376 */
377 if (bus_space_map(sc->sc_iot,
378 rom, 4, 0, &hrom)) {
379 aprint_error_dev(sc->sc_dev, "failed to map ROM, assuming 8bit\n");
380 config = 0;
381 } else {
382 /* alright, we got the ROM. now do the idle dance. */
383 volatile uint32_t r = hyperfb_read4(sc, NGLE_REG_15);
384 __USE(r);
385 hyperfb_wait(sc);
386 config = bus_space_read_4(sc->sc_iot, hrom, 0);
387 bus_space_unmap(sc->sc_iot, hrom, 4);
388 }
389 sc->sc_24bit = ((config & HCRX_CONFIG_24BIT) != 0);
390
391 printf(" %s\n", sc->sc_24bit ? "HCRX24" : "HCRX");
392 #ifdef HP7300LC_CPU
393 /*
394 * PCXL2: enable accel I/O for this space, see PCX-L2 ERS "ACCEL_IO".
395 * "pcxl2_ers.{ps,pdf}", (section / chapter . rel. page / abs. page)
396 * 8.7.4 / 8-12 / 92, 11.3.14 / 11-14 / 122 and 14.8 / 14-5 / 203.
397 */
398 if (hppa_cpu_info->hci_cputype == hpcxl2
399 && ca->ca_hpa >= PCXL2_ACCEL_IO_START
400 && ca->ca_hpa <= PCXL2_ACCEL_IO_END)
401 eaio_l2(PCXL2_ACCEL_IO_ADDR2MASK(ca->ca_hpa));
402 #endif /* HP7300LC_CPU */
403
404 hyperfb_setup(sc);
405 hyperfb_setup_fb(sc);
406
407 sc->sc_defaultscreen_descr = (struct wsscreen_descr){
408 "default",
409 0, 0,
410 NULL,
411 8, 16,
412 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE |
413 WSSCREEN_RESIZE,
414 NULL
415 };
416
417 sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
418 sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
419 sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
420 sc->sc_locked = 0;
421
422 vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
423 &hyperfb_accessops);
424 sc->vd.init_screen = hyperfb_init_screen;
425 sc->vd.show_screen_cookie = &sc->sc_gc;
426 sc->vd.show_screen_cb = glyphcache_adapt;
427
428 ri = &sc->sc_console_screen.scr_ri;
429
430 //sc->sc_gc.gc_bitblt = hyperfb_bitblt;
431 //sc->sc_gc.gc_blitcookie = sc;
432 //sc->sc_gc.gc_rop = RopSrc;
433
434 if (sc->sc_is_console) {
435 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
436 &defattr);
437 sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
438
439 sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
440 sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
441 sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
442 sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
443
444 #if 0
445 glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
446 sc->sc_scr.fbheight - sc->sc_height - 5,
447 sc->sc_scr.fbwidth,
448 ri->ri_font->fontwidth,
449 ri->ri_font->fontheight,
450 defattr);
451 #endif
452 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
453 defattr);
454
455 hyperfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height,
456 ri->ri_devcmap[(defattr >> 16) & 0xff]);
457
458 vcons_replay_msgbuf(&sc->sc_console_screen);
459 } else {
460 /*
461 * since we're not the console we can postpone the rest
462 * until someone actually allocates a screen for us
463 */
464 if (sc->sc_console_screen.scr_ri.ri_rows == 0) {
465 /* do some minimal setup to avoid weirdnesses later */
466 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
467 &defattr);
468 } else
469 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
470
471 #if 0
472 glyphcache_init(&sc->sc_gc, sc->sc_height + 5,
473 sc->sc_scr.fbheight - sc->sc_height - 5,
474 sc->sc_scr.fbwidth,
475 ri->ri_font->fontwidth,
476 ri->ri_font->fontheight,
477 defattr);
478 #endif
479 }
480
481 hyperfb_restore_palette(sc);
482
483 /* no suspend/resume support yet */
484 if (!pmf_device_register(sc->sc_dev, NULL, NULL))
485 aprint_error_dev(sc->sc_dev,
486 "couldn't establish power handler\n");
487
488 aa.console = sc->sc_is_console;
489 aa.scrdata = &sc->sc_screenlist;
490 aa.accessops = &hyperfb_accessops;
491 aa.accesscookie = &sc->vd;
492
493 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE);
494
495 }
496
497 static void
498 hyperfb_init_screen(void *cookie, struct vcons_screen *scr,
499 int existing, long *defattr)
500 {
501 struct hyperfb_softc *sc = cookie;
502 struct rasops_info *ri = &scr->scr_ri;
503
504 ri->ri_depth = 8;
505 ri->ri_width = 1280;
506 ri->ri_height = 1024;
507 ri->ri_stride = 2048;
508 ri->ri_flg = RI_CENTER | RI_8BIT_IS_RGB /*|
509 RI_ENABLE_ALPHA | RI_PREFER_ALPHA*/;
510
511 ri->ri_bits = (void *)sc->sc_fb;
512 rasops_init(ri, 0, 0);
513 ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE |
514 WSSCREEN_RESIZE;
515 scr->scr_flags |= VCONS_LOADFONT;
516
517 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
518 sc->sc_width / ri->ri_font->fontwidth);
519
520 ri->ri_hw = scr;
521
522 sc->sc_putchar = ri->ri_ops.putchar;
523 ri->ri_ops.copyrows = hyperfb_copyrows;
524 ri->ri_ops.copycols = hyperfb_copycols;
525 ri->ri_ops.eraserows = hyperfb_eraserows;
526 ri->ri_ops.erasecols = hyperfb_erasecols;
527 ri->ri_ops.cursor = hyperfb_cursor;
528 ri->ri_ops.putchar = hyperfb_putchar;
529 }
530
531 static int
532 hyperfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
533 struct lwp *l)
534 {
535 struct vcons_data *vd = v;
536 struct hyperfb_softc *sc = vd->cookie;
537 struct wsdisplay_fbinfo *wdf;
538 struct vcons_screen *ms = vd->active;
539
540 switch (cmd) {
541 case WSDISPLAYIO_GTYPE:
542 *(u_int *)data = WSDISPLAY_TYPE_STI;
543 return 0;
544
545 case WSDISPLAYIO_GINFO:
546 if (ms == NULL)
547 return ENODEV;
548 wdf = (void *)data;
549 wdf->height = ms->scr_ri.ri_height;
550 wdf->width = ms->scr_ri.ri_width;
551 wdf->depth = ms->scr_ri.ri_depth;
552 wdf->cmsize = 256;
553 return 0;
554
555 case WSDISPLAYIO_GETCMAP:
556 return hyperfb_getcmap(sc,
557 (struct wsdisplay_cmap *)data);
558
559 case WSDISPLAYIO_PUTCMAP:
560 return hyperfb_putcmap(sc,
561 (struct wsdisplay_cmap *)data);
562 case WSDISPLAYIO_LINEBYTES:
563 *(u_int *)data = 2048;
564 return 0;
565
566 case WSDISPLAYIO_SMODE: {
567 int new_mode = *(int*)data;
568 if (new_mode != sc->sc_mode) {
569 sc->sc_mode = new_mode;
570 if(new_mode == WSDISPLAYIO_MODE_EMUL) {
571 hyperfb_setup(sc);
572 hyperfb_restore_palette(sc);
573 #if 0
574 glyphcache_wipe(&sc->sc_gc);
575 #endif
576 hyperfb_rectfill(sc, 0, 0, sc->sc_width,
577 sc->sc_height, ms->scr_ri.ri_devcmap[
578 (ms->scr_defattr >> 16) & 0xff]);
579 vcons_redraw_screen(ms);
580 hyperfb_set_video(sc, 1);
581 }
582 }
583 }
584 return 0;
585
586 case WSDISPLAYIO_GET_FBINFO:
587 {
588 struct wsdisplayio_fbinfo *fbi = data;
589 int ret;
590
591 ret = wsdisplayio_get_fbinfo(&ms->scr_ri, fbi);
592 fbi->fbi_fbsize = sc->sc_height * 2048;
593 return ret;
594 }
595
596 #if 0
597 case WSDISPLAYIO_GCURPOS:
598 {
599 struct wsdisplay_curpos *cp = (void *)data;
600
601 cp->x = sc->sc_cursor_x;
602 cp->y = sc->sc_cursor_y;
603 }
604 return 0;
605
606 case WSDISPLAYIO_SCURPOS:
607 {
608 struct wsdisplay_curpos *cp = (void *)data;
609
610 hyperfb_move_cursor(sc, cp->x, cp->y);
611 }
612 return 0;
613
614 case WSDISPLAYIO_GCURMAX:
615 {
616 struct wsdisplay_curpos *cp = (void *)data;
617
618 cp->x = 64;
619 cp->y = 64;
620 }
621 return 0;
622
623 case WSDISPLAYIO_SCURSOR:
624 {
625 struct wsdisplay_cursor *cursor = (void *)data;
626
627 return hyperfb_do_cursor(sc, cursor);
628 }
629 #endif
630
631 case WSDISPLAYIO_SVIDEO:
632 hyperfb_set_video(sc, *(int *)data);
633 return 0;
634 case WSDISPLAYIO_GVIDEO:
635 return sc->sc_video_on ?
636 WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF;
637 }
638 return EPASSTHROUGH;
639 }
640
641 static paddr_t
642 hyperfb_mmap(void *v, void *vs, off_t offset, int prot)
643 {
644 struct vcons_data *vd = v;
645 struct hyperfb_softc *sc = vd->cookie;
646 paddr_t pa = -1;
647
648
649 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)
650 return -1;
651
652 if (offset >= 0 || offset < 2048 * 1024) {
653 /* framebuffer */
654 pa = bus_space_mmap(sc->sc_iot, sc->sc_base + HCRX_FBOFFSET, offset,
655 prot, BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE);
656 } else if (offset >= 0x80000000 && offset < 0x8040000) {
657 /* blitter registers etc. */
658 pa = bus_space_mmap(sc->sc_iot, sc->sc_base + HCRX_REGOFFSET,
659 offset - 0x80000000, prot, BUS_SPACE_MAP_LINEAR);
660 }
661
662 return pa;
663 }
664
665 static int
666 hyperfb_putcmap(struct hyperfb_softc *sc, struct wsdisplay_cmap *cm)
667 {
668 u_char *r, *g, *b;
669 u_int index = cm->index;
670 u_int count = cm->count;
671 int i, error;
672 u_char rbuf[256], gbuf[256], bbuf[256];
673
674 if (cm->index >= 256 || cm->count > 256 ||
675 (cm->index + cm->count) > 256)
676 return EINVAL;
677 error = copyin(cm->red, &rbuf[index], count);
678 if (error)
679 return error;
680 error = copyin(cm->green, &gbuf[index], count);
681 if (error)
682 return error;
683 error = copyin(cm->blue, &bbuf[index], count);
684 if (error)
685 return error;
686
687 memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
688 memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
689 memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
690
691 r = &sc->sc_cmap_red[index];
692 g = &sc->sc_cmap_green[index];
693 b = &sc->sc_cmap_blue[index];
694
695 for (i = 0; i < count; i++) {
696 hyperfb_putpalreg(sc, index, *r, *g, *b);
697 index++;
698 r++, g++, b++;
699 }
700 return 0;
701 }
702
703 static int
704 hyperfb_getcmap(struct hyperfb_softc *sc, struct wsdisplay_cmap *cm)
705 {
706 u_int index = cm->index;
707 u_int count = cm->count;
708 int error;
709
710 if (index >= 255 || count > 256 || index + count > 256)
711 return EINVAL;
712
713 error = copyout(&sc->sc_cmap_red[index], cm->red, count);
714 if (error)
715 return error;
716 error = copyout(&sc->sc_cmap_green[index], cm->green, count);
717 if (error)
718 return error;
719 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
720 if (error)
721 return error;
722
723 return 0;
724 }
725
726 static void
727 hyperfb_restore_palette(struct hyperfb_softc *sc)
728 {
729 uint8_t cmap[768];
730 int i, j;
731
732 j = 0;
733 rasops_get_cmap(&sc->sc_console_screen.scr_ri, cmap, sizeof(cmap));
734 for (i = 0; i < 256; i++) {
735 sc->sc_cmap_red[i] = cmap[j];
736 sc->sc_cmap_green[i] = cmap[j + 1];
737 sc->sc_cmap_blue[i] = cmap[j + 2];
738 hyperfb_putpalreg(sc, i, cmap[j], cmap[j + 1], cmap[j + 2]);
739 j += 3;
740 }
741 }
742
743 static int
744 hyperfb_putpalreg(struct hyperfb_softc *sc, uint8_t idx, uint8_t r, uint8_t g,
745 uint8_t b)
746 {
747
748 mutex_enter(&sc->sc_hwlock);
749 hyperfb_wait(sc);
750 hyperfb_write4(sc, NGLE_REG_10, 0xbbe0f000);
751 hyperfb_write4(sc, NGLE_REG_14, 0x03000300);
752 hyperfb_write4(sc, NGLE_REG_13, 0xffffffff);
753
754 hyperfb_wait(sc);
755 hyperfb_write4(sc, NGLE_REG_3, 0x400 | (idx << 2));
756 hyperfb_write4(sc, NGLE_REG_4, (r << 16) | (g << 8) | b);
757
758 hyperfb_write4(sc, NGLE_REG_2, 0x400);
759 hyperfb_write4(sc, NGLE_REG_38, 0x82000100);
760 hyperfb_setup_fb(sc);
761 mutex_exit(&sc->sc_hwlock);
762 return 0;
763 }
764
765 void
766 hyperfb_setup(struct hyperfb_softc *sc)
767 {
768 int i;
769 uint32_t reg;
770
771 sc->sc_hwmode = HW_FB;
772 sc->sc_hot_x = 0;
773 sc->sc_hot_y = 0;
774 sc->sc_enabled = 0;
775 sc->sc_video_on = 1;
776
777 sc->sc_rect_colour = 0xf0000000;
778 sc->sc_rect_height = 0;
779
780 /* set Bt458 read mask register to all planes */
781 /* XXX I'm not sure HCRX even has one of these */
782 hyperfb_wait(sc);
783 ngle_bt458_write(sc, 0x08, 0x04);
784 ngle_bt458_write(sc, 0x0a, 0xff);
785
786 reg = hyperfb_read4(sc, NGLE_REG_32);
787 DPRINTF("planereg %08x\n", reg);
788 hyperfb_write4(sc, NGLE_REG_32, 0xffff0000);
789
790 hyperfb_setup_fb(sc);
791
792 /* attr. planes */
793 hyperfb_wait(sc);
794 hyperfb_write4(sc, NGLE_REG_11, 0x2ea0d000);
795 hyperfb_write4(sc, NGLE_REG_14, 0x23000302);
796 hyperfb_write4(sc, NGLE_REG_12, NGLE_BUFF1_CMAP0);
797 hyperfb_write4(sc, NGLE_REG_8, 0xffffffff);
798
799 hyperfb_wait(sc);
800 hyperfb_write4(sc, NGLE_REG_6, 0x00000000);
801 hyperfb_write4(sc, NGLE_REG_9,
802 (sc->sc_width << 16) | sc->sc_height);
803 /*
804 * blit into offscreen memory to force flush previous - apparently
805 * some chips have a bug this works around
806 */
807 hyperfb_write4(sc, NGLE_REG_6, 0x05000000);
808 hyperfb_write4(sc, NGLE_REG_9, 0x00040001);
809
810 hyperfb_wait(sc);
811 hyperfb_write4(sc, NGLE_REG_12, 0x00000000);
812
813 hyperfb_setup_fb(sc);
814
815 /* make sure video output is enabled */
816 hyperfb_wait(sc);
817 hyperfb_write4(sc, NGLE_REG_33,
818 hyperfb_read4(sc, NGLE_REG_33) | 0x0a000000);
819
820 /* hyperbowl */
821 hyperfb_wait(sc);
822 if(sc->sc_24bit) {
823 /* write must happen twice because hw bug */
824 hyperfb_write4(sc, NGLE_REG_40, HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE);
825 hyperfb_write4(sc, NGLE_REG_40, HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE);
826 hyperfb_write4(sc, NGLE_REG_39, HYPERBOWL_MODE2_8_24);
827 hyperfb_write4(sc, NGLE_REG_42, 0x014c0148); /* Set lut 0 to be the direct color */
828 hyperfb_write4(sc, NGLE_REG_43, 0x404c4048);
829 hyperfb_write4(sc, NGLE_REG_44, 0x034c0348);
830 hyperfb_write4(sc, NGLE_REG_45, 0x444c4448);
831 } else {
832 hyperfb_write4(sc, NGLE_REG_40, HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES);
833 hyperfb_write4(sc, NGLE_REG_40, HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES);
834
835 hyperfb_write4(sc, NGLE_REG_42, 0);
836 hyperfb_write4(sc, NGLE_REG_43, 0);
837 hyperfb_write4(sc, NGLE_REG_44, 0);
838 hyperfb_write4(sc, NGLE_REG_45, 0);
839 }
840 /* cursor mask */
841 hyperfb_wait(sc);
842 hyperfb_write4(sc, NGLE_REG_30, 0);
843 for (i = 0; i < 64; i++) {
844 hyperfb_write4(sc, NGLE_REG_31, 0xffffffff);
845 hyperfb_write4(sc, NGLE_REG_31, 0xffffffff);
846 }
847
848 /* cursor image */
849 hyperfb_wait(sc);
850 hyperfb_write4(sc, NGLE_REG_30, 0x80);
851 for (i = 0; i < 64; i++) {
852 hyperfb_write4(sc, NGLE_REG_31, 0xff00ff00);
853 hyperfb_write4(sc, NGLE_REG_31, 0xff00ff00);
854 }
855
856 /* colour map - doesn't work yet*/
857 hyperfb_wait(sc);
858 hyperfb_write4(sc, NGLE_REG_10, 0xBBE0F000);
859 hyperfb_write4(sc, NGLE_REG_14, 0x03000300);
860 hyperfb_write4(sc, NGLE_REG_13, 0xffffffff);
861 hyperfb_wait(sc);
862 hyperfb_write4(sc, NGLE_REG_3, 0);
863 hyperfb_write4(sc, NGLE_REG_4, 0);
864 hyperfb_write4(sc, NGLE_REG_4, 0);
865 hyperfb_write4(sc, NGLE_REG_4, 0x000000ff); /* BG */
866 hyperfb_write4(sc, NGLE_REG_4, 0x00ff0000); /* FG */
867 hyperfb_wait(sc);
868 hyperfb_write4(sc, NGLE_REG_2, 0);
869 hyperfb_write4(sc, NGLE_REG_1, 0x80008004);
870 hyperfb_setup_fb(sc);
871
872 //hyperfb_write4(sc, NGLE_REG_29, 0x80200020);
873
874 //hyperfb_move_cursor(sc, 100, 100);
875
876 }
877
878 static void
879 hyperfb_set_video(struct hyperfb_softc *sc, int on)
880 {
881 uint32_t reg;
882
883 if (sc->sc_video_on == on)
884 return;
885
886 sc->sc_video_on = on;
887
888 hyperfb_wait(sc);
889 reg = hyperfb_read4(sc, NGLE_REG_33);
890
891 if (on) {
892 hyperfb_write4(sc, NGLE_REG_33, reg | 0x0a000000);
893 } else {
894 hyperfb_write4(sc, NGLE_REG_33, reg & ~0x0a000000);
895 }
896 }
897
898 static void
899 hyperfb_rectfill(struct hyperfb_softc *sc, int x, int y, int wi, int he,
900 uint32_t bg)
901 {
902 /*
903 * XXX
904 * HCRX has the same problem as VisEG drawing rectangles less than 32
905 * pixels wide, but here we don't seem to have any usable offscreen
906 * memory, at least not as long as we're using the overlay planes.
907 * As a workaround, fall back to memset()-based fills for rectangles
908 * less than 32 pixels wide
909 */
910 if (wi < 32) {
911 int i;
912 uint8_t *ptr = (uint8_t *)sc->sc_fb + (y << 11) + x;
913
914 if (sc->sc_hwmode != HW_FB)
915 hyperfb_setup_fb(sc);
916
917 for (i = 0; i < he; i++) {
918 memset(ptr, bg, wi);
919 ptr += 2048;
920 }
921 return;
922 }
923 if (sc->sc_hwmode != HW_FILL) {
924 hyperfb_wait_fifo(sc, 4);
925 /* transfer data */
926 hyperfb_write4(sc, NGLE_REG_8, 0xffffffff);
927 /* plane mask */
928 hyperfb_write4(sc, NGLE_REG_13, 0xff);
929 /* bitmap op */
930 hyperfb_write4(sc, NGLE_REG_14,
931 IBOvals(RopSrc, 0, BitmapExtent08, 0, DataDynamic, MaskOtc, 0, 0));
932 /* dst bitmap access */
933 hyperfb_write4(sc, NGLE_REG_11,
934 BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINovly, 0));
935 sc->sc_hwmode = HW_FILL;
936 }
937 hyperfb_wait_fifo(sc, 3);
938 hyperfb_write4(sc, NGLE_REG_35, bg);
939 /* dst XY */
940 hyperfb_write4(sc, NGLE_REG_6, (x << 16) | y);
941 /* len XY start */
942 hyperfb_write4(sc, NGLE_REG_9, (wi << 16) | he);
943 }
944
945 static void
946 hyperfb_bitblt(void *cookie, int xs, int ys, int xd, int yd, int wi,
947 int he, int rop)
948 {
949 struct hyperfb_softc *sc = cookie;
950
951 if (sc->sc_hwmode != HW_BLIT) {
952 hyperfb_wait(sc);
953 hyperfb_write4(sc, NGLE_REG_10, 0x13a02000);
954 hyperfb_write4(sc, NGLE_REG_13, 0xff);
955 sc->sc_hwmode = HW_BLIT;
956 }
957 hyperfb_wait_fifo(sc, 4);
958 hyperfb_write4(sc, NGLE_REG_14, ((rop << 8) & 0xf00) | 0x23000000);
959 /* IBOvals(rop, 0, BitmapExtent08, 1, DataDynamic, MaskOtc, 0, 0) */
960 hyperfb_write4(sc, NGLE_REG_24, (xs << 16) | ys);
961 hyperfb_write4(sc, NGLE_REG_7, (wi << 16) | he);
962 hyperfb_write4(sc, NGLE_REG_25, (xd << 16) | yd);
963 }
964
965 static void
966 hyperfb_nuke_cursor(struct rasops_info *ri)
967 {
968 struct vcons_screen *scr = ri->ri_hw;
969 struct hyperfb_softc *sc = scr->scr_cookie;
970 int wi, he, x, y;
971
972 if (ri->ri_flg & RI_CURSOR) {
973 wi = ri->ri_font->fontwidth;
974 he = ri->ri_font->fontheight;
975 x = ri->ri_ccol * wi + ri->ri_xorigin;
976 y = ri->ri_crow * he + ri->ri_yorigin;
977 hyperfb_bitblt(sc, x, y, x, y, wi, he, RopInv);
978 ri->ri_flg &= ~RI_CURSOR;
979 }
980 }
981
982 static void
983 hyperfb_cursor(void *cookie, int on, int row, int col)
984 {
985 struct rasops_info *ri = cookie;
986 struct vcons_screen *scr = ri->ri_hw;
987 struct hyperfb_softc *sc = scr->scr_cookie;
988 int x, y, wi, he;
989
990 wi = ri->ri_font->fontwidth;
991 he = ri->ri_font->fontheight;
992
993 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
994 if (on) {
995 if (ri->ri_flg & RI_CURSOR) {
996 hyperfb_nuke_cursor(ri);
997 }
998 x = col * wi + ri->ri_xorigin;
999 y = row * he + ri->ri_yorigin;
1000 hyperfb_bitblt(sc, x, y, x, y, wi, he, RopInv);
1001 ri->ri_flg |= RI_CURSOR;
1002 }
1003 ri->ri_crow = row;
1004 ri->ri_ccol = col;
1005 } else
1006 {
1007 ri->ri_crow = row;
1008 ri->ri_ccol = col;
1009 ri->ri_flg &= ~RI_CURSOR;
1010 }
1011
1012 }
1013
1014 static void
1015 hyperfb_putchar(void *cookie, int row, int col, u_int c, long attr)
1016 {
1017 struct rasops_info *ri = cookie;
1018 struct wsdisplay_font *font = PICK_FONT(ri, c);
1019 struct vcons_screen *scr = ri->ri_hw;
1020 struct hyperfb_softc *sc = scr->scr_cookie;
1021 int x, y, wi, he/*, rv = GC_NOPE*/;
1022 uint32_t bg;
1023
1024 if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL)
1025 return;
1026
1027 if (!CHAR_IN_FONT(c, font))
1028 return;
1029
1030 if (row == ri->ri_crow && col == ri->ri_ccol) {
1031 ri->ri_flg &= ~RI_CURSOR;
1032 }
1033
1034 wi = font->fontwidth;
1035 he = font->fontheight;
1036
1037 x = ri->ri_xorigin + col * wi;
1038 y = ri->ri_yorigin + row * he;
1039
1040 bg = ri->ri_devcmap[(attr >> 16) & 0xf];
1041
1042 if (c == 0x20) {
1043 hyperfb_rectfill(sc, x, y, wi, he, bg);
1044 return;
1045 }
1046
1047 #if 0
1048 rv = glyphcache_try(&sc->sc_gc, c, x, y, attr);
1049 if (rv == GC_OK)
1050 return;
1051 #endif
1052 if (sc->sc_hwmode != HW_FB) hyperfb_setup_fb(sc);
1053 sc->sc_putchar(cookie, row, col, c, attr);
1054 #if 0
1055 if (rv == GC_ADD)
1056 glyphcache_add(&sc->sc_gc, c, x, y);
1057 #endif
1058 }
1059
1060 static void
1061 hyperfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
1062 {
1063 struct rasops_info *ri = cookie;
1064 struct vcons_screen *scr = ri->ri_hw;
1065 struct hyperfb_softc *sc = scr->scr_cookie;
1066 int32_t xs, xd, y, width, height;
1067
1068 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1069 if (ri->ri_crow == row &&
1070 (ri->ri_ccol >= srccol && ri->ri_ccol < (srccol + ncols)) &&
1071 (ri->ri_flg & RI_CURSOR)) {
1072 hyperfb_nuke_cursor(ri);
1073 }
1074
1075 xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
1076 xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
1077 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1078 width = ri->ri_font->fontwidth * ncols;
1079 height = ri->ri_font->fontheight;
1080 hyperfb_bitblt(sc, xs, y, xd, y, width, height, RopSrc);
1081 if (ri->ri_crow == row &&
1082 (ri->ri_ccol >= dstcol && ri->ri_ccol < (dstcol + ncols)))
1083 ri->ri_flg &= ~RI_CURSOR;
1084 }
1085 }
1086
1087 static void
1088 hyperfb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
1089 {
1090 struct rasops_info *ri = cookie;
1091 struct vcons_screen *scr = ri->ri_hw;
1092 struct hyperfb_softc *sc = scr->scr_cookie;
1093 int32_t x, y, width, height, fg, bg, ul;
1094
1095 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1096 x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
1097 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1098 width = ri->ri_font->fontwidth * ncols;
1099 height = ri->ri_font->fontheight;
1100 rasops_unpack_attr(fillattr, &fg, &bg, &ul);
1101
1102 hyperfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
1103 if (ri->ri_crow == row &&
1104 (ri->ri_ccol >= startcol && ri->ri_ccol < (startcol + ncols)))
1105 ri->ri_flg &= ~RI_CURSOR;
1106 }
1107 }
1108
1109 static void
1110 hyperfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
1111 {
1112 struct rasops_info *ri = cookie;
1113 struct vcons_screen *scr = ri->ri_hw;
1114 struct hyperfb_softc *sc = scr->scr_cookie;
1115 int32_t x, ys, yd, width, height;
1116
1117 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1118 if ((ri->ri_crow >= srcrow && ri->ri_crow < (srcrow + nrows)) &&
1119 (ri->ri_flg & RI_CURSOR)) {
1120 hyperfb_nuke_cursor(ri);
1121 }
1122 x = ri->ri_xorigin;
1123 ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
1124 yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
1125 width = ri->ri_emuwidth;
1126 height = ri->ri_font->fontheight * nrows;
1127 hyperfb_bitblt(sc, x, ys, x, yd, width, height, RopSrc);
1128 if (ri->ri_crow >= dstrow && ri->ri_crow < (dstrow + nrows))
1129 ri->ri_flg &= ~RI_CURSOR;
1130 }
1131 }
1132
1133 static void
1134 hyperfb_eraserows(void *cookie, int row, int nrows, long fillattr)
1135 {
1136 struct rasops_info *ri = cookie;
1137 struct vcons_screen *scr = ri->ri_hw;
1138 struct hyperfb_softc *sc = scr->scr_cookie;
1139 int32_t x, y, width, height, fg, bg, ul;
1140
1141 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
1142 x = ri->ri_xorigin;
1143 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
1144 width = ri->ri_emuwidth;
1145 height = ri->ri_font->fontheight * nrows;
1146 rasops_unpack_attr(fillattr, &fg, &bg, &ul);
1147
1148 hyperfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
1149
1150 if (ri->ri_crow >= row && ri->ri_crow < (row + nrows))
1151 ri->ri_flg &= ~RI_CURSOR;
1152 }
1153 }
1154