Merge from vendor branch READLINE:
[dragonfly.git] / sys / dev / video / tga / tga_pci.c
1 /*
2  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
3  * All rights reserved.
4  *
5  * Author: Chris G. Demetriou
6  * 
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.
12  * 
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.
16  * 
17  * Carnegie Mellon requests users of this software to return to
18  *
19  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
20  *  School of Computer Science
21  *  Carnegie Mellon University
22  *  Pittsburgh PA 15213-3890
23  *
24  * any improvements or extensions that they make and grant Carnegie the
25  * rights to redistribute these changes.
26  *
27  * Copyright (c) 2000 Andrew Miklic, Andrew Gallatin, and Thomas V. Crimi
28  *
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 $
31  */
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/conf.h>
37 #include <sys/proc.h>
38 #include <sys/fcntl.h>
39 #include <sys/malloc.h>
40 #include <sys/fbio.h>
41
42 #include <vm/vm.h>
43 #include <vm/vm_param.h>
44 #include <vm/pmap.h>
45
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>
53
54 #include <sys/bus.h>
55 #include <sys/rman.h>
56
57 #include <bus/pci/pcireg.h>
58 #include <bus/pci/pcivar.h>
59
60 #include <dev/fb/fbreg.h>
61 #include <dev/fb/tga.h>
62 #include "tga_pci.h"
63 #include <dev/fb/gfb.h>
64 #include <dev/gfb/gfb_pci.h>
65
66 #include "opt_fb.h"
67
68 static int tga_probe(device_t);
69 static int tga_attach(device_t);
70 static void tga_intr(void *);
71
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),
76         { 0, 0 }
77 };
78
79 static driver_t tga_driver = {
80         "tga",
81         tga_methods,
82         sizeof(struct gfb_softc)
83 };
84
85 static devclass_t tga_devclass;
86
87 DRIVER_MODULE(tga, pci, tga_driver, tga_devclass, 0, 0);
88
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" },
94         { 0, 0, NULL }
95 };
96
97 #ifdef FB_INSTALL_CDEV
98
99 static struct cdevsw tga_cdevsw = {
100         /* name */      "tga",
101         /* maj */       -1,
102         /* flags */     0,
103         /* port */      NULL,
104         /* clone */     NULL,
105
106         /* open */      pcigfb_open,
107         /* close */     pcigfb_close,
108         /* read */      pcigfb_read,
109         /* write */     pcigfb_write,
110         /* ioctl */     pcigfb_ioctl,
111         /* poll */      nopoll,
112         /* mmap */      pcigfb_mmap,
113         /* strategy */  nostrategy,
114         /* dump */      nodump,
115         /* psize */     nopsize
116 };
117
118 #endif /*FB_INSTALL_CDEV*/
119
120 static int
121 tga_probe(device_t dev)
122 {
123         int error;
124         gfb_type_t t;
125
126         t = tga_devs;
127         error = ENXIO;
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);
132                         error = 0;
133                         break;
134                 }
135                 t++;
136         }
137         return(error);
138 }
139
140 static int
141 tga_attach(device_t dev)
142 {
143         gfb_softc_t sc;
144         int unit, error, rid;
145
146         error = 0;
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:
153                 sc->model = 1;
154                 sc->type = KD_TGA2;
155                 break;
156         case DEC_DEVICEID_TGA:
157                 sc->model = 0;
158                 sc->type = KD_TGA;
159                 break;
160         default:
161                 device_printf(dev, "Unrecognized TGA type\n");
162                 goto fail;
163         }
164         if((error = pcigfb_attach(dev))) {
165                 goto fail;
166         }
167         sc->regs = sc->bhandle + TGA_MEM_CREGS;
168         error = bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, tga_intr, sc,
169                     &sc->intrhand);
170         if(error) {
171                 device_printf(dev, "couldn't set up irq\n");
172                 goto fail;
173         }
174         switch(sc->rev) {
175         case 0x1:
176         case 0x2:
177         case 0x3:
178                 device_printf(dev, "TGA (21030) step %c\n", 'A' + sc->rev - 1);
179                 break;
180
181         case 0x20:
182                 device_printf(dev, "TGA2 (21130) abstract software model\n");
183                 break;
184
185         case 0x21:
186         case 0x22:
187                 device_printf(dev, "TGA2 (21130) pass %d\n", sc->rev - 0x20);
188                 break;
189
190         default:
191                 device_printf(dev, "Unknown stepping (0x%x)\n", sc->rev);
192                 break;
193         }
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*/
200         goto done;
201 fail:
202         if(sc->intrhand != NULL) {
203                 bus_teardown_intr(dev, sc->irq, sc->intrhand);
204                 sc->intrhand = NULL;
205         }
206         if(sc->irq != NULL) {
207                 rid = 0x0;
208                 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->irq);
209                 sc->irq = NULL;
210         }
211         if(sc->res != NULL) {
212                 rid = GFB_MEM_BASE_RID;
213                 bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->res);
214                 sc->res = NULL;
215         }
216         error = ENXIO;
217 done:
218         return(error);
219 }
220
221 static void 
222 tga_intr(void *v)
223 {
224         struct gfb_softc *sc = (struct gfb_softc *)v;
225         u_int32_t reg;
226
227         reg = READ_GFB_REGISTER(sc->adp, TGA_REG_SISR);
228         if((reg & 0x00010001) != 0x00010001) {
229
230                 /* Odd. We never set any of the other interrupt enables. */
231                 if((reg & 0x1f) != 0) {
232
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);
236
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.
240                          */
241                 }
242         }
243
244         /* Call the scheduled handler... */
245         sc->gfbc->ramdac_intr(sc);
246
247         /*
248            Clear interrupt field (this way, we will force a
249            memory error if we get an unexpected interrupt)...
250         */
251         sc->gfbc->ramdac_intr = NULL;
252
253         /* Disable the interrupt... */
254         WRITE_GFB_REGISTER(sc->adp, TGA_REG_SISR, 0x00000001);
255         GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_SISR, 1);
256 }