summaryrefslogtreecommitdiffstats
path: root/sys/dev/tga/tga_pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/tga/tga_pci.c')
-rw-r--r--sys/dev/tga/tga_pci.c251
1 files changed, 251 insertions, 0 deletions
diff --git a/sys/dev/tga/tga_pci.c b/sys/dev/tga/tga_pci.c
new file mode 100644
index 0000000..6a78523
--- /dev/null
+++ b/sys/dev/tga/tga_pci.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 1995, 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ *
+ * Copyright (c) 2000 Andrew Miklic, Andrew Gallatin, and Thomas V. Crimi
+ */
+
+#include "opt_fb.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/proc.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/fbio.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+#include <machine/md_var.h>
+#include <machine/pc/bios.h>
+#include <machine/clock.h>
+#include <machine/bus_memio.h>
+#include <machine/bus.h>
+#include <machine/pc/vesa.h>
+#include <machine/resource.h>
+
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <pci/pcireg.h>
+#include <pci/pcivar.h>
+
+#include <dev/fb/fbreg.h>
+#include <dev/fb/tga.h>
+#include <dev/tga/tga_pci.h>
+#include <dev/fb/gfb.h>
+#include <dev/gfb/gfb_pci.h>
+
+static int tga_probe(device_t);
+static int tga_attach(device_t);
+static void tga_intr(void *);
+
+static device_method_t tga_methods[] = {
+ DEVMETHOD(device_probe, tga_probe),
+ DEVMETHOD(device_attach, tga_attach),
+ DEVMETHOD(device_detach, pcigfb_detach),
+ { 0, 0 }
+};
+
+static driver_t tga_driver = {
+ "tga",
+ tga_methods,
+ sizeof(struct gfb_softc)
+};
+
+static devclass_t tga_devclass;
+
+DRIVER_MODULE(tga, pci, tga_driver, tga_devclass, 0, 0);
+
+static struct gfb_type tga_devs[] = {
+ { DEC_VENDORID, DEC_DEVICEID_TGA,
+ "DEC TGA (21030) 2D Graphics Accelerator" },
+ { DEC_VENDORID, DEC_DEVICEID_TGA2,
+ "DEC TGA2 (21130) 3D Graphics Accelerator" },
+ { 0, 0, NULL }
+};
+
+#ifdef FB_INSTALL_CDEV
+
+static struct cdevsw tga_cdevsw = {
+ /* open */ pcigfb_open,
+ /* close */ pcigfb_close,
+ /* read */ pcigfb_read,
+ /* write */ pcigfb_write,
+ /* ioctl */ pcigfb_ioctl,
+ /* poll */ nopoll,
+ /* mmap */ pcigfb_mmap,
+ /* strategy */ nostrategy,
+ /* name */ "tga",
+ /* maj */ -1,
+ /* dump */ nodump,
+ /* psize */ nopsize,
+ /* flags */ 0,
+ /* kqfilter */ nokqfilter
+};
+
+#endif /* FB_INSTALL_CDEV */
+
+static int
+tga_probe(device_t dev)
+{
+ int error;
+ gfb_type_t t;
+
+ t = tga_devs;
+ error = ENXIO;
+ while(t->name != NULL) {
+ if((pci_get_vendor(dev) == t->vendor_id) &&
+ (pci_get_device(dev) == t->device_id)) {
+ device_set_desc(dev, t->name);
+ error = 0;
+ break;
+ }
+ t++;
+ }
+ return(error);
+}
+
+static int
+tga_attach(device_t dev)
+{
+ gfb_softc_t sc;
+ int unit, error, rid;
+
+ error = 0;
+ unit = device_get_unit(dev);
+ sc = device_get_softc(dev);
+ sc->driver_name = TGA_DRIVER_NAME;
+ switch(pci_get_device(dev)) {
+ case DEC_DEVICEID_TGA2:
+ sc->model = 1;
+ sc->type = KD_TGA2;
+ break;
+ case DEC_DEVICEID_TGA:
+ sc->model = 0;
+ sc->type = KD_TGA;
+ break;
+ default:
+ device_printf(dev, "Unrecognized TGA type\n");
+ goto fail;
+ }
+ if((error = pcigfb_attach(dev))) {
+ goto fail;
+ }
+ sc->regs = sc->bhandle + TGA_MEM_CREGS;
+ error = bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, tga_intr, sc,
+ &sc->intrhand);
+ if(error) {
+ device_printf(dev, "couldn't set up irq\n");
+ goto fail;
+ }
+ switch(sc->rev) {
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ device_printf(dev, "TGA (21030) step %c\n", 'A' + sc->rev - 1);
+ break;
+
+ case 0x20:
+ device_printf(dev, "TGA2 (21130) abstract software model\n");
+ break;
+
+ case 0x21:
+ case 0x22:
+ device_printf(dev, "TGA2 (21130) pass %d\n", sc->rev - 0x20);
+ break;
+
+ default:
+ device_printf(dev, "Unknown stepping (0x%x)\n", sc->rev);
+ break;
+ }
+#ifdef FB_INSTALL_CDEV
+ sc->cdevsw = &tga_cdevsw;
+ sc->devt = make_dev(sc->cdevsw, unit, 0, 0, 02660, "tga%x", unit);
+#endif /* FB_INSTALL_CDEV */
+ goto done;
+fail:
+ if(sc->intrhand != NULL) {
+ bus_teardown_intr(dev, sc->irq, sc->intrhand);
+ sc->intrhand = NULL;
+ }
+ if(sc->irq != NULL) {
+ rid = 0x0;
+ bus_release_resource(dev, SYS_RES_IRQ, rid, sc->irq);
+ sc->irq = NULL;
+ }
+ if(sc->res != NULL) {
+ rid = GFB_MEM_BASE_RID;
+ bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->res);
+ sc->res = NULL;
+ }
+ error = ENXIO;
+done:
+ return(error);
+}
+
+static void
+tga_intr(void *v)
+{
+ struct gfb_softc *sc = (struct gfb_softc *)v;
+ u_int32_t reg;
+
+ reg = READ_GFB_REGISTER(sc->adp, TGA_REG_SISR);
+ if((reg & 0x00010001) != 0x00010001) {
+
+ /* Odd. We never set any of the other interrupt enables. */
+ if((reg & 0x1f) != 0) {
+
+ /* Clear the mysterious pending interrupts. */
+ WRITE_GFB_REGISTER(sc->adp, TGA_REG_SISR, (reg & 0x1f));
+ GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_SISR, 1);
+
+ /* This was our interrupt, even if we're puzzled as to
+ * why we got it. Don't make the interrupt handler
+ * think it was a stray.
+ */
+ }
+ }
+
+ /* Call the scheduled handler... */
+ sc->gfbc->ramdac_intr(sc);
+
+ /*
+ Clear interrupt field (this way, we will force a
+ memory error if we get an unexpected interrupt)...
+ */
+ sc->gfbc->ramdac_intr = NULL;
+
+ /* Disable the interrupt... */
+ WRITE_GFB_REGISTER(sc->adp, TGA_REG_SISR, 0x00000001);
+ GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_SISR, 1);
+}
OpenPOWER on IntegriCloud