timeout/untimeout ==> callout_*
[dragonfly.git] / sys / dev / video / gfb / gfb_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/gfb/gfb_pci.c,v 1.1.2.1 2001/11/01 08:33:15 obrien Exp $
30  * $DragonFly: src/sys/dev/video/gfb/Attic/gfb_pci.c,v 1.5 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/gfb.h>
62 #include "gfb_pci.h"
63
64 #ifdef __alpha__
65
66 #include <machine/rpb.h>
67 #include <machine/cpu.h>
68
69 #endif /* __alpha__ */
70
71 #include "opt_fb.h"
72
73 static devclass_t gfb_devclass;
74
75 #ifdef __alpha__
76
77 extern void sccnattach(void);
78
79 #endif /* __alpha__ */
80
81 extern struct gfb_font bold8x16;
82 extern struct gfb_softc *gfb_device_softcs[2][16];
83
84 int
85 pcigfb_attach(device_t dev)
86 {
87         int s;
88         gfb_softc_t sc;
89         video_adapter_t *adp;
90         int unit, flags, error, rid, va_index;
91 #ifdef __alpha__
92         struct ctb *ctb;
93 #endif /* __alpha__ */
94
95         s = splimp();
96         error = 0;
97         unit = device_get_unit(dev);
98         flags = device_get_flags(dev);
99         sc = device_get_softc(dev);
100         sc->rev = pci_get_revid(dev);
101         rid = GFB_MEM_BASE_RID;
102         sc->res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1,
103             RF_ACTIVE|PCI_RF_DENSE);
104         if(sc->res == NULL) {
105                 device_printf(dev, "couldn't map memory\n");
106                 goto fail;
107         }
108         sc->btag = rman_get_bustag(sc->res);
109         sc->bhandle = rman_get_bushandle(sc->res);
110
111         /* Allocate interrupt (irq)... */
112         rid = 0x0;
113         sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
114             RF_SHAREABLE|RF_ACTIVE);
115         if(sc->irq == NULL) {
116                 device_printf(dev, "Couldn't map interrupt\n");
117                 goto fail;
118         }
119         if((va_index = vid_find_adapter(sc->driver_name, unit)) < 0) {
120                 sc->adp = (video_adapter_t *)malloc(sizeof(video_adapter_t),
121                     M_DEVBUF, M_NOWAIT);
122                 adp = sc->adp;
123                 bzero(adp, sizeof(video_adapter_t));
124                 vid_init_struct(adp, sc->driver_name, sc->type, unit);
125                 if(vid_register(adp) < 0) {
126                         free(sc->adp, M_DEVBUF);
127                         goto fail;
128                 }
129                 adp->va_flags |= V_ADP_REGISTERED;
130                 adp->va_model = sc->model;
131                 adp->va_mem_base = (vm_offset_t)rman_get_virtual(sc->res);
132                 adp->va_mem_size = rman_get_end(sc->res) -
133                     rman_get_start(sc->res);
134                 adp->va_io_base = NULL;
135                 adp->va_io_size = 0;
136                 adp->va_crtc_addr = NULL;
137                 gfb_device_softcs[sc->model][unit] = sc;
138                 sc->gfbc = (struct gfb_conf *)malloc(sizeof(struct gfb_conf),
139                     M_DEVBUF, M_NOWAIT);
140                 bzero(sc->gfbc, sizeof(struct gfb_conf));
141                 if((*vidsw[adp->va_index]->init)(unit, adp, flags)) {
142                         device_printf(dev, "Couldn't initialize adapter\n");
143                         vid_unregister(adp);
144                         gfb_device_softcs[sc->model][unit] = NULL;
145                         free(sc->gfbc, M_DEVBUF);
146                         free(sc->adp, M_DEVBUF);
147                         goto fail;
148                 }
149                 sc->gfbc->palette.red =
150                     (u_char *)malloc(sc->gfbc->palette.count, M_DEVBUF,
151                     M_NOWAIT);
152                 sc->gfbc->palette.green =
153                     (u_char *)malloc(sc->gfbc->palette.count, M_DEVBUF,
154                     M_NOWAIT);
155                 sc->gfbc->palette.blue =
156                     (u_char *)malloc(sc->gfbc->palette.count, M_DEVBUF,
157                     M_NOWAIT);
158                 sc->gfbc->cursor_palette.red =
159                     (u_char *)malloc(sc->gfbc->cursor_palette.count, M_DEVBUF,
160                     M_NOWAIT);
161                 sc->gfbc->cursor_palette.green =
162                     (u_char *)malloc(sc->gfbc->cursor_palette.count, M_DEVBUF,
163                     M_NOWAIT);
164                 sc->gfbc->cursor_palette.blue =
165                     (u_char *)malloc(sc->gfbc->cursor_palette.count, M_DEVBUF,
166                     M_NOWAIT);
167                 if(gfb_init(unit, adp, flags)) {
168                         device_printf(dev, "Couldn't initialize framebuffer\n");
169                         vid_unregister(adp);
170                         gfb_device_softcs[sc->model][unit] = NULL;
171                         free(sc->gfbc->cursor_palette.blue, M_DEVBUF);
172                         free(sc->gfbc->cursor_palette.green, M_DEVBUF);
173                         free(sc->gfbc->cursor_palette.red, M_DEVBUF);
174                         free(sc->gfbc->palette.blue, M_DEVBUF);
175                         free(sc->gfbc->palette.green, M_DEVBUF);
176                         free(sc->gfbc->palette.red, M_DEVBUF);
177                         free(sc->gfbc, M_DEVBUF);
178                         free(sc->adp, M_DEVBUF);
179                         goto fail;
180                 }
181         } else {
182                 (*vidsw[va_index]->probe)(unit, &adp, (void *)sc->driver_name,
183                     flags);
184                 sc->adp = adp;
185                 sc->gfbc = gfb_device_softcs[sc->model][unit]->gfbc;
186                 gfb_device_softcs[sc->model][unit] = sc;
187         }
188
189         /*
190            This is a back-door for PCI devices--since FreeBSD no longer supports
191            PCI configuration-space accesses during the *configure() phase for
192            video adapters, we cannot identify a PCI device as the console during
193            the first call to sccnattach(). There must be a second chance for PCI
194            adapters to be recognized as the console, and this is it...
195         */
196 #ifdef __alpha__
197         ctb = (struct ctb *)(((caddr_t)hwrpb) + hwrpb->rpb_ctb_off);
198         if (ctb->ctb_term_type == 3) /* Display adapter */
199                 sccnattach();
200 #endif /* __alpha__ */
201
202         device_printf(dev, "Board type %s\n", sc->gfbc->name);
203         device_printf(dev, "%d x %d, %dbpp, %s RAMDAC\n",
204                sc->adp->va_info.vi_width, sc->adp->va_info.vi_height,
205                sc->adp->va_info.vi_depth, sc->gfbc->ramdac_name);
206 #ifdef FB_INSTALL_CDEV
207         /* attach a virtual frame buffer device */
208         error = fb_attach(sc->devt, sc->adp);
209         if(error)
210                 goto fail;
211         if(bootverbose)
212                 (*vidsw[sc->adp->va_index]->diag)(sc->adp, bootverbose);
213 #if experimental
214         device_add_child(dev, "fb", -1);
215         bus_generic_attach(dev);
216 #endif /*experimental*/
217 #endif /*FB_INSTALL_CDEV*/
218         goto done;
219 fail:
220         if(sc->intrhand != NULL) {
221                 bus_teardown_intr(dev, sc->irq, sc->intrhand);
222                 sc->intrhand = NULL;
223         }
224         if(sc->irq != NULL) {
225                 rid = 0x0;
226                 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->irq);
227                 sc->irq = NULL;
228         }
229         if(sc->res != NULL) {
230                 rid = GFB_MEM_BASE_RID;
231                 bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->res);
232                 sc->res = NULL;
233         }
234         error = ENXIO;
235 done:
236         splx(s);
237         return(error);
238 }
239
240 int
241 pcigfb_detach(device_t dev)
242 {
243         struct gfb_softc *sc;
244         int rid;
245
246         sc = device_get_softc(dev);
247 #ifdef FB_INSTALL_CDEV
248         fb_detach(sc->devt, sc->adp);
249 #endif /*FB_INSTALL_CDEV*/
250         bus_teardown_intr(dev, sc->irq, sc->intrhand);
251         rid = 0x0;
252         bus_release_resource(dev, SYS_RES_IRQ, rid, sc->irq);
253         rid = GFB_MEM_BASE_RID;
254         bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->res);
255         return(0);
256 }
257
258 #ifdef FB_INSTALL_CDEV
259
260 int
261 pcigfb_open(dev_t dev, int flag, int mode, struct proc *p)
262 {
263         struct gfb_softc *sc;
264         int error;
265
266         sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
267
268         if(sc == NULL)
269                 error = ENXIO;
270         else if(mode & (O_CREAT | O_APPEND | O_TRUNC))
271                 error = ENODEV;
272         else
273                 error = genfbopen(&sc->gensc, sc->adp, flag, mode, p);
274         return(error);
275 }
276
277 int
278 pcigfb_close(dev_t dev, int flag, int mode, struct proc *p)
279 {
280         struct gfb_softc *sc;
281
282         sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
283         return genfbclose(&sc->gensc, sc->adp, flag, mode, p);
284 }
285
286 int
287 pcigfb_read(dev_t dev, struct uio *uio, int flag)
288 {
289         struct gfb_softc *sc;
290
291         sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
292         return genfbread(&sc->gensc, sc->adp, uio, flag);
293 }
294
295 int
296 pcigfb_write(dev_t dev, struct uio *uio, int flag)
297 {
298         struct gfb_softc *sc;
299
300         sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
301         return genfbwrite(&sc->gensc, sc->adp, uio, flag);
302 }
303
304 int
305 pcigfb_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
306 {
307         struct gfb_softc *sc;
308
309         sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
310         return genfbioctl(&sc->gensc, sc->adp, cmd, arg, flag, p);
311 }
312
313 int
314 pcigfb_mmap(dev_t dev, vm_offset_t offset, int prot)
315 {
316         struct gfb_softc *sc;
317
318         sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
319         return genfbmmap(&sc->gensc, sc->adp, offset, prot);
320 }
321
322 #endif /*FB_INSTALL_CDEV*/