agten.c revision 1.3 1 /* $NetBSD: agten.c,v 1.3 2007/08/27 02:03:15 macallan Exp $ */
2
3 /*-
4 * Copyright (c) 2007 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 * 3. Neither the name of The NetBSD Foundation nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: agten.c,v 1.3 2007/08/27 02:03:15 macallan Exp $");
34
35 /*
36 * a driver for the Fujitsu AG-10e SBus framebuffer
37 *
38 * this thing is Frankenstein's Monster among graphics boards.
39 * it contains three graphics chips:
40 * a GLint - 24bit stuff, double-buffered
41 * an Imagine 128 which provides an 8bit overlay
42 * a Weitek P9100 which provides WIDs
43 * so here we need to mess only with the P9100 and the I128 - for X we just
44 * hide the overlay and let the Xserver mess with the GLint
45 */
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
50 #include <sys/device.h>
51 #include <sys/proc.h>
52 #include <sys/mutex.h>
53 #include <sys/ioctl.h>
54 #include <sys/kernel.h>
55 #include <sys/systm.h>
56 #include <sys/malloc.h>
57
58 #include <dev/sun/fbio.h>
59 #include <dev/sun/fbvar.h>
60 #include <dev/sun/btreg.h>
61 #include <dev/sun/btvar.h>
62
63 #include <machine/bus.h>
64 #include <machine/autoconf.h>
65
66 #include <dev/sbus/sbusvar.h>
67
68 #include <dev/wscons/wsconsio.h>
69 #include <dev/wscons/wsdisplayvar.h>
70 #include <dev/rasops/rasops.h>
71 #include <dev/wsfont/wsfont.h>
72
73 #include <dev/wscons/wsdisplay_vconsvar.h>
74
75 #include <dev/sbus/p9100reg.h>
76 #include <dev/ic/ibm561reg.h>
77 #include <dev/ic/i128reg.h>
78 #include <dev/ic/i128var.h>
79
80 #include "opt_agten.h"
81
82 static int agten_match(struct device *, struct cfdata *, void *);
83 static void agten_attach(struct device *, struct device *, void *);
84
85 #if 0
86 static void agten_unblank(struct device *);
87 #endif
88
89 static int agten_ioctl(void *, void *, u_long, void *, int, struct lwp *);
90 static paddr_t agten_mmap(void *, void *, off_t, int);
91 static void agten_init_screen(void *, struct vcons_screen *, int, long *);
92
93 struct agten_softc {
94 struct device sc_dev; /* base device */
95 struct sbusdev sc_sd; /* sbus device */
96 struct fbdevice sc_fb; /* frame buffer device */
97
98 struct vcons_screen sc_console_screen;
99 struct wsscreen_descr sc_defaultscreen_descr;
100 const struct wsscreen_descr *sc_screens[1];
101 struct wsscreen_list sc_screenlist;
102
103 bus_space_tag_t sc_bustag;
104
105 bus_space_handle_t sc_i128_fbh;
106 bus_size_t sc_i128_fbsz;
107 bus_space_handle_t sc_i128_regh;
108 bus_space_handle_t sc_p9100_regh;
109 bus_addr_t sc_glint_fb;
110 bus_addr_t sc_glint_regs;
111 uint32_t sc_glint_fbsz;
112
113 uint32_t sc_width;
114 uint32_t sc_height; /* panel width / height */
115 uint32_t sc_stride;
116 uint32_t sc_depth;
117
118 union bt_cmap sc_cmap; /* Brooktree color map */
119
120 int sc_mode;
121 int sc_video, sc_powerstate;
122 uint32_t sc_bg;
123 struct vcons_data vd;
124 };
125
126 CFATTACH_DECL(agten, sizeof(struct agten_softc),
127 agten_match, agten_attach, NULL, NULL);
128
129
130 static int agten_putcmap(struct agten_softc *, struct wsdisplay_cmap *);
131 static int agten_getcmap(struct agten_softc *, struct wsdisplay_cmap *);
132 static int agten_putpalreg(struct agten_softc *, uint8_t, uint8_t,
133 uint8_t, uint8_t);
134 static void agten_init(struct agten_softc *);
135 static void agten_gfx(struct agten_softc *);
136
137 static void agten_copycols(void *, int, int, int, int);
138 static void agten_erasecols(void *, int, int, int, long);
139 static void agten_copyrows(void *, int, int, int);
140 static void agten_eraserows(void *, int, int, long);
141
142 extern const u_char rasops_cmap[768];
143
144 struct wsdisplay_accessops agten_accessops = {
145 agten_ioctl,
146 agten_mmap,
147 NULL, /* alloc_screen */
148 NULL, /* free_screen */
149 NULL, /* show_screen */
150 NULL, /* load_font */
151 NULL, /* pollc */
152 NULL /* scroll */
153 };
154
155 static inline void
156 agten_write_dac(struct agten_softc *sc, int reg, uint8_t val)
157 {
158 bus_space_write_4(sc->sc_bustag, sc->sc_p9100_regh,
159 0x200 + (reg << 2), (uint32_t)val << 16);
160 }
161
162 static inline void
163 agten_write_idx(struct agten_softc *sc, int offset)
164 {
165 bus_space_write_4(sc->sc_bustag, sc->sc_p9100_regh,
166 0x200 + (IBM561_ADDR_LOW << 2), (offset & 0xff) << 16);
167 bus_space_write_4(sc->sc_bustag, sc->sc_p9100_regh,
168 0x200 + (IBM561_ADDR_HIGH << 2), ((offset >> 8) & 0xff) << 16);
169 }
170
171 static inline void
172 agten_write_dac_10(struct agten_softc *sc, int reg, uint16_t val)
173 {
174 agten_write_dac(sc, reg, (val >> 2) & 0xff);
175 agten_write_dac(sc, reg, (val & 0x3) << 6);
176 }
177
178 static int
179 agten_match(struct device *dev, struct cfdata *cf, void *aux)
180 {
181 struct sbus_attach_args *sa = aux;
182
183 if (strcmp("PFU,aga", sa->sa_name) == 0)
184 return 100;
185 return 0;
186 }
187
188 static void
189 agten_attach(struct device *parent, struct device *dev, void *aux)
190 {
191 struct agten_softc *sc = (struct agten_softc *)dev;
192 struct sbus_attach_args *sa = aux;
193 struct fbdevice *fb = &sc->sc_fb;
194 struct wsemuldisplaydev_attach_args aa;
195 struct rasops_info *ri;
196 long defattr;
197 uint32_t reg;
198 int node = sa->sa_node;
199 int console;
200
201 sc->sc_defaultscreen_descr = (struct wsscreen_descr){
202 "default",
203 0, 0,
204 NULL,
205 8, 16,
206 WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
207 NULL
208 };
209 sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
210 sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
211 sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
212 sc->sc_bustag = sa->sa_bustag;
213 #if 0
214 sc->sc_shadowfb = malloc(sc->sc_fbsize, M_DEVBUF, M_WAITOK);
215
216 dict = device_properties(&sc->sc_dev);
217
218 prop_dictionary_get_bool(dict, "is_console", &console);
219 #endif
220
221 reg = prom_getpropint(node, "i128_fb_physaddr", -1);
222 sc->sc_i128_fbsz = prom_getpropint(node, "i128_fb_size", -1);
223 if (sbus_bus_map(sc->sc_bustag,
224 sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base + reg,
225 sc->sc_i128_fbsz, BUS_SPACE_MAP_LINEAR, &sc->sc_i128_fbh) != 0) {
226
227 aprint_error("%s: unable to map the framebuffer\n",
228 dev->dv_xname);
229 return;
230 }
231 fb->fb_pixels = bus_space_vaddr(sc->sc_bustag, sc->sc_i128_fbh);
232
233 reg = prom_getpropint(node, "i128_reg_physaddr", -1);
234 if (sbus_bus_map(sc->sc_bustag,
235 sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base + reg,
236 0x10000, 0, &sc->sc_i128_regh) != 0) {
237
238 aprint_error("%s: unable to map I128 registers\n",
239 dev->dv_xname);
240 return;
241 }
242
243 reg = prom_getpropint(node, "p9100_reg_physaddr", -1);
244 if (sbus_bus_map(sc->sc_bustag,
245 sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base + reg,
246 0x8000, 0, &sc->sc_p9100_regh) != 0) {
247
248 aprint_error("%s: unable to map P9100 registers\n",
249 dev->dv_xname);
250 return;
251 }
252
253 reg = prom_getpropint(node, "glint_fb0_physaddr", -1);
254 sc->sc_glint_fb = sbus_bus_addr(sc->sc_bustag,
255 sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base + reg);
256 sc->sc_glint_fbsz = prom_getpropint(node, "glint_fb0_size", -1);
257 reg = prom_getpropint(node, "glint_reg_physaddr", -1);
258 sc->sc_glint_regs = sbus_bus_addr(sc->sc_bustag,
259 sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base + reg);
260
261 sbus_establish(&sc->sc_sd, &sc->sc_dev);
262 #if 0
263 bus_intr_establish(sc->sc_bustag, sa->sa_pri, IPL_BIO,
264 agten_intr, sc);
265 #endif
266
267 sc->sc_width = prom_getpropint(node, "ffb_width", 800);
268 sc->sc_height = prom_getpropint(node, "ffb_height", 600);
269 sc->sc_depth = prom_getpropint(node, "ffb_depth", 8);
270 sc->sc_stride = sc->sc_width * (sc->sc_depth >> 3);
271
272 agten_init(sc);
273
274 console = fb_is_console(node);
275
276 vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
277 &agten_accessops);
278 sc->vd.init_screen = agten_init_screen;
279
280 ri = &sc->sc_console_screen.scr_ri;
281
282 if (console) {
283 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
284 &defattr);
285 sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
286
287 sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
288 sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
289 sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
290 sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
291 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
292 defattr);
293 i128_rectfill(sc->sc_bustag, sc->sc_i128_regh, 0, 0,
294 sc->sc_width, sc->sc_height,
295 ri->ri_devcmap[(defattr >> 16) & 0xff]);
296 } else {
297 /*
298 * since we're not the console we can postpone the rest
299 * until someone actually allocates a screen for us
300 */
301 }
302
303 /* Initialize the default color map. */
304
305 aa.console = console;
306 aa.scrdata = &sc->sc_screenlist;
307 aa.accessops = &agten_accessops;
308 aa.accesscookie = &sc->vd;
309
310 config_found(&sc->sc_dev, &aa, wsemuldisplaydevprint);
311 }
312
313 static int
314 agten_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
315 struct lwp *l)
316 {
317 struct vcons_data *vd = v;
318 struct agten_softc *sc = vd->cookie;
319 struct wsdisplay_fbinfo *wdf;
320 struct vcons_screen *ms = vd->active;
321
322 switch (cmd) {
323
324 case WSDISPLAYIO_GTYPE:
325 *(u_int *)data = WSDISPLAY_TYPE_AG10;
326 return 0;
327
328 case WSDISPLAYIO_GINFO:
329 if (ms == NULL)
330 return ENODEV;
331 wdf = (void *)data;
332 wdf->height = ms->scr_ri.ri_height;
333 wdf->width = ms->scr_ri.ri_width;
334 wdf->depth = 32;
335 wdf->cmsize = 256;
336 return 0;
337
338 case WSDISPLAYIO_GETCMAP:
339 return agten_getcmap(sc,
340 (struct wsdisplay_cmap *)data);
341
342 case WSDISPLAYIO_PUTCMAP:
343 return agten_putcmap(sc,
344 (struct wsdisplay_cmap *)data);
345
346 case WSDISPLAYIO_LINEBYTES:
347 *(u_int *)data = sc->sc_stride << 2;
348 return 0;
349
350 case WSDISPLAYIO_SMODE:
351 {
352 int new_mode = *(int*)data;
353 if (new_mode != sc->sc_mode) {
354 sc->sc_mode = new_mode;
355 if(new_mode == WSDISPLAYIO_MODE_EMUL) {
356 agten_init(sc);
357 vcons_redraw_screen(ms);
358 } else {
359 agten_gfx(sc);
360 }
361 }
362 }
363 return 0;
364 }
365 return EPASSTHROUGH;
366 }
367
368 static paddr_t
369 agten_mmap(void *v, void *vs, off_t offset, int prot)
370 {
371 struct vcons_data *vd = v;
372 struct agten_softc *sc = vd->cookie;
373
374 if (offset < sc->sc_glint_fbsz)
375 return bus_space_mmap(sc->sc_bustag, sc->sc_glint_fb, offset,
376 prot, BUS_SPACE_MAP_LINEAR);
377 return -1;
378 }
379
380 static void
381 agten_init_screen(void *cookie, struct vcons_screen *scr,
382 int existing, long *defattr)
383 {
384 struct agten_softc *sc = cookie;
385 struct rasops_info *ri = &scr->scr_ri;
386
387 ri->ri_depth = sc->sc_depth;
388 ri->ri_width = sc->sc_width;
389 ri->ri_height = sc->sc_height;
390 ri->ri_stride = sc->sc_stride;
391 ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
392
393 ri->ri_bits = (char *)sc->sc_fb.fb_pixels;
394
395 if (existing) {
396 ri->ri_flg |= RI_CLEAR;
397 }
398
399 rasops_init(ri, sc->sc_height / 8, sc->sc_width / 8);
400 ri->ri_caps = WSSCREEN_WSCOLORS;
401
402 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
403 sc->sc_width / ri->ri_font->fontwidth);
404
405 ri->ri_hw = scr;
406 ri->ri_ops.copyrows = agten_copyrows;
407 ri->ri_ops.eraserows = agten_eraserows;
408 ri->ri_ops.copycols = agten_copycols;
409 ri->ri_ops.erasecols = agten_erasecols;
410
411 }
412
413 static int
414 agten_putcmap(struct agten_softc *sc, struct wsdisplay_cmap *cm)
415 {
416 u_int index = cm->index;
417 u_int count = cm->count;
418 int i, error;
419 u_char rbuf[256], gbuf[256], bbuf[256];
420 u_char *r, *g, *b;
421
422 if (cm->index >= 256 || cm->count > 256 ||
423 (cm->index + cm->count) > 256)
424 return EINVAL;
425 error = copyin(cm->red, &rbuf[index], count);
426 if (error)
427 return error;
428 error = copyin(cm->green, &gbuf[index], count);
429 if (error)
430 return error;
431 error = copyin(cm->blue, &bbuf[index], count);
432 if (error)
433 return error;
434
435 r = &rbuf[index];
436 g = &gbuf[index];
437 b = &bbuf[index];
438
439 for (i = 0; i < count; i++) {
440 agten_putpalreg(sc, index, *r, *g, *b);
441 index++;
442 r++, g++, b++;
443 }
444 return 0;
445 }
446
447 static int
448 agten_getcmap(struct agten_softc *sc, struct wsdisplay_cmap *cm)
449 {
450 u_int index = cm->index;
451 u_int count = cm->count;
452 int error, i;
453 uint8_t red[256], green[256], blue[256];
454
455 if (index >= 255 || count > 256 || index + count > 256)
456 return EINVAL;
457
458 i = index;
459 while (i < (index + count)) {
460 red[i] = sc->sc_cmap.cm_map[i][0];
461 green[i] = sc->sc_cmap.cm_map[i][1];
462 blue[i] = sc->sc_cmap.cm_map[i][2];
463 i++;
464 }
465 error = copyout(&red[index], cm->red, count);
466 if (error)
467 return error;
468 error = copyout(&green[index], cm->green, count);
469 if (error)
470 return error;
471 error = copyout(&blue[index], cm->blue, count);
472 if (error)
473 return error;
474
475 return 0;
476 }
477
478 static int
479 agten_putpalreg(struct agten_softc *sc, uint8_t idx, uint8_t r, uint8_t g,
480 uint8_t b)
481 {
482
483 sc->sc_cmap.cm_map[idx][0] = r;
484 sc->sc_cmap.cm_map[idx][1] = g;
485 sc->sc_cmap.cm_map[idx][2] = b;
486 agten_write_idx(sc, IBM561_CMAP_TABLE + idx);
487 agten_write_dac(sc, IBM561_CMD_CMAP, r);
488 agten_write_dac(sc, IBM561_CMD_CMAP, g);
489 agten_write_dac(sc, IBM561_CMD_CMAP, b);
490 return 0;
491 }
492
493 static void
494 agten_init(struct agten_softc *sc)
495 {
496 int i, j;
497 uint32_t src, srcw;
498 volatile uint32_t junk;
499
500 /* first we set up the colour map */
501 j = 0;
502 for (i = 0; i < 256; i++) {
503
504 agten_putpalreg(sc, i, rasops_cmap[j], rasops_cmap[j + 1],
505 rasops_cmap[j + 2]);
506 j += 3;
507 }
508
509 /* then we set up a linear LUT for 24bit colour */
510 agten_write_idx(sc, IBM561_CMAP_TABLE + 256);
511 for (i = 0; i < 256; i++) {
512 agten_write_dac(sc, IBM561_CMD_CMAP, i);
513 agten_write_dac(sc, IBM561_CMD_CMAP, i);
514 agten_write_dac(sc, IBM561_CMD_CMAP, i);
515 }
516
517 /* and the linear gamma maps */
518 agten_write_idx(sc, IBM561_RED_GAMMA_TABLE);
519 for (i = 0; i < 0x3ff; i+= 4)
520 agten_write_dac_10(sc, IBM561_CMD_GAMMA, i);
521 agten_write_idx(sc, IBM561_GREEN_GAMMA_TABLE);
522 for (i = 0; i < 0x3ff; i+= 4)
523 agten_write_dac_10(sc, IBM561_CMD_GAMMA, i);
524 agten_write_idx(sc, IBM561_BLUE_GAMMA_TABLE);
525 for (i = 0; i < 0x3ff; i+= 4)
526 agten_write_dac_10(sc, IBM561_CMD_GAMMA, i);
527
528 /* enable outouts, RGB mode */
529 agten_write_idx(sc, IBM561_CONFIG_REG3);
530 agten_write_dac(sc, IBM561_CMD, 0x41);
531
532 /* MUX 4:1 basic, 8bit overlay, 8bit WIDs */
533 agten_write_idx(sc, IBM561_CONFIG_REG1);
534 agten_write_dac(sc, IBM561_CMD, 0x2c);
535
536 /* now set up some window attributes */
537
538 /*
539 * direct colour, 24 bit, transparency off, LUT from 0x100
540 * we need to use direct colour and a linear LUT because for some
541 * reason true color mode gives messed up colours
542 */
543 agten_write_idx(sc, IBM561_FB_WINTYPE);
544 agten_write_dac_10(sc, IBM561_CMD_FB_WAT, 0x134);
545
546 /* use gamma LUTs, no crosshair, 0 is transparent */
547 agten_write_idx(sc, IBM561_AUXFB_WINTYPE);
548 agten_write_dac(sc, IBM561_CMD_FB_WAT, 0x0);
549
550 /* overlay is 8 bit, opaque */
551 agten_write_idx(sc, IBM561_OL_WINTYPE);
552 agten_write_dac_10(sc, IBM561_CMD_FB_WAT, 0x00);
553
554 /* now we fill the WID fb with zeroes */
555 src = 0;
556 srcw = sc->sc_width << 16 | sc->sc_height;
557 bus_space_write_4(sc->sc_bustag, sc->sc_p9100_regh, FOREGROUND_COLOR,
558 0x0);
559 bus_space_write_4(sc->sc_bustag, sc->sc_p9100_regh, BACKGROUND_COLOR,
560 0x0);
561 bus_space_write_4(sc->sc_bustag, sc->sc_p9100_regh, RASTER_OP, ROP_PAT);
562 bus_space_write_4(sc->sc_bustag, sc->sc_p9100_regh, COORD_INDEX, 0);
563 bus_space_write_4(sc->sc_bustag, sc->sc_p9100_regh, RECT_RTW_XY, src);
564 bus_space_write_4(sc->sc_bustag, sc->sc_p9100_regh, RECT_RTW_XY, srcw);
565 junk = bus_space_read_4(sc->sc_bustag, sc->sc_p9100_regh, COMMAND_QUAD);
566
567 i128_init(sc->sc_bustag, sc->sc_i128_regh, sc->sc_stride, 8);
568 }
569
570 static void
571 agten_gfx(struct agten_softc *sc)
572 {
573 /* enable overlay transparency on colour 0x00 */
574 agten_write_idx(sc, IBM561_OL_WINTYPE);
575 agten_write_dac_10(sc, IBM561_CMD_FB_WAT, 0x01);
576
577 /* then blit the overlay full of 0x00 */
578 i128_rectfill(sc->sc_bustag, sc->sc_i128_regh, 0, 0, sc->sc_width,
579 sc->sc_height, 0);
580
581 /* ... so we can see the 24bit framebuffer */
582 }
583
584 static void
585 agten_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
586 {
587 struct rasops_info *ri = cookie;
588 struct vcons_screen *scr = ri->ri_hw;
589 struct agten_softc *sc = scr->scr_cookie;
590 int32_t xs, xd, y, width, height;
591
592 xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
593 xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
594 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
595 width = ri->ri_font->fontwidth * ncols;
596 height = ri->ri_font->fontheight;
597 i128_bitblt(sc->sc_bustag, sc->sc_i128_regh, xs, y, xd, y, width,
598 height, CR_COPY);
599 }
600
601 static void
602 agten_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
603 {
604 struct rasops_info *ri = cookie;
605 struct vcons_screen *scr = ri->ri_hw;
606 struct agten_softc *sc = scr->scr_cookie;
607 int32_t x, y, width, height, bg;
608
609 x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
610 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
611 width = ri->ri_font->fontwidth * ncols;
612 height = ri->ri_font->fontheight;
613 bg = (uint32_t)ri->ri_devcmap[(fillattr >> 16) & 0xff];
614 i128_rectfill(sc->sc_bustag, sc->sc_i128_regh, x, y, width, height, bg);
615 }
616
617 static void
618 agten_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
619 {
620 struct rasops_info *ri = cookie;
621 struct vcons_screen *scr = ri->ri_hw;
622 struct agten_softc *sc = scr->scr_cookie;
623 int32_t x, ys, yd, width, height;
624
625 x = ri->ri_xorigin;
626 ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
627 yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
628 width = ri->ri_emuwidth;
629 height = ri->ri_font->fontheight * nrows;
630 i128_bitblt(sc->sc_bustag, sc->sc_i128_regh, x, ys, x, yd, width,
631 height, CR_COPY);
632 }
633
634 static void
635 agten_eraserows(void *cookie, int row, int nrows, long fillattr)
636 {
637 struct rasops_info *ri = cookie;
638 struct vcons_screen *scr = ri->ri_hw;
639 struct agten_softc *sc = scr->scr_cookie;
640 int32_t x, y, width, height, bg;
641
642 if ((row == 0) && (nrows == ri->ri_rows)) {
643 x = y = 0;
644 width = ri->ri_width;
645 height = ri->ri_height;
646 } else {
647 x = ri->ri_xorigin;
648 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
649 width = ri->ri_emuwidth;
650 height = ri->ri_font->fontheight * nrows;
651 }
652 bg = (uint32_t)ri->ri_devcmap[(fillattr >> 16) & 0xff];
653 i128_rectfill(sc->sc_bustag, sc->sc_i128_regh, x, y, width, height, bg);
654 }
655