Device layer rollup commit.
[dragonfly.git] / sys / dev / video / gfb / gfb_pci.c
... / ...
CommitLineData
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
73static devclass_t gfb_devclass;
74
75#ifdef __alpha__
76
77extern void sccnattach(void);
78
79#endif /* __alpha__ */
80
81extern struct gfb_font bold8x16;
82extern struct gfb_softc *gfb_device_softcs[2][16];
83
84int
85pcigfb_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;
219fail:
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;
235done:
236 splx(s);
237 return(error);
238}
239
240int
241pcigfb_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
260int
261pcigfb_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
277int
278pcigfb_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
286int
287pcigfb_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
295int
296pcigfb_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
304int
305pcigfb_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
313int
314pcigfb_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*/