Annotation of sys/arch/macppc/pci/vgafb_pci.c, Revision 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