1 /* $OpenBSD: mgx.c,v 1.16 2022/07/15 17:57:27 kettenis Exp $ */
2 /*
3 * Copyright (c) 2003, Miodrag Vallat.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29 /*
30 * Driver for the Southland Media Systems (now Quantum 3D) MGX and MGXPlus
31 * frame buffers.
32 *
33 * This board is built of an Alliance Promotion AT24 chip, and a simple
34 * SBus-PCI glue logic. It also sports an EEPROM to store configuration
35 * parameters, which can be controlled from SunOS or Solaris with the
36 * mgxconfig utility.
37 *
38 * We currently don't reprogram the video mode at all, so only the resolution
39 * and depth set by the PROM (or mgxconfig) will be used.
40 *
41 * Also, interrupts are not handled.
42 */
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/buf.h>
47 #include <sys/device.h>
48 #include <sys/ioctl.h>
49 #include <sys/malloc.h>
50 #include <sys/mman.h>
51 #include <sys/tty.h>
52 #include <sys/conf.h>
53
54 #include <uvm/uvm_extern.h>
55
56 #include <machine/autoconf.h>
57 #include <machine/pmap.h>
58 #include <machine/cpu.h>
59 #include <machine/conf.h>
60
61 #include <dev/wscons/wsconsio.h>
62 #include <dev/wscons/wsdisplayvar.h>
63 #include <dev/rasops/rasops.h>
64 #include <machine/fbvar.h>
65
66 #include <dev/ic/vgareg.h>
67 #include <dev/ic/atxxreg.h>
68
69 #include <dev/sbus/sbusvar.h>
70
71 /*
72 * MGX PROM register layout
73 *
74 * The cards FCode registers 9 regions:
75 *
76 * region offset size description
77 * 0 00000000 00010000 FCode (32KB only)
78 * 1 00100000 00010000 FCode, repeated
79 * 2 00200000 00001000 unknown, repeats every 0x100
80 * with little differences, could be the EEPROM image
81 * 3 00400000 00001000 PCI configuration space
82 * 4 00500000 00001000 CRTC
83 * 5 00600000 00001000 AT24 registers (offset 0xb0000)
84 * 6 00700000 00010000 unknown
85 * 7 00800000 00800000 unknown
86 * 8 01000000 00400000 video memory
87 */
88
89 #define MGX_NREG 9
90 #define MGX_REG_CRTC 4 /* video control and ramdac */
91 #define MGX_REG_ATREG 5 /* AT24 registers */
92 #define MGX_REG_ATREG_OFFSET 0x000b0000
93 #define MGX_REG_ATREG_SIZE 0x00000400
94 #define MGX_REG_VRAM8 8 /* 8-bit memory space */
95
96 /*
97 * MGX CRTC access
98 *
99 * The CRTC only answers to the following ``port'' locations:
100 * - a subset of the VGA registers:
101 * 3c0, 3c1 (ATC)
102 * 3c4, 3c5 (TS sequencer)
103 * 3c6-3c9 (DAC)
104 * 3c2, 3cc (Misc)
105 * 3ce, 3cf (GDC)
106 *
107 * - the CRTC (6845-style) registers:
108 * 3d4 index register
109 * 3d5 data register
110 */
111
112 #define VGA_BASE 0x03c0
113 #define TS_INDEX (VGA_BASE + VGA_TS_INDEX)
114 #define TS_DATA (VGA_BASE + VGA_TS_DATA)
115 #define CD_DISABLEVIDEO 0x0020
116 #define CMAP_WRITE_INDEX (VGA_BASE + 0x08)
117 #define CMAP_DATA (VGA_BASE + 0x09)
118
119 /* per-display variables */
120 struct mgx_softc {
121 struct sunfb sc_sunfb; /* common base device */
122 bus_space_tag_t sc_bustag;
123 bus_addr_t sc_paddr; /* for mmap() */
124 u_int8_t sc_cmap[256 * 3]; /* shadow colormap */
125 vaddr_t sc_vidc; /* ramdac registers */
126 vaddr_t sc_xreg; /* AT24 registers */
127 uint32_t sc_dec; /* dec register template */
128 int sc_nscreens;
129 };
130
131 void mgx_burner(void *, u_int ,u_int);
132 int mgx_ioctl(void *, u_long, caddr_t, int, struct proc *);
133 paddr_t mgx_mmap(void *, off_t, int);
134
135 struct wsdisplay_accessops mgx_accessops = {
136 .ioctl = mgx_ioctl,
137 .mmap = mgx_mmap,
138 .burn_screen = mgx_burner
139 };
140
141 int mgx_getcmap(u_int8_t *, struct wsdisplay_cmap *);
142 void mgx_loadcmap(struct mgx_softc *, int, int);
143 int mgx_putcmap(u_int8_t *, struct wsdisplay_cmap *);
144 void mgx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
145
146 int mgx_ras_copycols(void *, int, int, int, int);
147 int mgx_ras_copyrows(void *, int, int, int);
148 int mgx_ras_do_cursor(struct rasops_info *);
149 int mgx_ras_erasecols(void *, int, int, int, uint32_t);
150 int mgx_ras_eraserows(void *, int, int, uint32_t);
151 void mgx_ras_init(struct mgx_softc *, uint);
152
153 uint8_t mgx_read_1(vaddr_t, uint);
154 uint16_t mgx_read_2(vaddr_t, uint);
155 void mgx_write_1(vaddr_t, uint, uint8_t);
156 void mgx_write_4(vaddr_t, uint, uint32_t);
157
158 int mgx_wait_engine(struct mgx_softc *);
159 int mgx_wait_fifo(struct mgx_softc *, uint);
160
161 /*
162 * Attachment Glue
163 */
164
165 int mgxmatch(struct device *, void *, void *);
166 void mgxattach(struct device *, struct device *, void *);
167
168 const struct cfattach mgx_ca = {
169 sizeof(struct mgx_softc), mgxmatch, mgxattach
170 };
171
172 struct cfdriver mgx_cd = {
173 NULL, "mgx", DV_DULL
174 };
175
176 /*
177 * Match an MGX or MGX+ card.
178 */
179 int
mgxmatch(struct device * parent,void * vcf,void * aux)180 mgxmatch(struct device *parent, void *vcf, void *aux)
181 {
182 struct sbus_attach_args *sa = aux;
183
184 if (strcmp(sa->sa_name, "SMSI,mgx") != 0 &&
185 strcmp(sa->sa_name, "mgx") != 0)
186 return (0);
187
188 return (1);
189 }
190
191 /*
192 * Attach an MGX frame buffer.
193 * This will keep the frame buffer in the actual PROM mode, and attach
194 * a wsdisplay child device to itself.
195 */
196 void
mgxattach(struct device * parent,struct device * self,void * args)197 mgxattach(struct device *parent, struct device *self, void *args)
198 {
199 struct mgx_softc *sc = (struct mgx_softc *)self;
200 struct sbus_attach_args *sa = args;
201 bus_space_tag_t bt;
202 bus_space_handle_t bh;
203 int node, fbsize;
204 int isconsole;
205 uint16_t chipid;
206
207 bt = sa->sa_bustag;
208 node = sa->sa_node;
209
210 printf(": %s", getpropstring(node, "model"));
211
212 isconsole = node == fbnode;
213
214 /* Check registers */
215 if (sa->sa_nreg < MGX_NREG) {
216 printf("\n%s: expected %d registers, got %d\n",
217 self->dv_xname, MGX_NREG, sa->sa_nreg);
218 return;
219 }
220
221 sc->sc_bustag = bt;
222 if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_CRTC].sbr_slot,
223 sa->sa_reg[MGX_REG_CRTC].sbr_offset, PAGE_SIZE,
224 BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
225 printf("\n%s: couldn't map crtc registers\n", self->dv_xname);
226 return;
227 }
228 sc->sc_vidc = (vaddr_t)bus_space_vaddr(bt, bh);
229
230 sc->sc_bustag = bt;
231 if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_ATREG].sbr_slot,
232 sa->sa_reg[MGX_REG_ATREG].sbr_offset + MGX_REG_ATREG_OFFSET,
233 MGX_REG_ATREG_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
234 printf("\n%s: couldn't map crtc registers\n", self->dv_xname);
235 /* XXX unmap vidc */
236 return;
237 }
238 sc->sc_xreg = (vaddr_t)bus_space_vaddr(bt, bh);
239
240 /*
241 * Check the chip ID. If it's not an AT24, prefer not to access
242 * the extended registers at all.
243 */
244 chipid = mgx_read_2(sc->sc_xreg, ATR_ID);
245 if (chipid != ID_AT24) {
246 sc->sc_xreg = (vaddr_t)0;
247 }
248
249 /* enable video */
250 mgx_burner(sc, 1, 0);
251
252 fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
253
254 /* Sanity check frame buffer memory */
255 fbsize = getpropint(node, "fb_size", 0);
256 if (fbsize != 0 && sc->sc_sunfb.sf_fbsize > fbsize) {
257 printf("\n%s: expected at least %d bytes of vram, but card "
258 "only provides %d\n",
259 self->dv_xname, sc->sc_sunfb.sf_fbsize, fbsize);
260 return;
261 }
262
263 /* Map the frame buffer memory area we're interested in */
264 sc->sc_paddr = sbus_bus_addr(bt, sa->sa_reg[MGX_REG_VRAM8].sbr_slot,
265 sa->sa_reg[MGX_REG_VRAM8].sbr_offset);
266 if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_VRAM8].sbr_slot,
267 sa->sa_reg[MGX_REG_VRAM8].sbr_offset,
268 round_page(sc->sc_sunfb.sf_fbsize),
269 BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
270 printf("\n%s: couldn't map video memory\n", self->dv_xname);
271 /* XXX unmap vidc and xreg */
272 return;
273 }
274 sc->sc_sunfb.sf_ro.ri_bits = bus_space_vaddr(bt, bh);
275 sc->sc_sunfb.sf_ro.ri_hw = sc;
276
277 printf(", %dx%d\n",
278 sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
279
280 fbwscons_init(&sc->sc_sunfb, 0, isconsole);
281
282 bzero(sc->sc_cmap, sizeof(sc->sc_cmap));
283 fbwscons_setcolormap(&sc->sc_sunfb, mgx_setcolor);
284
285 if (chipid != ID_AT24) {
286 printf("%s: unexpected engine id %04x\n",
287 self->dv_xname, chipid);
288 }
289
290 mgx_ras_init(sc, chipid);
291
292 if (isconsole)
293 fbwscons_console_init(&sc->sc_sunfb, -1);
294
295 fbwscons_attach(&sc->sc_sunfb, &mgx_accessops, isconsole);
296 }
297
298 /*
299 * Register Access
300 *
301 * On big-endian systems such as the sparc, it is necessary to flip
302 * the low-order bits of the addresses to reach the right register.
303 */
304
305 uint8_t
mgx_read_1(vaddr_t regs,uint offs)306 mgx_read_1(vaddr_t regs, uint offs)
307 {
308 #if _BYTE_ORDER == _LITTLE_ENDIAN
309 return *(volatile uint8_t *)(regs + offs);
310 #else
311 return *(volatile uint8_t *)(regs + (offs ^ 3));
312 #endif
313 }
314
315 uint16_t
mgx_read_2(vaddr_t regs,uint offs)316 mgx_read_2(vaddr_t regs, uint offs)
317 {
318 #if _BYTE_ORDER == _LITTLE_ENDIAN
319 return *(volatile uint16_t *)(regs + offs);
320 #else
321 return *(volatile uint16_t *)(regs + (offs ^ 2));
322 #endif
323 }
324
325 void
mgx_write_1(vaddr_t regs,uint offs,uint8_t val)326 mgx_write_1(vaddr_t regs, uint offs, uint8_t val)
327 {
328 #if _BYTE_ORDER == _LITTLE_ENDIAN
329 *(volatile uint8_t *)(regs + offs) = val;
330 #else
331 *(volatile uint8_t *)(regs + (offs ^ 3)) = val;
332 #endif
333 }
334
335 void
mgx_write_4(vaddr_t regs,uint offs,uint32_t val)336 mgx_write_4(vaddr_t regs, uint offs, uint32_t val)
337 {
338 *(volatile uint32_t *)(regs + offs) = val;
339 }
340
341 /*
342 * Wsdisplay Operations
343 */
344
345 int
mgx_ioctl(void * dev,u_long cmd,caddr_t data,int flags,struct proc * p)346 mgx_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
347 {
348 struct mgx_softc *sc = dev;
349 struct wsdisplay_cmap *cm;
350 struct wsdisplay_fbinfo *wdf;
351 int error;
352
353 switch (cmd) {
354 case WSDISPLAYIO_GTYPE:
355 *(u_int *)data = WSDISPLAY_TYPE_MGX;
356 break;
357 case WSDISPLAYIO_GINFO:
358 wdf = (struct wsdisplay_fbinfo *)data;
359 wdf->height = sc->sc_sunfb.sf_height;
360 wdf->width = sc->sc_sunfb.sf_width;
361 wdf->depth = sc->sc_sunfb.sf_depth;
362 wdf->stride = sc->sc_sunfb.sf_linebytes;
363 wdf->offset = 0;
364 wdf->cmsize = 256;
365 break;
366 case WSDISPLAYIO_LINEBYTES:
367 *(u_int *)data = sc->sc_sunfb.sf_linebytes;
368 break;
369
370 case WSDISPLAYIO_GETCMAP:
371 cm = (struct wsdisplay_cmap *)data;
372 error = mgx_getcmap(sc->sc_cmap, cm);
373 if (error != 0)
374 return (error);
375 break;
376 case WSDISPLAYIO_PUTCMAP:
377 cm = (struct wsdisplay_cmap *)data;
378 error = mgx_putcmap(sc->sc_cmap, cm);
379 if (error != 0)
380 return (error);
381 mgx_loadcmap(sc, cm->index, cm->count);
382 break;
383
384 case WSDISPLAYIO_SVIDEO:
385 case WSDISPLAYIO_GVIDEO:
386 break;
387
388 default:
389 return (-1);
390 }
391
392 return (0);
393 }
394
395 paddr_t
mgx_mmap(void * v,off_t offset,int prot)396 mgx_mmap(void *v, off_t offset, int prot)
397 {
398 struct mgx_softc *sc = v;
399
400 if (offset & PGOFSET)
401 return (-1);
402
403 /* Allow mapping as a dumb framebuffer from offset 0 */
404 if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
405 return (bus_space_mmap(sc->sc_bustag, sc->sc_paddr,
406 offset, prot, BUS_SPACE_MAP_LINEAR));
407 }
408
409 return (-1);
410 }
411
412 void
mgx_burner(void * v,u_int on,u_int flags)413 mgx_burner(void *v, u_int on, u_int flags)
414 {
415 struct mgx_softc *sc = v;
416 uint mode;
417
418 #ifdef notyet
419 if (sc->sc_xreg != 0) {
420 mode = mgx_read_1(sc->sc_xreg, ATR_DPMS);
421 if (on)
422 CLR(mode, DPMS_HSYNC_DISABLE | DPMS_VSYNC_DISABLE);
423 else {
424 SET(mode, DPMS_HSYNC_DISABLE);
425 #if 0 /* needs ramdac reprogramming on resume */
426 if (flags & WSDISPLAY_BURN_VBLANK)
427 SET(mode, DPMS_VSYNC_DISABLE);
428 #endif
429 }
430 mgx_write_1(sc->sc_xreg, ATR_DPMS, mode);
431 return;
432 }
433 #endif
434
435 mgx_write_1(sc->sc_vidc, TS_INDEX, 1); /* TS mode register */
436 mode = mgx_read_1(sc->sc_vidc, TS_DATA);
437 if (on)
438 mode &= ~CD_DISABLEVIDEO;
439 else
440 mode |= CD_DISABLEVIDEO;
441 mgx_write_1(sc->sc_vidc, TS_DATA, mode);
442 }
443
444 /*
445 * Colormap Handling Routines
446 */
447
448 void
mgx_setcolor(void * v,u_int index,u_int8_t r,u_int8_t g,u_int8_t b)449 mgx_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
450 {
451 struct mgx_softc *sc = v;
452 u_int i = index * 3;
453
454 sc->sc_cmap[i++] = r;
455 sc->sc_cmap[i++] = g;
456 sc->sc_cmap[i] = b;
457
458 mgx_loadcmap(sc, index, 1);
459 }
460
461 void
mgx_loadcmap(struct mgx_softc * sc,int start,int ncolors)462 mgx_loadcmap(struct mgx_softc *sc, int start, int ncolors)
463 {
464 u_int8_t *color;
465 int i;
466
467 mgx_write_1(sc->sc_vidc, CMAP_WRITE_INDEX, start);
468 color = sc->sc_cmap + start * 3;
469 for (i = ncolors * 3; i != 0; i--)
470 mgx_write_1(sc->sc_vidc, CMAP_DATA, *color++);
471 }
472
473 int
mgx_getcmap(u_int8_t * cm,struct wsdisplay_cmap * rcm)474 mgx_getcmap(u_int8_t *cm, struct wsdisplay_cmap *rcm)
475 {
476 u_int index = rcm->index, count = rcm->count, i;
477 int error;
478
479 if (index >= 256 || count > 256 - index)
480 return (EINVAL);
481
482 index *= 3;
483 for (i = 0; i < count; i++) {
484 if ((error =
485 copyout(cm + index++, &rcm->red[i], 1)) != 0)
486 return (error);
487 if ((error =
488 copyout(cm + index++, &rcm->green[i], 1)) != 0)
489 return (error);
490 if ((error =
491 copyout(cm + index++, &rcm->blue[i], 1)) != 0)
492 return (error);
493 }
494
495 return (0);
496 }
497
498 int
mgx_putcmap(u_int8_t * cm,struct wsdisplay_cmap * rcm)499 mgx_putcmap(u_int8_t *cm, struct wsdisplay_cmap *rcm)
500 {
501 u_int index = rcm->index, count = rcm->count, i;
502 int error;
503
504 if (index >= 256 || count > 256 - index)
505 return (EINVAL);
506
507 index *= 3;
508 for (i = 0; i < count; i++) {
509 if ((error =
510 copyin(&rcm->red[i], cm + index++, 1)) != 0)
511 return (error);
512 if ((error =
513 copyin(&rcm->green[i], cm + index++, 1)) != 0)
514 return (error);
515 if ((error =
516 copyin(&rcm->blue[i], cm + index++, 1)) != 0)
517 return (error);
518 }
519
520 return (0);
521 }
522
523 /*
524 * Accelerated Text Console Code
525 *
526 * The X driver makes sure there are at least as many FIFOs available as
527 * registers to write. They can thus be considered as write slots.
528 *
529 * The code below expects to run on at least an AT24 chip, and does not
530 * care for the AP6422 which has fewer FIFOs; some operations would need
531 * to be done in two steps to support this chip.
532 */
533
534 int
mgx_wait_engine(struct mgx_softc * sc)535 mgx_wait_engine(struct mgx_softc *sc)
536 {
537 uint i;
538 uint stat;
539
540 for (i = 10000; i != 0; i--) {
541 stat = mgx_read_1(sc->sc_xreg, ATR_BLT_STATUS);
542 if (!ISSET(stat, BLT_HOST_BUSY | BLT_ENGINE_BUSY))
543 break;
544 }
545
546 return i;
547 }
548
549 int
mgx_wait_fifo(struct mgx_softc * sc,uint nfifo)550 mgx_wait_fifo(struct mgx_softc *sc, uint nfifo)
551 {
552 uint i;
553 uint stat;
554
555 for (i = 10000; i != 0; i--) {
556 stat = (mgx_read_1(sc->sc_xreg, ATR_FIFO_STATUS) & FIFO_MASK) >>
557 FIFO_SHIFT;
558 if (stat >= nfifo)
559 break;
560 mgx_write_1(sc->sc_xreg, ATR_FIFO_STATUS, 0);
561 }
562
563 return i;
564 }
565
566 void
mgx_ras_init(struct mgx_softc * sc,uint chipid)567 mgx_ras_init(struct mgx_softc *sc, uint chipid)
568 {
569 /*
570 * Check the chip ID. If it's not a 6424, do not plug the
571 * accelerated routines.
572 */
573
574 if (chipid != ID_AT24)
575 return;
576
577 /*
578 * Wait until the chip is completely idle.
579 */
580
581 if (mgx_wait_engine(sc) == 0)
582 return;
583 if (mgx_wait_fifo(sc, FIFO_AT24) == 0)
584 return;
585
586 /*
587 * Compute the invariant bits of the DEC register.
588 */
589
590 switch (sc->sc_sunfb.sf_depth) {
591 case 8:
592 sc->sc_dec = DEC_DEPTH_8 << DEC_DEPTH_SHIFT;
593 break;
594 case 15:
595 case 16:
596 sc->sc_dec = DEC_DEPTH_16 << DEC_DEPTH_SHIFT;
597 break;
598 case 32:
599 sc->sc_dec = DEC_DEPTH_32 << DEC_DEPTH_SHIFT;
600 break;
601 default:
602 return; /* not supported */
603 }
604
605 switch (sc->sc_sunfb.sf_width) {
606 case 640:
607 sc->sc_dec |= DEC_WIDTH_640 << DEC_WIDTH_SHIFT;
608 break;
609 case 800:
610 sc->sc_dec |= DEC_WIDTH_800 << DEC_WIDTH_SHIFT;
611 break;
612 case 1024:
613 sc->sc_dec |= DEC_WIDTH_1024 << DEC_WIDTH_SHIFT;
614 break;
615 case 1152:
616 sc->sc_dec |= DEC_WIDTH_1152 << DEC_WIDTH_SHIFT;
617 break;
618 case 1280:
619 sc->sc_dec |= DEC_WIDTH_1280 << DEC_WIDTH_SHIFT;
620 break;
621 case 1600:
622 sc->sc_dec |= DEC_WIDTH_1600 << DEC_WIDTH_SHIFT;
623 break;
624 default:
625 return; /* not supported */
626 }
627
628 sc->sc_sunfb.sf_ro.ri_ops.copycols = mgx_ras_copycols;
629 sc->sc_sunfb.sf_ro.ri_ops.copyrows = mgx_ras_copyrows;
630 sc->sc_sunfb.sf_ro.ri_ops.erasecols = mgx_ras_erasecols;
631 sc->sc_sunfb.sf_ro.ri_ops.eraserows = mgx_ras_eraserows;
632 sc->sc_sunfb.sf_ro.ri_do_cursor = mgx_ras_do_cursor;
633
634 #ifdef notneeded
635 mgx_write_1(sc->sc_xreg, ATR_CLIP_CONTROL, 1);
636 mgx_write_4(sc->sc_xreg, ATR_CLIP_LEFTTOP, ATR_DUAL(0, 0));
637 mgx_write_4(sc->sc_xreg, ATR_CLIP_RIGHTBOTTOM,
638 ATR_DUAL(sc->sc_sunfb.sf_width - 1, sc->sc_sunfb.sf_depth - 1));
639 #else
640 mgx_write_1(sc->sc_xreg, ATR_CLIP_CONTROL, 0);
641 #endif
642 mgx_write_1(sc->sc_xreg, ATR_BYTEMASK, 0xff);
643 }
644
645 int
mgx_ras_copycols(void * v,int row,int src,int dst,int n)646 mgx_ras_copycols(void *v, int row, int src, int dst, int n)
647 {
648 struct rasops_info *ri = v;
649 struct mgx_softc *sc = ri->ri_hw;
650 uint dec = sc->sc_dec;
651
652 n *= ri->ri_font->fontwidth;
653 src *= ri->ri_font->fontwidth;
654 src += ri->ri_xorigin;
655 dst *= ri->ri_font->fontwidth;
656 dst += ri->ri_xorigin;
657 row *= ri->ri_font->fontheight;
658 row += ri->ri_yorigin;
659
660 dec |= (DEC_COMMAND_BLT << DEC_COMMAND_SHIFT) |
661 (DEC_START_DIMX << DEC_START_SHIFT);
662 if (src < dst) {
663 src += n - 1;
664 dst += n - 1;
665 dec |= DEC_DIR_X_REVERSE;
666 }
667 mgx_wait_fifo(sc, 5);
668 mgx_write_1(sc->sc_xreg, ATR_ROP, ROP_SRC);
669 mgx_write_4(sc->sc_xreg, ATR_DEC, dec);
670 mgx_write_4(sc->sc_xreg, ATR_SRC_XY, ATR_DUAL(row, src));
671 mgx_write_4(sc->sc_xreg, ATR_DST_XY, ATR_DUAL(row, dst));
672 mgx_write_4(sc->sc_xreg, ATR_WH, ATR_DUAL(ri->ri_font->fontheight, n));
673 mgx_wait_engine(sc);
674
675 return 0;
676 }
677
678 int
mgx_ras_copyrows(void * v,int src,int dst,int n)679 mgx_ras_copyrows(void *v, int src, int dst, int n)
680 {
681 struct rasops_info *ri = v;
682 struct mgx_softc *sc = ri->ri_hw;
683 uint dec = sc->sc_dec;
684
685 n *= ri->ri_font->fontheight;
686 src *= ri->ri_font->fontheight;
687 src += ri->ri_yorigin;
688 dst *= ri->ri_font->fontheight;
689 dst += ri->ri_yorigin;
690
691 dec |= (DEC_COMMAND_BLT << DEC_COMMAND_SHIFT) |
692 (DEC_START_DIMX << DEC_START_SHIFT);
693 if (src < dst) {
694 src += n - 1;
695 dst += n - 1;
696 dec |= DEC_DIR_Y_REVERSE;
697 }
698 mgx_wait_fifo(sc, 5);
699 mgx_write_1(sc->sc_xreg, ATR_ROP, ROP_SRC);
700 mgx_write_4(sc->sc_xreg, ATR_DEC, dec);
701 mgx_write_4(sc->sc_xreg, ATR_SRC_XY, ATR_DUAL(src, ri->ri_xorigin));
702 mgx_write_4(sc->sc_xreg, ATR_DST_XY, ATR_DUAL(dst, ri->ri_xorigin));
703 mgx_write_4(sc->sc_xreg, ATR_WH, ATR_DUAL(n, ri->ri_emuwidth));
704 mgx_wait_engine(sc);
705
706 return 0;
707 }
708
709 int
mgx_ras_erasecols(void * v,int row,int col,int n,uint32_t attr)710 mgx_ras_erasecols(void *v, int row, int col, int n, uint32_t attr)
711 {
712 struct rasops_info *ri = v;
713 struct mgx_softc *sc = ri->ri_hw;
714 int fg, bg;
715 uint dec = sc->sc_dec;
716
717 ri->ri_ops.unpack_attr(v, attr, &fg, &bg, NULL);
718 bg = ri->ri_devcmap[bg];
719
720 n *= ri->ri_font->fontwidth;
721 col *= ri->ri_font->fontwidth;
722 col += ri->ri_xorigin;
723 row *= ri->ri_font->fontheight;
724 row += ri->ri_yorigin;
725
726 dec |= (DEC_COMMAND_RECT << DEC_COMMAND_SHIFT) |
727 (DEC_START_DIMX << DEC_START_SHIFT);
728 mgx_wait_fifo(sc, 5);
729 mgx_write_1(sc->sc_xreg, ATR_ROP, ROP_SRC);
730 mgx_write_4(sc->sc_xreg, ATR_FG, bg);
731 mgx_write_4(sc->sc_xreg, ATR_DEC, dec);
732 mgx_write_4(sc->sc_xreg, ATR_DST_XY, ATR_DUAL(row, col));
733 mgx_write_4(sc->sc_xreg, ATR_WH, ATR_DUAL(ri->ri_font->fontheight, n));
734 mgx_wait_engine(sc);
735
736 return 0;
737 }
738
739 int
mgx_ras_eraserows(void * v,int row,int n,uint32_t attr)740 mgx_ras_eraserows(void *v, int row, int n, uint32_t attr)
741 {
742 struct rasops_info *ri = v;
743 struct mgx_softc *sc = ri->ri_hw;
744 int fg, bg;
745 uint dec = sc->sc_dec;
746
747 ri->ri_ops.unpack_attr(v, attr, &fg, &bg, NULL);
748 bg = ri->ri_devcmap[bg];
749
750 dec |= (DEC_COMMAND_RECT << DEC_COMMAND_SHIFT) |
751 (DEC_START_DIMX << DEC_START_SHIFT);
752 mgx_wait_fifo(sc, 5);
753 mgx_write_1(sc->sc_xreg, ATR_ROP, ROP_SRC);
754 mgx_write_4(sc->sc_xreg, ATR_FG, bg);
755 mgx_write_4(sc->sc_xreg, ATR_DEC, dec);
756 if (n == ri->ri_rows && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
757 mgx_write_4(sc->sc_xreg, ATR_DST_XY, ATR_DUAL(0, 0));
758 mgx_write_4(sc->sc_xreg, ATR_WH,
759 ATR_DUAL(ri->ri_height, ri->ri_width));
760 } else {
761 n *= ri->ri_font->fontheight;
762 row *= ri->ri_font->fontheight;
763 row += ri->ri_yorigin;
764
765 mgx_write_4(sc->sc_xreg, ATR_DST_XY,
766 ATR_DUAL(row, ri->ri_xorigin));
767 mgx_write_4(sc->sc_xreg, ATR_WH, ATR_DUAL(n, ri->ri_emuwidth));
768 }
769 mgx_wait_engine(sc);
770
771 return 0;
772 }
773
774 int
mgx_ras_do_cursor(struct rasops_info * ri)775 mgx_ras_do_cursor(struct rasops_info *ri)
776 {
777 struct mgx_softc *sc = ri->ri_hw;
778 int row, col;
779 uint dec = sc->sc_dec;
780
781 row = ri->ri_crow * ri->ri_font->fontheight + ri->ri_yorigin;
782 col = ri->ri_ccol * ri->ri_font->fontwidth + ri->ri_xorigin;
783
784 dec |= (DEC_COMMAND_BLT << DEC_COMMAND_SHIFT) |
785 (DEC_START_DIMX << DEC_START_SHIFT);
786 mgx_wait_fifo(sc, 5);
787 mgx_write_1(sc->sc_xreg, ATR_ROP, (uint8_t)~ROP_SRC);
788 mgx_write_4(sc->sc_xreg, ATR_DEC, dec);
789 mgx_write_4(sc->sc_xreg, ATR_SRC_XY, ATR_DUAL(row, col));
790 mgx_write_4(sc->sc_xreg, ATR_DST_XY, ATR_DUAL(row, col));
791 mgx_write_4(sc->sc_xreg, ATR_WH,
792 ATR_DUAL(ri->ri_font->fontheight, ri->ri_font->fontwidth));
793 mgx_wait_engine(sc);
794
795 return 0;
796 }
797