vga_pci.c revision 294883
1153577Sjhb/*-
2153577Sjhb * Copyright (c) 2005 John Baldwin <jhb@FreeBSD.org>
3153577Sjhb * All rights reserved.
4153577Sjhb *
5153577Sjhb * Redistribution and use in source and binary forms, with or without
6153577Sjhb * modification, are permitted provided that the following conditions
7153577Sjhb * are met:
8153577Sjhb * 1. Redistributions of source code must retain the above copyright
9153577Sjhb *    notice, this list of conditions and the following disclaimer.
10153577Sjhb * 2. Redistributions in binary form must reproduce the above copyright
11153577Sjhb *    notice, this list of conditions and the following disclaimer in the
12153577Sjhb *    documentation and/or other materials provided with the distribution.
13153577Sjhb *
14153577Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15153577Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16153577Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17153577Sjhb * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18153577Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19153577Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20153577Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21153577Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22153577Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23153577Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24153577Sjhb * SUCH DAMAGE.
25153577Sjhb */
26153577Sjhb
27153577Sjhb#include <sys/cdefs.h>
28153577Sjhb__FBSDID("$FreeBSD: head/sys/dev/pci/vga_pci.c 294883 2016-01-27 02:23:54Z jhibbits $");
29153577Sjhb
30153577Sjhb/*
31153577Sjhb * Simple driver for PCI VGA display devices.  Drivers such as agp(4) and
32153577Sjhb * drm(4) should attach as children of this device.
33153577Sjhb *
34153577Sjhb * XXX: The vgapci name is a hack until we somehow merge the isa vga driver
35153577Sjhb * in or rename it.
36153577Sjhb */
37153577Sjhb
38153577Sjhb#include <sys/param.h>
39153577Sjhb#include <sys/bus.h>
40153577Sjhb#include <sys/kernel.h>
41153577Sjhb#include <sys/module.h>
42189373Sjhb#include <sys/rman.h>
43198251Sjkim#include <sys/sysctl.h>
44189373Sjhb#include <sys/systm.h>
45153577Sjhb
46268351Smarcel#if defined(__amd64__) || defined(__i386__)
47254882Sdumbbell#include <vm/vm.h>
48254882Sdumbbell#include <vm/pmap.h>
49254882Sdumbbell#endif
50254882Sdumbbell
51153577Sjhb#include <dev/pci/pcireg.h>
52153577Sjhb#include <dev/pci/pcivar.h>
53153577Sjhb
54279487Sdumbbell#include <compat/x86bios/x86bios.h> /* To re-POST the card. */
55279487Sdumbbell
56189373Sjhbstruct vga_resource {
57189373Sjhb	struct resource	*vr_res;
58189373Sjhb	int	vr_refs;
59189373Sjhb};
60189373Sjhb
61183095Sjhbstruct vga_pci_softc {
62183095Sjhb	device_t	vga_msi_child;	/* Child driver using MSI. */
63249315Sjhb	struct vga_resource vga_bars[PCIR_MAX_BAR_0 + 1];
64249315Sjhb	struct vga_resource vga_bios;
65183095Sjhb};
66183095Sjhb
67198251SjkimSYSCTL_DECL(_hw_pci);
68198251Sjkim
69255571Sdumbbellstatic struct vga_resource *lookup_res(struct vga_pci_softc *sc, int rid);
70255571Sdumbbellstatic struct resource *vga_pci_alloc_resource(device_t dev, device_t child,
71294883Sjhibbits    int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count,
72294883Sjhibbits    u_int flags);
73255571Sdumbbellstatic int	vga_pci_release_resource(device_t dev, device_t child, int type,
74255571Sdumbbell    int rid, struct resource *r);
75255571Sdumbbell
76198251Sjkimint vga_pci_default_unit = -1;
77198964SjkimSYSCTL_INT(_hw_pci, OID_AUTO, default_vgapci_unit, CTLFLAG_RDTUN,
78198251Sjkim    &vga_pci_default_unit, -1, "Default VGA-compatible display");
79198251Sjkim
80254882Sdumbbellint
81254882Sdumbbellvga_pci_is_boot_display(device_t dev)
82254882Sdumbbell{
83259679Sdumbbell	int unit;
84259679Sdumbbell	device_t pcib;
85259679Sdumbbell	uint16_t config;
86254882Sdumbbell
87259679Sdumbbell	/* Check that the given device is a video card */
88259679Sdumbbell	if ((pci_get_class(dev) != PCIC_DISPLAY &&
89259679Sdumbbell	    (pci_get_class(dev) != PCIC_OLD ||
90259679Sdumbbell	     pci_get_subclass(dev) != PCIS_OLD_VGA)))
91259679Sdumbbell		return (0);
92259679Sdumbbell
93259679Sdumbbell	unit = device_get_unit(dev);
94259679Sdumbbell
95259679Sdumbbell	if (vga_pci_default_unit >= 0) {
96259679Sdumbbell		/*
97259679Sdumbbell		 * The boot display device was determined by a previous
98259679Sdumbbell		 * call to this function, or the user forced it using
99259679Sdumbbell		 * the hw.pci.default_vgapci_unit tunable.
100259679Sdumbbell		 */
101259679Sdumbbell		return (vga_pci_default_unit == unit);
102259679Sdumbbell	}
103259679Sdumbbell
104254882Sdumbbell	/*
105259679Sdumbbell	 * The primary video card used as a boot display must have the
106259679Sdumbbell	 * "I/O" and "Memory Address Space Decoding" bits set in its
107259679Sdumbbell	 * Command register.
108259679Sdumbbell	 *
109259679Sdumbbell	 * Furthermore, if the card is attached to a bridge, instead of
110259679Sdumbbell	 * the root PCI bus, the bridge must have the "VGA Enable" bit
111259679Sdumbbell	 * set in its Control register.
112254882Sdumbbell	 */
113259679Sdumbbell
114259679Sdumbbell	pcib = device_get_parent(device_get_parent(dev));
115259679Sdumbbell	if (device_get_devclass(device_get_parent(pcib)) ==
116259679Sdumbbell	    devclass_find("pci")) {
117259679Sdumbbell		/*
118259679Sdumbbell		 * The parent bridge is a PCI-to-PCI bridge: check the
119259679Sdumbbell		 * value of the "VGA Enable" bit.
120259679Sdumbbell		 */
121259679Sdumbbell		config = pci_read_config(pcib, PCIR_BRIDGECTL_1, 2);
122259679Sdumbbell		if ((config & PCIB_BCR_VGA_ENABLE) == 0)
123259679Sdumbbell			return (0);
124259679Sdumbbell	}
125259679Sdumbbell
126259679Sdumbbell	config = pci_read_config(dev, PCIR_COMMAND, 2);
127259679Sdumbbell	if ((config & (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN)) == 0)
128259679Sdumbbell		return (0);
129259679Sdumbbell
130284012Shselasky	/*
131284012Shselasky	 * Disable interrupts until a chipset driver is loaded for
132284012Shselasky	 * this PCI device. Else unhandled display adapter interrupts
133284012Shselasky	 * might freeze the CPU.
134284012Shselasky	 */
135284012Shselasky	pci_write_config(dev, PCIR_COMMAND, config | PCIM_CMD_INTxDIS, 2);
136284012Shselasky
137259679Sdumbbell	/* This video card is the boot display: record its unit number. */
138259679Sdumbbell	vga_pci_default_unit = unit;
139259679Sdumbbell	device_set_flags(dev, 1);
140259679Sdumbbell
141259679Sdumbbell	return (1);
142254882Sdumbbell}
143254882Sdumbbell
144254882Sdumbbellvoid *
145254882Sdumbbellvga_pci_map_bios(device_t dev, size_t *size)
146254882Sdumbbell{
147254882Sdumbbell	int rid;
148254882Sdumbbell	struct resource *res;
149254882Sdumbbell
150268351Smarcel#if defined(__amd64__) || defined(__i386__)
151254882Sdumbbell	if (vga_pci_is_boot_display(dev)) {
152254882Sdumbbell		/*
153254882Sdumbbell		 * On x86, the System BIOS copy the default display
154254882Sdumbbell		 * device's Video BIOS at a fixed location in system
155254882Sdumbbell		 * memory (0xC0000, 128 kBytes long) at boot time.
156254882Sdumbbell		 *
157254882Sdumbbell		 * We use this copy for the default boot device, because
158254882Sdumbbell		 * the original ROM may not be valid after boot.
159254882Sdumbbell		 */
160254882Sdumbbell
161254882Sdumbbell		*size = VGA_PCI_BIOS_SHADOW_SIZE;
162254882Sdumbbell		return (pmap_mapbios(VGA_PCI_BIOS_SHADOW_ADDR, *size));
163254882Sdumbbell	}
164254882Sdumbbell#endif
165254882Sdumbbell
166254882Sdumbbell	rid = PCIR_BIOS;
167255571Sdumbbell	res = vga_pci_alloc_resource(dev, NULL, SYS_RES_MEMORY, &rid, 0ul,
168255571Sdumbbell	    ~0ul, 1, RF_ACTIVE);
169254882Sdumbbell	if (res == NULL) {
170254882Sdumbbell		return (NULL);
171254882Sdumbbell	}
172254882Sdumbbell
173254882Sdumbbell	*size = rman_get_size(res);
174254882Sdumbbell	return (rman_get_virtual(res));
175254882Sdumbbell}
176254882Sdumbbell
177254882Sdumbbellvoid
178254882Sdumbbellvga_pci_unmap_bios(device_t dev, void *bios)
179254882Sdumbbell{
180255571Sdumbbell	struct vga_resource *vr;
181254882Sdumbbell
182254882Sdumbbell	if (bios == NULL) {
183254882Sdumbbell		return;
184254882Sdumbbell	}
185254882Sdumbbell
186268351Smarcel#if defined(__amd64__) || defined(__i386__)
187254882Sdumbbell	if (vga_pci_is_boot_display(dev)) {
188254882Sdumbbell		/* We mapped the BIOS shadow copy located at 0xC0000. */
189254882Sdumbbell		pmap_unmapdev((vm_offset_t)bios, VGA_PCI_BIOS_SHADOW_SIZE);
190254882Sdumbbell
191254882Sdumbbell		return;
192254882Sdumbbell	}
193254882Sdumbbell#endif
194254882Sdumbbell
195254882Sdumbbell	/*
196255571Sdumbbell	 * Look up the PCIR_BIOS resource in our softc.  It should match
197255571Sdumbbell	 * the address we returned previously.
198254882Sdumbbell	 */
199255571Sdumbbell	vr = lookup_res(device_get_softc(dev), PCIR_BIOS);
200255571Sdumbbell	KASSERT(vr->vr_res != NULL, ("vga_pci_unmap_bios: bios not mapped"));
201255571Sdumbbell	KASSERT(rman_get_virtual(vr->vr_res) == bios,
202255571Sdumbbell	    ("vga_pci_unmap_bios: mismatch"));
203255571Sdumbbell	vga_pci_release_resource(dev, NULL, SYS_RES_MEMORY, PCIR_BIOS,
204255571Sdumbbell	    vr->vr_res);
205254882Sdumbbell}
206254882Sdumbbell
207279487Sdumbbellint
208279487Sdumbbellvga_pci_repost(device_t dev)
209279487Sdumbbell{
210279494Sdumbbell#if defined(__amd64__) || (defined(__i386__) && !defined(PC98))
211279487Sdumbbell	x86regs_t regs;
212279487Sdumbbell
213279487Sdumbbell	if (!vga_pci_is_boot_display(dev))
214279487Sdumbbell		return (EINVAL);
215279487Sdumbbell
216279487Sdumbbell	if (x86bios_get_orm(VGA_PCI_BIOS_SHADOW_ADDR) == NULL)
217279487Sdumbbell		return (ENOTSUP);
218279487Sdumbbell
219279487Sdumbbell	x86bios_init_regs(&regs);
220279487Sdumbbell
221279487Sdumbbell	regs.R_AH = pci_get_bus(dev);
222279487Sdumbbell	regs.R_AL = (pci_get_slot(dev) << 3) | (pci_get_function(dev) & 0x07);
223279487Sdumbbell	regs.R_DL = 0x80;
224279487Sdumbbell
225279487Sdumbbell	device_printf(dev, "REPOSTing\n");
226279487Sdumbbell	x86bios_call(&regs, X86BIOS_PHYSTOSEG(VGA_PCI_BIOS_SHADOW_ADDR + 3),
227279487Sdumbbell	    X86BIOS_PHYSTOOFF(VGA_PCI_BIOS_SHADOW_ADDR + 3));
228279487Sdumbbell
229279487Sdumbbell	x86bios_get_intr(0x10);
230279487Sdumbbell
231279487Sdumbbell	return (0);
232279487Sdumbbell#else
233279487Sdumbbell	return (ENOTSUP);
234279487Sdumbbell#endif
235279487Sdumbbell}
236279487Sdumbbell
237153577Sjhbstatic int
238153577Sjhbvga_pci_probe(device_t dev)
239153577Sjhb{
240153577Sjhb
241153577Sjhb	switch (pci_get_class(dev)) {
242153577Sjhb	case PCIC_DISPLAY:
243153577Sjhb		break;
244153577Sjhb	case PCIC_OLD:
245153577Sjhb		if (pci_get_subclass(dev) != PCIS_OLD_VGA)
246153577Sjhb			return (ENXIO);
247153577Sjhb		break;
248153577Sjhb	default:
249153577Sjhb		return (ENXIO);
250153577Sjhb	}
251198251Sjkim
252198251Sjkim	/* Probe default display. */
253259679Sdumbbell	vga_pci_is_boot_display(dev);
254198251Sjkim
255153577Sjhb	device_set_desc(dev, "VGA-compatible display");
256153646Sjhb	return (BUS_PROBE_GENERIC);
257153577Sjhb}
258153577Sjhb
259153577Sjhbstatic int
260153577Sjhbvga_pci_attach(device_t dev)
261153577Sjhb{
262153577Sjhb
263153577Sjhb	bus_generic_probe(dev);
264153577Sjhb
265153577Sjhb	/* Always create a drm child for now to make it easier on drm. */
266153577Sjhb	device_add_child(dev, "drm", -1);
267235846Skib	device_add_child(dev, "drmn", -1);
268153577Sjhb	bus_generic_attach(dev);
269259679Sdumbbell
270259679Sdumbbell	if (vga_pci_is_boot_display(dev))
271259679Sdumbbell		device_printf(dev, "Boot video device\n");
272259679Sdumbbell
273153577Sjhb	return (0);
274153577Sjhb}
275153577Sjhb
276153577Sjhbstatic int
277153577Sjhbvga_pci_suspend(device_t dev)
278153577Sjhb{
279153577Sjhb
280199002Sjkim	return (bus_generic_suspend(dev));
281153577Sjhb}
282153577Sjhb
283153577Sjhbstatic int
284153577Sjhbvga_pci_resume(device_t dev)
285153577Sjhb{
286153577Sjhb
287153577Sjhb	return (bus_generic_resume(dev));
288153577Sjhb}
289153577Sjhb
290153577Sjhb/* Bus interface. */
291153577Sjhb
292153577Sjhbstatic int
293153577Sjhbvga_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
294153577Sjhb{
295153577Sjhb
296153577Sjhb	return (BUS_READ_IVAR(device_get_parent(dev), dev, which, result));
297153577Sjhb}
298153577Sjhb
299153577Sjhbstatic int
300153577Sjhbvga_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
301153577Sjhb{
302153577Sjhb
303153577Sjhb	return (EINVAL);
304153577Sjhb}
305153577Sjhb
306183194Srnolandstatic int
307183194Srnolandvga_pci_setup_intr(device_t dev, device_t child, struct resource *irq,
308183194Srnoland    int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg,
309183194Srnoland    void **cookiep)
310183194Srnoland{
311183194Srnoland	return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags,
312183194Srnoland	    filter, intr, arg, cookiep));
313183194Srnoland}
314183194Srnoland
315183194Srnolandstatic int
316183194Srnolandvga_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
317183194Srnoland    void *cookie)
318183194Srnoland{
319183194Srnoland	return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie));
320183194Srnoland}
321183194Srnoland
322249315Sjhbstatic struct vga_resource *
323249315Sjhblookup_res(struct vga_pci_softc *sc, int rid)
324249315Sjhb{
325249315Sjhb	int bar;
326249315Sjhb
327249315Sjhb	if (rid == PCIR_BIOS)
328249315Sjhb		return (&sc->vga_bios);
329249315Sjhb	bar = PCI_RID2BAR(rid);
330249315Sjhb	if (bar >= 0 && bar <= PCIR_MAX_BAR_0)
331249315Sjhb		return (&sc->vga_bars[bar]);
332249315Sjhb	return (NULL);
333249315Sjhb}
334249315Sjhb
335153577Sjhbstatic struct resource *
336153577Sjhbvga_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
337294883Sjhibbits    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
338153577Sjhb{
339249315Sjhb	struct vga_resource *vr;
340153577Sjhb
341189373Sjhb	switch (type) {
342189373Sjhb	case SYS_RES_MEMORY:
343189373Sjhb	case SYS_RES_IOPORT:
344189373Sjhb		/*
345189373Sjhb		 * For BARs, we cache the resource so that we only allocate it
346189373Sjhb		 * from the PCI bus once.
347189373Sjhb		 */
348249315Sjhb		vr = lookup_res(device_get_softc(dev), *rid);
349249315Sjhb		if (vr == NULL)
350189373Sjhb			return (NULL);
351249315Sjhb		if (vr->vr_res == NULL)
352249315Sjhb			vr->vr_res = bus_alloc_resource(dev, type, rid, start,
353249315Sjhb			    end, count, flags);
354249315Sjhb		if (vr->vr_res != NULL)
355249315Sjhb			vr->vr_refs++;
356249315Sjhb		return (vr->vr_res);
357189373Sjhb	}
358153577Sjhb	return (bus_alloc_resource(dev, type, rid, start, end, count, flags));
359153577Sjhb}
360153577Sjhb
361153577Sjhbstatic int
362153577Sjhbvga_pci_release_resource(device_t dev, device_t child, int type, int rid,
363153577Sjhb    struct resource *r)
364153577Sjhb{
365249315Sjhb	struct vga_resource *vr;
366249315Sjhb	int error;
367153577Sjhb
368189373Sjhb	switch (type) {
369189373Sjhb	case SYS_RES_MEMORY:
370189373Sjhb	case SYS_RES_IOPORT:
371189373Sjhb		/*
372189373Sjhb		 * For BARs, we release the resource from the PCI bus
373189373Sjhb		 * when the last child reference goes away.
374189373Sjhb		 */
375249315Sjhb		vr = lookup_res(device_get_softc(dev), rid);
376249315Sjhb		if (vr == NULL)
377189373Sjhb			return (EINVAL);
378249315Sjhb		if (vr->vr_res == NULL)
379189373Sjhb			return (EINVAL);
380249315Sjhb		KASSERT(vr->vr_res == r, ("vga_pci resource mismatch"));
381249315Sjhb		if (vr->vr_refs > 1) {
382249315Sjhb			vr->vr_refs--;
383189373Sjhb			return (0);
384189373Sjhb		}
385249315Sjhb		KASSERT(vr->vr_refs > 0,
386189373Sjhb		    ("vga_pci resource reference count underflow"));
387189373Sjhb		error = bus_release_resource(dev, type, rid, r);
388189373Sjhb		if (error == 0) {
389249315Sjhb			vr->vr_res = NULL;
390249315Sjhb			vr->vr_refs = 0;
391189373Sjhb		}
392189373Sjhb		return (error);
393189373Sjhb	}
394189373Sjhb
395153577Sjhb	return (bus_release_resource(dev, type, rid, r));
396153577Sjhb}
397153577Sjhb
398153577Sjhb/* PCI interface. */
399153577Sjhb
400153577Sjhbstatic uint32_t
401153577Sjhbvga_pci_read_config(device_t dev, device_t child, int reg, int width)
402153577Sjhb{
403153577Sjhb
404153577Sjhb	return (pci_read_config(dev, reg, width));
405153577Sjhb}
406153577Sjhb
407153577Sjhbstatic void
408205018Sjhbvga_pci_write_config(device_t dev, device_t child, int reg,
409153577Sjhb    uint32_t val, int width)
410153577Sjhb{
411153577Sjhb
412153577Sjhb	pci_write_config(dev, reg, val, width);
413153577Sjhb}
414153577Sjhb
415153577Sjhbstatic int
416153577Sjhbvga_pci_enable_busmaster(device_t dev, device_t child)
417153577Sjhb{
418153577Sjhb
419153577Sjhb	return (pci_enable_busmaster(dev));
420153577Sjhb}
421153577Sjhb
422153577Sjhbstatic int
423153577Sjhbvga_pci_disable_busmaster(device_t dev, device_t child)
424153577Sjhb{
425153577Sjhb
426153577Sjhb	return (pci_disable_busmaster(dev));
427153577Sjhb}
428153577Sjhb
429153577Sjhbstatic int
430153577Sjhbvga_pci_enable_io(device_t dev, device_t child, int space)
431153577Sjhb{
432153577Sjhb
433153577Sjhb	device_printf(dev, "child %s requested pci_enable_io\n",
434153577Sjhb	    device_get_nameunit(child));
435153577Sjhb	return (pci_enable_io(dev, space));
436153577Sjhb}
437153577Sjhb
438153577Sjhbstatic int
439153577Sjhbvga_pci_disable_io(device_t dev, device_t child, int space)
440153577Sjhb{
441153577Sjhb
442153577Sjhb	device_printf(dev, "child %s requested pci_disable_io\n",
443153577Sjhb	    device_get_nameunit(child));
444153577Sjhb	return (pci_disable_io(dev, space));
445153577Sjhb}
446153577Sjhb
447153577Sjhbstatic int
448183095Sjhbvga_pci_get_vpd_ident(device_t dev, device_t child, const char **identptr)
449183095Sjhb{
450183095Sjhb
451183095Sjhb	return (pci_get_vpd_ident(dev, identptr));
452183095Sjhb}
453183095Sjhb
454183095Sjhbstatic int
455183095Sjhbvga_pci_get_vpd_readonly(device_t dev, device_t child, const char *kw,
456183095Sjhb    const char **vptr)
457183095Sjhb{
458183095Sjhb
459183095Sjhb	return (pci_get_vpd_readonly(dev, kw, vptr));
460183095Sjhb}
461183095Sjhb
462183095Sjhbstatic int
463153577Sjhbvga_pci_set_powerstate(device_t dev, device_t child, int state)
464153577Sjhb{
465153577Sjhb
466153577Sjhb	device_printf(dev, "child %s requested pci_set_powerstate\n",
467153577Sjhb	    device_get_nameunit(child));
468153577Sjhb	return (pci_set_powerstate(dev, state));
469153577Sjhb}
470153577Sjhb
471153577Sjhbstatic int
472153577Sjhbvga_pci_get_powerstate(device_t dev, device_t child)
473153577Sjhb{
474153577Sjhb
475153577Sjhb	device_printf(dev, "child %s requested pci_get_powerstate\n",
476153577Sjhb	    device_get_nameunit(child));
477153577Sjhb	return (pci_get_powerstate(dev));
478153577Sjhb}
479153577Sjhb
480153577Sjhbstatic int
481153577Sjhbvga_pci_assign_interrupt(device_t dev, device_t child)
482153577Sjhb{
483153577Sjhb
484153577Sjhb	device_printf(dev, "child %s requested pci_assign_interrupt\n",
485153577Sjhb	    device_get_nameunit(child));
486153577Sjhb	return (PCI_ASSIGN_INTERRUPT(device_get_parent(dev), dev));
487153577Sjhb}
488153577Sjhb
489153577Sjhbstatic int
490232472Sjhbvga_pci_find_cap(device_t dev, device_t child, int capability,
491232472Sjhb    int *capreg)
492232472Sjhb{
493232472Sjhb
494232472Sjhb	return (pci_find_cap(dev, capability, capreg));
495232472Sjhb}
496232472Sjhb
497232472Sjhbstatic int
498153577Sjhbvga_pci_find_extcap(device_t dev, device_t child, int capability,
499153577Sjhb    int *capreg)
500153577Sjhb{
501153577Sjhb
502153577Sjhb	return (pci_find_extcap(dev, capability, capreg));
503153577Sjhb}
504153577Sjhb
505183095Sjhbstatic int
506232472Sjhbvga_pci_find_htcap(device_t dev, device_t child, int capability,
507232472Sjhb    int *capreg)
508232472Sjhb{
509232472Sjhb
510232472Sjhb	return (pci_find_htcap(dev, capability, capreg));
511232472Sjhb}
512232472Sjhb
513232472Sjhbstatic int
514183095Sjhbvga_pci_alloc_msi(device_t dev, device_t child, int *count)
515183095Sjhb{
516183095Sjhb	struct vga_pci_softc *sc;
517183095Sjhb	int error;
518183095Sjhb
519183095Sjhb	sc = device_get_softc(dev);
520183095Sjhb	if (sc->vga_msi_child != NULL)
521183095Sjhb		return (EBUSY);
522183095Sjhb	error = pci_alloc_msi(dev, count);
523183095Sjhb	if (error == 0)
524183095Sjhb		sc->vga_msi_child = child;
525183095Sjhb	return (error);
526183095Sjhb}
527183095Sjhb
528183095Sjhbstatic int
529183095Sjhbvga_pci_alloc_msix(device_t dev, device_t child, int *count)
530183095Sjhb{
531183095Sjhb	struct vga_pci_softc *sc;
532183095Sjhb	int error;
533183095Sjhb
534183095Sjhb	sc = device_get_softc(dev);
535183095Sjhb	if (sc->vga_msi_child != NULL)
536183095Sjhb		return (EBUSY);
537183095Sjhb	error = pci_alloc_msix(dev, count);
538183095Sjhb	if (error == 0)
539183095Sjhb		sc->vga_msi_child = child;
540183095Sjhb	return (error);
541183095Sjhb}
542183095Sjhb
543183095Sjhbstatic int
544183095Sjhbvga_pci_remap_msix(device_t dev, device_t child, int count,
545183095Sjhb    const u_int *vectors)
546183095Sjhb{
547183095Sjhb	struct vga_pci_softc *sc;
548183095Sjhb
549183095Sjhb	sc = device_get_softc(dev);
550183095Sjhb	if (sc->vga_msi_child != child)
551183095Sjhb		return (ENXIO);
552183095Sjhb	return (pci_remap_msix(dev, count, vectors));
553183095Sjhb}
554183095Sjhb
555183095Sjhbstatic int
556183095Sjhbvga_pci_release_msi(device_t dev, device_t child)
557183095Sjhb{
558183095Sjhb	struct vga_pci_softc *sc;
559183095Sjhb	int error;
560183095Sjhb
561183095Sjhb	sc = device_get_softc(dev);
562183095Sjhb	if (sc->vga_msi_child != child)
563183095Sjhb		return (ENXIO);
564183095Sjhb	error = pci_release_msi(dev);
565183095Sjhb	if (error == 0)
566183095Sjhb		sc->vga_msi_child = NULL;
567183095Sjhb	return (error);
568183095Sjhb}
569183095Sjhb
570183095Sjhbstatic int
571183095Sjhbvga_pci_msi_count(device_t dev, device_t child)
572183095Sjhb{
573183095Sjhb
574183095Sjhb	return (pci_msi_count(dev));
575183095Sjhb}
576183095Sjhb
577183095Sjhbstatic int
578183095Sjhbvga_pci_msix_count(device_t dev, device_t child)
579183095Sjhb{
580183095Sjhb
581183095Sjhb	return (pci_msix_count(dev));
582183095Sjhb}
583183095Sjhb
584249476Skibstatic bus_dma_tag_t
585249476Skibvga_pci_get_dma_tag(device_t bus, device_t child)
586249476Skib{
587249476Skib
588249476Skib	return (bus_get_dma_tag(bus));
589249476Skib}
590249476Skib
591153577Sjhbstatic device_method_t vga_pci_methods[] = {
592153577Sjhb	/* Device interface */
593153577Sjhb	DEVMETHOD(device_probe,		vga_pci_probe),
594153577Sjhb	DEVMETHOD(device_attach,	vga_pci_attach),
595153577Sjhb	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
596153577Sjhb	DEVMETHOD(device_suspend,	vga_pci_suspend),
597153577Sjhb	DEVMETHOD(device_resume,	vga_pci_resume),
598153577Sjhb
599153577Sjhb	/* Bus interface */
600153577Sjhb	DEVMETHOD(bus_read_ivar,	vga_pci_read_ivar),
601153577Sjhb	DEVMETHOD(bus_write_ivar,	vga_pci_write_ivar),
602183194Srnoland	DEVMETHOD(bus_setup_intr,	vga_pci_setup_intr),
603183194Srnoland	DEVMETHOD(bus_teardown_intr,	vga_pci_teardown_intr),
604153577Sjhb	DEVMETHOD(bus_alloc_resource,	vga_pci_alloc_resource),
605153577Sjhb	DEVMETHOD(bus_release_resource,	vga_pci_release_resource),
606153577Sjhb	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
607153577Sjhb	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
608249476Skib	DEVMETHOD(bus_get_dma_tag,	vga_pci_get_dma_tag),
609153577Sjhb
610153577Sjhb	/* PCI interface */
611153577Sjhb	DEVMETHOD(pci_read_config,	vga_pci_read_config),
612153577Sjhb	DEVMETHOD(pci_write_config,	vga_pci_write_config),
613153577Sjhb	DEVMETHOD(pci_enable_busmaster,	vga_pci_enable_busmaster),
614153577Sjhb	DEVMETHOD(pci_disable_busmaster, vga_pci_disable_busmaster),
615153577Sjhb	DEVMETHOD(pci_enable_io,	vga_pci_enable_io),
616153577Sjhb	DEVMETHOD(pci_disable_io,	vga_pci_disable_io),
617183095Sjhb	DEVMETHOD(pci_get_vpd_ident,	vga_pci_get_vpd_ident),
618183095Sjhb	DEVMETHOD(pci_get_vpd_readonly,	vga_pci_get_vpd_readonly),
619153577Sjhb	DEVMETHOD(pci_get_powerstate,	vga_pci_get_powerstate),
620153577Sjhb	DEVMETHOD(pci_set_powerstate,	vga_pci_set_powerstate),
621153577Sjhb	DEVMETHOD(pci_assign_interrupt,	vga_pci_assign_interrupt),
622232472Sjhb	DEVMETHOD(pci_find_cap,		vga_pci_find_cap),
623153577Sjhb	DEVMETHOD(pci_find_extcap,	vga_pci_find_extcap),
624232472Sjhb	DEVMETHOD(pci_find_htcap,	vga_pci_find_htcap),
625183095Sjhb	DEVMETHOD(pci_alloc_msi,	vga_pci_alloc_msi),
626183095Sjhb	DEVMETHOD(pci_alloc_msix,	vga_pci_alloc_msix),
627183095Sjhb	DEVMETHOD(pci_remap_msix,	vga_pci_remap_msix),
628183095Sjhb	DEVMETHOD(pci_release_msi,	vga_pci_release_msi),
629183095Sjhb	DEVMETHOD(pci_msi_count,	vga_pci_msi_count),
630183095Sjhb	DEVMETHOD(pci_msix_count,	vga_pci_msix_count),
631153577Sjhb
632153577Sjhb	{ 0, 0 }
633153577Sjhb};
634153577Sjhb
635153577Sjhbstatic driver_t vga_pci_driver = {
636153577Sjhb	"vgapci",
637153577Sjhb	vga_pci_methods,
638183095Sjhb	sizeof(struct vga_pci_softc),
639153577Sjhb};
640153577Sjhb
641153577Sjhbstatic devclass_t vga_devclass;
642153577Sjhb
643153577SjhbDRIVER_MODULE(vgapci, pci, vga_pci_driver, vga_devclass, 0, 0);
644279494SdumbbellMODULE_DEPEND(vgapci, x86bios, 1, 1, 1);
645