1 /* $OpenBSD: machfb.c,v 1.13 2022/07/15 17:57:26 kettenis Exp $ */
2
3 /*
4 * Copyright (c) 2009 Mark Kettenis.
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/param.h>
20 #include <sys/device.h>
21 #include <sys/pciio.h>
22 #include <sys/systm.h>
23
24 #include <machine/autoconf.h>
25 #include <machine/bus.h>
26 #include <machine/openfirm.h>
27
28 #include <dev/pci/pcireg.h>
29 #include <dev/pci/pcivar.h>
30 #include <dev/pci/pcidevs.h>
31
32 #include <dev/wscons/wsconsio.h>
33 #include <dev/wscons/wsdisplayvar.h>
34
35 #include <dev/rasops/rasops.h>
36
37 #include <machine/fbvar.h>
38
39 #define M64_PCI_MEM 0x10
40 #define M64_PCI_MMIO 0x18
41
42 #define M64_REG_OFF 0x007ffc00
43 #define M64_REG_SIZE 0x0400
44
45 #define M64_CRTC_INT_CNTL 0x0018
46
47 #define M64_BUS_CNTL 0x00a0
48 #define M64_BUS_FIFO_ERR_ACK 0x00200000
49 #define M64_BUS_HOST_ERR_ACK 0x00800000
50 #define M64_BUS_APER_REG_DIS 0x00000010
51
52 #define M64_DAC_WINDEX 0x00c0
53 #define M64_DAC_DATA 0x00c1
54 #define M64_DAC_MASK 0x00c2
55 #define M64_DAC_RINDEX 0x00c3
56 #define M64_DAC_CNTL 0x00c4
57 #define M64_DAC_8BIT_EN 0x00000100
58
59 #define M64_GEN_TEST_CNTL 0x00d0
60 #define M64_GEN_GUI_EN 0x00000100
61
62 #define M64_DST_OFF_PITCH 0x0100
63 #define M64_DST_X 0x0104
64 #define M64_DST_Y 0x0108
65 #define M64_DST_Y_X 0x010c
66 #define M64_DST_WIDTH 0x0110
67 #define M64_DST_HEIGHT 0x0114
68 #define M64_DST_HEIGHT_WIDTH 0x0118
69 #define M64_DST_X_WIDTH 0x011c
70 #define M64_DST_BRES_LNTH 0x0120
71 #define M64_DST_BRES_ERR 0x0124
72 #define M64_DST_BRES_INC 0x0128
73 #define M64_DST_BRES_DEC 0x012c
74 #define M64_DST_CNTL 0x0130
75 #define M64_DST_X_RIGHT_TO_LEFT 0x00000000
76 #define M64_DST_X_LEFT_TO_RIGHT 0x00000001
77 #define M64_DST_Y_BOTTOM_TO_TOP 0x00000000
78 #define M64_DST_Y_TOP_TO_BOTTOM 0x00000002
79 #define M64_DST_X_MAJOR 0x00000000
80 #define M64_DST_Y_MAJOR 0x00000004
81 #define M64_DST_X_TILE 0x00000008
82 #define M64_DST_Y_TILE 0x00000010
83 #define M64_DST_LAST_PEL 0x00000020
84 #define M64_DST_POLYGON_EN 0x00000040
85 #define M64_DST_24_ROT_EN 0x00000080
86
87 #define M64_SRC_OFF_PITCH 0x0180
88 #define M64_SRC_X 0x0184
89 #define M64_SRC_Y 0x0188
90 #define M64_SRC_Y_X 0x018c
91 #define M64_SRC_WIDTH1 0x0190
92 #define M64_SRC_HEIGHT1 0x0194
93 #define M64_SRC_HEIGHT1_WIDTH1 0x0198
94 #define M64_SRC_X_START 0x019c
95 #define M64_SRC_Y_START 0x01a0
96 #define M64_SRC_Y_X_START 0x01a4
97 #define M64_SRC_WIDTH2 0x01a8
98 #define M64_SRC_HEIGHT2 0x01ac
99 #define M64_SRC_HEIGHT2_WIDTH2 0x01b0
100 #define M64_SRC_CNTL 0x01b4
101 #define M64_SRC_PATT_EN 0x00000001
102 #define M64_SRC_PATT_ROT_EN 0x00000002
103 #define M64_SRC_LINEAR_EN 0x00000004
104 #define M64_SRC_BYTE_ALIGN 0x00000008
105 #define M64_SRC_LINE_X_RIGHT_TO_LEFT 0x00000000
106 #define M64_SRC_LINE_X_LEFT_TO_RIGHT 0x00000010
107
108 #define M64_HOST_CNTL 0x0240
109
110 #define M64_PAT_REG0 0x0280
111 #define M64_PAT_REG1 0x0284
112 #define M64_PAT_CNTL 0x0288
113
114 #define M64_SC_LEFT 0x02a0
115 #define M64_SC_RIGHT 0x02a4
116 #define M64_SC_LEFT_RIGHT 0x02a8
117 #define M64_SC_TOP 0x02ac
118 #define M64_SC_BOTTOM 0x02b0
119 #define M64_SC_TOP_BOTTOM 0x02b4
120
121 #define M64_DP_BKGD_CLR 0x02c0
122 #define M64_DP_FRGD_CLR 0x02c4
123 #define M64_DP_WRITE_MASK 0x02c8
124
125 #define M64_DP_CHAIN_MASK 0x02cc
126 #define M64_DP_CHAIN_8BPP 0x00008080
127 #define M64_DP_PIX_WIDTH 0x02d0
128 #define M64_DST_8BPP 0x00000002
129 #define M64_SRC_8BPP 0x00000200
130 #define M64_HOST_8BPP 0x00020000
131 #define M64_DP_MIX 0x02d4
132 #define M64_MIX_DST 0x00000003
133 #define M64_MIX_SRC 0x00000007
134 #define M64_DP_SRC 0x02d8
135 #define M64_BKGD_SRC_BKGD_CLR 0x00000000
136 #define M64_BKGD_SRC_FRGD_CLR 0x00000001
137 #define M64_BKGD_SRC_HOST 0x00000002
138 #define M64_BKGD_SRC_BLIT 0x00000003
139 #define M64_BKGD_SRC_PATTERN 0x00000004
140 #define M64_FRGD_SRC_BKGD_CLR 0x00000000
141 #define M64_FRGD_SRC_FRGD_CLR 0x00000100
142 #define M64_FRGD_SRC_HOST 0x00000200
143 #define M64_FRGD_SRC_BLIT 0x00000300
144 #define M64_FRGD_SRC_PATTERN 0x00000400
145 #define M64_MONO_SRC_ONE 0x00000000
146 #define M64_MONO_SRC_PATTERN 0x00010000
147 #define M64_MONO_SRC_HOST 0x00020000
148 #define M64_MONO_SRC_BLIT 0x00030000
149
150 #define M64_CLR_CMP_CLR 0x0300
151 #define M64_CLR_CMP_MASK 0x0304
152 #define M64_CLR_CMP_CNTL 0x0308
153
154 #define M64_FIFO_STAT 0x0310
155 #define M64_FIFO_STAT_MASK 0x0000ffff
156
157 #define M64_CONTEXT_MASK 0x0320
158
159 #define M64_GUI_TRAJ_CNTL 0x0330
160 #define M64_GUI_STAT 0x0338
161 #define M64_GUI_ACTIVE 0x00000001
162
163 #define M64_COORDS(x, y) ((x << 16) | (y))
164
165 #ifdef APERTURE
166 extern int allowaperture;
167 #endif
168
169 struct machfb_softc {
170 struct sunfb sc_sunfb;
171
172 bus_space_tag_t sc_memt;
173 bus_space_handle_t sc_memh;
174 bus_addr_t sc_membase;
175 bus_size_t sc_memsize;
176
177 bus_space_tag_t sc_regt;
178 bus_space_handle_t sc_regh;
179
180 bus_space_tag_t sc_mmiot;
181 bus_space_handle_t sc_mmioh;
182 bus_addr_t sc_mmiobase;
183 bus_size_t sc_mmiosize;
184
185 pcitag_t sc_pcitag;
186
187 int sc_mode;
188 u_int8_t sc_cmap_red[256];
189 u_int8_t sc_cmap_green[256];
190 u_int8_t sc_cmap_blue[256];
191 };
192
193 int machfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
194 paddr_t machfb_mmap(void *, off_t, int);
195
196 struct wsdisplay_accessops machfb_accessops = {
197 .ioctl = machfb_ioctl,
198 .mmap = machfb_mmap
199 };
200
201 int machfb_match(struct device *, void *, void *);
202 void machfb_attach(struct device *, struct device *, void *);
203
204 const struct cfattach machfb_ca = {
205 sizeof(struct machfb_softc), machfb_match, machfb_attach
206 };
207
208 struct cfdriver machfb_cd = {
209 NULL, "machfb", DV_DULL
210 };
211
212 int machfb_is_console(int);
213 int machfb_getcmap(struct machfb_softc *, struct wsdisplay_cmap *);
214 int machfb_putcmap(struct machfb_softc *, struct wsdisplay_cmap *);
215 void machfb_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
216
217 int machfb_copycols(void *, int, int, int, int);
218 int machfb_erasecols(void *, int, int, int, uint32_t);
219 int machfb_copyrows(void *, int, int, int);
220 int machfb_eraserows(void *, int, int, uint32_t);
221
222 void machfb_init(struct machfb_softc *);
223 int machfb_wait_fifo(struct machfb_softc *, int);
224 int machfb_wait(struct machfb_softc *);
225 void machfb_copyrect(struct machfb_softc *, int, int, int, int, int, int);
226 void machfb_fillrect(struct machfb_softc *, int, int, int, int, int);
227
228 int
machfb_match(struct device * parent,void * cf,void * aux)229 machfb_match(struct device *parent, void *cf, void *aux)
230 {
231 struct pci_attach_args *pa = aux;
232 char buf[32];
233 int node;
234
235 node = PCITAG_NODE(pa->pa_tag);
236 OF_getprop(node, "name", buf, sizeof(buf));
237 if (strcmp(buf, "SUNW,m64B") == 0)
238 return (10);
239
240 if (OF_getprop(node, "compatible", buf, sizeof(buf)) > 0 &&
241 strcmp(buf, "SUNW,m64B") == 0)
242 return (10);
243
244 return (0);
245 }
246
247 void
machfb_attach(struct device * parent,struct device * self,void * aux)248 machfb_attach(struct device *parent, struct device *self, void *aux)
249 {
250 struct machfb_softc *sc = (struct machfb_softc *)self;
251 struct pci_attach_args *pa = aux;
252 struct rasops_info *ri;
253 int node, console;
254 char *model;
255
256 sc->sc_pcitag = pa->pa_tag;
257
258 node = PCITAG_NODE(pa->pa_tag);
259 console = machfb_is_console(node);
260
261 printf("\n");
262
263 model = getpropstring(node, "model");
264 printf("%s: %s", self->dv_xname, model);
265
266 if (pci_mapreg_map(pa, M64_PCI_MEM, PCI_MAPREG_TYPE_MEM,
267 BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh,
268 &sc->sc_membase, &sc->sc_memsize, 0)) {
269 printf("\n%s: can't map video memory\n", self->dv_xname);
270 return;
271 }
272
273 sc->sc_regt = sc->sc_memt;
274 if (bus_space_subregion(sc->sc_memt, sc->sc_memh,
275 M64_REG_OFF, M64_REG_SIZE, &sc->sc_regh)) {
276 printf("\n%s: can't map registers\n", self->dv_xname);
277 return;
278 }
279
280 if (pci_mapreg_map(pa, M64_PCI_MMIO, PCI_MAPREG_TYPE_MEM, 0,
281 &sc->sc_mmiot, &sc->sc_mmioh, &sc->sc_mmiobase,
282 &sc->sc_mmiosize, 0)) {
283 printf("\n%s: can't map registers\n", self->dv_xname);
284 return;
285 }
286
287 fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
288 if (sc->sc_sunfb.sf_depth == 24) {
289 sc->sc_sunfb.sf_depth = 32;
290 sc->sc_sunfb.sf_linebytes =
291 (sc->sc_sunfb.sf_depth / 8) * sc->sc_sunfb.sf_width;
292 sc->sc_sunfb.sf_fbsize =
293 sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes;
294 }
295
296 printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
297
298 #ifdef RAMDISK_HOOKS
299 printf("%s: aperture needed\n", self->dv_xname);
300 #endif
301
302 ri = &sc->sc_sunfb.sf_ro;
303 ri->ri_bits = bus_space_vaddr(sc->sc_memt, sc->sc_memh);
304 ri->ri_hw = sc;
305
306 fbwscons_init(&sc->sc_sunfb, RI_BSWAP, console);
307 fbwscons_setcolormap(&sc->sc_sunfb, machfb_setcolor);
308 sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
309
310 machfb_init(sc);
311 ri->ri_ops.copyrows = machfb_copyrows;
312 ri->ri_ops.copycols = machfb_copycols;
313 ri->ri_ops.eraserows = machfb_eraserows;
314 ri->ri_ops.erasecols = machfb_erasecols;
315
316 if (console)
317 fbwscons_console_init(&sc->sc_sunfb, -1);
318 fbwscons_attach(&sc->sc_sunfb, &machfb_accessops, console);
319 }
320
321 int
machfb_ioctl(void * v,u_long cmd,caddr_t data,int flags,struct proc * p)322 machfb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
323 {
324 struct machfb_softc *sc = v;
325 struct wsdisplay_fbinfo *wdf;
326 struct pcisel *sel;
327
328 switch (cmd) {
329 case WSDISPLAYIO_GTYPE:
330 *(u_int *)data = WSDISPLAY_TYPE_MACHFB;
331 break;
332 case WSDISPLAYIO_SMODE:
333 sc->sc_mode = *(u_int *)data;
334 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
335 struct rasops_info *ri = &sc->sc_sunfb.sf_ro;
336
337 /* Restore colormap. */
338 fbwscons_setcolormap(&sc->sc_sunfb, machfb_setcolor);
339
340 /* Clear screen. */
341 machfb_fillrect(sc, 0, 0, ri->ri_width, ri->ri_height,
342 ri->ri_devcmap[WSCOL_WHITE]);
343 }
344 break;
345 case WSDISPLAYIO_GINFO:
346 wdf = (void *)data;
347 wdf->height = sc->sc_sunfb.sf_height;
348 wdf->width = sc->sc_sunfb.sf_width;
349 wdf->depth = sc->sc_sunfb.sf_depth;
350 wdf->stride = sc->sc_sunfb.sf_linebytes;
351 wdf->offset = 0;
352 wdf->cmsize = 256;
353 break;
354 case WSDISPLAYIO_LINEBYTES:
355 *(u_int *)data = sc->sc_sunfb.sf_linebytes;
356 break;
357
358 case WSDISPLAYIO_GETCMAP:
359 return machfb_getcmap(sc, (struct wsdisplay_cmap *)data);
360 case WSDISPLAYIO_PUTCMAP:
361 return machfb_putcmap(sc, (struct wsdisplay_cmap *)data);
362
363 case WSDISPLAYIO_GPCIID:
364 sel = (struct pcisel *)data;
365 sel->pc_bus = PCITAG_BUS(sc->sc_pcitag);
366 sel->pc_dev = PCITAG_DEV(sc->sc_pcitag);
367 sel->pc_func = PCITAG_FUN(sc->sc_pcitag);
368 break;
369
370 case WSDISPLAYIO_SVIDEO:
371 case WSDISPLAYIO_GVIDEO:
372 break;
373
374 case WSDISPLAYIO_GCURPOS:
375 case WSDISPLAYIO_SCURPOS:
376 case WSDISPLAYIO_GCURMAX:
377 case WSDISPLAYIO_GCURSOR:
378 case WSDISPLAYIO_SCURSOR:
379 default:
380 return -1; /* not supported yet */
381 }
382
383 return (0);
384 }
385
386 paddr_t
machfb_mmap(void * v,off_t off,int prot)387 machfb_mmap(void *v, off_t off, int prot)
388 {
389 struct machfb_softc *sc = v;
390
391 if (off & PGOFSET)
392 return (-1);
393
394 switch (sc->sc_mode) {
395 case WSDISPLAYIO_MODE_MAPPED:
396 #ifdef APERTURE
397 if (allowaperture == 0)
398 return (-1);
399 #endif
400
401 if (sc->sc_mmiosize == 0)
402 return (-1);
403
404 if (off >= sc->sc_membase &&
405 off < (sc->sc_membase + sc->sc_memsize))
406 return (bus_space_mmap(sc->sc_memt,
407 sc->sc_membase, off - sc->sc_membase,
408 prot, BUS_SPACE_MAP_LINEAR));
409
410 if (off >= sc->sc_mmiobase &&
411 off < (sc->sc_mmiobase + sc->sc_mmiosize))
412 return (bus_space_mmap(sc->sc_mmiot,
413 sc->sc_mmiobase, off - sc->sc_mmiobase,
414 prot, BUS_SPACE_MAP_LINEAR));
415 break;
416
417 case WSDISPLAYIO_MODE_DUMBFB:
418 if (off >= 0 && off < sc->sc_memsize)
419 return (bus_space_mmap(sc->sc_memt, sc->sc_membase,
420 off, prot, BUS_SPACE_MAP_LINEAR));
421 break;
422 }
423
424 return (-1);
425 }
426
427 int
machfb_is_console(int node)428 machfb_is_console(int node)
429 {
430 extern int fbnode;
431
432 return (fbnode == node);
433 }
434
435 int
machfb_getcmap(struct machfb_softc * sc,struct wsdisplay_cmap * cm)436 machfb_getcmap(struct machfb_softc *sc, struct wsdisplay_cmap *cm)
437 {
438 u_int index = cm->index;
439 u_int count = cm->count;
440 int error;
441
442 if (index >= 256 || count > 256 - index)
443 return (EINVAL);
444
445 error = copyout(&sc->sc_cmap_red[index], cm->red, count);
446 if (error)
447 return (error);
448 error = copyout(&sc->sc_cmap_green[index], cm->green, count);
449 if (error)
450 return (error);
451 error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
452 if (error)
453 return (error);
454 return (0);
455 }
456
457 int
machfb_putcmap(struct machfb_softc * sc,struct wsdisplay_cmap * cm)458 machfb_putcmap(struct machfb_softc *sc, struct wsdisplay_cmap *cm)
459 {
460 u_int index = cm->index;
461 u_int count = cm->count;
462 u_int i;
463 int error;
464 u_char *r, *g, *b;
465
466 if (index >= 256 || count > 256 - index)
467 return (EINVAL);
468
469 if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0)
470 return (error);
471 if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0)
472 return (error);
473 if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0)
474 return (error);
475
476 r = &sc->sc_cmap_red[index];
477 g = &sc->sc_cmap_green[index];
478 b = &sc->sc_cmap_blue[index];
479
480 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_MASK, 0xff);
481 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_WINDEX, index);
482 for (i = 0; i < count; i++) {
483 bus_space_write_1(sc->sc_regt, sc->sc_regh,
484 M64_DAC_DATA, *r);
485 bus_space_write_1(sc->sc_regt, sc->sc_regh,
486 M64_DAC_DATA, *g);
487 bus_space_write_1(sc->sc_regt, sc->sc_regh,
488 M64_DAC_DATA, *b);
489 r++, g++, b++;
490 }
491 return (0);
492 }
493
494 void
machfb_setcolor(void * v,u_int index,u_int8_t r,u_int8_t g,u_int8_t b)495 machfb_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
496 {
497 struct machfb_softc *sc = v;
498
499 sc->sc_cmap_red[index] = r;
500 sc->sc_cmap_green[index] = g;
501 sc->sc_cmap_blue[index] = b;
502
503 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_MASK, 0xff);
504 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_WINDEX, index);
505 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, r);
506 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, g);
507 bus_space_write_1(sc->sc_regt, sc->sc_regh, M64_DAC_DATA, b);
508 }
509
510 /*
511 * Accelerated routines.
512 */
513
514 int
machfb_copycols(void * cookie,int row,int src,int dst,int num)515 machfb_copycols(void *cookie, int row, int src, int dst, int num)
516 {
517 struct rasops_info *ri = cookie;
518 struct machfb_softc *sc = ri->ri_hw;
519
520 num *= ri->ri_font->fontwidth;
521 src *= ri->ri_font->fontwidth;
522 dst *= ri->ri_font->fontwidth;
523 row *= ri->ri_font->fontheight;
524
525 machfb_copyrect(sc, ri->ri_xorigin + src, ri->ri_yorigin + row,
526 ri->ri_xorigin + dst, ri->ri_yorigin + row,
527 num, ri->ri_font->fontheight);
528
529 return 0;
530 }
531
532 int
machfb_erasecols(void * cookie,int row,int col,int num,uint32_t attr)533 machfb_erasecols(void *cookie, int row, int col, int num, uint32_t attr)
534 {
535 struct rasops_info *ri = cookie;
536 struct machfb_softc *sc = ri->ri_hw;
537 int bg, fg;
538
539 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
540
541 row *= ri->ri_font->fontheight;
542 col *= ri->ri_font->fontwidth;
543 num *= ri->ri_font->fontwidth;
544
545 machfb_fillrect(sc, ri->ri_xorigin + col, ri->ri_yorigin + row,
546 num, ri->ri_font->fontheight, ri->ri_devcmap[bg]);
547
548 return 0;
549 }
550
551 int
machfb_copyrows(void * cookie,int src,int dst,int num)552 machfb_copyrows(void *cookie, int src, int dst, int num)
553 {
554 struct rasops_info *ri = cookie;
555 struct machfb_softc *sc = ri->ri_hw;
556
557 num *= ri->ri_font->fontheight;
558 src *= ri->ri_font->fontheight;
559 dst *= ri->ri_font->fontheight;
560
561 machfb_copyrect(sc, ri->ri_xorigin, ri->ri_yorigin + src,
562 ri->ri_xorigin, ri->ri_yorigin + dst, ri->ri_emuwidth, num);
563
564 return 0;
565 }
566
567 int
machfb_eraserows(void * cookie,int row,int num,uint32_t attr)568 machfb_eraserows(void *cookie, int row, int num, uint32_t attr)
569 {
570 struct rasops_info *ri = cookie;
571 struct machfb_softc *sc = ri->ri_hw;
572 int bg, fg;
573 int x, y, w;
574
575 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
576
577 if ((num == ri->ri_rows) && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
578 num = ri->ri_height;
579 x = y = 0;
580 w = ri->ri_width;
581 } else {
582 num *= ri->ri_font->fontheight;
583 x = ri->ri_xorigin;
584 y = ri->ri_yorigin + row * ri->ri_font->fontheight;
585 w = ri->ri_emuwidth;
586 }
587 machfb_fillrect(sc, x, y, w, num, ri->ri_devcmap[bg]);
588
589 return 0;
590 }
591
592 void
machfb_init(struct machfb_softc * sc)593 machfb_init(struct machfb_softc *sc)
594 {
595 uint32_t reg;
596
597 /* Reset engine. */
598 reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL);
599 reg &= ~M64_GEN_GUI_EN;
600 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL, reg);
601
602 /* Enable engine. */
603 reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL);
604 reg &= M64_GEN_GUI_EN;
605 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GEN_TEST_CNTL, reg);
606
607 /* Clearing any FIFO or host errors. */
608 reg = bus_space_read_4(sc->sc_regt, sc->sc_regh, M64_BUS_CNTL);
609 reg |= M64_BUS_HOST_ERR_ACK | M64_BUS_FIFO_ERR_ACK;
610 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_BUS_CNTL, reg);
611
612 machfb_wait_fifo(sc, 14);
613
614 bus_space_write_4(sc->sc_regt, sc->sc_regh,
615 M64_CONTEXT_MASK, 0xffffffff);
616
617 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_OFF_PITCH,
618 (sc->sc_sunfb.sf_linebytes / 8) << 22);
619
620 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_Y_X, 0);
621 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_HEIGHT, 0);
622 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_ERR, 0);
623 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_INC, 0);
624 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_BRES_DEC, 0);
625
626 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_CNTL,
627 M64_DST_LAST_PEL | M64_DST_X_LEFT_TO_RIGHT |
628 M64_DST_Y_TOP_TO_BOTTOM);
629
630 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_OFF_PITCH,
631 (sc->sc_sunfb.sf_linebytes / 8) << 22);
632
633 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_Y_X, 0);
634 bus_space_write_4(sc->sc_regt, sc->sc_regh,
635 M64_SRC_HEIGHT1_WIDTH1, 1);
636 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_Y_X_START, 0);
637 bus_space_write_4(sc->sc_regt, sc->sc_regh,
638 M64_SRC_HEIGHT2_WIDTH2, 1);
639
640 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_CNTL,
641 M64_SRC_LINE_X_LEFT_TO_RIGHT);
642
643 machfb_wait_fifo(sc, 13);
644
645 /* Host attributes. */
646 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_HOST_CNTL, 0);
647
648 /* Pattern attributes. */
649 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_REG0, 0);
650 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_REG1, 0);
651 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_PAT_CNTL, 0);
652
653 /* Scissors. */
654 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_LEFT, 0);
655 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_TOP, 0);
656 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_BOTTOM,
657 sc->sc_sunfb.sf_height - 1);
658 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SC_RIGHT,
659 sc->sc_sunfb.sf_linebytes - 1);
660
661 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_BKGD_CLR, 0);
662 bus_space_write_4(sc->sc_regt, sc->sc_regh,
663 M64_DP_FRGD_CLR, 0xffffffff);
664 bus_space_write_4(sc->sc_regt, sc->sc_regh,
665 M64_DP_WRITE_MASK, 0xffffffff);
666 bus_space_write_4(sc->sc_regt, sc->sc_regh,
667 M64_DP_MIX, (M64_MIX_SRC << 16) | M64_MIX_DST);
668
669 bus_space_write_4(sc->sc_regt, sc->sc_regh,
670 M64_DP_SRC, M64_FRGD_SRC_FRGD_CLR);
671
672 machfb_wait_fifo(sc, 3);
673
674 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CLR, 0);
675 bus_space_write_4(sc->sc_regt, sc->sc_regh,
676 M64_CLR_CMP_MASK, 0xffffffff);
677 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0);
678
679 machfb_wait_fifo(sc, 3);
680
681 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_PIX_WIDTH,
682 M64_HOST_8BPP | M64_SRC_8BPP | M64_DST_8BPP);
683 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_CHAIN_MASK,
684 M64_DP_CHAIN_8BPP);
685
686 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_GUI_TRAJ_CNTL,
687 M64_DST_X_LEFT_TO_RIGHT | M64_DST_Y_TOP_TO_BOTTOM);
688
689 machfb_wait(sc);
690 }
691
692 int
machfb_wait_fifo(struct machfb_softc * sc,int v)693 machfb_wait_fifo(struct machfb_softc *sc, int v)
694 {
695 int i;
696
697 for (i = 1000000; i != 0; i--) {
698 if ((bus_space_read_4(sc->sc_regt, sc->sc_regh,
699 M64_FIFO_STAT) & M64_FIFO_STAT_MASK) <= (0x8000 >> v))
700 break;
701 DELAY(1);
702 }
703
704 return i;
705 }
706
707 int
machfb_wait(struct machfb_softc * sc)708 machfb_wait(struct machfb_softc *sc)
709 {
710 int i;
711
712 machfb_wait_fifo(sc, 16);
713 for (i = 1000000; i != 0; i--) {
714 if ((bus_space_read_4(sc->sc_regt, sc->sc_regh,
715 M64_GUI_STAT) & M64_GUI_ACTIVE) == 0)
716 break;
717 DELAY(1);
718 }
719
720 return i;
721 }
722
723 void
machfb_copyrect(struct machfb_softc * sc,int sx,int sy,int dx,int dy,int w,int h)724 machfb_copyrect(struct machfb_softc *sc, int sx, int sy, int dx, int dy,
725 int w, int h)
726 {
727 uint32_t dest_ctl = 0;
728
729 machfb_wait_fifo(sc, 10);
730
731 bus_space_write_4(sc->sc_regt, sc->sc_regh,
732 M64_DP_WRITE_MASK, 0xff);
733 bus_space_write_4(sc->sc_regt, sc->sc_regh,
734 M64_DP_SRC, M64_FRGD_SRC_BLIT);
735 bus_space_write_4(sc->sc_regt, sc->sc_regh,
736 M64_DP_MIX, M64_MIX_SRC << 16);
737 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0);
738 if (dy < sy) {
739 dest_ctl = M64_DST_Y_TOP_TO_BOTTOM;
740 } else {
741 sy += h - 1;
742 dy += h - 1;
743 dest_ctl = M64_DST_Y_BOTTOM_TO_TOP;
744 }
745 if (dx < sx) {
746 dest_ctl |= M64_DST_X_LEFT_TO_RIGHT;
747 bus_space_write_4(sc->sc_regt, sc->sc_regh,
748 M64_SRC_CNTL, M64_SRC_LINE_X_LEFT_TO_RIGHT);
749 } else {
750 dest_ctl |= M64_DST_X_RIGHT_TO_LEFT;
751 sx += w - 1;
752 dx += w - 1;
753 bus_space_write_4(sc->sc_regt, sc->sc_regh,
754 M64_SRC_CNTL, M64_SRC_LINE_X_RIGHT_TO_LEFT);
755 }
756 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DST_CNTL, dest_ctl);
757
758 bus_space_write_4(sc->sc_regt, sc->sc_regh,
759 M64_SRC_Y_X, M64_COORDS(sx, sy));
760 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_WIDTH1, w);
761 bus_space_write_4(sc->sc_regt, sc->sc_regh,
762 M64_DST_Y_X, M64_COORDS(dx, dy));
763 bus_space_write_4(sc->sc_regt, sc->sc_regh,
764 M64_DST_HEIGHT_WIDTH, M64_COORDS(w, h));
765
766 machfb_wait(sc);
767 }
768
769 void
machfb_fillrect(struct machfb_softc * sc,int x,int y,int w,int h,int color)770 machfb_fillrect(struct machfb_softc *sc, int x, int y, int w, int h, int color)
771 {
772 machfb_wait_fifo(sc, 11);
773
774 bus_space_write_4(sc->sc_regt, sc->sc_regh,
775 M64_DP_WRITE_MASK, 0xff);
776 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_DP_FRGD_CLR, color);
777 bus_space_write_4(sc->sc_regt, sc->sc_regh,
778 M64_DP_SRC, M64_FRGD_SRC_FRGD_CLR);
779 bus_space_write_4(sc->sc_regt, sc->sc_regh,
780 M64_DP_MIX, M64_MIX_SRC << 16);
781 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_CLR_CMP_CNTL, 0);
782 bus_space_write_4(sc->sc_regt, sc->sc_regh,
783 M64_SRC_CNTL, M64_SRC_LINE_X_LEFT_TO_RIGHT);
784 bus_space_write_4(sc->sc_regt, sc->sc_regh,
785 M64_DST_CNTL, M64_DST_X_LEFT_TO_RIGHT | M64_DST_Y_TOP_TO_BOTTOM);
786
787 bus_space_write_4(sc->sc_regt, sc->sc_regh,
788 M64_SRC_Y_X, M64_COORDS(x, y));
789 bus_space_write_4(sc->sc_regt, sc->sc_regh, M64_SRC_WIDTH1, w);
790 bus_space_write_4(sc->sc_regt, sc->sc_regh,
791 M64_DST_Y_X, M64_COORDS(x, y));
792 bus_space_write_4(sc->sc_regt, sc->sc_regh,
793 M64_DST_HEIGHT_WIDTH, M64_COORDS(w, h));
794
795 machfb_wait(sc);
796 }
797