]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/gfb/gfb_pci.c
This commit was generated by cvs2svn to compensate for changes in r155511,
[FreeBSD/FreeBSD.git] / sys / dev / 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
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include "opt_fb.h"
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/conf.h>
39 #include <sys/proc.h>
40 #include <sys/fcntl.h>
41 #include <sys/malloc.h>
42 #include <sys/fbio.h>
43
44 #include <vm/vm.h>
45 #include <vm/vm_param.h>
46 #include <vm/pmap.h>
47
48 #include <machine/md_var.h>
49 #include <machine/pc/bios.h>
50 #include <machine/clock.h>
51 #include <machine/bus.h>
52 #include <machine/pc/vesa.h>
53 #include <machine/resource.h>
54
55 #include <sys/bus.h>
56 #include <sys/rman.h>
57
58 #include <dev/pci/pcireg.h>
59 #include <dev/pci/pcivar.h>
60
61 #include <dev/fb/fbreg.h>
62 #include <dev/fb/gfb.h>
63 #include <dev/gfb/gfb_pci.h>
64
65 #if 0
66 static devclass_t gfb_devclass;
67 #endif
68
69 extern struct gfb_font bold8x16;
70 extern struct gfb_softc *gfb_device_softcs[2][16];
71
72 int
73 pcigfb_attach(device_t dev)
74 {
75         int s;
76         gfb_softc_t sc;
77         video_adapter_t *adp;
78         int unit, flags, error, rid, va_index;
79
80         s = splimp();
81         error = 0;
82         unit = device_get_unit(dev);
83         flags = device_get_flags(dev);
84         sc = device_get_softc(dev);
85         sc->rev = pci_get_revid(dev);
86         rid = GFB_MEM_BASE_RID;
87         sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
88             RF_ACTIVE|PCI_RF_DENSE);
89         if(sc->res == NULL) {
90                 device_printf(dev, "couldn't map memory\n");
91                 goto fail;
92         }
93         sc->btag = rman_get_bustag(sc->res);
94         sc->bhandle = rman_get_bushandle(sc->res);
95
96         /* Allocate interrupt (irq)... */
97         rid = 0x0;
98         sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
99             RF_SHAREABLE|RF_ACTIVE);
100         if(sc->irq == NULL) {
101                 device_printf(dev, "Couldn't map interrupt\n");
102                 goto fail;
103         }
104         if((va_index = vid_find_adapter(sc->driver_name, unit)) < 0) {
105                 sc->adp = (video_adapter_t *)malloc(sizeof(video_adapter_t),
106                     M_DEVBUF, M_NOWAIT);
107                 adp = sc->adp;
108                 bzero(adp, sizeof(video_adapter_t));
109                 vid_init_struct(adp, sc->driver_name, sc->type, unit);
110                 if(vid_register(adp) < 0) {
111                         free(sc->adp, M_DEVBUF);
112                         goto fail;
113                 }
114                 adp->va_flags |= V_ADP_REGISTERED;
115                 adp->va_model = sc->model;
116                 adp->va_mem_base = (vm_offset_t)rman_get_virtual(sc->res);
117                 adp->va_mem_size = rman_get_end(sc->res) -
118                     rman_get_start(sc->res);
119                 adp->va_io_base = (vm_offset_t)sc->res; /* XXX */
120                 adp->va_io_size = 0;
121                 adp->va_crtc_addr = 0;
122                 gfb_device_softcs[sc->model][unit] = sc;
123                 sc->gfbc = (struct gfb_conf *)malloc(sizeof(struct gfb_conf),
124                     M_DEVBUF, M_NOWAIT);
125                 bzero(sc->gfbc, sizeof(struct gfb_conf));
126                 if((*vidsw[adp->va_index]->init)(unit, adp, flags)) {
127                         device_printf(dev, "Couldn't initialize adapter\n");
128                         vid_unregister(adp);
129                         gfb_device_softcs[sc->model][unit] = NULL;
130                         free(sc->gfbc, M_DEVBUF);
131                         free(sc->adp, M_DEVBUF);
132                         goto fail;
133                 }
134                 sc->gfbc->palette.red =
135                     (u_char *)malloc(sc->gfbc->palette.count, M_DEVBUF,
136                     M_NOWAIT);
137                 sc->gfbc->palette.green =
138                     (u_char *)malloc(sc->gfbc->palette.count, M_DEVBUF,
139                     M_NOWAIT);
140                 sc->gfbc->palette.blue =
141                     (u_char *)malloc(sc->gfbc->palette.count, M_DEVBUF,
142                     M_NOWAIT);
143                 sc->gfbc->cursor_palette.red =
144                     (u_char *)malloc(sc->gfbc->cursor_palette.count, M_DEVBUF,
145                     M_NOWAIT);
146                 sc->gfbc->cursor_palette.green =
147                     (u_char *)malloc(sc->gfbc->cursor_palette.count, M_DEVBUF,
148                     M_NOWAIT);
149                 sc->gfbc->cursor_palette.blue =
150                     (u_char *)malloc(sc->gfbc->cursor_palette.count, M_DEVBUF,
151                     M_NOWAIT);
152                 if(gfb_init(unit, adp, flags)) {
153                         device_printf(dev, "Couldn't initialize framebuffer\n");
154                         vid_unregister(adp);
155                         gfb_device_softcs[sc->model][unit] = NULL;
156                         free(sc->gfbc->cursor_palette.blue, M_DEVBUF);
157                         free(sc->gfbc->cursor_palette.green, M_DEVBUF);
158                         free(sc->gfbc->cursor_palette.red, M_DEVBUF);
159                         free(sc->gfbc->palette.blue, M_DEVBUF);
160                         free(sc->gfbc->palette.green, M_DEVBUF);
161                         free(sc->gfbc->palette.red, M_DEVBUF);
162                         free(sc->gfbc, M_DEVBUF);
163                         free(sc->adp, M_DEVBUF);
164                         goto fail;
165                 }
166         } else {
167                 (*vidsw[va_index]->probe)(unit, &adp, (void *)sc->driver_name,
168                     flags);
169                 sc->adp = adp;
170                 sc->gfbc = gfb_device_softcs[sc->model][unit]->gfbc;
171                 gfb_device_softcs[sc->model][unit] = sc;
172         }
173
174         device_printf(dev, "Board type %s\n", sc->gfbc->name);
175         device_printf(dev, "%d x %d, %dbpp, %s RAMDAC\n",
176                sc->adp->va_info.vi_width, sc->adp->va_info.vi_height,
177                sc->adp->va_info.vi_depth, sc->gfbc->ramdac_name);
178 #ifdef FB_INSTALL_CDEV
179         /* attach a virtual frame buffer device */
180         error = fb_attach(unit, sc->adp, sc->cdevsw);
181         if(error)
182                 goto fail;
183         if(bootverbose)
184                 (*vidsw[sc->adp->va_index]->diag)(sc->adp, bootverbose);
185 #if experimental
186         device_add_child(dev, "fb", -1);
187         bus_generic_attach(dev);
188 #endif /*experimental*/
189 #endif /*FB_INSTALL_CDEV*/
190         goto done;
191 fail:
192         if(sc->intrhand != NULL) {
193                 bus_teardown_intr(dev, sc->irq, sc->intrhand);
194                 sc->intrhand = NULL;
195         }
196         if(sc->irq != NULL) {
197                 rid = 0x0;
198                 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->irq);
199                 sc->irq = NULL;
200         }
201         if(sc->res != NULL) {
202                 rid = GFB_MEM_BASE_RID;
203                 bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->res);
204                 sc->res = NULL;
205         }
206         error = ENXIO;
207 done:
208         splx(s);
209         return(error);
210 }
211
212 int
213 pcigfb_detach(device_t dev)
214 {
215         struct gfb_softc *sc;
216         int rid;
217
218         sc = device_get_softc(dev);
219         bus_teardown_intr(dev, sc->irq, sc->intrhand);
220         rid = 0x0;
221         bus_release_resource(dev, SYS_RES_IRQ, rid, sc->irq);
222         rid = GFB_MEM_BASE_RID;
223         bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->res);
224         return(0);
225 }
226
227 #ifdef FB_INSTALL_CDEV
228
229 int
230 pcigfb_open(struct cdev *dev, int flag, int mode, struct thread *td)
231 {
232         struct gfb_softc *sc;
233         int error;
234
235         sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
236
237         if(sc == NULL)
238                 error = ENXIO;
239         else if(mode & (O_CREAT | O_APPEND | O_TRUNC))
240                 error = ENODEV;
241         else
242                 error = genfbopen(&sc->gensc, sc->adp, flag, mode, td);
243         return(error);
244 }
245
246 int
247 pcigfb_close(struct cdev *dev, int flag, int mode, struct thread *td)
248 {
249         struct gfb_softc *sc;
250
251         sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
252         return genfbclose(&sc->gensc, sc->adp, flag, mode, td);
253 }
254
255 int
256 pcigfb_read(struct cdev *dev, struct uio *uio, int flag)
257 {
258         struct gfb_softc *sc;
259
260         sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
261         return genfbread(&sc->gensc, sc->adp, uio, flag);
262 }
263
264 int
265 pcigfb_write(struct cdev *dev, struct uio *uio, int flag)
266 {
267         struct gfb_softc *sc;
268
269         sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
270         return genfbwrite(&sc->gensc, sc->adp, uio, flag);
271 }
272
273 int
274 pcigfb_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
275 {
276         struct gfb_softc *sc;
277
278         sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
279         return genfbioctl(&sc->gensc, sc->adp, cmd, arg, flag, td);
280 }
281
282 int
283 pcigfb_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int prot)
284 {
285         struct gfb_softc *sc;
286
287         sc = (struct gfb_softc *)devclass_get_softc(gfb_devclass, minor(dev));
288         return genfbmmap(&sc->gensc, sc->adp, offset, paddr, prot);
289 }
290
291 #endif /*FB_INSTALL_CDEV*/