Annotation of sys/arch/sparc64/dev/vgafb.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: vgafb.c,v 1.50 2007/03/06 19:13:13 miod Exp $ */
2:
3: /*
4: * Copyright (c) 2001 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: * Effort sponsored in part by the Defense Advanced Research Projects
29: * Agency (DARPA) and Air Force Research Laboratory, Air Force
30: * Materiel Command, USAF, under agreement number F30602-01-2-0537.
31: *
32: */
33:
34: #include <sys/param.h>
35: #include <sys/systm.h>
36: #include <sys/device.h>
37: #include <sys/errno.h>
38: #include <sys/ioctl.h>
39: #include <sys/malloc.h>
40: #include <sys/pciio.h>
41:
42: #include <uvm/uvm_extern.h>
43:
44: #include <machine/autoconf.h>
45: #include <machine/bus.h>
46: #include <machine/intr.h>
47: #include <machine/openfirm.h>
48:
49: #include <dev/pci/pcidevs.h>
50: #include <dev/pci/pcireg.h>
51: #include <dev/pci/pcivar.h>
52:
53: #include <dev/wscons/wsconsio.h>
54: #include <dev/wscons/wsdisplayvar.h>
55: #include <dev/rasops/rasops.h>
56:
57: #include <machine/fbvar.h>
58:
59: struct vgafb_softc {
60: struct sunfb sc_sunfb;
61: int sc_nscreens;
62: int sc_node, sc_ofhandle;
63: bus_space_tag_t sc_mem_t;
64: bus_space_tag_t sc_io_t;
65: pcitag_t sc_pcitag;
66: bus_space_handle_t sc_mem_h;
67: bus_addr_t sc_io_addr, sc_mem_addr, sc_mmio_addr;
68: bus_size_t sc_io_size, sc_mem_size, sc_mmio_size;
69: int sc_console;
70: u_int sc_mode;
71: u_int8_t sc_cmap_red[256];
72: u_int8_t sc_cmap_green[256];
73: u_int8_t sc_cmap_blue[256];
74: };
75:
76: int vgafb_mapregs(struct vgafb_softc *, struct pci_attach_args *);
77: int vgafb_rommap(struct vgafb_softc *, struct pci_attach_args *);
78: int vgafb_ioctl(void *, u_long, caddr_t, int, struct proc *);
79: int vgafb_alloc_screen(void *, const struct wsscreen_descr *, void **,
80: int *, int *, long *);
81: void vgafb_free_screen(void *, void *);
82: int vgafb_show_screen(void *, void *, int,
83: void (*cb)(void *, int, int), void *);
84: paddr_t vgafb_mmap(void *, off_t, int);
85: int vgafb_is_console(int);
86: int vgafb_getcmap(struct vgafb_softc *, struct wsdisplay_cmap *);
87: int vgafb_putcmap(struct vgafb_softc *, struct wsdisplay_cmap *);
88: void vgafb_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
89:
90: struct wsdisplay_accessops vgafb_accessops = {
91: vgafb_ioctl,
92: vgafb_mmap,
93: vgafb_alloc_screen,
94: vgafb_free_screen,
95: vgafb_show_screen,
96: 0 /* load_font */
97: };
98:
99: int vgafbmatch(struct device *, void *, void *);
100: void vgafbattach(struct device *, struct device *, void *);
101:
102: struct cfattach vgafb_ca = {
103: sizeof (struct vgafb_softc), vgafbmatch, vgafbattach
104: };
105:
106: struct cfdriver vgafb_cd = {
107: NULL, "vgafb", DV_DULL
108: };
109:
110: #ifdef APERTURE
111: extern int allowaperture;
112: #endif
113:
114: static const struct pci_matchid ifb_devices[] = {
115: { PCI_VENDOR_INTERGRAPH, 0x108 }, /* XXX */
116: { PCI_VENDOR_INTERGRAPH, 0x140 }, /* XXX */
117: { PCI_VENDOR_INTERGRAPH, PCI_PRODUCT_INTERGRAPH_EXPERT3D },
118: { PCI_VENDOR_3DLABS, 0x7a1 }, /* Wildcat III 6210 */
119: { PCI_VENDOR_3DLABS, 0x7a2 }, /* Sun XVR-500 */
120: { PCI_VENDOR_3DLABS, 0x7a3 }, /* Wildcat IV 7210 */
121: };
122:
123: int
124: vgafbmatch(parent, vcf, aux)
125: struct device *parent;
126: void *vcf, *aux;
127: {
128: struct pci_attach_args *pa = aux;
129: int node;
130: char *name;
131:
132: /*
133: * Do not match on Expert3D devices, which need a different
134: * driver.
135: */
136: if (pci_matchbyid(pa, ifb_devices,
137: sizeof(ifb_devices) / sizeof(ifb_devices[0])) != 0)
138: return (0);
139:
140: node = PCITAG_NODE(pa->pa_tag);
141: name = getpropstring(node, "name");
142: if (strcmp(name, "SUNW,Expert3D") == 0 ||
143: strcmp(name, "SUNW,Expert3D-Lite") == 0)
144: return (0);
145:
146:
147: if (PCI_CLASS(pa->pa_class) == PCI_CLASS_PREHISTORIC &&
148: PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_PREHISTORIC_VGA)
149: return (1);
150:
151: if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
152: PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA)
153: return (1);
154:
155: if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
156: PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_MISC)
157: return (1);
158:
159: return (0);
160: }
161:
162: void
163: vgafbattach(parent, self, aux)
164: struct device *parent, *self;
165: void *aux;
166: {
167: struct vgafb_softc *sc = (struct vgafb_softc *)self;
168: struct pci_attach_args *pa = aux;
169:
170: sc->sc_mem_t = pa->pa_memt;
171: sc->sc_io_t = pa->pa_iot;
172: sc->sc_node = PCITAG_NODE(pa->pa_tag);
173: sc->sc_pcitag = pa->pa_tag;
174:
175: printf("\n");
176:
177: if (vgafb_mapregs(sc, pa))
178: return;
179:
180: sc->sc_console = vgafb_is_console(sc->sc_node);
181:
182: fb_setsize(&sc->sc_sunfb, 8, 1152, 900, sc->sc_node, 0);
183: if (sc->sc_sunfb.sf_depth == 24) {
184: sc->sc_sunfb.sf_depth = 32;
185: sc->sc_sunfb.sf_linebytes =
186: (sc->sc_sunfb.sf_depth / 8) * sc->sc_sunfb.sf_width;
187: sc->sc_sunfb.sf_fbsize =
188: sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes;
189: }
190:
191: sc->sc_sunfb.sf_ro.ri_bits = (void *)bus_space_vaddr(sc->sc_mem_t,
192: sc->sc_mem_h);
193: sc->sc_sunfb.sf_ro.ri_hw = sc;
194:
195: fbwscons_init(&sc->sc_sunfb,
196: RI_BSWAP | (sc->sc_console ? 0 : RI_FORCEMONO | RI_CLEAR));
197:
198: if (sc->sc_console) {
199: sc->sc_ofhandle = OF_stdout();
200: fbwscons_setcolormap(&sc->sc_sunfb, vgafb_setcolor);
201: fbwscons_console_init(&sc->sc_sunfb, -1);
202: } else {
203: /* sc->sc_ofhandle = PCITAG_NODE(sc->sc_pcitag); */
204: }
205:
206: fbwscons_attach(&sc->sc_sunfb, &vgafb_accessops, sc->sc_console);
207: }
208:
209: int
210: vgafb_ioctl(v, cmd, data, flags, p)
211: void *v;
212: u_long cmd;
213: caddr_t data;
214: int flags;
215: struct proc *p;
216: {
217: struct vgafb_softc *sc = v;
218: struct wsdisplay_fbinfo *wdf;
219: struct pcisel *sel;
220:
221: switch (cmd) {
222: case WSDISPLAYIO_GTYPE:
223: *(u_int *)data = WSDISPLAY_TYPE_UNKNOWN;
224: break;
225: case WSDISPLAYIO_SMODE:
226: sc->sc_mode = *(u_int *)data;
227: if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
228: if (sc->sc_console) /* XXX needs sc_ofhandle */
229: fbwscons_setcolormap(&sc->sc_sunfb,
230: vgafb_setcolor);
231: }
232: break;
233: case WSDISPLAYIO_GINFO:
234: wdf = (void *)data;
235: wdf->height = sc->sc_sunfb.sf_height;
236: wdf->width = sc->sc_sunfb.sf_width;
237: wdf->depth = sc->sc_sunfb.sf_depth;
238: wdf->cmsize = 256;
239: break;
240: case WSDISPLAYIO_LINEBYTES:
241: *(u_int *)data = sc->sc_sunfb.sf_linebytes;
242: break;
243:
244: case WSDISPLAYIO_GETCMAP:
245: if (sc->sc_console == 0)
246: return (EINVAL);
247: return vgafb_getcmap(sc, (struct wsdisplay_cmap *)data);
248: case WSDISPLAYIO_PUTCMAP:
249: if (sc->sc_console == 0)
250: return (EINVAL);
251: return vgafb_putcmap(sc, (struct wsdisplay_cmap *)data);
252:
253: case WSDISPLAYIO_GPCIID:
254: sel = (struct pcisel *)data;
255: sel->pc_bus = PCITAG_BUS(sc->sc_pcitag);
256: sel->pc_dev = PCITAG_DEV(sc->sc_pcitag);
257: sel->pc_func = PCITAG_FUN(sc->sc_pcitag);
258: break;
259:
260: case WSDISPLAYIO_SVIDEO:
261: case WSDISPLAYIO_GVIDEO:
262: break;
263:
264: case WSDISPLAYIO_GCURPOS:
265: case WSDISPLAYIO_SCURPOS:
266: case WSDISPLAYIO_GCURMAX:
267: case WSDISPLAYIO_GCURSOR:
268: case WSDISPLAYIO_SCURSOR:
269: default:
270: return -1; /* not supported yet */
271: }
272:
273: return (0);
274: }
275:
276: int
277: vgafb_getcmap(sc, cm)
278: struct vgafb_softc *sc;
279: struct wsdisplay_cmap *cm;
280: {
281: u_int index = cm->index;
282: u_int count = cm->count;
283: int error;
284:
285: if (index >= 256 || count > 256 - index)
286: return (EINVAL);
287:
288: error = copyout(&sc->sc_cmap_red[index], cm->red, count);
289: if (error)
290: return (error);
291: error = copyout(&sc->sc_cmap_green[index], cm->green, count);
292: if (error)
293: return (error);
294: error = copyout(&sc->sc_cmap_blue[index], cm->blue, count);
295: if (error)
296: return (error);
297: return (0);
298: }
299:
300: int
301: vgafb_putcmap(sc, cm)
302: struct vgafb_softc *sc;
303: struct wsdisplay_cmap *cm;
304: {
305: u_int index = cm->index;
306: u_int count = cm->count;
307: u_int i;
308: int error;
309: u_char *r, *g, *b;
310:
311: if (index >= 256 || count > 256 - index)
312: return (EINVAL);
313:
314: if ((error = copyin(cm->red, &sc->sc_cmap_red[index], count)) != 0)
315: return (error);
316: if ((error = copyin(cm->green, &sc->sc_cmap_green[index], count)) != 0)
317: return (error);
318: if ((error = copyin(cm->blue, &sc->sc_cmap_blue[index], count)) != 0)
319: return (error);
320:
321: r = &sc->sc_cmap_red[index];
322: g = &sc->sc_cmap_green[index];
323: b = &sc->sc_cmap_blue[index];
324:
325: for (i = 0; i < count; i++) {
326: OF_call_method("color!", sc->sc_ofhandle, 4, 0, *r, *g, *b,
327: index);
328: r++, g++, b++, index++;
329: }
330: return (0);
331: }
332:
333: void
334: vgafb_setcolor(v, index, r, g, b)
335: void *v;
336: u_int index;
337: u_int8_t r, g, b;
338: {
339: struct vgafb_softc *sc = v;
340:
341: sc->sc_cmap_red[index] = r;
342: sc->sc_cmap_green[index] = g;
343: sc->sc_cmap_blue[index] = b;
344: OF_call_method("color!", sc->sc_ofhandle, 4, 0, r, g, b, index);
345: }
346:
347: int
348: vgafb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
349: void *v;
350: const struct wsscreen_descr *type;
351: void **cookiep;
352: int *curxp, *curyp;
353: long *attrp;
354: {
355: struct vgafb_softc *sc = v;
356:
357: if (sc->sc_nscreens > 0)
358: return (ENOMEM);
359:
360: *cookiep = &sc->sc_sunfb.sf_ro;
361: *curyp = 0;
362: *curxp = 0;
363: sc->sc_sunfb.sf_ro.ri_ops.alloc_attr(&sc->sc_sunfb.sf_ro,
364: WSCOL_BLACK, WSCOL_WHITE, WSATTR_WSCOLORS, attrp);
365: sc->sc_nscreens++;
366: return (0);
367: }
368:
369: void
370: vgafb_free_screen(v, cookie)
371: void *v;
372: void *cookie;
373: {
374: struct vgafb_softc *sc = v;
375:
376: sc->sc_nscreens--;
377: }
378:
379: int
380: vgafb_show_screen(v, cookie, waitok, cb, cbarg)
381: void *v;
382: void *cookie;
383: int waitok;
384: void (*cb)(void *, int, int);
385: void *cbarg;
386: {
387: return (0);
388: }
389:
390: paddr_t
391: vgafb_mmap(v, off, prot)
392: void *v;
393: off_t off;
394: int prot;
395: {
396: struct vgafb_softc *sc = v;
397:
398: if (off & PGOFSET)
399: return (-1);
400:
401: switch (sc->sc_mode) {
402: case WSDISPLAYIO_MODE_MAPPED:
403: #ifdef APERTURE
404: if (allowaperture == 0)
405: return (-1);
406: #endif
407:
408: if (sc->sc_mmio_size == 0)
409: return (-1);
410:
411: if (off >= sc->sc_mem_addr &&
412: off < (sc->sc_mem_addr + sc->sc_mem_size))
413: return (bus_space_mmap(sc->sc_mem_t,
414: sc->sc_mem_addr, off - sc->sc_mem_addr,
415: prot, BUS_SPACE_MAP_LINEAR));
416:
417: if (off >= sc->sc_mmio_addr &&
418: off < (sc->sc_mmio_addr + sc->sc_mmio_size))
419: return (bus_space_mmap(sc->sc_mem_t,
420: sc->sc_mmio_addr, off - sc->sc_mmio_addr,
421: prot, BUS_SPACE_MAP_LINEAR));
422: break;
423:
424: case WSDISPLAYIO_MODE_DUMBFB:
425: if (off >= 0 && off < sc->sc_mem_size)
426: return (bus_space_mmap(sc->sc_mem_t, sc->sc_mem_addr,
427: off, prot, BUS_SPACE_MAP_LINEAR));
428: break;
429: }
430:
431: return (-1);
432: }
433:
434: int
435: vgafb_is_console(node)
436: int node;
437: {
438: extern int fbnode;
439:
440: return (fbnode == node);
441: }
442:
443: int
444: vgafb_mapregs(sc, pa)
445: struct vgafb_softc *sc;
446: struct pci_attach_args *pa;
447: {
448: bus_addr_t ba;
449: bus_size_t bs;
450: int hasio = 0, hasmem = 0, hasmmio = 0;
451: u_int32_t i, cf;
452: int rv;
453:
454: for (i = PCI_MAPREG_START; i <= PCI_MAPREG_PPB_END; i += 4) {
455: cf = pci_conf_read(pa->pa_pc, pa->pa_tag, i);
456: if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO) {
457: if (hasio)
458: continue;
459: rv = pci_io_find(pa->pa_pc, pa->pa_tag, i,
460: &sc->sc_io_addr, &sc->sc_io_size);
461: if (rv != 0) {
462: if (rv != ENOENT)
463: printf("%s: failed to find io at 0x%x\n",
464: sc->sc_sunfb.sf_dev.dv_xname, i);
465: continue;
466: }
467: hasio = 1;
468: } else {
469: /* Memory mapping... frame memory or mmio? */
470: rv = pci_mem_find(pa->pa_pc, pa->pa_tag, i,
471: &ba, &bs, NULL);
472: if (rv != 0) {
473: if (rv != ENOENT)
474: printf("%s: failed to find mem at 0x%x\n",
475: sc->sc_sunfb.sf_dev.dv_xname, i);
476: continue;
477: }
478:
479: if (bs == 0 /* || ba == 0 */) {
480: /* ignore this entry */
481: } else if (hasmem == 0) {
482: /*
483: * first memory slot found goes into memory,
484: * this is for the case of no mmio
485: */
486: sc->sc_mem_addr = ba;
487: sc->sc_mem_size = bs;
488: hasmem = 1;
489: } else {
490: /*
491: * Oh, we have a second `memory'
492: * region, is this region the vga memory
493: * or mmio, we guess that memory is
494: * the larger of the two.
495: */
496: if (sc->sc_mem_size > bs) {
497: /* this is the mmio */
498: sc->sc_mmio_addr = ba;
499: /* ATI driver maps 0x80000 mmio, grr */
500: if (bs < 0x80000) {
501: bs = 0x80000;
502: }
503: sc->sc_mmio_size = bs;
504: hasmmio = 1;
505: } else {
506: /* this is the memory */
507: sc->sc_mmio_addr = sc->sc_mem_addr;
508: sc->sc_mmio_size = sc->sc_mem_size;
509: sc->sc_mem_addr = ba;
510: sc->sc_mem_size = bs;
511: /* ATI driver maps 0x80000 mmio, grr */
512: if (sc->sc_mmio_size < 0x80000) {
513: sc->sc_mmio_size = 0x80000;
514: }
515: }
516: }
517: }
518: }
519:
520: if (hasmem != 0) {
521: if (bus_space_map(pa->pa_memt, sc->sc_mem_addr, sc->sc_mem_size,
522: 0, &sc->sc_mem_h)) {
523: printf("%s: can't map mem space\n",
524: sc->sc_sunfb.sf_dev.dv_xname);
525: return (1);
526: }
527: }
528:
529: /* failure to initialize io ports should not prevent attachment */
530: if (hasmem == 0) {
531: printf("%s: could not find memory space\n",
532: sc->sc_sunfb.sf_dev.dv_xname);
533: return (1);
534: }
535:
536: #ifdef DIAGNOSTIC
537: if (hasmmio == 0) {
538: printf("%s: WARNING: no mmio space configured\n",
539: sc->sc_sunfb.sf_dev.dv_xname);
540: }
541: #endif
542:
543: return (0);
544: }
CVSweb