Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / voyagerfb.c
blob88c56d47002a35138cd8d43d93d3818552bba90e
1 /* $NetBSD: voyagerfb.c,v 1.1 2009/08/12 19:28:00 macallan Exp $ */
3 /*
4 * Copyright (c) 2009 Michael Lorenz
5 * All rights reserved.
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.
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 BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * A console driver for Silicon Motion SM502 / Voyager GX graphics controllers
30 * tested on GDIUM only so far
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: voyagerfb.c,v 1.1 2009/08/12 19:28:00 macallan Exp $");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/device.h>
40 #include <sys/malloc.h>
41 #include <sys/lwp.h>
42 #include <sys/kauth.h>
44 #include <uvm/uvm_extern.h>
46 #include <dev/videomode/videomode.h>
48 #include <dev/pci/pcivar.h>
49 #include <dev/pci/pcireg.h>
50 #include <dev/pci/pcidevs.h>
51 #include <dev/pci/pciio.h>
52 #include <dev/ic/sm502reg.h>
54 #include <dev/wscons/wsdisplayvar.h>
55 #include <dev/wscons/wsconsio.h>
56 #include <dev/wsfont/wsfont.h>
57 #include <dev/rasops/rasops.h>
58 #include <dev/wscons/wsdisplay_vconsvar.h>
60 #include <dev/i2c/i2cvar.h>
62 struct voyagerfb_softc {
63 device_t sc_dev;
65 pci_chipset_tag_t sc_pc;
66 pcitag_t sc_pcitag;
68 bus_space_tag_t sc_memt;
69 bus_space_tag_t sc_iot;
71 bus_space_handle_t sc_fbh;
72 bus_space_handle_t sc_regh;
73 bus_addr_t sc_fb, sc_reg;
74 bus_size_t sc_fbsize, sc_regsize;
76 int sc_width, sc_height, sc_depth, sc_stride;
77 int sc_locked;
78 void *sc_fbaddr;
79 struct vcons_screen sc_console_screen;
80 struct wsscreen_descr sc_defaultscreen_descr;
81 const struct wsscreen_descr *sc_screens[1];
82 struct wsscreen_list sc_screenlist;
83 struct vcons_data vd;
84 uint8_t *sc_dataport;
85 int sc_mode;
86 u_char sc_cmap_red[256];
87 u_char sc_cmap_green[256];
88 u_char sc_cmap_blue[256];
91 static int voyagerfb_match(device_t, cfdata_t, void *);
92 static void voyagerfb_attach(device_t, device_t, void *);
94 CFATTACH_DECL_NEW(voyagerfb, sizeof(struct voyagerfb_softc),
95 voyagerfb_match, voyagerfb_attach, NULL, NULL);
97 extern const u_char rasops_cmap[768];
99 static int voyagerfb_ioctl(void *, void *, u_long, void *, int,
100 struct lwp *);
101 static paddr_t voyagerfb_mmap(void *, void *, off_t, int);
102 static void voyagerfb_init_screen(void *, struct vcons_screen *, int,
103 long *);
105 static int voyagerfb_putcmap(struct voyagerfb_softc *,
106 struct wsdisplay_cmap *);
107 static int voyagerfb_getcmap(struct voyagerfb_softc *,
108 struct wsdisplay_cmap *);
109 static void voyagerfb_restore_palette(struct voyagerfb_softc *);
110 static int voyagerfb_putpalreg(struct voyagerfb_softc *, int, uint8_t,
111 uint8_t, uint8_t);
113 static void voyagerfb_init(struct voyagerfb_softc *);
115 static void voyagerfb_rectfill(struct voyagerfb_softc *, int, int, int, int,
116 uint32_t);
117 static void voyagerfb_bitblt(struct voyagerfb_softc *, int, int, int, int,
118 int, int, int);
120 static void voyagerfb_cursor(void *, int, int, int);
121 static void voyagerfb_putchar(void *, int, int, u_int, long);
122 static void voyagerfb_copycols(void *, int, int, int, int);
123 static void voyagerfb_erasecols(void *, int, int, int, long);
124 static void voyagerfb_copyrows(void *, int, int, int);
125 static void voyagerfb_eraserows(void *, int, int, long);
127 struct wsdisplay_accessops voyagerfb_accessops = {
128 voyagerfb_ioctl,
129 voyagerfb_mmap,
130 NULL, /* alloc_screen */
131 NULL, /* free_screen */
132 NULL, /* show_screen */
133 NULL, /* load_font */
134 NULL, /* pollc */
135 NULL /* scroll */
138 /* wait for FIFO empty so we can feed it another command */
139 static inline void
140 voyagerfb_ready(struct voyagerfb_softc *sc)
142 do {} while ((bus_space_read_4(sc->sc_memt, sc->sc_regh,
143 SM502_SYSTEM_CTRL) & SM502_SYSCTL_FIFO_EMPTY) == 0);
146 /* wait for the drawing engine to be idle */
147 static inline void
148 voyagerfb_wait(struct voyagerfb_softc *sc)
150 do {} while ((bus_space_read_4(sc->sc_memt, sc->sc_regh,
151 SM502_SYSTEM_CTRL) & SM502_SYSCTL_ENGINE_BUSY) != 0);
154 static int
155 voyagerfb_match(device_t parent, cfdata_t match, void *aux)
157 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
159 if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY)
160 return 0;
161 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_SILMOTION)
162 return 0;
164 /* only chip tested on so far - may need a list */
165 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SILMOTION_SM502)
166 return 100;
167 return (0);
170 static void
171 voyagerfb_attach(device_t parent, device_t self, void *aux)
173 struct voyagerfb_softc *sc = device_private(self);
174 struct pci_attach_args *pa = aux;
175 struct rasops_info *ri;
176 char devinfo[256];
177 struct wsemuldisplaydev_attach_args aa;
178 prop_dictionary_t dict;
179 unsigned long defattr;
180 uint32_t reg;
181 bool is_console;
182 int i, j;
184 sc->sc_pc = pa->pa_pc;
185 sc->sc_pcitag = pa->pa_tag;
186 sc->sc_memt = pa->pa_memt;
187 sc->sc_iot = pa->pa_iot;
188 sc->sc_dev = self;
190 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
191 aprint_normal(": %s\n", devinfo);
193 dict = device_properties(self);
194 prop_dictionary_get_bool(dict, "is_console", &is_console);
196 if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_MEM,
197 BUS_SPACE_MAP_LINEAR,
198 &sc->sc_memt, &sc->sc_fbh, &sc->sc_fb, &sc->sc_fbsize)) {
199 aprint_error("%s: failed to map the frame buffer.\n",
200 device_xname(sc->sc_dev));
202 sc->sc_fbaddr = bus_space_vaddr(sc->sc_memt, sc->sc_fbh);
204 if (pci_mapreg_map(pa, 0x14, PCI_MAPREG_TYPE_MEM, 0,
205 &sc->sc_memt, &sc->sc_regh, &sc->sc_reg, &sc->sc_regsize)) {
206 aprint_error("%s: failed to map registers.\n",
207 device_xname(sc->sc_dev));
209 sc->sc_dataport = bus_space_vaddr(sc->sc_memt, sc->sc_regh);
210 sc->sc_dataport += SM502_DATAPORT;
212 reg = bus_space_read_8(sc->sc_memt, sc->sc_regh, SM502_PANEL_DISP_CRTL);
213 switch (reg & SM502_PDC_DEPTH_MASK) {
214 case SM502_PDC_8BIT:
215 sc->sc_depth = 8;
216 break;
217 case SM502_PDC_16BIT:
218 sc->sc_depth = 16;
219 break;
220 case SM502_PDC_32BIT:
221 sc->sc_depth = 24;
222 break;
223 default:
224 panic("%s: unsupported depth", device_xname(self));
226 sc->sc_stride = (bus_space_read_4(sc->sc_memt, sc->sc_regh,
227 SM502_PANEL_FB_OFFSET) & SM502_FBA_WIN_STRIDE_MASK) >> 16;
228 sc->sc_width = (bus_space_read_4(sc->sc_memt, sc->sc_regh,
229 SM502_PANEL_FB_WIDTH) & SM502_FBW_WIN_WIDTH_MASK) >> 16;
230 sc->sc_height = (bus_space_read_4(sc->sc_memt, sc->sc_regh,
231 SM502_PANEL_FB_HEIGHT) & SM502_FBH_WIN_HEIGHT_MASK) >> 16;
233 printf("%s: %d x %d, %d bit, stride %d\n", device_xname(self),
234 sc->sc_width, sc->sc_height, sc->sc_depth, sc->sc_stride);
236 * XXX yeah, casting the fb address to uint32_t is formally wrong
237 * but as far as I know there are no SM502 with 64bit BARs
239 aprint_normal("%s: %d MB aperture at 0x%08x\n", device_xname(self),
240 (int)(sc->sc_fbsize >> 20), (uint32_t)sc->sc_fb);
242 sc->sc_defaultscreen_descr = (struct wsscreen_descr){
243 "default",
244 0, 0,
245 NULL,
246 8, 16,
247 WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
248 NULL
250 sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
251 sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
252 sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
253 sc->sc_locked = 0;
255 vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
256 &voyagerfb_accessops);
257 sc->vd.init_screen = voyagerfb_init_screen;
259 /* init engine here */
260 voyagerfb_init(sc);
262 ri = &sc->sc_console_screen.scr_ri;
264 if (is_console) {
265 vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
266 &defattr);
267 sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
269 sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
270 sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
271 sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
272 sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
273 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
274 defattr);
275 } else {
277 * since we're not the console we can postpone the rest
278 * until someone actually allocates a screen for us
280 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
283 j = 0;
284 if (sc->sc_depth <= 8) {
285 for (i = 0; i < (1 << sc->sc_depth); i++) {
287 sc->sc_cmap_red[i] = rasops_cmap[j];
288 sc->sc_cmap_green[i] = rasops_cmap[j + 1];
289 sc->sc_cmap_blue[i] = rasops_cmap[j + 2];
290 voyagerfb_putpalreg(sc, i, rasops_cmap[j],
291 rasops_cmap[j + 1], rasops_cmap[j + 2]);
292 j += 3;
296 voyagerfb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height,
297 ri->ri_devcmap[(defattr >> 16) & 0xff]);
299 if (is_console)
300 vcons_replay_msgbuf(&sc->sc_console_screen);
302 aa.console = is_console;
303 aa.scrdata = &sc->sc_screenlist;
304 aa.accessops = &voyagerfb_accessops;
305 aa.accesscookie = &sc->vd;
307 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
310 static int
311 voyagerfb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
312 struct lwp *l)
314 struct vcons_data *vd = v;
315 struct voyagerfb_softc *sc = vd->cookie;
316 struct wsdisplay_fbinfo *wdf;
317 struct vcons_screen *ms = vd->active;
319 switch (cmd) {
321 case WSDISPLAYIO_GTYPE:
322 *(u_int *)data = WSDISPLAY_TYPE_PCIMISC;
323 return 0;
325 /* PCI config read/write passthrough. */
326 case PCI_IOC_CFGREAD:
327 case PCI_IOC_CFGWRITE:
328 return (pci_devioctl(sc->sc_pc, sc->sc_pcitag,
329 cmd, data, flag, l));
331 case WSDISPLAYIO_GINFO:
332 if (ms == NULL)
333 return ENODEV;
334 wdf = (void *)data;
335 wdf->height = ms->scr_ri.ri_height;
336 wdf->width = ms->scr_ri.ri_width;
337 wdf->depth = ms->scr_ri.ri_depth;
338 wdf->cmsize = 256;
339 return 0;
341 case WSDISPLAYIO_GETCMAP:
342 return voyagerfb_getcmap(sc,
343 (struct wsdisplay_cmap *)data);
345 case WSDISPLAYIO_PUTCMAP:
346 return voyagerfb_putcmap(sc,
347 (struct wsdisplay_cmap *)data);
349 case WSDISPLAYIO_LINEBYTES:
350 *(u_int *)data = sc->sc_stride;
351 return 0;
353 case WSDISPLAYIO_SMODE:
355 int new_mode = *(int*)data;
357 if (new_mode != sc->sc_mode) {
358 sc->sc_mode = new_mode;
359 if(new_mode == WSDISPLAYIO_MODE_EMUL) {
360 voyagerfb_restore_palette(sc);
361 vcons_redraw_screen(ms);
365 return 0;
367 return EPASSTHROUGH;
370 static paddr_t
371 voyagerfb_mmap(void *v, void *vs, off_t offset, int prot)
373 struct vcons_data *vd = v;
374 struct voyagerfb_softc *sc = vd->cookie;
375 paddr_t pa;
377 /* 'regular' framebuffer mmap()ing */
378 if (offset < sc->sc_fbsize) {
379 pa = bus_space_mmap(sc->sc_memt, sc->sc_fb + offset, 0, prot,
380 BUS_SPACE_MAP_LINEAR);
381 return pa;
385 * restrict all other mappings to processes with superuser privileges
386 * or the kernel itself
388 if (kauth_authorize_generic(kauth_cred_get(), KAUTH_GENERIC_ISSUSER,
389 NULL) != 0) {
390 aprint_normal("%s: mmap() rejected.\n",
391 device_xname(sc->sc_dev));
392 return -1;
395 if ((offset >= sc->sc_fb) && (offset < (sc->sc_fb + sc->sc_fbsize))) {
396 pa = bus_space_mmap(sc->sc_memt, offset, 0, prot,
397 BUS_SPACE_MAP_LINEAR);
398 return pa;
401 if ((offset >= sc->sc_reg) &&
402 (offset < (sc->sc_reg + sc->sc_regsize))) {
403 pa = bus_space_mmap(sc->sc_memt, offset, 0, prot,
404 BUS_SPACE_MAP_LINEAR);
405 return pa;
408 return -1;
411 static void
412 voyagerfb_init_screen(void *cookie, struct vcons_screen *scr,
413 int existing, long *defattr)
415 struct voyagerfb_softc *sc = cookie;
416 struct rasops_info *ri = &scr->scr_ri;
418 ri->ri_depth = sc->sc_depth;
419 ri->ri_width = sc->sc_width;
420 ri->ri_height = sc->sc_height;
421 ri->ri_stride = sc->sc_stride;
422 ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
424 ri->ri_bits = (char *)sc->sc_fbaddr;
426 if (existing) {
427 ri->ri_flg |= RI_CLEAR;
430 rasops_init(ri, sc->sc_height / 8, sc->sc_width / 8);
431 ri->ri_caps = WSSCREEN_WSCOLORS;
433 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
434 sc->sc_width / ri->ri_font->fontwidth);
436 ri->ri_hw = scr;
437 ri->ri_ops.copyrows = voyagerfb_copyrows;
438 ri->ri_ops.copycols = voyagerfb_copycols;
439 ri->ri_ops.eraserows = voyagerfb_eraserows;
440 ri->ri_ops.erasecols = voyagerfb_erasecols;
441 ri->ri_ops.cursor = voyagerfb_cursor;
442 ri->ri_ops.putchar = voyagerfb_putchar;
445 static int
446 voyagerfb_putcmap(struct voyagerfb_softc *sc, struct wsdisplay_cmap *cm)
448 u_char *r, *g, *b;
449 u_int index = cm->index;
450 u_int count = cm->count;
451 int i, error;
452 u_char rbuf[256], gbuf[256], bbuf[256];
454 #ifdef VOYAGERFB_DEBUG
455 aprint_debug("putcmap: %d %d\n",index, count);
456 #endif
457 if (cm->index >= 256 || cm->count > 256 ||
458 (cm->index + cm->count) > 256)
459 return EINVAL;
460 error = copyin(cm->red, &rbuf[index], count);
461 if (error)
462 return error;
463 error = copyin(cm->green, &gbuf[index], count);
464 if (error)
465 return error;
466 error = copyin(cm->blue, &bbuf[index], count);
467 if (error)
468 return error;
470 memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
471 memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
472 memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
474 r = &sc->sc_cmap_red[index];
475 g = &sc->sc_cmap_green[index];
476 b = &sc->sc_cmap_blue[index];
478 for (i = 0; i < count; i++) {
479 voyagerfb_putpalreg(sc, index, *r, *g, *b);
480 index++;
481 r++, g++, b++;
483 return 0;
486 static int
487 voyagerfb_getcmap(struct voyagerfb_softc *sc, struct wsdisplay_cmap *cm)
489 u_int index = cm->index;
490 u_int count = cm->count;
491 int error;
493 if (index >= 255 || count > 256 || index + count > 256)
494 return EINVAL;
496 error = copyout(&sc->sc_cmap_red[index], cm->red, count);
497 if (error)
498 return error;
499 error = copyout(&sc->sc_cmap_green[index], cm->green, count);
500 if (error)
501 return error;
502 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
503 if (error)
504 return error;
506 return 0;
509 static void
510 voyagerfb_restore_palette(struct voyagerfb_softc *sc)
512 int i;
514 for (i = 0; i < (1 << sc->sc_depth); i++) {
515 voyagerfb_putpalreg(sc, i, sc->sc_cmap_red[i],
516 sc->sc_cmap_green[i], sc->sc_cmap_blue[i]);
520 static int
521 voyagerfb_putpalreg(struct voyagerfb_softc *sc, int idx, uint8_t r,
522 uint8_t g, uint8_t b)
524 uint32_t reg;
526 reg = (r << 16) | (g << 8) | b;
527 /* XXX we should probably write the CRT palette too */
528 bus_space_write_4(sc->sc_memt, sc->sc_regh,
529 SM502_PALETTE_PANEL + (idx << 2), reg);
530 return 0;
533 static void
534 voyagerfb_init(struct voyagerfb_softc *sc)
537 voyagerfb_wait(sc);
538 /* disable colour compare */
539 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_COLOR_COMP_MASK, 0);
540 /* allow writes to all planes */
541 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PLANEMASK,
542 0xffffffff);
543 /* disable clipping */
544 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_CLIP_TOP_LEFT, 0);
545 /* source and destination in local memory, no offset */
546 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_SRC_BASE, 0);
547 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_DST_BASE, 0);
548 /* pitch is screen stride */
549 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_PITCH,
550 sc->sc_width | (sc->sc_width << 16));
551 /* window is screen width */
552 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_WINDOW_WIDTH,
553 sc->sc_width | (sc->sc_width << 16));
554 switch (sc->sc_depth) {
555 case 8:
556 bus_space_write_4(sc->sc_memt, sc->sc_regh,
557 SM502_STRETCH, SM502_STRETCH_8BIT);
558 break;
559 case 16:
560 bus_space_write_4(sc->sc_memt, sc->sc_regh,
561 SM502_STRETCH, SM502_STRETCH_16BIT);
562 break;
563 case 24:
564 case 32:
565 bus_space_write_4(sc->sc_memt, sc->sc_regh,
566 SM502_STRETCH, SM502_STRETCH_32BIT);
567 break;
571 static void
572 voyagerfb_rectfill(struct voyagerfb_softc *sc, int x, int y, int wi, int he,
573 uint32_t colour)
576 voyagerfb_ready(sc);
577 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_CONTROL,
578 ROP_COPY |
579 SM502_CTRL_USE_ROP2 |
580 SM502_CTRL_CMD_RECTFILL |
581 SM502_CTRL_QUICKSTART_E);
582 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_FOREGROUND,
583 colour);
584 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_DST,
585 (x << 16) | y);
586 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_DIMENSION,
587 (wi << 16) | he);
590 static void
591 voyagerfb_bitblt(struct voyagerfb_softc *sc, int xs, int ys, int xd, int yd,
592 int wi, int he, int rop)
594 uint32_t cmd;
596 cmd = (rop & 0xf) | SM502_CTRL_USE_ROP2 | SM502_CTRL_CMD_BITBLT |
597 SM502_CTRL_QUICKSTART_E;
599 voyagerfb_ready(sc);
601 if (xd <= xs) {
602 /* left to right */
603 } else {
604 cmd |= SM502_CTRL_R_TO_L;
605 xs += he - 1;
606 xd += wi - 1;
609 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_CONTROL, cmd);
610 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_SRC,
611 (xs << 16) | ys);
612 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_DST,
613 (xd << 16) | yd);
614 bus_space_write_4(sc->sc_memt, sc->sc_regh, SM502_DIMENSION,
615 (wi << 16) | he);
618 static void
619 voyagerfb_cursor(void *cookie, int on, int row, int col)
621 struct rasops_info *ri = cookie;
622 struct vcons_screen *scr = ri->ri_hw;
623 struct voyagerfb_softc *sc = scr->scr_cookie;
624 int x, y, wi, he;
626 wi = ri->ri_font->fontwidth;
627 he = ri->ri_font->fontheight;
629 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
630 x = ri->ri_ccol * wi + ri->ri_xorigin;
631 y = ri->ri_crow * he + ri->ri_yorigin;
632 if (ri->ri_flg & RI_CURSOR) {
633 voyagerfb_bitblt(sc, x, y, x, y, wi, he, ROP_INVERT);
634 ri->ri_flg &= ~RI_CURSOR;
636 ri->ri_crow = row;
637 ri->ri_ccol = col;
638 if (on) {
639 x = ri->ri_ccol * wi + ri->ri_xorigin;
640 y = ri->ri_crow * he + ri->ri_yorigin;
641 voyagerfb_bitblt(sc, x, y, x, y, wi, he, ROP_INVERT);
642 ri->ri_flg |= RI_CURSOR;
644 } else {
645 scr->scr_ri.ri_crow = row;
646 scr->scr_ri.ri_ccol = col;
647 scr->scr_ri.ri_flg &= ~RI_CURSOR;
652 static inline void
653 voyagerfb_feed8(struct voyagerfb_softc *sc, uint8_t *data, int len)
655 uint32_t *port = (uint32_t *)sc->sc_dataport;
656 int i;
658 for (i = 0; i < ((len + 3) & 0xfffc); i++) {
659 *port = *data;
660 data++;
664 static inline void
665 voyagerfb_feed16(struct voyagerfb_softc *sc, uint16_t *data, int len)
667 uint32_t *port = (uint32_t *)sc->sc_dataport;
668 int i;
670 len = len << 1;
671 for (i = 0; i < ((len + 1) & 0xfffe); i++) {
672 *port = *data;
673 data++;
678 static void
679 voyagerfb_putchar(void *cookie, int row, int col, u_int c, long attr)
681 struct rasops_info *ri = cookie;
682 struct vcons_screen *scr = ri->ri_hw;
683 struct voyagerfb_softc *sc = scr->scr_cookie;
684 uint32_t cmd;
686 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
687 int fg, bg, uc;
688 uint8_t *data;
689 int x, y, wi, he;
690 wi = ri->ri_font->fontwidth;
691 he = ri->ri_font->fontheight;
693 if (!CHAR_IN_FONT(c, ri->ri_font))
694 return;
695 bg = ri->ri_devcmap[(attr >> 16) & 0x0f];
696 fg = ri->ri_devcmap[(attr >> 24) & 0x0f];
697 x = ri->ri_xorigin + col * wi;
698 y = ri->ri_yorigin + row * he;
699 if (c == 0x20) {
700 voyagerfb_rectfill(sc, x, y, wi, he, bg);
701 } else {
702 uc = c - ri->ri_font->firstchar;
703 data = (uint8_t *)ri->ri_font->data + uc *
704 ri->ri_fontscale;
705 cmd = ROP_COPY |
706 SM502_CTRL_USE_ROP2 |
707 SM502_CTRL_CMD_HOSTWRT |
708 SM502_CTRL_HOSTBLT_MONO |
709 SM502_CTRL_QUICKSTART_E |
710 SM502_CTRL_MONO_PACK_32BIT;
711 voyagerfb_ready(sc);
712 bus_space_write_4(sc->sc_memt, sc->sc_regh,
713 SM502_CONTROL, cmd);
714 bus_space_write_4(sc->sc_memt, sc->sc_regh,
715 SM502_FOREGROUND, fg);
716 bus_space_write_4(sc->sc_memt, sc->sc_regh,
717 SM502_BACKGROUND, bg);
718 bus_space_write_4(sc->sc_memt, sc->sc_regh,
719 SM502_SRC, 0);
720 bus_space_write_4(sc->sc_memt, sc->sc_regh,
721 SM502_DST, (x << 16) | y);
722 bus_space_write_4(sc->sc_memt, sc->sc_regh,
723 SM502_DIMENSION, (wi << 16) | he);
724 /* now feed the data, padded to 32bit */
725 switch (ri->ri_font->stride) {
726 case 1:
727 voyagerfb_feed8(sc, data, ri->ri_fontscale);
728 break;
729 case 2:
730 voyagerfb_feed16(sc, (uint16_t *)data,
731 ri->ri_fontscale);
732 break;
739 static void
740 voyagerfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
742 struct rasops_info *ri = cookie;
743 struct vcons_screen *scr = ri->ri_hw;
744 struct voyagerfb_softc *sc = scr->scr_cookie;
745 int32_t xs, xd, y, width, height;
747 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
748 xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
749 xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
750 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
751 width = ri->ri_font->fontwidth * ncols;
752 height = ri->ri_font->fontheight;
753 voyagerfb_bitblt(sc, xs, y, xd, y, width, height, ROP_COPY);
757 static void
758 voyagerfb_erasecols(void *cookie, int row, int startcol, int ncols,
759 long fillattr)
761 struct rasops_info *ri = cookie;
762 struct vcons_screen *scr = ri->ri_hw;
763 struct voyagerfb_softc *sc = scr->scr_cookie;
764 int32_t x, y, width, height, fg, bg, ul;
766 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
767 x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
768 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
769 width = ri->ri_font->fontwidth * ncols;
770 height = ri->ri_font->fontheight;
771 rasops_unpack_attr(fillattr, &fg, &bg, &ul);
773 voyagerfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
777 static void
778 voyagerfb_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
780 struct rasops_info *ri = cookie;
781 struct vcons_screen *scr = ri->ri_hw;
782 struct voyagerfb_softc *sc = scr->scr_cookie;
783 int32_t x, ys, yd, width, height;
784 int i;
786 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
787 x = ri->ri_xorigin;
788 ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
789 yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
790 width = ri->ri_emuwidth;
791 height = ri->ri_font->fontheight * nrows;
792 if ((nrows > 1) && (dstrow > srcrow)) {
794 * the blitter can't do bottom-up copies so we have
795 * to copy line by line here
796 * should probably use a command sequence
798 for (i = 0; i < nrows; i++) {
799 voyagerfb_bitblt(sc, x, ys, x, yd, width,
800 ri->ri_font->fontheight, ROP_COPY);
801 ys += ri->ri_font->fontheight;
802 yd += ri->ri_font->fontheight;
804 } else
805 voyagerfb_bitblt(sc, x, ys, x, yd, width, height,
806 ROP_COPY);
810 static void
811 voyagerfb_eraserows(void *cookie, int row, int nrows, long fillattr)
813 struct rasops_info *ri = cookie;
814 struct vcons_screen *scr = ri->ri_hw;
815 struct voyagerfb_softc *sc = scr->scr_cookie;
816 int32_t x, y, width, height, fg, bg, ul;
818 if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
819 x = ri->ri_xorigin;
820 y = ri->ri_yorigin + ri->ri_font->fontheight * row;
821 width = ri->ri_emuwidth;
822 height = ri->ri_font->fontheight * nrows;
823 rasops_unpack_attr(fillattr, &fg, &bg, &ul);
825 voyagerfb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);