Annotation of sys/arch/macppc/pci/vgafb_pci.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: vgafb_pci.c,v 1.18 2006/12/17 22:18:14 miod Exp $ */
2: /* $NetBSD: vga_pci.c,v 1.4 1996/12/05 01:39:38 cgd Exp $ */
3:
4: /*
5: * Copyright (c) 1995, 1996 Carnegie-Mellon University.
6: * All rights reserved.
7: *
8: * Author: Chris G. Demetriou
9: *
10: * Permission to use, copy, modify and distribute this software and
11: * its documentation is hereby granted, provided that both the copyright
12: * notice and this permission notice appear in all copies of the
13: * software, derivative works or modified versions, and any portions
14: * thereof, and that both notices appear in supporting documentation.
15: *
16: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
18: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19: *
20: * Carnegie Mellon requests users of this software to return to
21: *
22: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23: * School of Computer Science
24: * Carnegie Mellon University
25: * Pittsburgh PA 15213-3890
26: *
27: * any improvements or extensions that they make and grant Carnegie the
28: * rights to redistribute these changes.
29: */
30:
31: #include <sys/param.h>
32: #include <sys/systm.h>
33: #include <sys/kernel.h>
34: #include <sys/device.h>
35: #include <sys/malloc.h>
36:
37: #ifndef i386
38: #include <machine/autoconf.h>
39: #endif
40: #include <machine/pte.h>
41:
42: #include <dev/cons.h>
43: #include <dev/pci/pcireg.h>
44: #include <dev/pci/pcivar.h>
45: #include <dev/pci/pcidevs.h>
46:
47: #include <dev/wscons/wsconsio.h>
48: #include <dev/wscons/wsdisplayvar.h>
49: #include <dev/rasops/rasops.h>
50: #include <dev/wsfont/wsfont.h>
51:
52: #include <arch/macppc/pci/vgafbvar.h>
53: #include <arch/macppc/pci/vgafb_pcivar.h>
54:
55: #define PCI_VENDORID(x) ((x) & 0xFFFF)
56: #define PCI_CHIPID(x) (((x) >> 16) & 0xFFFF)
57:
58: struct vgafb_pci_softc {
59: struct device sc_dev;
60:
61: pcitag_t sc_pcitag; /* PCI tag, in case we need it. */
62: struct vgafb_config *sc_vc; /* VGA configuration */
63: };
64:
65: int vgafb_pci_probe(struct pci_attach_args *pa, int id, u_int32_t *ioaddr,
66: u_int32_t *iosize, u_int32_t *memaddr, u_int32_t *memsize,
67: u_int32_t *cacheable, u_int32_t *mmioaddr, u_int32_t *mmiosize);
68: int vgafb_pci_match(struct device *, void *, void *);
69: void vgafb_pci_attach(struct device *, struct device *, void *);
70:
71: paddr_t vgafbpcimmap(void *, off_t, int);
72: int vgafbpciioctl(void *, u_long, caddr_t, int, struct proc *);
73:
74: struct cfattach vgafb_pci_ca = {
75: sizeof(struct vgafb_pci_softc), (cfmatch_t)vgafb_pci_match, vgafb_pci_attach,
76: };
77:
78: pcitag_t vgafb_pci_console_tag;
79: struct vgafb_config vgafb_pci_console_vc;
80:
81: #if 0
82: #define DEBUG_VGAFB
83: #endif
84:
85: int
86: vgafb_pci_probe(struct pci_attach_args *pa, int id, u_int32_t *ioaddr,
87: u_int32_t *iosize, u_int32_t *memaddr, u_int32_t *memsize,
88: u_int32_t *cacheable, u_int32_t *mmioaddr, u_int32_t *mmiosize)
89: {
90: u_long addr;
91: u_int32_t size, tcacheable;
92: pci_chipset_tag_t pc = pa->pa_pc;
93: int retval;
94: int i;
95:
96: *iosize = 0x0;
97: *memsize = 0x0;
98: *mmiosize = 0x0;
99: for (i = PCI_MAPREG_START; i <= PCI_MAPREG_PPB_END; i += 4) {
100: #ifdef DEBUG_VGAFB
101: printf("vgafb confread %x %x\n",
102: i, pci_conf_read(pc, pa->pa_tag, i));
103: #endif
104: /* need to check more than just two base addresses? */
105: if (PCI_MAPREG_TYPE(pci_conf_read(pc, pa->pa_tag, i)) ==
106: PCI_MAPREG_TYPE_IO) {
107: retval = pci_io_find(pc, pa->pa_tag, i,
108: &addr, &size);
109: if (retval != 0) {
110: continue;
111: }
112: #ifdef DEBUG_VGAFB
113: printf("vgafb_pci_probe: io %x addr %x size %x\n", i, addr, size);
114: #endif
115: if (*iosize == 0) {
116: *ioaddr = addr;
117: *iosize = size;
118: }
119:
120: } else {
121: retval = pci_mem_find(pc, pa->pa_tag, i,
122: &addr, &size, &tcacheable);
123: if (retval != 0) {
124: continue;
125: }
126: #ifdef DEBUG_VGAFB
127: printf("vgafb_pci_probe: mem %x addr %x size %x\n", i, addr, size);
128: #endif
129: if (size == 0 || addr == 0) {
130: /* ignore this entry */
131: } else if (*memsize == 0) {
132: /*
133: * first memory slot found goes into memory,
134: * this is for the case of no mmio
135: */
136: *memaddr = addr;
137: *memsize = size;
138: *cacheable = tcacheable;
139: } else {
140: /*
141: * Oh, we have a second 'memory'
142: * region, is this region the vga memory
143: * or mmio, we guess that memory is
144: * the larger of the two.
145: */
146: if (*memaddr > size) {
147: /* this is the mmio */
148: *mmioaddr = addr;
149: /* ATI driver maps 0x80000 mmio, grr */
150: if (size < 0x80000) {
151: size = 0x80000;
152: }
153: *mmiosize = size;
154: } else {
155: /* this is the memory */
156: *mmioaddr = *memaddr;
157: *memaddr = addr;
158: *mmiosize = *memsize;
159: *memsize = size;
160: *cacheable = tcacheable;
161: /* ATI driver maps 0x80000 mmio, grr */
162: if (*mmiosize < 0x80000) {
163: *mmiosize = 0x80000;
164: }
165: }
166: }
167: }
168: }
169: #ifdef DEBUG_VGAFB
170: printf("vgafb_pci_probe: id %x ioaddr %x, iosize %x, memaddr %x,\n memsize %x, mmioaddr %x, mmiosize %x\n",
171: id, *ioaddr, *iosize, *memaddr, *memsize, *mmioaddr, *mmiosize);
172: #endif
173: if (*iosize == 0) {
174: if (id == 0) {
175: #ifdef powerpc
176: /* this is only used if on openfirmware system and
177: * the device does not have a iobase config register,
178: * eg CirrusLogic 5434 VGA. (they hardcode iobase to 0
179: * thus giving standard PC addresses for the registers)
180: */
181: int s;
182: u_int32_t sizedata;
183:
184: /*
185: * Open Firmware (yuck) shuts down devices before
186: * entering a program so we need to bring them back
187: * 'online' to respond to bus accesses... so far
188: * this is true on the power.4e.
189: */
190: s = splhigh();
191: sizedata = pci_conf_read(pc, pa->pa_tag,
192: PCI_COMMAND_STATUS_REG);
193: sizedata |= (PCI_COMMAND_MASTER_ENABLE |
194: PCI_COMMAND_IO_ENABLE |
195: PCI_COMMAND_PARITY_ENABLE |
196: PCI_COMMAND_SERR_ENABLE);
197: pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
198: sizedata);
199: splx(s);
200:
201: #endif
202: /* if this is the first card, allow it
203: * to be accessed in vga iospace
204: */
205: *ioaddr = 0;
206: *iosize = 0x10000; /* 64k, good as any */
207: } else {
208: /* iospace not available, assume 640x480, pray */
209: *ioaddr = 0;
210: *iosize = 0;
211: }
212: }
213: #ifdef DEBUG_VGAFB
214: printf("vgafb_pci_probe: id %x ioaddr %x, iosize %x, memaddr %x,\n memsize %x, mmioaddr %x, mmiosize %x\n",
215: id, *ioaddr, *iosize, *memaddr, *memsize, *mmioaddr, *mmiosize);
216: #endif
217:
218: /* io and mmio spaces are not required to attach */
219: if (/* *iosize == 0 || */ *memsize == 0 /* || *mmiosize == 0 */)
220: return (0);
221:
222: return (1);
223: }
224:
225: int
226: vgafb_pci_match(parent, match, aux)
227: struct device *parent;
228: void *match;
229: void *aux;
230: {
231: struct pci_attach_args *pa = aux;
232: int potential;
233: static int id = 0;
234: int myid;
235:
236: myid = id;
237:
238: potential = 0;
239:
240: /*
241: * If it's prehistoric/vga or display/vga, we might match.
242: * For the console device, this is jut a sanity check.
243: */
244: if (PCI_CLASS(pa->pa_class) == PCI_CLASS_PREHISTORIC &&
245: PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_PREHISTORIC_VGA)
246: potential = 1;
247: if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
248: PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA)
249: potential = 1;
250: if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
251: PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_MISC)
252: potential = 1;
253:
254: if (!potential)
255: return (0);
256:
257: /* If it's the console, we have a winner! */
258: if (!bcmp(&pa->pa_tag, &vgafb_pci_console_tag, sizeof(pa->pa_tag))) {
259: id++;
260: return (1);
261: }
262:
263: #ifdef DEBUG_VGAFB
264: {
265: int i;
266: pci_chipset_tag_t pc = pa->pa_pc;
267: for (i = 0x10; i < 0x24; i+=4) {
268: printf("vgafb confread %x %x\n",
269: i, pci_conf_read(pc, pa->pa_tag, i));
270: }
271: }
272: #endif
273:
274: return (0);
275: }
276:
277: void
278: vgafb_pci_attach(struct device *parent, struct device *self, void *aux)
279: {
280: struct pci_attach_args *pa = aux;
281: struct vgafb_pci_softc *sc = (struct vgafb_pci_softc *)self;
282: struct vgafb_config *vc;
283: u_int32_t memaddr, memsize, cacheable;
284: u_int32_t ioaddr, iosize;
285: u_int32_t mmioaddr, mmiosize;
286: int console;
287: static int id = 0;
288: int myid;
289:
290: myid = id;
291:
292: vgafb_pci_probe(pa, myid, &ioaddr, &iosize,
293: &memaddr, &memsize, &cacheable, &mmioaddr, &mmiosize);
294:
295:
296: console = (!bcmp(&pa->pa_tag, &vgafb_pci_console_tag, sizeof(pa->pa_tag)));
297: if (console)
298: vc = sc->sc_vc = &vgafb_pci_console_vc;
299: else {
300: vc = sc->sc_vc = (struct vgafb_config *)
301: malloc(sizeof(struct vgafb_config), M_DEVBUF, M_WAITOK);
302:
303: /* set up bus-independent VGA configuration */
304: vgafb_common_setup(pa->pa_iot, pa->pa_memt, vc,
305: ioaddr, iosize, memaddr, memsize, mmioaddr, mmiosize);
306: }
307: vc->vc_mmap = vgafbpcimmap;
308: vc->vc_ioctl = vgafbpciioctl;
309: vc->membase = memaddr;
310: vc->memsize = memsize;
311: vc->mmiobase = mmioaddr;
312: vc->mmiosize = mmiosize;
313:
314: sc->sc_pcitag = pa->pa_tag;
315:
316: if (iosize == 0)
317: printf (", no io");
318:
319: if (mmiosize != 0)
320: printf (", mmio");
321:
322: printf("\n");
323:
324: vgafb_wsdisplay_attach(self, vc, console);
325: id++;
326: }
327:
328: void
329: vgafb_pci_console(bus_space_tag_t iot, u_int32_t ioaddr, u_int32_t iosize,
330: bus_space_tag_t memt, u_int32_t memaddr, u_int32_t memsize,
331: pci_chipset_tag_t pc, int bus, int device, int function)
332: {
333: struct vgafb_config *vc = &vgafb_pci_console_vc;
334: u_int32_t mmioaddr;
335: u_int32_t mmiosize;
336: static struct pci_attach_args spa;
337: struct pci_attach_args *pa = &spa;
338:
339: /* for later recognition */
340: vgafb_pci_console_tag = pci_make_tag(pc, bus, device, function);
341:
342: pa->pa_iot = iot;
343: pa->pa_memt = memt;
344: pa->pa_tag = vgafb_pci_console_tag;
345: /*
346: pa->pa_pc = XXX;
347: */
348:
349: /* XXX probe pci before pci bus config? */
350:
351: mmioaddr =0;
352: mmiosize =0;
353: #if 0
354: vgafb_pci_probe(pa, 0, &ioaddr, &iosize,
355: &memaddr, &memsize, &cacheable, mmioaddr, mmiosize);
356: #endif
357:
358:
359: /* set up bus-independent VGA configuration */
360: vgafb_common_setup(iot, memt, vc,
361: ioaddr, iosize, memaddr, memsize, mmioaddr, mmiosize);
362:
363: vgafb_cnattach(iot, memt, pc, bus, device, function);
364: vc->nscreens++;
365: }
366:
367: int
368: vgafbpciioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
369: {
370: struct vgafb_pci_softc *sc = v;
371:
372: return (vgafb_ioctl(sc->sc_vc, cmd, data, flag, p));
373: }
374:
375: paddr_t
376: vgafbpcimmap(void *v, off_t offset, int prot)
377: {
378: struct vgafb_pci_softc *sc = v;
379:
380: return (vgafb_mmap(sc->sc_vc, offset, prot));
381: }
382:
383: int
384: vgafb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
385: int *curxp, int *curyp, long *attrp)
386: {
387: struct vgafb_config *vc = v;
388: long defattr;
389:
390: if (vc->nscreens > 0)
391: return (ENOMEM);
392:
393: *cookiep = &vc->dc_rinfo; /* one and only for now */
394: *curxp = 0;
395: *curyp = 0;
396: vc->dc_rinfo.ri_ops.alloc_attr(&vc->dc_rinfo, 0, 0, 0, &defattr);
397: *attrp = defattr;
398: vc->nscreens++;
399: return (0);
400: }
401:
402: void
403: vgafb_free_screen(void *v, void *cookie)
404: {
405: struct vgafb_config *vc = v;
406:
407: if (vc == &vgafb_pci_console_vc)
408: panic("vgafb_free_screen: console");
409:
410: vc->nscreens--;
411: }
412:
413: int
414: vgafb_show_screen(void *v, void *cookie, int waitok,
415: void (*cb)(void *, int, int), void *cbarg)
416: {
417:
418: return (0);
419: }
CVSweb