14d28e78fSSepherosa Ziehau /*-
24d28e78fSSepherosa Ziehau * Copyright (c) 2005 John Baldwin <jhb@FreeBSD.org>
34d28e78fSSepherosa Ziehau * All rights reserved.
44d28e78fSSepherosa Ziehau *
54d28e78fSSepherosa Ziehau * Redistribution and use in source and binary forms, with or without
64d28e78fSSepherosa Ziehau * modification, are permitted provided that the following conditions
74d28e78fSSepherosa Ziehau * are met:
84d28e78fSSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright
94d28e78fSSepherosa Ziehau * notice, this list of conditions and the following disclaimer.
104d28e78fSSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright
114d28e78fSSepherosa Ziehau * notice, this list of conditions and the following disclaimer in the
124d28e78fSSepherosa Ziehau * documentation and/or other materials provided with the distribution.
134d28e78fSSepherosa Ziehau * 3. Neither the name of the author nor the names of any co-contributors
144d28e78fSSepherosa Ziehau * may be used to endorse or promote products derived from this software
154d28e78fSSepherosa Ziehau * without specific prior written permission.
164d28e78fSSepherosa Ziehau *
174d28e78fSSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
184d28e78fSSepherosa Ziehau * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
194d28e78fSSepherosa Ziehau * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
204d28e78fSSepherosa Ziehau * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
214d28e78fSSepherosa Ziehau * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
224d28e78fSSepherosa Ziehau * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
234d28e78fSSepherosa Ziehau * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
244d28e78fSSepherosa Ziehau * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
254d28e78fSSepherosa Ziehau * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
264d28e78fSSepherosa Ziehau * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
274d28e78fSSepherosa Ziehau * SUCH DAMAGE.
2883c1faaaSSascha Wildner *
2983c1faaaSSascha Wildner * $FreeBSD: src/sys/dev/pci/vga_pci.c,v 1.5.8.1 2009/04/15 03:14:26 kensmith Exp $
304d28e78fSSepherosa Ziehau */
314d28e78fSSepherosa Ziehau
324d28e78fSSepherosa Ziehau /*
334d28e78fSSepherosa Ziehau * Simple driver for PCI VGA display devices. Drivers such as agp(4) and
344d28e78fSSepherosa Ziehau * drm(4) should attach as children of this device.
354d28e78fSSepherosa Ziehau *
364d28e78fSSepherosa Ziehau * XXX: The vgapci name is a hack until we somehow merge the isa vga driver
374d28e78fSSepherosa Ziehau * in or rename it.
384d28e78fSSepherosa Ziehau */
394d28e78fSSepherosa Ziehau
404d28e78fSSepherosa Ziehau #include <sys/param.h>
414d28e78fSSepherosa Ziehau #include <sys/bus.h>
424d28e78fSSepherosa Ziehau #include <sys/kernel.h>
434d28e78fSSepherosa Ziehau #include <sys/module.h>
44a02ece1fSFrançois Tigeot #include <sys/rman.h>
45a02ece1fSFrançois Tigeot #include <sys/sysctl.h>
46a02ece1fSFrançois Tigeot #include <sys/systm.h>
47a02ece1fSFrançois Tigeot
48a02ece1fSFrançois Tigeot #include <machine/pmap.h>
494d28e78fSSepherosa Ziehau
504d28e78fSSepherosa Ziehau #include <bus/pci/pcireg.h>
514d28e78fSSepherosa Ziehau #include <bus/pci/pcivar.h>
524d28e78fSSepherosa Ziehau
53072d6095SFrançois Tigeot struct vga_resource {
54072d6095SFrançois Tigeot struct resource *vr_res;
55072d6095SFrançois Tigeot int vr_refs;
56072d6095SFrançois Tigeot };
57072d6095SFrançois Tigeot
58072d6095SFrançois Tigeot struct vga_pci_softc {
59072d6095SFrançois Tigeot device_t vga_msi_child; /* Child driver using MSI. */
60072d6095SFrançois Tigeot struct vga_resource vga_bars[PCIR_MAX_BAR_0 + 1];
61072d6095SFrançois Tigeot struct vga_resource vga_bios;
62072d6095SFrançois Tigeot };
63072d6095SFrançois Tigeot
64a02ece1fSFrançois Tigeot SYSCTL_DECL(_hw_pci);
65a02ece1fSFrançois Tigeot
66072d6095SFrançois Tigeot static struct vga_resource *lookup_res(struct vga_pci_softc *sc, int rid);
67072d6095SFrançois Tigeot static struct resource *vga_pci_alloc_resource(device_t dev, device_t child,
68384438e3SSepherosa Ziehau int type, int *rid, u_long start, u_long end, u_long count, u_int flags,
69384438e3SSepherosa Ziehau int cpuid);
70072d6095SFrançois Tigeot static int vga_pci_release_resource(device_t dev, device_t child, int type,
71072d6095SFrançois Tigeot int rid, struct resource *r);
72072d6095SFrançois Tigeot
73a02ece1fSFrançois Tigeot int vga_pci_default_unit = -1;
74a02ece1fSFrançois Tigeot TUNABLE_INT("hw.pci.default_vgapci_unit", &vga_pci_default_unit);
75a02ece1fSFrançois Tigeot SYSCTL_INT(_hw_pci, OID_AUTO, default_vgapci_unit, CTLFLAG_RD,
76a02ece1fSFrançois Tigeot &vga_pci_default_unit, -1, "Default VGA-compatible display");
77a02ece1fSFrançois Tigeot
78a02ece1fSFrançois Tigeot int
vga_pci_is_boot_display(device_t dev)79a02ece1fSFrançois Tigeot vga_pci_is_boot_display(device_t dev)
80a02ece1fSFrançois Tigeot {
812a979d81SImre Vadasz int unit;
822a979d81SImre Vadasz device_t pcib;
832a979d81SImre Vadasz uint16_t config;
842a979d81SImre Vadasz
852a979d81SImre Vadasz /* Check that the given device is a video card */
862a979d81SImre Vadasz if ((pci_get_class(dev) != PCIC_DISPLAY &&
872a979d81SImre Vadasz (pci_get_class(dev) != PCIC_OLD ||
882a979d81SImre Vadasz pci_get_subclass(dev) != PCIS_OLD_VGA)))
892a979d81SImre Vadasz return (0);
902a979d81SImre Vadasz
912a979d81SImre Vadasz unit = device_get_unit(dev);
922a979d81SImre Vadasz
932a979d81SImre Vadasz if (vga_pci_default_unit >= 0) {
942a979d81SImre Vadasz /*
952a979d81SImre Vadasz * The boot display device was determined by a previous
962a979d81SImre Vadasz * call to this function, or the user forced it using
972a979d81SImre Vadasz * the hw.pci.default_vgapci_unit tunable.
982a979d81SImre Vadasz */
992a979d81SImre Vadasz return (vga_pci_default_unit == unit);
1002a979d81SImre Vadasz }
101a02ece1fSFrançois Tigeot
102a02ece1fSFrançois Tigeot /*
1032a979d81SImre Vadasz * The primary video card used as a boot display must have the
1042a979d81SImre Vadasz * "I/O" and "Memory Address Space Decoding" bits set in its
1052a979d81SImre Vadasz * Command register.
1062a979d81SImre Vadasz *
1072a979d81SImre Vadasz * Furthermore, if the card is attached to a bridge, instead of
1082a979d81SImre Vadasz * the root PCI bus, the bridge must have the "VGA Enable" bit
1092a979d81SImre Vadasz * set in its Control register.
110a02ece1fSFrançois Tigeot */
1112a979d81SImre Vadasz
1122a979d81SImre Vadasz pcib = device_get_parent(device_get_parent(dev));
1132a979d81SImre Vadasz if (device_get_devclass(device_get_parent(pcib)) ==
1142a979d81SImre Vadasz devclass_find("pci")) {
1152a979d81SImre Vadasz /*
1162a979d81SImre Vadasz * The parent bridge is a PCI-to-PCI bridge: check the
1172a979d81SImre Vadasz * value of the "VGA Enable" bit.
1182a979d81SImre Vadasz */
1192a979d81SImre Vadasz config = pci_read_config(pcib, PCIR_BRIDGECTL_1, 2);
1202a979d81SImre Vadasz if ((config & PCIB_BCR_VGA_ENABLE) == 0)
1212a979d81SImre Vadasz return (0);
1222a979d81SImre Vadasz }
1232a979d81SImre Vadasz
1242a979d81SImre Vadasz config = pci_read_config(dev, PCIR_COMMAND, 2);
1252a979d81SImre Vadasz if ((config & (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN)) == 0)
1262a979d81SImre Vadasz return (0);
1272a979d81SImre Vadasz
1282a979d81SImre Vadasz /* This video card is the boot display: record its unit number. */
1292a979d81SImre Vadasz vga_pci_default_unit = unit;
1302a979d81SImre Vadasz device_set_flags(dev, 1);
1312a979d81SImre Vadasz
1322a979d81SImre Vadasz return (1);
133a02ece1fSFrançois Tigeot }
134a02ece1fSFrançois Tigeot
135a02ece1fSFrançois Tigeot void *
vga_pci_map_bios(device_t dev,size_t * size)136a02ece1fSFrançois Tigeot vga_pci_map_bios(device_t dev, size_t *size)
137a02ece1fSFrançois Tigeot {
138a02ece1fSFrançois Tigeot int rid;
139a02ece1fSFrançois Tigeot struct resource *res;
140a02ece1fSFrançois Tigeot
141a02ece1fSFrançois Tigeot if (vga_pci_is_boot_display(dev)) {
142a02ece1fSFrançois Tigeot /*
143a02ece1fSFrançois Tigeot * On x86, the System BIOS copy the default display
144a02ece1fSFrançois Tigeot * device's Video BIOS at a fixed location in system
145a02ece1fSFrançois Tigeot * memory (0xC0000, 128 kBytes long) at boot time.
146a02ece1fSFrançois Tigeot *
147a02ece1fSFrançois Tigeot * We use this copy for the default boot device, because
148a02ece1fSFrançois Tigeot * the original ROM may not be valid after boot.
149a02ece1fSFrançois Tigeot */
150a02ece1fSFrançois Tigeot
151a02ece1fSFrançois Tigeot *size = VGA_PCI_BIOS_SHADOW_SIZE;
152a02ece1fSFrançois Tigeot return (pmap_mapbios(VGA_PCI_BIOS_SHADOW_ADDR, *size));
153a02ece1fSFrançois Tigeot }
154a02ece1fSFrançois Tigeot
155a02ece1fSFrançois Tigeot rid = PCIR_BIOS;
156072d6095SFrançois Tigeot res = vga_pci_alloc_resource(dev, NULL, SYS_RES_MEMORY, &rid, 0ul,
157384438e3SSepherosa Ziehau ~0ul, 1, RF_ACTIVE, -1);
158a02ece1fSFrançois Tigeot if (res == NULL) {
159a02ece1fSFrançois Tigeot return (NULL);
160a02ece1fSFrançois Tigeot }
161a02ece1fSFrançois Tigeot
162a02ece1fSFrançois Tigeot *size = rman_get_size(res);
163a02ece1fSFrançois Tigeot return (rman_get_virtual(res));
164a02ece1fSFrançois Tigeot }
165a02ece1fSFrançois Tigeot
166a02ece1fSFrançois Tigeot void
vga_pci_unmap_bios(device_t dev,void * bios)167a02ece1fSFrançois Tigeot vga_pci_unmap_bios(device_t dev, void *bios)
168a02ece1fSFrançois Tigeot {
169072d6095SFrançois Tigeot struct vga_resource *vr;
170a02ece1fSFrançois Tigeot
171a02ece1fSFrançois Tigeot if (bios == NULL) {
172a02ece1fSFrançois Tigeot return;
173a02ece1fSFrançois Tigeot }
174a02ece1fSFrançois Tigeot
175a02ece1fSFrançois Tigeot if (vga_pci_is_boot_display(dev)) {
176a02ece1fSFrançois Tigeot /* We mapped the BIOS shadow copy located at 0xC0000. */
177a02ece1fSFrançois Tigeot pmap_unmapdev((vm_offset_t)bios, VGA_PCI_BIOS_SHADOW_SIZE);
178a02ece1fSFrançois Tigeot
179a02ece1fSFrançois Tigeot return;
180a02ece1fSFrançois Tigeot }
181a02ece1fSFrançois Tigeot
182a02ece1fSFrançois Tigeot /*
183072d6095SFrançois Tigeot * Look up the PCIR_BIOS resource in our softc. It should match
184072d6095SFrançois Tigeot * the address we returned previously.
185a02ece1fSFrançois Tigeot */
186072d6095SFrançois Tigeot vr = lookup_res(device_get_softc(dev), PCIR_BIOS);
187072d6095SFrançois Tigeot KASSERT(vr->vr_res != NULL, ("vga_pci_unmap_bios: bios not mapped"));
188072d6095SFrançois Tigeot KASSERT(rman_get_virtual(vr->vr_res) == bios,
189072d6095SFrançois Tigeot ("vga_pci_unmap_bios: mismatch"));
190072d6095SFrançois Tigeot vga_pci_release_resource(dev, NULL, SYS_RES_MEMORY, PCIR_BIOS,
191072d6095SFrançois Tigeot vr->vr_res);
192a02ece1fSFrançois Tigeot }
193a02ece1fSFrançois Tigeot
1944d28e78fSSepherosa Ziehau static int
vga_pci_probe(device_t dev)1954d28e78fSSepherosa Ziehau vga_pci_probe(device_t dev)
1964d28e78fSSepherosa Ziehau {
1974d28e78fSSepherosa Ziehau
1984d28e78fSSepherosa Ziehau switch (pci_get_class(dev)) {
1994d28e78fSSepherosa Ziehau case PCIC_DISPLAY:
2004d28e78fSSepherosa Ziehau break;
2014d28e78fSSepherosa Ziehau case PCIC_OLD:
2024d28e78fSSepherosa Ziehau if (pci_get_subclass(dev) != PCIS_OLD_VGA)
2034d28e78fSSepherosa Ziehau return (ENXIO);
2044d28e78fSSepherosa Ziehau break;
2054d28e78fSSepherosa Ziehau default:
2064d28e78fSSepherosa Ziehau return (ENXIO);
2074d28e78fSSepherosa Ziehau }
208a02ece1fSFrançois Tigeot
209a02ece1fSFrançois Tigeot /* Probe default display. */
2102a979d81SImre Vadasz vga_pci_is_boot_display(dev);
211a02ece1fSFrançois Tigeot
2124d28e78fSSepherosa Ziehau device_set_desc(dev, "VGA-compatible display");
2134d28e78fSSepherosa Ziehau return (BUS_PROBE_GENERIC);
2144d28e78fSSepherosa Ziehau }
2154d28e78fSSepherosa Ziehau
2164d28e78fSSepherosa Ziehau static int
vga_pci_attach(device_t dev)2174d28e78fSSepherosa Ziehau vga_pci_attach(device_t dev)
2184d28e78fSSepherosa Ziehau {
2194d28e78fSSepherosa Ziehau
2204d28e78fSSepherosa Ziehau bus_generic_probe(dev);
2214d28e78fSSepherosa Ziehau
2224d28e78fSSepherosa Ziehau /* Always create a drm child for now to make it easier on drm. */
2234d28e78fSSepherosa Ziehau device_add_child(dev, "drm", -1);
2244d28e78fSSepherosa Ziehau bus_generic_attach(dev);
2252a979d81SImre Vadasz
2262a979d81SImre Vadasz if (vga_pci_is_boot_display(dev))
2272a979d81SImre Vadasz device_printf(dev, "Boot video device\n");
2282a979d81SImre Vadasz
2294d28e78fSSepherosa Ziehau return (0);
2304d28e78fSSepherosa Ziehau }
2314d28e78fSSepherosa Ziehau
2324d28e78fSSepherosa Ziehau static int
vga_pci_suspend(device_t dev)2334d28e78fSSepherosa Ziehau vga_pci_suspend(device_t dev)
2344d28e78fSSepherosa Ziehau {
2354d28e78fSSepherosa Ziehau
2364d28e78fSSepherosa Ziehau return (bus_generic_suspend(dev));
2374d28e78fSSepherosa Ziehau }
2384d28e78fSSepherosa Ziehau
2394d28e78fSSepherosa Ziehau static int
vga_pci_resume(device_t dev)2404d28e78fSSepherosa Ziehau vga_pci_resume(device_t dev)
2414d28e78fSSepherosa Ziehau {
2424d28e78fSSepherosa Ziehau
2434d28e78fSSepherosa Ziehau return (bus_generic_resume(dev));
2444d28e78fSSepherosa Ziehau }
2454d28e78fSSepherosa Ziehau
2464d28e78fSSepherosa Ziehau /* Bus interface. */
2474d28e78fSSepherosa Ziehau
2484d28e78fSSepherosa Ziehau static int
vga_pci_read_ivar(device_t dev,device_t child,int which,uintptr_t * result)2494d28e78fSSepherosa Ziehau vga_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
2504d28e78fSSepherosa Ziehau {
2514d28e78fSSepherosa Ziehau
2524d28e78fSSepherosa Ziehau return (BUS_READ_IVAR(device_get_parent(dev), dev, which, result));
2534d28e78fSSepherosa Ziehau }
2544d28e78fSSepherosa Ziehau
2554d28e78fSSepherosa Ziehau static int
vga_pci_write_ivar(device_t dev,device_t child,int which,uintptr_t value)2564d28e78fSSepherosa Ziehau vga_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
2574d28e78fSSepherosa Ziehau {
2584d28e78fSSepherosa Ziehau
2594d28e78fSSepherosa Ziehau return (EINVAL);
2604d28e78fSSepherosa Ziehau }
2614d28e78fSSepherosa Ziehau
262*0855c8c0SImre Vadász static int
vga_pci_setup_intr(device_t dev,device_t child,struct resource * irq,int flags,driver_intr_t * intr,void * arg,void ** cookiep,lwkt_serialize_t serializer,const char * desc)263*0855c8c0SImre Vadász vga_pci_setup_intr(device_t dev, device_t child, struct resource *irq,
264*0855c8c0SImre Vadász int flags, driver_intr_t *intr, void *arg, void **cookiep,
265*0855c8c0SImre Vadász lwkt_serialize_t serializer, const char *desc)
266*0855c8c0SImre Vadász {
267*0855c8c0SImre Vadász
268*0855c8c0SImre Vadász return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags,
269*0855c8c0SImre Vadász intr, arg, cookiep, serializer, desc));
270*0855c8c0SImre Vadász }
271*0855c8c0SImre Vadász
272*0855c8c0SImre Vadász static int
vga_pci_teardown_intr(device_t dev,device_t child,struct resource * irq,void * cookie)273*0855c8c0SImre Vadász vga_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
274*0855c8c0SImre Vadász void *cookie)
275*0855c8c0SImre Vadász {
276*0855c8c0SImre Vadász
277*0855c8c0SImre Vadász return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie));
278*0855c8c0SImre Vadász }
279*0855c8c0SImre Vadász
280072d6095SFrançois Tigeot static struct vga_resource *
lookup_res(struct vga_pci_softc * sc,int rid)281072d6095SFrançois Tigeot lookup_res(struct vga_pci_softc *sc, int rid)
282072d6095SFrançois Tigeot {
283072d6095SFrançois Tigeot int bar;
284072d6095SFrançois Tigeot
285072d6095SFrançois Tigeot if (rid == PCIR_BIOS)
286072d6095SFrançois Tigeot return (&sc->vga_bios);
287072d6095SFrançois Tigeot bar = PCI_RID2BAR(rid);
288072d6095SFrançois Tigeot if (bar >= 0 && bar <= PCIR_MAX_BAR_0)
289072d6095SFrançois Tigeot return (&sc->vga_bars[bar]);
290072d6095SFrançois Tigeot return (NULL);
291072d6095SFrançois Tigeot }
292072d6095SFrançois Tigeot
2934d28e78fSSepherosa Ziehau static struct resource *
vga_pci_alloc_resource(device_t dev,device_t child,int type,int * rid,u_long start,u_long end,u_long count,u_int flags,int cpuid __unused)2944d28e78fSSepherosa Ziehau vga_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
295384438e3SSepherosa Ziehau u_long start, u_long end, u_long count, u_int flags, int cpuid __unused)
2964d28e78fSSepherosa Ziehau {
297072d6095SFrançois Tigeot struct vga_resource *vr;
2984d28e78fSSepherosa Ziehau
299072d6095SFrançois Tigeot switch (type) {
300072d6095SFrançois Tigeot case SYS_RES_MEMORY:
301072d6095SFrançois Tigeot case SYS_RES_IOPORT:
302072d6095SFrançois Tigeot /*
303072d6095SFrançois Tigeot * For BARs, we cache the resource so that we only allocate it
304072d6095SFrançois Tigeot * from the PCI bus once.
305072d6095SFrançois Tigeot */
306072d6095SFrançois Tigeot vr = lookup_res(device_get_softc(dev), *rid);
307072d6095SFrançois Tigeot if (vr == NULL)
308072d6095SFrançois Tigeot return (NULL);
309072d6095SFrançois Tigeot if (vr->vr_res == NULL)
310072d6095SFrançois Tigeot vr->vr_res = bus_alloc_resource(dev, type, rid, start,
311072d6095SFrançois Tigeot end, count, flags);
312072d6095SFrançois Tigeot if (vr->vr_res != NULL)
313072d6095SFrançois Tigeot vr->vr_refs++;
314072d6095SFrançois Tigeot return (vr->vr_res);
315072d6095SFrançois Tigeot }
3164d28e78fSSepherosa Ziehau return (bus_alloc_resource(dev, type, rid, start, end, count, flags));
3174d28e78fSSepherosa Ziehau }
3184d28e78fSSepherosa Ziehau
3194d28e78fSSepherosa Ziehau static int
vga_pci_release_resource(device_t dev,device_t child,int type,int rid,struct resource * r)3204d28e78fSSepherosa Ziehau vga_pci_release_resource(device_t dev, device_t child, int type, int rid,
3214d28e78fSSepherosa Ziehau struct resource *r)
3224d28e78fSSepherosa Ziehau {
323e8be1190SSepherosa Ziehau struct vga_resource *vr;
3244d28e78fSSepherosa Ziehau
325e8be1190SSepherosa Ziehau switch (type) {
326e8be1190SSepherosa Ziehau case SYS_RES_MEMORY:
327e8be1190SSepherosa Ziehau case SYS_RES_IOPORT:
328e8be1190SSepherosa Ziehau /*
329e8be1190SSepherosa Ziehau * Stop caching the resource when refs drops to 0
330e8be1190SSepherosa Ziehau */
331e8be1190SSepherosa Ziehau vr = lookup_res(device_get_softc(dev), rid);
332e8be1190SSepherosa Ziehau if (vr && vr->vr_refs > 0) {
333e8be1190SSepherosa Ziehau if (--vr->vr_refs > 0)
334e8be1190SSepherosa Ziehau return(0);
335e8be1190SSepherosa Ziehau vr->vr_res = NULL;
336e8be1190SSepherosa Ziehau /* fall through */
337e8be1190SSepherosa Ziehau }
338e8be1190SSepherosa Ziehau /* fall through */
339e8be1190SSepherosa Ziehau break;
340e8be1190SSepherosa Ziehau }
3414d28e78fSSepherosa Ziehau return (bus_release_resource(dev, type, rid, r));
3424d28e78fSSepherosa Ziehau }
3434d28e78fSSepherosa Ziehau
3444d28e78fSSepherosa Ziehau /* PCI interface. */
3454d28e78fSSepherosa Ziehau
3464d28e78fSSepherosa Ziehau static uint32_t
vga_pci_read_config(device_t dev,device_t child,int reg,int width)3474d28e78fSSepherosa Ziehau vga_pci_read_config(device_t dev, device_t child, int reg, int width)
3484d28e78fSSepherosa Ziehau {
3494d28e78fSSepherosa Ziehau
3504d28e78fSSepherosa Ziehau return (pci_read_config(dev, reg, width));
3514d28e78fSSepherosa Ziehau }
3524d28e78fSSepherosa Ziehau
3534d28e78fSSepherosa Ziehau static void
vga_pci_write_config(device_t dev,device_t child,int reg,uint32_t val,int width)3544d28e78fSSepherosa Ziehau vga_pci_write_config(device_t dev, device_t child, int reg,
3554d28e78fSSepherosa Ziehau uint32_t val, int width)
3564d28e78fSSepherosa Ziehau {
3574d28e78fSSepherosa Ziehau
3584d28e78fSSepherosa Ziehau pci_write_config(dev, reg, val, width);
3594d28e78fSSepherosa Ziehau }
3604d28e78fSSepherosa Ziehau
3614d28e78fSSepherosa Ziehau static int
vga_pci_enable_busmaster(device_t dev,device_t child)3624d28e78fSSepherosa Ziehau vga_pci_enable_busmaster(device_t dev, device_t child)
3634d28e78fSSepherosa Ziehau {
3644d28e78fSSepherosa Ziehau
3654d28e78fSSepherosa Ziehau return (pci_enable_busmaster(dev));
3664d28e78fSSepherosa Ziehau }
3674d28e78fSSepherosa Ziehau
3684d28e78fSSepherosa Ziehau static int
vga_pci_disable_busmaster(device_t dev,device_t child)3694d28e78fSSepherosa Ziehau vga_pci_disable_busmaster(device_t dev, device_t child)
3704d28e78fSSepherosa Ziehau {
3714d28e78fSSepherosa Ziehau
3724d28e78fSSepherosa Ziehau return (pci_disable_busmaster(dev));
3734d28e78fSSepherosa Ziehau }
3744d28e78fSSepherosa Ziehau
3754d28e78fSSepherosa Ziehau static int
vga_pci_enable_io(device_t dev,device_t child,int space)3764d28e78fSSepherosa Ziehau vga_pci_enable_io(device_t dev, device_t child, int space)
3774d28e78fSSepherosa Ziehau {
3784d28e78fSSepherosa Ziehau
3794d28e78fSSepherosa Ziehau device_printf(dev, "child %s requested pci_enable_io\n",
3804d28e78fSSepherosa Ziehau device_get_nameunit(child));
3814d28e78fSSepherosa Ziehau return (pci_enable_io(dev, space));
3824d28e78fSSepherosa Ziehau }
3834d28e78fSSepherosa Ziehau
3844d28e78fSSepherosa Ziehau static int
vga_pci_disable_io(device_t dev,device_t child,int space)3854d28e78fSSepherosa Ziehau vga_pci_disable_io(device_t dev, device_t child, int space)
3864d28e78fSSepherosa Ziehau {
3874d28e78fSSepherosa Ziehau
3884d28e78fSSepherosa Ziehau device_printf(dev, "child %s requested pci_disable_io\n",
3894d28e78fSSepherosa Ziehau device_get_nameunit(child));
3904d28e78fSSepherosa Ziehau return (pci_disable_io(dev, space));
3914d28e78fSSepherosa Ziehau }
3924d28e78fSSepherosa Ziehau
3934d28e78fSSepherosa Ziehau static int
vga_pci_get_vpd_ident(device_t dev,device_t child,const char ** identptr)394*0855c8c0SImre Vadász vga_pci_get_vpd_ident(device_t dev, device_t child, const char **identptr)
395*0855c8c0SImre Vadász {
396*0855c8c0SImre Vadász
397*0855c8c0SImre Vadász return (pci_get_vpd_ident(dev, identptr));
398*0855c8c0SImre Vadász }
399*0855c8c0SImre Vadász
400*0855c8c0SImre Vadász static int
vga_pci_get_vpd_readonly(device_t dev,device_t child,const char * kw,const char ** vptr)401*0855c8c0SImre Vadász vga_pci_get_vpd_readonly(device_t dev, device_t child, const char *kw,
402*0855c8c0SImre Vadász const char **vptr)
403*0855c8c0SImre Vadász {
404*0855c8c0SImre Vadász
405*0855c8c0SImre Vadász return (pci_get_vpd_readonly(dev, kw, vptr));
406*0855c8c0SImre Vadász }
407*0855c8c0SImre Vadász
408*0855c8c0SImre Vadász static int
vga_pci_set_powerstate(device_t dev,device_t child,int state)4094d28e78fSSepherosa Ziehau vga_pci_set_powerstate(device_t dev, device_t child, int state)
4104d28e78fSSepherosa Ziehau {
4114d28e78fSSepherosa Ziehau
4124d28e78fSSepherosa Ziehau return (pci_set_powerstate(dev, state));
4134d28e78fSSepherosa Ziehau }
4144d28e78fSSepherosa Ziehau
4154d28e78fSSepherosa Ziehau static int
vga_pci_get_powerstate(device_t dev,device_t child)4164d28e78fSSepherosa Ziehau vga_pci_get_powerstate(device_t dev, device_t child)
4174d28e78fSSepherosa Ziehau {
4184d28e78fSSepherosa Ziehau
4194d28e78fSSepherosa Ziehau return (pci_get_powerstate(dev));
4204d28e78fSSepherosa Ziehau }
4214d28e78fSSepherosa Ziehau
4224d28e78fSSepherosa Ziehau static int
vga_pci_assign_interrupt(device_t dev,device_t child)4234d28e78fSSepherosa Ziehau vga_pci_assign_interrupt(device_t dev, device_t child)
4244d28e78fSSepherosa Ziehau {
4254d28e78fSSepherosa Ziehau
4264d28e78fSSepherosa Ziehau device_printf(dev, "child %s requested pci_assign_interrupt\n",
4274d28e78fSSepherosa Ziehau device_get_nameunit(child));
4284d28e78fSSepherosa Ziehau return (PCI_ASSIGN_INTERRUPT(device_get_parent(dev), dev));
4294d28e78fSSepherosa Ziehau }
4304d28e78fSSepherosa Ziehau
4314d28e78fSSepherosa Ziehau static int
vga_pci_find_extcap(device_t dev,device_t child,int capability,int * capreg)4324d28e78fSSepherosa Ziehau vga_pci_find_extcap(device_t dev, device_t child, int capability,
4334d28e78fSSepherosa Ziehau int *capreg)
4344d28e78fSSepherosa Ziehau {
4354d28e78fSSepherosa Ziehau
4364d28e78fSSepherosa Ziehau return (pci_find_extcap(dev, capability, capreg));
4374d28e78fSSepherosa Ziehau }
4384d28e78fSSepherosa Ziehau
439*0855c8c0SImre Vadász static int
vga_pci_alloc_msi(device_t dev,device_t child,int * rid,int count,int cpuid)440*0855c8c0SImre Vadász vga_pci_alloc_msi(device_t dev, device_t child, int *rid, int count,
441*0855c8c0SImre Vadász int cpuid)
442*0855c8c0SImre Vadász {
443*0855c8c0SImre Vadász struct vga_pci_softc *sc;
444*0855c8c0SImre Vadász int error;
445*0855c8c0SImre Vadász
446*0855c8c0SImre Vadász sc = device_get_softc(dev);
447*0855c8c0SImre Vadász if (sc->vga_msi_child != NULL)
448*0855c8c0SImre Vadász return (EBUSY);
449*0855c8c0SImre Vadász error = pci_alloc_msi(dev, rid, count, cpuid);
450*0855c8c0SImre Vadász if (error == 0)
451*0855c8c0SImre Vadász sc->vga_msi_child = child;
452*0855c8c0SImre Vadász return (error);
453*0855c8c0SImre Vadász }
454*0855c8c0SImre Vadász
455*0855c8c0SImre Vadász static int
vga_pci_release_msi(device_t dev,device_t child)456*0855c8c0SImre Vadász vga_pci_release_msi(device_t dev, device_t child)
457*0855c8c0SImre Vadász {
458*0855c8c0SImre Vadász struct vga_pci_softc *sc;
459*0855c8c0SImre Vadász int error;
460*0855c8c0SImre Vadász
461*0855c8c0SImre Vadász sc = device_get_softc(dev);
462*0855c8c0SImre Vadász if (sc->vga_msi_child != child)
463*0855c8c0SImre Vadász return (ENXIO);
464*0855c8c0SImre Vadász error = pci_release_msi(dev);
465*0855c8c0SImre Vadász if (error == 0)
466*0855c8c0SImre Vadász sc->vga_msi_child = NULL;
467*0855c8c0SImre Vadász return (error);
468*0855c8c0SImre Vadász }
469*0855c8c0SImre Vadász
470*0855c8c0SImre Vadász static int
vga_pci_msi_count(device_t dev,device_t child)471*0855c8c0SImre Vadász vga_pci_msi_count(device_t dev, device_t child)
472*0855c8c0SImre Vadász {
473*0855c8c0SImre Vadász
474*0855c8c0SImre Vadász return (pci_msi_count(dev));
475*0855c8c0SImre Vadász }
476*0855c8c0SImre Vadász
4774d28e78fSSepherosa Ziehau static device_method_t vga_pci_methods[] = {
4784d28e78fSSepherosa Ziehau /* Device interface */
4794d28e78fSSepherosa Ziehau DEVMETHOD(device_probe, vga_pci_probe),
4804d28e78fSSepherosa Ziehau DEVMETHOD(device_attach, vga_pci_attach),
4814d28e78fSSepherosa Ziehau DEVMETHOD(device_shutdown, bus_generic_shutdown),
4824d28e78fSSepherosa Ziehau DEVMETHOD(device_suspend, vga_pci_suspend),
4834d28e78fSSepherosa Ziehau DEVMETHOD(device_resume, vga_pci_resume),
4844d28e78fSSepherosa Ziehau
4854d28e78fSSepherosa Ziehau /* Bus interface */
4864d28e78fSSepherosa Ziehau DEVMETHOD(bus_read_ivar, vga_pci_read_ivar),
4874d28e78fSSepherosa Ziehau DEVMETHOD(bus_write_ivar, vga_pci_write_ivar),
488*0855c8c0SImre Vadász DEVMETHOD(bus_setup_intr, vga_pci_setup_intr),
489*0855c8c0SImre Vadász DEVMETHOD(bus_teardown_intr, vga_pci_teardown_intr),
4904d28e78fSSepherosa Ziehau
4914d28e78fSSepherosa Ziehau DEVMETHOD(bus_alloc_resource, vga_pci_alloc_resource),
4924d28e78fSSepherosa Ziehau DEVMETHOD(bus_release_resource, vga_pci_release_resource),
4934d28e78fSSepherosa Ziehau DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
4944d28e78fSSepherosa Ziehau DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
4954d28e78fSSepherosa Ziehau
4964d28e78fSSepherosa Ziehau /* PCI interface */
4974d28e78fSSepherosa Ziehau DEVMETHOD(pci_read_config, vga_pci_read_config),
4984d28e78fSSepherosa Ziehau DEVMETHOD(pci_write_config, vga_pci_write_config),
4994d28e78fSSepherosa Ziehau DEVMETHOD(pci_enable_busmaster, vga_pci_enable_busmaster),
5004d28e78fSSepherosa Ziehau DEVMETHOD(pci_disable_busmaster, vga_pci_disable_busmaster),
5014d28e78fSSepherosa Ziehau DEVMETHOD(pci_enable_io, vga_pci_enable_io),
5024d28e78fSSepherosa Ziehau DEVMETHOD(pci_disable_io, vga_pci_disable_io),
503*0855c8c0SImre Vadász DEVMETHOD(pci_get_vpd_ident, vga_pci_get_vpd_ident),
504*0855c8c0SImre Vadász DEVMETHOD(pci_get_vpd_readonly, vga_pci_get_vpd_readonly),
5054d28e78fSSepherosa Ziehau DEVMETHOD(pci_get_powerstate, vga_pci_get_powerstate),
5064d28e78fSSepherosa Ziehau DEVMETHOD(pci_set_powerstate, vga_pci_set_powerstate),
5074d28e78fSSepherosa Ziehau DEVMETHOD(pci_assign_interrupt, vga_pci_assign_interrupt),
5084d28e78fSSepherosa Ziehau DEVMETHOD(pci_find_extcap, vga_pci_find_extcap),
509*0855c8c0SImre Vadász DEVMETHOD(pci_alloc_msi, vga_pci_alloc_msi),
510*0855c8c0SImre Vadász DEVMETHOD(pci_release_msi, vga_pci_release_msi),
511*0855c8c0SImre Vadász DEVMETHOD(pci_msi_count, vga_pci_msi_count),
5124d28e78fSSepherosa Ziehau
513d3c9c58eSSascha Wildner DEVMETHOD_END
5144d28e78fSSepherosa Ziehau };
5154d28e78fSSepherosa Ziehau
5164d28e78fSSepherosa Ziehau static driver_t vga_pci_driver = {
5174d28e78fSSepherosa Ziehau "vgapci",
5184d28e78fSSepherosa Ziehau vga_pci_methods,
519e8be1190SSepherosa Ziehau sizeof(struct vga_pci_softc),
5204d28e78fSSepherosa Ziehau };
5214d28e78fSSepherosa Ziehau
5224d28e78fSSepherosa Ziehau static devclass_t vga_devclass;
5234d28e78fSSepherosa Ziehau
524aa2b9d05SSascha Wildner DRIVER_MODULE(vgapci, pci, vga_pci_driver, vga_devclass, NULL, NULL);
525