2 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
5 * Author: Chris G. Demetriou
7 * Permission to use, copy, modify and distribute this software and
8 * its documentation is hereby granted, provided that both the copyright
9 * notice and this permission notice appear in all copies of the
10 * software, derivative works or modified versions, and any portions
11 * thereof, and that both notices appear in supporting documentation.
13 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
14 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
15 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 * Carnegie Mellon requests users of this software to return to
19 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
20 * School of Computer Science
21 * Carnegie Mellon University
22 * Pittsburgh PA 15213-3890
24 * any improvements or extensions that they make and grant Carnegie the
25 * rights to redistribute these changes.
27 * Copyright (c) 2000 Andrew Miklic, Andrew Gallatin, and Thomas V. Crimi
29 * $FreeBSD: src/sys/dev/tga/tga_pci.c,v 1.1.2.1 2001/11/01 08:33:15 obrien Exp $
30 * $DragonFly: src/sys/dev/video/tga/Attic/tga_pci.c,v 1.7 2004/05/19 22:52:54 dillon Exp $
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
38 #include <sys/fcntl.h>
39 #include <sys/malloc.h>
43 #include <vm/vm_param.h>
46 #include <machine/md_var.h>
47 #include <machine/pc/bios.h>
48 #include <machine/clock.h>
49 #include <machine/bus_memio.h>
50 #include <machine/bus.h>
51 #include <machine/pc/vesa.h>
52 #include <machine/resource.h>
57 #include <bus/pci/pcireg.h>
58 #include <bus/pci/pcivar.h>
60 #include <dev/fb/fbreg.h>
61 #include <dev/fb/tga.h>
63 #include <dev/fb/gfb.h>
64 #include <dev/gfb/gfb_pci.h>
68 static int tga_probe(device_t);
69 static int tga_attach(device_t);
70 static void tga_intr(void *);
72 static device_method_t tga_methods[] = {
73 DEVMETHOD(device_probe, tga_probe),
74 DEVMETHOD(device_attach, tga_attach),
75 DEVMETHOD(device_detach, pcigfb_detach),
79 static driver_t tga_driver = {
82 sizeof(struct gfb_softc)
85 static devclass_t tga_devclass;
87 DRIVER_MODULE(tga, pci, tga_driver, tga_devclass, 0, 0);
89 static struct gfb_type tga_devs[] = {
90 { DEC_VENDORID, DEC_DEVICEID_TGA,
91 "DEC TGA (21030) 2D Graphics Accelerator" },
92 { DEC_VENDORID, DEC_DEVICEID_TGA2,
93 "DEC TGA2 (21130) 3D Graphics Accelerator" },
97 #ifdef FB_INSTALL_CDEV
99 static struct cdevsw tga_cdevsw = {
106 /* open */ pcigfb_open,
107 /* close */ pcigfb_close,
108 /* read */ pcigfb_read,
109 /* write */ pcigfb_write,
110 /* ioctl */ pcigfb_ioctl,
112 /* mmap */ pcigfb_mmap,
113 /* strategy */ nostrategy,
118 #endif /*FB_INSTALL_CDEV*/
121 tga_probe(device_t dev)
128 while(t->name != NULL) {
129 if((pci_get_vendor(dev) == t->vendor_id) &&
130 (pci_get_device(dev) == t->device_id)) {
131 device_set_desc(dev, t->name);
141 tga_attach(device_t dev)
144 int unit, error, rid;
147 unit = device_get_unit(dev);
148 sc = device_get_softc(dev);
149 bzero(sc, sizeof(struct gfb_softc));
150 sc->driver_name = TGA_DRIVER_NAME;
151 switch(pci_get_device(dev)) {
152 case DEC_DEVICEID_TGA2:
156 case DEC_DEVICEID_TGA:
161 device_printf(dev, "Unrecognized TGA type\n");
164 if((error = pcigfb_attach(dev))) {
167 sc->regs = sc->bhandle + TGA_MEM_CREGS;
168 error = bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, tga_intr, sc,
171 device_printf(dev, "couldn't set up irq\n");
178 device_printf(dev, "TGA (21030) step %c\n", 'A' + sc->rev - 1);
182 device_printf(dev, "TGA2 (21130) abstract software model\n");
187 device_printf(dev, "TGA2 (21130) pass %d\n", sc->rev - 0x20);
191 device_printf(dev, "Unknown stepping (0x%x)\n", sc->rev);
194 #ifdef FB_INSTALL_CDEV
195 cdevsw_add(&tga_cdevsw, -1, unit);
196 sc->devt = make_dev(&tga_cdevsw, unit, 0, 0, 02660, "tga%x", unit);
197 reference_dev(sc->devt);
198 /* XXX fb_attach done too early in pcigfb_attach? */
199 #endif /*FB_INSTALL_CDEV*/
202 if(sc->intrhand != NULL) {
203 bus_teardown_intr(dev, sc->irq, sc->intrhand);
206 if(sc->irq != NULL) {
208 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->irq);
211 if(sc->res != NULL) {
212 rid = GFB_MEM_BASE_RID;
213 bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->res);
224 struct gfb_softc *sc = (struct gfb_softc *)v;
227 reg = READ_GFB_REGISTER(sc->adp, TGA_REG_SISR);
228 if((reg & 0x00010001) != 0x00010001) {
230 /* Odd. We never set any of the other interrupt enables. */
231 if((reg & 0x1f) != 0) {
233 /* Clear the mysterious pending interrupts. */
234 WRITE_GFB_REGISTER(sc->adp, TGA_REG_SISR, (reg & 0x1f));
235 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_SISR, 1);
237 /* This was our interrupt, even if we're puzzled as to
238 * why we got it. Don't make the interrupt handler
239 * think it was a stray.
244 /* Call the scheduled handler... */
245 sc->gfbc->ramdac_intr(sc);
248 Clear interrupt field (this way, we will force a
249 memory error if we get an unexpected interrupt)...
251 sc->gfbc->ramdac_intr = NULL;
253 /* Disable the interrupt... */
254 WRITE_GFB_REGISTER(sc->adp, TGA_REG_SISR, 0x00000001);
255 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_SISR, 1);