1153577Sjhb/*-
2153577Sjhb * Copyright (c) 2005 John Baldwin <jhb@FreeBSD.org>
3153577Sjhb *
4153577Sjhb * Redistribution and use in source and binary forms, with or without
5153577Sjhb * modification, are permitted provided that the following conditions
6153577Sjhb * are met:
7153577Sjhb * 1. Redistributions of source code must retain the above copyright
8153577Sjhb *    notice, this list of conditions and the following disclaimer.
9153577Sjhb * 2. Redistributions in binary form must reproduce the above copyright
10153577Sjhb *    notice, this list of conditions and the following disclaimer in the
11153577Sjhb *    documentation and/or other materials provided with the distribution.
12153577Sjhb *
13153577Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14153577Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15153577Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16153577Sjhb * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17153577Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18153577Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19153577Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20153577Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21153577Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22153577Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23153577Sjhb * SUCH DAMAGE.
24153577Sjhb */
25153577Sjhb
26153577Sjhb#include <sys/cdefs.h>
27153577Sjhb__FBSDID("$FreeBSD: stable/11/sys/dev/pci/vga_pci.c 367457 2020-11-07 18:10:59Z dim $");
28153577Sjhb
29153577Sjhb/*
30153577Sjhb * Simple driver for PCI VGA display devices.  Drivers such as agp(4) and
31153577Sjhb * drm(4) should attach as children of this device.
32153577Sjhb *
33153577Sjhb * XXX: The vgapci name is a hack until we somehow merge the isa vga driver
34153577Sjhb * in or rename it.
35153577Sjhb */
36153577Sjhb
37153577Sjhb#include <sys/param.h>
38153577Sjhb#include <sys/bus.h>
39153577Sjhb#include <sys/kernel.h>
40153577Sjhb#include <sys/module.h>
41189373Sjhb#include <sys/rman.h>
42198251Sjkim#include <sys/sysctl.h>
43189373Sjhb#include <sys/systm.h>
44153577Sjhb
45268351Smarcel#if defined(__amd64__) || defined(__i386__)
46254882Sdumbbell#include <vm/vm.h>
47254882Sdumbbell#include <vm/pmap.h>
48254882Sdumbbell#endif
49254882Sdumbbell
50153577Sjhb#include <dev/pci/pcireg.h>
51153577Sjhb#include <dev/pci/pcivar.h>
52153577Sjhb
53279487Sdumbbell#include <compat/x86bios/x86bios.h> /* To re-POST the card. */
54279487Sdumbbell
55189373Sjhbstruct vga_resource {
56189373Sjhb	struct resource	*vr_res;
57189373Sjhb	int	vr_refs;
58189373Sjhb};
59189373Sjhb
60183095Sjhbstruct vga_pci_softc {
61183095Sjhb	device_t	vga_msi_child;	/* Child driver using MSI. */
62249315Sjhb	struct vga_resource vga_bars[PCIR_MAX_BAR_0 + 1];
63249315Sjhb	struct vga_resource vga_bios;
64183095Sjhb};
65183095Sjhb
66198251SjkimSYSCTL_DECL(_hw_pci);
67198251Sjkim
68255571Sdumbbellstatic struct vga_resource *lookup_res(struct vga_pci_softc *sc, int rid);
69255571Sdumbbellstatic struct resource *vga_pci_alloc_resource(device_t dev, device_t child,
70294883Sjhibbits    int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count,
71294883Sjhibbits    u_int flags);
72255571Sdumbbellstatic int	vga_pci_release_resource(device_t dev, device_t child, int type,
73255571Sdumbbell    int rid, struct resource *r);
74255571Sdumbbell
75198251Sjkimint vga_pci_default_unit = -1;
76198964SjkimSYSCTL_INT(_hw_pci, OID_AUTO, default_vgapci_unit, CTLFLAG_RDTUN,
77198251Sjkim    &vga_pci_default_unit, -1, "Default VGA-compatible display");
78198251Sjkim
79254882Sdumbbellint
80254882Sdumbbellvga_pci_is_boot_display(device_t dev)
81254882Sdumbbell{
82259679Sdumbbell	int unit;
83259679Sdumbbell	device_t pcib;
84259679Sdumbbell	uint16_t config;
85254882Sdumbbell
86259679Sdumbbell	/* Check that the given device is a video card */
87259679Sdumbbell	if ((pci_get_class(dev) != PCIC_DISPLAY &&
88259679Sdumbbell	    (pci_get_class(dev) != PCIC_OLD ||
89259679Sdumbbell	     pci_get_subclass(dev) != PCIS_OLD_VGA)))
90259679Sdumbbell		return (0);
91259679Sdumbbell
92259679Sdumbbell	unit = device_get_unit(dev);
93259679Sdumbbell
94259679Sdumbbell	if (vga_pci_default_unit >= 0) {
95259679Sdumbbell		/*
96259679Sdumbbell		 * The boot display device was determined by a previous
97259679Sdumbbell		 * call to this function, or the user forced it using
98259679Sdumbbell		 * the hw.pci.default_vgapci_unit tunable.
99259679Sdumbbell		 */
100259679Sdumbbell		return (vga_pci_default_unit == unit);
101259679Sdumbbell	}
102259679Sdumbbell
103254882Sdumbbell	/*
104259679Sdumbbell	 * The primary video card used as a boot display must have the
105259679Sdumbbell	 * "I/O" and "Memory Address Space Decoding" bits set in its
106259679Sdumbbell	 * Command register.
107259679Sdumbbell	 *
108259679Sdumbbell	 * Furthermore, if the card is attached to a bridge, instead of
109259679Sdumbbell	 * the root PCI bus, the bridge must have the "VGA Enable" bit
110259679Sdumbbell	 * set in its Control register.
111254882Sdumbbell	 */
112259679Sdumbbell
113259679Sdumbbell	pcib = device_get_parent(device_get_parent(dev));
114259679Sdumbbell	if (device_get_devclass(device_get_parent(pcib)) ==
115259679Sdumbbell	    devclass_find("pci")) {
116259679Sdumbbell		/*
117259679Sdumbbell		 * The parent bridge is a PCI-to-PCI bridge: check the
118259679Sdumbbell		 * value of the "VGA Enable" bit.
119259679Sdumbbell		 */
120259679Sdumbbell		config = pci_read_config(pcib, PCIR_BRIDGECTL_1, 2);
121259679Sdumbbell		if ((config & PCIB_BCR_VGA_ENABLE) == 0)
122259679Sdumbbell			return (0);
123259679Sdumbbell	}
124259679Sdumbbell
125259679Sdumbbell	config = pci_read_config(dev, PCIR_COMMAND, 2);
126259679Sdumbbell	if ((config & (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN)) == 0)
127259679Sdumbbell		return (0);
128259679Sdumbbell
129284012Shselasky	/*
130284012Shselasky	 * Disable interrupts until a chipset driver is loaded for
131284012Shselasky	 * this PCI device. Else unhandled display adapter interrupts
132284012Shselasky	 * might freeze the CPU.
133284012Shselasky	 */
134284012Shselasky	pci_write_config(dev, PCIR_COMMAND, config | PCIM_CMD_INTxDIS, 2);
135284012Shselasky
136259679Sdumbbell	/* This video card is the boot display: record its unit number. */
137259679Sdumbbell	vga_pci_default_unit = unit;
138259679Sdumbbell	device_set_flags(dev, 1);
139259679Sdumbbell
140259679Sdumbbell	return (1);
141254882Sdumbbell}
142254882Sdumbbell
143254882Sdumbbellvoid *
144254882Sdumbbellvga_pci_map_bios(device_t dev, size_t *size)
145254882Sdumbbell{
146254882Sdumbbell	int rid;
147254882Sdumbbell	struct resource *res;
148254882Sdumbbell
149268351Smarcel#if defined(__amd64__) || defined(__i386__)
150254882Sdumbbell	if (vga_pci_is_boot_display(dev)) {
151254882Sdumbbell		/*
152254882Sdumbbell		 * On x86, the System BIOS copy the default display
153254882Sdumbbell		 * device's Video BIOS at a fixed location in system
154254882Sdumbbell		 * memory (0xC0000, 128 kBytes long) at boot time.
155254882Sdumbbell		 *
156254882Sdumbbell		 * We use this copy for the default boot device, because
157254882Sdumbbell		 * the original ROM may not be valid after boot.
158254882Sdumbbell		 */
159254882Sdumbbell
160254882Sdumbbell		*size = VGA_PCI_BIOS_SHADOW_SIZE;
161254882Sdumbbell		return (pmap_mapbios(VGA_PCI_BIOS_SHADOW_ADDR, *size));
162254882Sdumbbell	}
163254882Sdumbbell#endif
164254882Sdumbbell
165254882Sdumbbell	rid = PCIR_BIOS;
166296336Sjhibbits	res = vga_pci_alloc_resource(dev, NULL, SYS_RES_MEMORY, &rid, 0,
167296336Sjhibbits	    ~0, 1, RF_ACTIVE);
168254882Sdumbbell	if (res == NULL) {
169254882Sdumbbell		return (NULL);
170254882Sdumbbell	}
171254882Sdumbbell
172254882Sdumbbell	*size = rman_get_size(res);
173254882Sdumbbell	return (rman_get_virtual(res));
174254882Sdumbbell}
175254882Sdumbbell
176254882Sdumbbellvoid
177254882Sdumbbellvga_pci_unmap_bios(device_t dev, void *bios)
178254882Sdumbbell{
179255571Sdumbbell	struct vga_resource *vr;
180254882Sdumbbell
181254882Sdumbbell	if (bios == NULL) {
182254882Sdumbbell		return;
183254882Sdumbbell	}
184254882Sdumbbell
185268351Smarcel#if defined(__amd64__) || defined(__i386__)
186254882Sdumbbell	if (vga_pci_is_boot_display(dev)) {
187254882Sdumbbell		/* We mapped the BIOS shadow copy located at 0xC0000. */
188254882Sdumbbell		pmap_unmapdev((vm_offset_t)bios, VGA_PCI_BIOS_SHADOW_SIZE);
189254882Sdumbbell
190254882Sdumbbell		return;
191254882Sdumbbell	}
192254882Sdumbbell#endif
193254882Sdumbbell
194254882Sdumbbell	/*
195255571Sdumbbell	 * Look up the PCIR_BIOS resource in our softc.  It should match
196255571Sdumbbell	 * the address we returned previously.
197254882Sdumbbell	 */
198255571Sdumbbell	vr = lookup_res(device_get_softc(dev), PCIR_BIOS);
199255571Sdumbbell	KASSERT(vr->vr_res != NULL, ("vga_pci_unmap_bios: bios not mapped"));
200255571Sdumbbell	KASSERT(rman_get_virtual(vr->vr_res) == bios,
201255571Sdumbbell	    ("vga_pci_unmap_bios: mismatch"));
202255571Sdumbbell	vga_pci_release_resource(dev, NULL, SYS_RES_MEMORY, PCIR_BIOS,
203255571Sdumbbell	    vr->vr_res);
204254882Sdumbbell}
205254882Sdumbbell
206279487Sdumbbellint
207279487Sdumbbellvga_pci_repost(device_t dev)
208279487Sdumbbell{
209279494Sdumbbell#if defined(__amd64__) || (defined(__i386__) && !defined(PC98))
210279487Sdumbbell	x86regs_t regs;
211279487Sdumbbell
212279487Sdumbbell	if (!vga_pci_is_boot_display(dev))
213279487Sdumbbell		return (EINVAL);
214279487Sdumbbell
215279487Sdumbbell	if (x86bios_get_orm(VGA_PCI_BIOS_SHADOW_ADDR) == NULL)
216279487Sdumbbell		return (ENOTSUP);
217279487Sdumbbell
218279487Sdumbbell	x86bios_init_regs(&regs);
219279487Sdumbbell
220279487Sdumbbell	regs.R_AH = pci_get_bus(dev);
221279487Sdumbbell	regs.R_AL = (pci_get_slot(dev) << 3) | (pci_get_function(dev) & 0x07);
222279487Sdumbbell	regs.R_DL = 0x80;
223279487Sdumbbell
224279487Sdumbbell	device_printf(dev, "REPOSTing\n");
225279487Sdumbbell	x86bios_call(&regs, X86BIOS_PHYSTOSEG(VGA_PCI_BIOS_SHADOW_ADDR + 3),
226279487Sdumbbell	    X86BIOS_PHYSTOOFF(VGA_PCI_BIOS_SHADOW_ADDR + 3));
227279487Sdumbbell
228279487Sdumbbell	x86bios_get_intr(0x10);
229279487Sdumbbell
230279487Sdumbbell	return (0);
231279487Sdumbbell#else
232279487Sdumbbell	return (ENOTSUP);
233279487Sdumbbell#endif
234279487Sdumbbell}
235279487Sdumbbell
236153577Sjhbstatic int
237153577Sjhbvga_pci_probe(device_t dev)
238153577Sjhb{
239153577Sjhb
240153577Sjhb	switch (pci_get_class(dev)) {
241153577Sjhb	case PCIC_DISPLAY:
242153577Sjhb		break;
243153577Sjhb	case PCIC_OLD:
244153577Sjhb		if (pci_get_subclass(dev) != PCIS_OLD_VGA)
245153577Sjhb			return (ENXIO);
246153577Sjhb		break;
247153577Sjhb	default:
248153577Sjhb		return (ENXIO);
249153577Sjhb	}
250198251Sjkim
251198251Sjkim	/* Probe default display. */
252259679Sdumbbell	vga_pci_is_boot_display(dev);
253198251Sjkim
254153577Sjhb	device_set_desc(dev, "VGA-compatible display");
255153646Sjhb	return (BUS_PROBE_GENERIC);
256153577Sjhb}
257153577Sjhb
258153577Sjhbstatic int
259153577Sjhbvga_pci_attach(device_t dev)
260153577Sjhb{
261153577Sjhb
262153577Sjhb	bus_generic_probe(dev);
263153577Sjhb
264153577Sjhb	/* Always create a drm child for now to make it easier on drm. */
265153577Sjhb	device_add_child(dev, "drm", -1);
266235846Skib	device_add_child(dev, "drmn", -1);
267153577Sjhb	bus_generic_attach(dev);
268259679Sdumbbell
269259679Sdumbbell	if (vga_pci_is_boot_display(dev))
270259679Sdumbbell		device_printf(dev, "Boot video device\n");
271259679Sdumbbell
272153577Sjhb	return (0);
273153577Sjhb}
274153577Sjhb
275153577Sjhbstatic int
276153577Sjhbvga_pci_suspend(device_t dev)
277153577Sjhb{
278153577Sjhb
279199002Sjkim	return (bus_generic_suspend(dev));
280153577Sjhb}
281153577Sjhb
282153577Sjhbstatic int
283153577Sjhbvga_pci_resume(device_t dev)
284153577Sjhb{
285153577Sjhb
286153577Sjhb	return (bus_generic_resume(dev));
287153577Sjhb}
288153577Sjhb
289153577Sjhb/* Bus interface. */
290153577Sjhb
291153577Sjhbstatic int
292153577Sjhbvga_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
293153577Sjhb{
294153577Sjhb
295153577Sjhb	return (BUS_READ_IVAR(device_get_parent(dev), dev, which, result));
296153577Sjhb}
297153577Sjhb
298153577Sjhbstatic int
299153577Sjhbvga_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
300153577Sjhb{
301153577Sjhb
302153577Sjhb	return (EINVAL);
303153577Sjhb}
304153577Sjhb
305183194Srnolandstatic int
306183194Srnolandvga_pci_setup_intr(device_t dev, device_t child, struct resource *irq,
307183194Srnoland    int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg,
308183194Srnoland    void **cookiep)
309183194Srnoland{
310183194Srnoland	return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags,
311183194Srnoland	    filter, intr, arg, cookiep));
312183194Srnoland}
313183194Srnoland
314183194Srnolandstatic int
315183194Srnolandvga_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
316183194Srnoland    void *cookie)
317183194Srnoland{
318183194Srnoland	return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie));
319183194Srnoland}
320183194Srnoland
321249315Sjhbstatic struct vga_resource *
322249315Sjhblookup_res(struct vga_pci_softc *sc, int rid)
323249315Sjhb{
324249315Sjhb	int bar;
325249315Sjhb
326249315Sjhb	if (rid == PCIR_BIOS)
327249315Sjhb		return (&sc->vga_bios);
328249315Sjhb	bar = PCI_RID2BAR(rid);
329249315Sjhb	if (bar >= 0 && bar <= PCIR_MAX_BAR_0)
330249315Sjhb		return (&sc->vga_bars[bar]);
331249315Sjhb	return (NULL);
332249315Sjhb}
333249315Sjhb
334153577Sjhbstatic struct resource *
335153577Sjhbvga_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
336294883Sjhibbits    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
337153577Sjhb{
338249315Sjhb	struct vga_resource *vr;
339153577Sjhb
340189373Sjhb	switch (type) {
341189373Sjhb	case SYS_RES_MEMORY:
342189373Sjhb	case SYS_RES_IOPORT:
343189373Sjhb		/*
344189373Sjhb		 * For BARs, we cache the resource so that we only allocate it
345189373Sjhb		 * from the PCI bus once.
346189373Sjhb		 */
347249315Sjhb		vr = lookup_res(device_get_softc(dev), *rid);
348249315Sjhb		if (vr == NULL)
349189373Sjhb			return (NULL);
350249315Sjhb		if (vr->vr_res == NULL)
351249315Sjhb			vr->vr_res = bus_alloc_resource(dev, type, rid, start,
352249315Sjhb			    end, count, flags);
353249315Sjhb		if (vr->vr_res != NULL)
354249315Sjhb			vr->vr_refs++;
355249315Sjhb		return (vr->vr_res);
356189373Sjhb	}
357153577Sjhb	return (bus_alloc_resource(dev, type, rid, start, end, count, flags));
358153577Sjhb}
359153577Sjhb
360153577Sjhbstatic int
361153577Sjhbvga_pci_release_resource(device_t dev, device_t child, int type, int rid,
362153577Sjhb    struct resource *r)
363153577Sjhb{
364249315Sjhb	struct vga_resource *vr;
365249315Sjhb	int error;
366153577Sjhb
367189373Sjhb	switch (type) {
368189373Sjhb	case SYS_RES_MEMORY:
369189373Sjhb	case SYS_RES_IOPORT:
370189373Sjhb		/*
371189373Sjhb		 * For BARs, we release the resource from the PCI bus
372189373Sjhb		 * when the last child reference goes away.
373189373Sjhb		 */
374249315Sjhb		vr = lookup_res(device_get_softc(dev), rid);
375249315Sjhb		if (vr == NULL)
376189373Sjhb			return (EINVAL);
377249315Sjhb		if (vr->vr_res == NULL)
378189373Sjhb			return (EINVAL);
379249315Sjhb		KASSERT(vr->vr_res == r, ("vga_pci resource mismatch"));
380249315Sjhb		if (vr->vr_refs > 1) {
381249315Sjhb			vr->vr_refs--;
382189373Sjhb			return (0);
383189373Sjhb		}
384249315Sjhb		KASSERT(vr->vr_refs > 0,
385189373Sjhb		    ("vga_pci resource reference count underflow"));
386189373Sjhb		error = bus_release_resource(dev, type, rid, r);
387189373Sjhb		if (error == 0) {
388249315Sjhb			vr->vr_res = NULL;
389249315Sjhb			vr->vr_refs = 0;
390189373Sjhb		}
391189373Sjhb		return (error);
392189373Sjhb	}
393189373Sjhb
394153577Sjhb	return (bus_release_resource(dev, type, rid, r));
395153577Sjhb}
396153577Sjhb
397153577Sjhb/* PCI interface. */
398153577Sjhb
399153577Sjhbstatic uint32_t
400153577Sjhbvga_pci_read_config(device_t dev, device_t child, int reg, int width)
401153577Sjhb{
402153577Sjhb
403153577Sjhb	return (pci_read_config(dev, reg, width));
404153577Sjhb}
405153577Sjhb
406153577Sjhbstatic void
407205018Sjhbvga_pci_write_config(device_t dev, device_t child, int reg,
408153577Sjhb    uint32_t val, int width)
409153577Sjhb{
410153577Sjhb
411153577Sjhb	pci_write_config(dev, reg, val, width);
412153577Sjhb}
413153577Sjhb
414153577Sjhbstatic int
415153577Sjhbvga_pci_enable_busmaster(device_t dev, device_t child)
416153577Sjhb{
417153577Sjhb
418153577Sjhb	return (pci_enable_busmaster(dev));
419153577Sjhb}
420153577Sjhb
421153577Sjhbstatic int
422153577Sjhbvga_pci_disable_busmaster(device_t dev, device_t child)
423153577Sjhb{
424153577Sjhb
425153577Sjhb	return (pci_disable_busmaster(dev));
426153577Sjhb}
427153577Sjhb
428153577Sjhbstatic int
429153577Sjhbvga_pci_enable_io(device_t dev, device_t child, int space)
430153577Sjhb{
431153577Sjhb
432153577Sjhb	device_printf(dev, "child %s requested pci_enable_io\n",
433153577Sjhb	    device_get_nameunit(child));
434153577Sjhb	return (pci_enable_io(dev, space));
435153577Sjhb}
436153577Sjhb
437153577Sjhbstatic int
438153577Sjhbvga_pci_disable_io(device_t dev, device_t child, int space)
439153577Sjhb{
440153577Sjhb
441153577Sjhb	device_printf(dev, "child %s requested pci_disable_io\n",
442153577Sjhb	    device_get_nameunit(child));
443153577Sjhb	return (pci_disable_io(dev, space));
444153577Sjhb}
445153577Sjhb
446153577Sjhbstatic int
447183095Sjhbvga_pci_get_vpd_ident(device_t dev, device_t child, const char **identptr)
448183095Sjhb{
449183095Sjhb
450183095Sjhb	return (pci_get_vpd_ident(dev, identptr));
451183095Sjhb}
452183095Sjhb
453183095Sjhbstatic int
454183095Sjhbvga_pci_get_vpd_readonly(device_t dev, device_t child, const char *kw,
455183095Sjhb    const char **vptr)
456183095Sjhb{
457183095Sjhb
458183095Sjhb	return (pci_get_vpd_readonly(dev, kw, vptr));
459183095Sjhb}
460183095Sjhb
461183095Sjhbstatic int
462153577Sjhbvga_pci_set_powerstate(device_t dev, device_t child, int state)
463153577Sjhb{
464153577Sjhb
465153577Sjhb	device_printf(dev, "child %s requested pci_set_powerstate\n",
466153577Sjhb	    device_get_nameunit(child));
467153577Sjhb	return (pci_set_powerstate(dev, state));
468153577Sjhb}
469153577Sjhb
470153577Sjhbstatic int
471153577Sjhbvga_pci_get_powerstate(device_t dev, device_t child)
472153577Sjhb{
473153577Sjhb
474153577Sjhb	device_printf(dev, "child %s requested pci_get_powerstate\n",
475153577Sjhb	    device_get_nameunit(child));
476153577Sjhb	return (pci_get_powerstate(dev));
477153577Sjhb}
478153577Sjhb
479153577Sjhbstatic int
480153577Sjhbvga_pci_assign_interrupt(device_t dev, device_t child)
481153577Sjhb{
482153577Sjhb
483153577Sjhb	device_printf(dev, "child %s requested pci_assign_interrupt\n",
484153577Sjhb	    device_get_nameunit(child));
485153577Sjhb	return (PCI_ASSIGN_INTERRUPT(device_get_parent(dev), dev));
486153577Sjhb}
487153577Sjhb
488153577Sjhbstatic int
489232472Sjhbvga_pci_find_cap(device_t dev, device_t child, int capability,
490232472Sjhb    int *capreg)
491232472Sjhb{
492232472Sjhb
493232472Sjhb	return (pci_find_cap(dev, capability, capreg));
494232472Sjhb}
495232472Sjhb
496232472Sjhbstatic int
497331111Sbryanvvga_pci_find_next_cap(device_t dev, device_t child, int capability,
498331111Sbryanv    int start, int *capreg)
499331111Sbryanv{
500331111Sbryanv
501331111Sbryanv	return (pci_find_next_cap(dev, capability, start, capreg));
502331111Sbryanv}
503331111Sbryanv
504331111Sbryanvstatic int
505153577Sjhbvga_pci_find_extcap(device_t dev, device_t child, int capability,
506153577Sjhb    int *capreg)
507153577Sjhb{
508153577Sjhb
509153577Sjhb	return (pci_find_extcap(dev, capability, capreg));
510153577Sjhb}
511153577Sjhb
512183095Sjhbstatic int
513331111Sbryanvvga_pci_find_next_extcap(device_t dev, device_t child, int capability,
514331111Sbryanv    int start, int *capreg)
515331111Sbryanv{
516331111Sbryanv
517331111Sbryanv	return (pci_find_next_extcap(dev, capability, start, capreg));
518331111Sbryanv}
519331111Sbryanv
520331111Sbryanvstatic int
521232472Sjhbvga_pci_find_htcap(device_t dev, device_t child, int capability,
522232472Sjhb    int *capreg)
523232472Sjhb{
524232472Sjhb
525232472Sjhb	return (pci_find_htcap(dev, capability, capreg));
526232472Sjhb}
527232472Sjhb
528232472Sjhbstatic int
529331111Sbryanvvga_pci_find_next_htcap(device_t dev, device_t child, int capability,
530331111Sbryanv    int start, int *capreg)
531331111Sbryanv{
532331111Sbryanv
533331111Sbryanv	return (pci_find_next_htcap(dev, capability, start, capreg));
534331111Sbryanv}
535331111Sbryanv
536331111Sbryanvstatic int
537183095Sjhbvga_pci_alloc_msi(device_t dev, device_t child, int *count)
538183095Sjhb{
539183095Sjhb	struct vga_pci_softc *sc;
540183095Sjhb	int error;
541183095Sjhb
542183095Sjhb	sc = device_get_softc(dev);
543183095Sjhb	if (sc->vga_msi_child != NULL)
544183095Sjhb		return (EBUSY);
545183095Sjhb	error = pci_alloc_msi(dev, count);
546183095Sjhb	if (error == 0)
547183095Sjhb		sc->vga_msi_child = child;
548183095Sjhb	return (error);
549183095Sjhb}
550183095Sjhb
551183095Sjhbstatic int
552183095Sjhbvga_pci_alloc_msix(device_t dev, device_t child, int *count)
553183095Sjhb{
554183095Sjhb	struct vga_pci_softc *sc;
555183095Sjhb	int error;
556183095Sjhb
557183095Sjhb	sc = device_get_softc(dev);
558183095Sjhb	if (sc->vga_msi_child != NULL)
559183095Sjhb		return (EBUSY);
560183095Sjhb	error = pci_alloc_msix(dev, count);
561183095Sjhb	if (error == 0)
562183095Sjhb		sc->vga_msi_child = child;
563183095Sjhb	return (error);
564183095Sjhb}
565183095Sjhb
566183095Sjhbstatic int
567183095Sjhbvga_pci_remap_msix(device_t dev, device_t child, int count,
568183095Sjhb    const u_int *vectors)
569183095Sjhb{
570183095Sjhb	struct vga_pci_softc *sc;
571183095Sjhb
572183095Sjhb	sc = device_get_softc(dev);
573183095Sjhb	if (sc->vga_msi_child != child)
574183095Sjhb		return (ENXIO);
575183095Sjhb	return (pci_remap_msix(dev, count, vectors));
576183095Sjhb}
577183095Sjhb
578183095Sjhbstatic int
579183095Sjhbvga_pci_release_msi(device_t dev, device_t child)
580183095Sjhb{
581183095Sjhb	struct vga_pci_softc *sc;
582183095Sjhb	int error;
583183095Sjhb
584183095Sjhb	sc = device_get_softc(dev);
585183095Sjhb	if (sc->vga_msi_child != child)
586183095Sjhb		return (ENXIO);
587183095Sjhb	error = pci_release_msi(dev);
588183095Sjhb	if (error == 0)
589183095Sjhb		sc->vga_msi_child = NULL;
590183095Sjhb	return (error);
591183095Sjhb}
592183095Sjhb
593183095Sjhbstatic int
594183095Sjhbvga_pci_msi_count(device_t dev, device_t child)
595183095Sjhb{
596183095Sjhb
597183095Sjhb	return (pci_msi_count(dev));
598183095Sjhb}
599183095Sjhb
600183095Sjhbstatic int
601183095Sjhbvga_pci_msix_count(device_t dev, device_t child)
602183095Sjhb{
603183095Sjhb
604183095Sjhb	return (pci_msix_count(dev));
605183095Sjhb}
606183095Sjhb
607249476Skibstatic bus_dma_tag_t
608249476Skibvga_pci_get_dma_tag(device_t bus, device_t child)
609249476Skib{
610249476Skib
611249476Skib	return (bus_get_dma_tag(bus));
612249476Skib}
613249476Skib
614153577Sjhbstatic device_method_t vga_pci_methods[] = {
615153577Sjhb	/* Device interface */
616153577Sjhb	DEVMETHOD(device_probe,		vga_pci_probe),
617153577Sjhb	DEVMETHOD(device_attach,	vga_pci_attach),
618153577Sjhb	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
619153577Sjhb	DEVMETHOD(device_suspend,	vga_pci_suspend),
620153577Sjhb	DEVMETHOD(device_resume,	vga_pci_resume),
621153577Sjhb
622153577Sjhb	/* Bus interface */
623153577Sjhb	DEVMETHOD(bus_read_ivar,	vga_pci_read_ivar),
624153577Sjhb	DEVMETHOD(bus_write_ivar,	vga_pci_write_ivar),
625183194Srnoland	DEVMETHOD(bus_setup_intr,	vga_pci_setup_intr),
626183194Srnoland	DEVMETHOD(bus_teardown_intr,	vga_pci_teardown_intr),
627153577Sjhb	DEVMETHOD(bus_alloc_resource,	vga_pci_alloc_resource),
628153577Sjhb	DEVMETHOD(bus_release_resource,	vga_pci_release_resource),
629153577Sjhb	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
630153577Sjhb	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
631249476Skib	DEVMETHOD(bus_get_dma_tag,	vga_pci_get_dma_tag),
632153577Sjhb
633153577Sjhb	/* PCI interface */
634153577Sjhb	DEVMETHOD(pci_read_config,	vga_pci_read_config),
635153577Sjhb	DEVMETHOD(pci_write_config,	vga_pci_write_config),
636153577Sjhb	DEVMETHOD(pci_enable_busmaster,	vga_pci_enable_busmaster),
637153577Sjhb	DEVMETHOD(pci_disable_busmaster, vga_pci_disable_busmaster),
638153577Sjhb	DEVMETHOD(pci_enable_io,	vga_pci_enable_io),
639153577Sjhb	DEVMETHOD(pci_disable_io,	vga_pci_disable_io),
640183095Sjhb	DEVMETHOD(pci_get_vpd_ident,	vga_pci_get_vpd_ident),
641183095Sjhb	DEVMETHOD(pci_get_vpd_readonly,	vga_pci_get_vpd_readonly),
642153577Sjhb	DEVMETHOD(pci_get_powerstate,	vga_pci_get_powerstate),
643153577Sjhb	DEVMETHOD(pci_set_powerstate,	vga_pci_set_powerstate),
644153577Sjhb	DEVMETHOD(pci_assign_interrupt,	vga_pci_assign_interrupt),
645232472Sjhb	DEVMETHOD(pci_find_cap,		vga_pci_find_cap),
646331111Sbryanv	DEVMETHOD(pci_find_next_cap,	vga_pci_find_next_cap),
647153577Sjhb	DEVMETHOD(pci_find_extcap,	vga_pci_find_extcap),
648331111Sbryanv	DEVMETHOD(pci_find_next_extcap,	vga_pci_find_next_extcap),
649232472Sjhb	DEVMETHOD(pci_find_htcap,	vga_pci_find_htcap),
650331111Sbryanv	DEVMETHOD(pci_find_next_htcap,	vga_pci_find_next_htcap),
651183095Sjhb	DEVMETHOD(pci_alloc_msi,	vga_pci_alloc_msi),
652183095Sjhb	DEVMETHOD(pci_alloc_msix,	vga_pci_alloc_msix),
653183095Sjhb	DEVMETHOD(pci_remap_msix,	vga_pci_remap_msix),
654183095Sjhb	DEVMETHOD(pci_release_msi,	vga_pci_release_msi),
655183095Sjhb	DEVMETHOD(pci_msi_count,	vga_pci_msi_count),
656183095Sjhb	DEVMETHOD(pci_msix_count,	vga_pci_msix_count),
657153577Sjhb
658153577Sjhb	{ 0, 0 }
659153577Sjhb};
660153577Sjhb
661153577Sjhbstatic driver_t vga_pci_driver = {
662153577Sjhb	"vgapci",
663153577Sjhb	vga_pci_methods,
664183095Sjhb	sizeof(struct vga_pci_softc),
665153577Sjhb};
666153577Sjhb
667153577Sjhbstatic devclass_t vga_devclass;
668153577Sjhb
669153577SjhbDRIVER_MODULE(vgapci, pci, vga_pci_driver, vga_devclass, 0, 0);
670279494SdumbbellMODULE_DEPEND(vgapci, x86bios, 1, 1, 1);
671