Annotation of sys/arch/sparc64/dev/creator.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: creator.c,v 1.39 2007/03/06 23:10:26 kettenis Exp $ */
2:
3: /*
4: * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26: * POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29: #include <sys/types.h>
30: #include <sys/param.h>
31: #include <sys/systm.h>
32: #include <sys/kernel.h>
33: #include <sys/device.h>
34: #include <sys/conf.h>
35: #include <sys/timeout.h>
36:
37: #include <machine/bus.h>
38: #include <machine/autoconf.h>
39: #include <machine/openfirm.h>
40:
41: #include <dev/wscons/wsconsio.h>
42: #include <dev/wscons/wsdisplayvar.h>
43: #include <dev/rasops/rasops.h>
44: #include <machine/fbvar.h>
45:
46: #include <sparc64/dev/creatorreg.h>
47: #include <sparc64/dev/creatorvar.h>
48:
49: int creator_match(struct device *, void *, void *);
50: void creator_attach(struct device *, struct device *, void *);
51: int creator_ioctl(void *, u_long, caddr_t, int, struct proc *);
52: int creator_alloc_screen(void *, const struct wsscreen_descr *, void **,
53: int *, int *, long *);
54: void creator_free_screen(void *, void *);
55: int creator_show_screen(void *, void *, int, void (*cb)(void *, int, int),
56: void *);
57: paddr_t creator_mmap(void *, off_t, int);
58: void creator_ras_fifo_wait(struct creator_softc *, int);
59: void creator_ras_wait(struct creator_softc *);
60: void creator_ras_init(struct creator_softc *);
61: void creator_ras_copyrows(void *, int, int, int);
62: void creator_ras_erasecols(void *, int, int, int, long int);
63: void creator_ras_eraserows(void *, int, int, long int);
64: void creator_ras_fill(struct creator_softc *);
65: void creator_ras_setfg(struct creator_softc *, int32_t);
66: int creator_setcursor(struct creator_softc *, struct wsdisplay_cursor *);
67: int creator_updatecursor(struct creator_softc *, u_int);
68: void creator_curs_enable(struct creator_softc *, u_int);
69:
70: struct wsdisplay_accessops creator_accessops = {
71: creator_ioctl,
72: creator_mmap,
73: creator_alloc_screen,
74: creator_free_screen,
75: creator_show_screen,
76: NULL, /* load font */
77: NULL, /* scrollback */
78: NULL, /* getchar */
79: NULL, /* burner */
80: };
81:
82: struct cfdriver creator_cd = {
83: NULL, "creator", DV_DULL
84: };
85:
86: struct cfattach creator_ca = {
87: sizeof(struct creator_softc), creator_match, creator_attach
88: };
89:
90: int
91: creator_match(parent, match, aux)
92: struct device *parent;
93: void *match, *aux;
94: {
95: struct mainbus_attach_args *ma = aux;
96:
97: if (strcmp(ma->ma_name, "SUNW,ffb") == 0 ||
98: strcmp(ma->ma_name, "SUNW,afb") == 0)
99: return (1);
100: return (0);
101: }
102:
103: void
104: creator_attach(parent, self, aux)
105: struct device *parent, *self;
106: void *aux;
107: {
108: struct creator_softc *sc = (struct creator_softc *)self;
109: struct mainbus_attach_args *ma = aux;
110: extern int fbnode;
111: int i, nregs;
112: char *model;
113: int btype;
114:
115: sc->sc_bt = ma->ma_bustag;
116:
117: nregs = min(ma->ma_nreg, FFB_NREGS);
118:
119: if (nregs <= FFB_REG_DFB24) {
120: printf(": no dfb24 regs found\n");
121: return;
122: }
123:
124: if (bus_space_map(sc->sc_bt, ma->ma_reg[FFB_REG_DFB24].ur_paddr,
125: ma->ma_reg[FFB_REG_DFB24].ur_len, BUS_SPACE_MAP_LINEAR,
126: &sc->sc_pixel_h)) {
127: printf(": failed to map dfb24\n");
128: return;
129: }
130:
131: if (bus_space_map(sc->sc_bt, ma->ma_reg[FFB_REG_FBC].ur_paddr,
132: ma->ma_reg[FFB_REG_FBC].ur_len, 0, &sc->sc_fbc_h)) {
133: printf(": failed to map fbc\n");
134: goto unmap_dfb24;
135: }
136:
137: if (bus_space_map(sc->sc_bt, ma->ma_reg[FFB_REG_DAC].ur_paddr,
138: ma->ma_reg[FFB_REG_DAC].ur_len, 0, &sc->sc_dac_h)) {
139: printf(": failed to map dac\n");
140: goto unmap_fbc;
141: }
142:
143: for (i = 0; i < nregs; i++) {
144: sc->sc_addrs[i] = ma->ma_reg[i].ur_paddr;
145: sc->sc_sizes[i] = ma->ma_reg[i].ur_len;
146: }
147: sc->sc_nreg = nregs;
148:
149: sc->sc_console = (fbnode == ma->ma_node);
150: sc->sc_node = ma->ma_node;
151:
152: if (strcmp(ma->ma_name, "SUNW,afb") == 0)
153: sc->sc_type = FFB_AFB;
154:
155: /*
156: * Prom reports only the length of the fcode header, we need
157: * the whole thing.
158: */
159: sc->sc_sizes[0] = 0x00400000;
160:
161: if (sc->sc_type == FFB_CREATOR) {
162: btype = getpropint(sc->sc_node, "board_type", 0);
163: if ((btype & 7) == 3)
164: printf(": Creator3D");
165: else
166: printf(": Creator");
167: } else
168: printf(": Elite3D");
169:
170: model = getpropstring(sc->sc_node, "model");
171: if (model == NULL || strlen(model) == 0)
172: model = "unknown";
173:
174: DAC_WRITE(sc, FFB_DAC_TYPE, DAC_TYPE_GETREV);
175: sc->sc_dacrev = DAC_READ(sc, FFB_DAC_VALUE) >> 28;
176:
177: printf(", model %s, dac %u\n", model, sc->sc_dacrev);
178:
179: if (sc->sc_type == FFB_AFB)
180: sc->sc_dacrev = 10;
181:
182: fb_setsize(&sc->sc_sunfb, 32, 1152, 900, sc->sc_node, 0);
183: /* linesize has a fixed value, compensate */
184: sc->sc_sunfb.sf_linebytes = 8192;
185: sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height * 8192;
186:
187: sc->sc_sunfb.sf_ro.ri_bits = (void *)bus_space_vaddr(sc->sc_bt,
188: sc->sc_pixel_h);
189: sc->sc_sunfb.sf_ro.ri_hw = sc;
190: fbwscons_init(&sc->sc_sunfb, sc->sc_console ? 0 : RI_CLEAR);
191:
192: if ((sc->sc_sunfb.sf_dev.dv_cfdata->cf_flags & CREATOR_CFFLAG_NOACCEL)
193: == 0) {
194: sc->sc_sunfb.sf_ro.ri_ops.eraserows = creator_ras_eraserows;
195: sc->sc_sunfb.sf_ro.ri_ops.erasecols = creator_ras_erasecols;
196: sc->sc_sunfb.sf_ro.ri_ops.copyrows = creator_ras_copyrows;
197: creator_ras_init(sc);
198: }
199:
200: if (sc->sc_console) {
201: fbwscons_console_init(&sc->sc_sunfb, -1);
202: }
203:
204: fbwscons_attach(&sc->sc_sunfb, &creator_accessops, sc->sc_console);
205: return;
206:
207: unmap_fbc:
208: bus_space_unmap(sc->sc_bt, sc->sc_fbc_h,
209: ma->ma_reg[FFB_REG_FBC].ur_len);
210: unmap_dfb24:
211: bus_space_unmap(sc->sc_bt, sc->sc_pixel_h,
212: ma->ma_reg[FFB_REG_DFB24].ur_len);
213: }
214:
215: int
216: creator_ioctl(v, cmd, data, flags, p)
217: void *v;
218: u_long cmd;
219: caddr_t data;
220: int flags;
221: struct proc *p;
222: {
223: struct creator_softc *sc = v;
224: struct wsdisplay_cursor *curs;
225: struct wsdisplay_fbinfo *wdf;
226: struct wsdisplay_curpos *pos;
227: u_char r[2], g[2], b[2];
228: int error;
229:
230: switch (cmd) {
231: case WSDISPLAYIO_GTYPE:
232: *(u_int *)data = WSDISPLAY_TYPE_SUNFFB;
233: break;
234: case WSDISPLAYIO_SMODE:
235: sc->sc_mode = *(u_int *)data;
236: break;
237: case WSDISPLAYIO_GINFO:
238: wdf = (void *)data;
239: wdf->height = sc->sc_sunfb.sf_height;
240: wdf->width = sc->sc_sunfb.sf_width;
241: wdf->depth = 32;
242: wdf->cmsize = 0;
243: break;
244: case WSDISPLAYIO_GETSUPPORTEDDEPTH:
245: *(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
246: break;
247: case WSDISPLAYIO_LINEBYTES:
248: *(u_int *)data = sc->sc_sunfb.sf_linebytes;
249: break;
250: case WSDISPLAYIO_GCURSOR:
251: curs = (struct wsdisplay_cursor *)data;
252: if (curs->which & WSDISPLAY_CURSOR_DOCUR)
253: curs->enable = sc->sc_curs_enabled;
254: if (curs->which & WSDISPLAY_CURSOR_DOPOS) {
255: curs->pos.x = sc->sc_curs_pos.x;
256: curs->pos.y = sc->sc_curs_pos.y;
257: }
258: if (curs->which & WSDISPLAY_CURSOR_DOHOT) {
259: curs->hot.x = sc->sc_curs_hot.x;
260: curs->hot.y = sc->sc_curs_hot.y;
261: }
262: if (curs->which & WSDISPLAY_CURSOR_DOCMAP) {
263: curs->cmap.index = 0;
264: curs->cmap.count = 2;
265: r[0] = sc->sc_curs_fg >> 0;
266: g[0] = sc->sc_curs_fg >> 8;
267: b[0] = sc->sc_curs_fg >> 16;
268: r[1] = sc->sc_curs_bg >> 0;
269: g[1] = sc->sc_curs_bg >> 8;
270: b[1] = sc->sc_curs_bg >> 16;
271: error = copyout(r, curs->cmap.red, sizeof(r));
272: if (error)
273: return (error);
274: error = copyout(g, curs->cmap.green, sizeof(g));
275: if (error)
276: return (error);
277: error = copyout(b, curs->cmap.blue, sizeof(b));
278: if (error)
279: return (error);
280: }
281: if (curs->which & WSDISPLAY_CURSOR_DOSHAPE) {
282: size_t l;
283:
284: curs->size.x = sc->sc_curs_size.x;
285: curs->size.y = sc->sc_curs_size.y;
286: l = (sc->sc_curs_size.x * sc->sc_curs_size.y) / NBBY;
287: error = copyout(sc->sc_curs_image, curs->image, l);
288: if (error)
289: return (error);
290: error = copyout(sc->sc_curs_mask, curs->mask, l);
291: if (error)
292: return (error);
293: }
294: break;
295: case WSDISPLAYIO_SCURPOS:
296: pos = (struct wsdisplay_curpos *)data;
297: sc->sc_curs_pos.x = pos->x;
298: sc->sc_curs_pos.y = pos->y;
299: creator_updatecursor(sc, WSDISPLAY_CURSOR_DOPOS);
300: break;
301: case WSDISPLAYIO_GCURPOS:
302: pos = (struct wsdisplay_curpos *)data;
303: pos->x = sc->sc_curs_pos.x;
304: pos->y = sc->sc_curs_pos.y;
305: break;
306: case WSDISPLAYIO_SCURSOR:
307: curs = (struct wsdisplay_cursor *)data;
308: return (creator_setcursor(sc, curs));
309: case WSDISPLAYIO_GCURMAX:
310: pos = (struct wsdisplay_curpos *)data;
311: pos->x = CREATOR_CURS_MAX;
312: pos->y = CREATOR_CURS_MAX;
313: break;
314: case WSDISPLAYIO_SVIDEO:
315: case WSDISPLAYIO_GVIDEO:
316: break;
317:
318: case WSDISPLAYIO_GETCMAP:
319: case WSDISPLAYIO_PUTCMAP:
320: default:
321: return -1; /* not supported yet */
322: }
323:
324: return (0);
325: }
326:
327: int
328: creator_setcursor(struct creator_softc *sc, struct wsdisplay_cursor *curs)
329: {
330: u_int8_t r[2], g[2], b[2], image[128], mask[128];
331: int error;
332: size_t imcount;
333:
334: /*
335: * Do stuff that can generate errors first, then we'll blast it
336: * all at once.
337: */
338: if (curs->which & WSDISPLAY_CURSOR_DOCMAP) {
339: if (curs->cmap.count < 2)
340: return (EINVAL);
341: error = copyin(curs->cmap.red, r, sizeof(r));
342: if (error)
343: return (error);
344: error = copyin(curs->cmap.green, g, sizeof(g));
345: if (error)
346: return (error);
347: error = copyin(curs->cmap.blue, b, sizeof(b));
348: if (error)
349: return (error);
350: }
351:
352: if (curs->which & WSDISPLAY_CURSOR_DOSHAPE) {
353: if (curs->size.x > CREATOR_CURS_MAX ||
354: curs->size.y > CREATOR_CURS_MAX)
355: return (EINVAL);
356: imcount = (curs->size.x * curs->size.y) / NBBY;
357: error = copyin(curs->image, image, imcount);
358: if (error)
359: return (error);
360: error = copyin(curs->mask, mask, imcount);
361: if (error)
362: return (error);
363: }
364:
365: /*
366: * Ok, everything is in kernel space and sane, update state.
367: */
368:
369: if (curs->which & WSDISPLAY_CURSOR_DOCUR)
370: sc->sc_curs_enabled = curs->enable;
371: if (curs->which & WSDISPLAY_CURSOR_DOPOS) {
372: sc->sc_curs_pos.x = curs->pos.x;
373: sc->sc_curs_pos.y = curs->pos.y;
374: }
375: if (curs->which & WSDISPLAY_CURSOR_DOHOT) {
376: sc->sc_curs_hot.x = curs->hot.x;
377: sc->sc_curs_hot.y = curs->hot.y;
378: }
379: if (curs->which & WSDISPLAY_CURSOR_DOCMAP) {
380: sc->sc_curs_fg = ((r[0] << 0) | (g[0] << 8) | (b[0] << 16));
381: sc->sc_curs_bg = ((r[1] << 0) | (g[1] << 8) | (b[1] << 16));
382: }
383: if (curs->which & WSDISPLAY_CURSOR_DOSHAPE) {
384: sc->sc_curs_size.x = curs->size.x;
385: sc->sc_curs_size.y = curs->size.y;
386: bcopy(image, sc->sc_curs_image, imcount);
387: bcopy(mask, sc->sc_curs_mask, imcount);
388: }
389:
390: creator_updatecursor(sc, curs->which);
391:
392: return (0);
393: }
394:
395: void
396: creator_curs_enable(struct creator_softc *sc, u_int ena)
397: {
398: u_int32_t v;
399:
400: DAC_WRITE(sc, FFB_DAC_TYPE2, DAC_TYPE2_CURSENAB);
401: if (sc->sc_dacrev <= 2)
402: v = ena ? 3 : 0;
403: else
404: v = ena ? 0 : 3;
405: DAC_WRITE(sc, FFB_DAC_VALUE2, v);
406: }
407:
408: int
409: creator_updatecursor(struct creator_softc *sc, u_int which)
410: {
411: creator_curs_enable(sc, 0);
412:
413: if (which & WSDISPLAY_CURSOR_DOCMAP) {
414: DAC_WRITE(sc, FFB_DAC_TYPE2, DAC_TYPE2_CURSCMAP);
415: DAC_WRITE(sc, FFB_DAC_VALUE2, sc->sc_curs_fg);
416: DAC_WRITE(sc, FFB_DAC_VALUE2, sc->sc_curs_bg);
417: }
418:
419: if (which & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
420: u_int32_t x, y;
421:
422: x = sc->sc_curs_pos.x + CREATOR_CURS_MAX - sc->sc_curs_hot.x;
423: y = sc->sc_curs_pos.y + CREATOR_CURS_MAX - sc->sc_curs_hot.y;
424: DAC_WRITE(sc, FFB_DAC_TYPE2, DAC_TYPE2_CURSPOS);
425: DAC_WRITE(sc, FFB_DAC_VALUE2,
426: ((x & 0xffff) << 16) | (y & 0xffff));
427: }
428:
429: if (which & WSDISPLAY_CURSOR_DOCUR)
430: creator_curs_enable(sc, sc->sc_curs_enabled);
431:
432: return (0);
433: }
434:
435: int
436: creator_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
437: void *v;
438: const struct wsscreen_descr *type;
439: void **cookiep;
440: int *curxp, *curyp;
441: long *attrp;
442: {
443: struct creator_softc *sc = v;
444:
445: if (sc->sc_nscreens > 0)
446: return (ENOMEM);
447:
448: *cookiep = &sc->sc_sunfb.sf_ro;
449: *curyp = 0;
450: *curxp = 0;
451: sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro,
452: WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp);
453: sc->sc_nscreens++;
454: return (0);
455: }
456:
457: void
458: creator_free_screen(v, cookie)
459: void *v;
460: void *cookie;
461: {
462: struct creator_softc *sc = v;
463:
464: sc->sc_nscreens--;
465: }
466:
467: int
468: creator_show_screen(v, cookie, waitok, cb, cbarg)
469: void *v;
470: void *cookie;
471: int waitok;
472: void (*cb)(void *, int, int);
473: void *cbarg;
474: {
475: return (0);
476: }
477:
478: const struct creator_mappings {
479: bus_addr_t uoff;
480: bus_addr_t poff;
481: bus_size_t ulen;
482: } creator_map[] = {
483: { FFB_VOFF_SFB8R, FFB_POFF_SFB8R, FFB_VLEN_SFB8R },
484: { FFB_VOFF_SFB8G, FFB_POFF_SFB8G, FFB_VLEN_SFB8G },
485: { FFB_VOFF_SFB8B, FFB_POFF_SFB8B, FFB_VLEN_SFB8B },
486: { FFB_VOFF_SFB8X, FFB_POFF_SFB8X, FFB_VLEN_SFB8X },
487: { FFB_VOFF_SFB32, FFB_POFF_SFB32, FFB_VLEN_SFB32 },
488: { FFB_VOFF_SFB64, FFB_POFF_SFB64, FFB_VLEN_SFB64 },
489: { FFB_VOFF_FBC_REGS, FFB_POFF_FBC_REGS, FFB_VLEN_FBC_REGS },
490: { FFB_VOFF_BM_FBC_REGS, FFB_POFF_BM_FBC_REGS, FFB_VLEN_BM_FBC_REGS },
491: { FFB_VOFF_DFB8R, FFB_POFF_DFB8R, FFB_VLEN_DFB8R },
492: { FFB_VOFF_DFB8G, FFB_POFF_DFB8G, FFB_VLEN_DFB8G },
493: { FFB_VOFF_DFB8B, FFB_POFF_DFB8B, FFB_VLEN_DFB8B },
494: { FFB_VOFF_DFB8X, FFB_POFF_DFB8X, FFB_VLEN_DFB8X },
495: { FFB_VOFF_DFB24, FFB_POFF_DFB24, FFB_VLEN_DFB24 },
496: { FFB_VOFF_DFB32, FFB_POFF_DFB32, FFB_VLEN_DFB32 },
497: { FFB_VOFF_DFB422A, FFB_POFF_DFB422A, FFB_VLEN_DFB422A },
498: { FFB_VOFF_DFB422AD, FFB_POFF_DFB422AD, FFB_VLEN_DFB422AD },
499: { FFB_VOFF_DFB24B, FFB_POFF_DFB24B, FFB_VLEN_DFB24B },
500: { FFB_VOFF_DFB422B, FFB_POFF_DFB422B, FFB_VLEN_DFB422B },
501: { FFB_VOFF_DFB422BD, FFB_POFF_DFB422BD, FFB_VLEN_DFB422BD },
502: { FFB_VOFF_SFB16Z, FFB_POFF_SFB16Z, FFB_VLEN_SFB16Z },
503: { FFB_VOFF_SFB8Z, FFB_POFF_SFB8Z, FFB_VLEN_SFB8Z },
504: { FFB_VOFF_SFB422, FFB_POFF_SFB422, FFB_VLEN_SFB422 },
505: { FFB_VOFF_SFB422D, FFB_POFF_SFB422D, FFB_VLEN_SFB422D },
506: { FFB_VOFF_FBC_KREGS, FFB_POFF_FBC_KREGS, FFB_VLEN_FBC_KREGS },
507: { FFB_VOFF_DAC, FFB_POFF_DAC, FFB_VLEN_DAC },
508: { FFB_VOFF_PROM, FFB_POFF_PROM, FFB_VLEN_PROM },
509: { FFB_VOFF_EXP, FFB_POFF_EXP, FFB_VLEN_EXP },
510: };
511: #define CREATOR_NMAPPINGS (sizeof(creator_map)/sizeof(creator_map[0]))
512:
513: paddr_t
514: creator_mmap(vsc, off, prot)
515: void *vsc;
516: off_t off;
517: int prot;
518: {
519: paddr_t x;
520: struct creator_softc *sc = vsc;
521: int i;
522:
523: switch (sc->sc_mode) {
524: case WSDISPLAYIO_MODE_MAPPED:
525: /* Turn virtual offset into physical offset */
526: for (i = 0; i < CREATOR_NMAPPINGS; i++) {
527: if (off >= creator_map[i].uoff &&
528: off < (creator_map[i].uoff + creator_map[i].ulen))
529: break;
530: }
531: if (i == CREATOR_NMAPPINGS)
532: break;
533:
534: off -= creator_map[i].uoff;
535: off += creator_map[i].poff;
536: off += sc->sc_addrs[0];
537:
538: /* Map based on physical offset */
539: for (i = 0; i < sc->sc_nreg; i++) {
540: /* Before this set? */
541: if (off < sc->sc_addrs[i])
542: continue;
543: /* After this set? */
544: if (off >= (sc->sc_addrs[i] + sc->sc_sizes[i]))
545: continue;
546:
547: x = bus_space_mmap(sc->sc_bt, 0, off, prot,
548: BUS_SPACE_MAP_LINEAR);
549: return (x);
550: }
551: break;
552: case WSDISPLAYIO_MODE_DUMBFB:
553: if (sc->sc_nreg <= FFB_REG_DFB24)
554: break;
555: if (off >= 0 && off < sc->sc_sizes[FFB_REG_DFB24])
556: return (bus_space_mmap(sc->sc_bt,
557: sc->sc_addrs[FFB_REG_DFB24], off, prot,
558: BUS_SPACE_MAP_LINEAR));
559: break;
560: }
561:
562: return (-1);
563: }
564:
565: void
566: creator_ras_fifo_wait(sc, n)
567: struct creator_softc *sc;
568: int n;
569: {
570: int32_t cache = sc->sc_fifo_cache;
571:
572: if (cache < n) {
573: do {
574: cache = FBC_READ(sc, FFB_FBC_UCSR);
575: cache = (cache & FBC_UCSR_FIFO_MASK) - 8;
576: } while (cache < n);
577: }
578: sc->sc_fifo_cache = cache - n;
579: }
580:
581: void
582: creator_ras_wait(sc)
583: struct creator_softc *sc;
584: {
585: u_int32_t ucsr, r;
586:
587: while (1) {
588: ucsr = FBC_READ(sc, FFB_FBC_UCSR);
589: if ((ucsr & (FBC_UCSR_FB_BUSY|FBC_UCSR_RP_BUSY)) == 0)
590: break;
591: r = ucsr & (FBC_UCSR_READ_ERR | FBC_UCSR_FIFO_OVFL);
592: if (r != 0)
593: FBC_WRITE(sc, FFB_FBC_UCSR, r);
594: }
595: }
596:
597: void
598: creator_ras_init(sc)
599: struct creator_softc *sc;
600: {
601: creator_ras_fifo_wait(sc, 7);
602: FBC_WRITE(sc, FFB_FBC_PPC,
603: FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE |
604: FBC_PPC_APE_DIS | FBC_PPC_CS_CONST);
605: FBC_WRITE(sc, FFB_FBC_FBC,
606: FFB_FBC_WB_A | FFB_FBC_RB_A | FFB_FBC_SB_BOTH |
607: FFB_FBC_XE_OFF | FFB_FBC_RGBE_MASK);
608: FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW);
609: FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE);
610: FBC_WRITE(sc, FFB_FBC_PMASK, 0xffffffff);
611: FBC_WRITE(sc, FFB_FBC_FONTINC, 0x10000);
612: sc->sc_fg_cache = 0;
613: FBC_WRITE(sc, FFB_FBC_FG, sc->sc_fg_cache);
614: creator_ras_wait(sc);
615: }
616:
617: void
618: creator_ras_eraserows(cookie, row, n, attr)
619: void *cookie;
620: int row, n;
621: long int attr;
622: {
623: struct rasops_info *ri = cookie;
624: struct creator_softc *sc = ri->ri_hw;
625: int bg, fg;
626:
627: if (row < 0) {
628: n += row;
629: row = 0;
630: }
631: if (row + n > ri->ri_rows)
632: n = ri->ri_rows - row;
633: if (n <= 0)
634: return;
635:
636: ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
637: creator_ras_fill(sc);
638: creator_ras_setfg(sc, ri->ri_devcmap[bg]);
639: creator_ras_fifo_wait(sc, 4);
640: if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) {
641: FBC_WRITE(sc, FFB_FBC_BY, 0);
642: FBC_WRITE(sc, FFB_FBC_BX, 0);
643: FBC_WRITE(sc, FFB_FBC_BH, ri->ri_height);
644: FBC_WRITE(sc, FFB_FBC_BW, ri->ri_width);
645: } else {
646: row *= ri->ri_font->fontheight;
647: FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + row);
648: FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin);
649: FBC_WRITE(sc, FFB_FBC_BH, n * ri->ri_font->fontheight);
650: FBC_WRITE(sc, FFB_FBC_BW, ri->ri_emuwidth);
651: }
652: creator_ras_wait(sc);
653: }
654:
655: void
656: creator_ras_erasecols(cookie, row, col, n, attr)
657: void *cookie;
658: int row, col, n;
659: long int attr;
660: {
661: struct rasops_info *ri = cookie;
662: struct creator_softc *sc = ri->ri_hw;
663: int fg, bg;
664:
665: if ((row < 0) || (row >= ri->ri_rows))
666: return;
667: if (col < 0) {
668: n += col;
669: col = 0;
670: }
671: if (col + n > ri->ri_cols)
672: n = ri->ri_cols - col;
673: if (n <= 0)
674: return;
675: n *= ri->ri_font->fontwidth;
676: col *= ri->ri_font->fontwidth;
677: row *= ri->ri_font->fontheight;
678:
679: ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
680: creator_ras_fill(sc);
681: creator_ras_setfg(sc, ri->ri_devcmap[bg]);
682: creator_ras_fifo_wait(sc, 4);
683: FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + row);
684: FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin + col);
685: FBC_WRITE(sc, FFB_FBC_BH, ri->ri_font->fontheight);
686: FBC_WRITE(sc, FFB_FBC_BW, n - 1);
687: creator_ras_wait(sc);
688: }
689:
690: void
691: creator_ras_fill(sc)
692: struct creator_softc *sc;
693: {
694: creator_ras_fifo_wait(sc, 2);
695: FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW);
696: FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE);
697: creator_ras_wait(sc);
698: }
699:
700: void
701: creator_ras_copyrows(cookie, src, dst, n)
702: void *cookie;
703: int src, dst, n;
704: {
705: struct rasops_info *ri = cookie;
706: struct creator_softc *sc = ri->ri_hw;
707:
708: if (dst == src)
709: return;
710: if (src < 0) {
711: n += src;
712: src = 0;
713: }
714: if ((src + n) > ri->ri_rows)
715: n = ri->ri_rows - src;
716: if (dst < 0) {
717: n += dst;
718: dst = 0;
719: }
720: if ((dst + n) > ri->ri_rows)
721: n = ri->ri_rows - dst;
722: if (n <= 0)
723: return;
724: n *= ri->ri_font->fontheight;
725: src *= ri->ri_font->fontheight;
726: dst *= ri->ri_font->fontheight;
727:
728: creator_ras_fifo_wait(sc, 8);
729: FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_OLD | (FBC_ROP_OLD << 8));
730: FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_VSCROLL);
731: FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + src);
732: FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin);
733: FBC_WRITE(sc, FFB_FBC_DY, ri->ri_yorigin + dst);
734: FBC_WRITE(sc, FFB_FBC_DX, ri->ri_xorigin);
735: FBC_WRITE(sc, FFB_FBC_BH, n);
736: FBC_WRITE(sc, FFB_FBC_BW, ri->ri_emuwidth);
737: creator_ras_wait(sc);
738: }
739:
740: void
741: creator_ras_setfg(sc, fg)
742: struct creator_softc *sc;
743: int32_t fg;
744: {
745: creator_ras_fifo_wait(sc, 1);
746: if (fg == sc->sc_fg_cache)
747: return;
748: sc->sc_fg_cache = fg;
749: FBC_WRITE(sc, FFB_FBC_FG, fg);
750: creator_ras_wait(sc);
751: }
CVSweb