vga_pci.c revision 279487
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 279487 2015-03-01 12:47:36Z dumbbell $");
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,
71255571Sdumbbell    int type, int *rid, u_long start, u_long end, u_long count, 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
129259679Sdumbbell	/* This video card is the boot display: record its unit number. */
130259679Sdumbbell	vga_pci_default_unit = unit;
131259679Sdumbbell	device_set_flags(dev, 1);
132259679Sdumbbell
133259679Sdumbbell	return (1);
134254882Sdumbbell}
135254882Sdumbbell
136254882Sdumbbellvoid *
137254882Sdumbbellvga_pci_map_bios(device_t dev, size_t *size)
138254882Sdumbbell{
139254882Sdumbbell	int rid;
140254882Sdumbbell	struct resource *res;
141254882Sdumbbell
142268351Smarcel#if defined(__amd64__) || defined(__i386__)
143254882Sdumbbell	if (vga_pci_is_boot_display(dev)) {
144254882Sdumbbell		/*
145254882Sdumbbell		 * On x86, the System BIOS copy the default display
146254882Sdumbbell		 * device's Video BIOS at a fixed location in system
147254882Sdumbbell		 * memory (0xC0000, 128 kBytes long) at boot time.
148254882Sdumbbell		 *
149254882Sdumbbell		 * We use this copy for the default boot device, because
150254882Sdumbbell		 * the original ROM may not be valid after boot.
151254882Sdumbbell		 */
152254882Sdumbbell
153254882Sdumbbell		*size = VGA_PCI_BIOS_SHADOW_SIZE;
154254882Sdumbbell		return (pmap_mapbios(VGA_PCI_BIOS_SHADOW_ADDR, *size));
155254882Sdumbbell	}
156254882Sdumbbell#endif
157254882Sdumbbell
158254882Sdumbbell	rid = PCIR_BIOS;
159255571Sdumbbell	res = vga_pci_alloc_resource(dev, NULL, SYS_RES_MEMORY, &rid, 0ul,
160255571Sdumbbell	    ~0ul, 1, RF_ACTIVE);
161254882Sdumbbell	if (res == NULL) {
162254882Sdumbbell		return (NULL);
163254882Sdumbbell	}
164254882Sdumbbell
165254882Sdumbbell	*size = rman_get_size(res);
166254882Sdumbbell	return (rman_get_virtual(res));
167254882Sdumbbell}
168254882Sdumbbell
169254882Sdumbbellvoid
170254882Sdumbbellvga_pci_unmap_bios(device_t dev, void *bios)
171254882Sdumbbell{
172255571Sdumbbell	struct vga_resource *vr;
173254882Sdumbbell
174254882Sdumbbell	if (bios == NULL) {
175254882Sdumbbell		return;
176254882Sdumbbell	}
177254882Sdumbbell
178268351Smarcel#if defined(__amd64__) || defined(__i386__)
179254882Sdumbbell	if (vga_pci_is_boot_display(dev)) {
180254882Sdumbbell		/* We mapped the BIOS shadow copy located at 0xC0000. */
181254882Sdumbbell		pmap_unmapdev((vm_offset_t)bios, VGA_PCI_BIOS_SHADOW_SIZE);
182254882Sdumbbell
183254882Sdumbbell		return;
184254882Sdumbbell	}
185254882Sdumbbell#endif
186254882Sdumbbell
187254882Sdumbbell	/*
188255571Sdumbbell	 * Look up the PCIR_BIOS resource in our softc.  It should match
189255571Sdumbbell	 * the address we returned previously.
190254882Sdumbbell	 */
191255571Sdumbbell	vr = lookup_res(device_get_softc(dev), PCIR_BIOS);
192255571Sdumbbell	KASSERT(vr->vr_res != NULL, ("vga_pci_unmap_bios: bios not mapped"));
193255571Sdumbbell	KASSERT(rman_get_virtual(vr->vr_res) == bios,
194255571Sdumbbell	    ("vga_pci_unmap_bios: mismatch"));
195255571Sdumbbell	vga_pci_release_resource(dev, NULL, SYS_RES_MEMORY, PCIR_BIOS,
196255571Sdumbbell	    vr->vr_res);
197254882Sdumbbell}
198254882Sdumbbell
199279487Sdumbbellint
200279487Sdumbbellvga_pci_repost(device_t dev)
201279487Sdumbbell{
202279487Sdumbbell#if defined(__amd64__) || defined(__i386__)
203279487Sdumbbell	x86regs_t regs;
204279487Sdumbbell
205279487Sdumbbell	if (!vga_pci_is_boot_display(dev))
206279487Sdumbbell		return (EINVAL);
207279487Sdumbbell
208279487Sdumbbell	if (x86bios_get_orm(VGA_PCI_BIOS_SHADOW_ADDR) == NULL)
209279487Sdumbbell		return (ENOTSUP);
210279487Sdumbbell
211279487Sdumbbell	x86bios_init_regs(&regs);
212279487Sdumbbell
213279487Sdumbbell	regs.R_AH = pci_get_bus(dev);
214279487Sdumbbell	regs.R_AL = (pci_get_slot(dev) << 3) | (pci_get_function(dev) & 0x07);
215279487Sdumbbell	regs.R_DL = 0x80;
216279487Sdumbbell
217279487Sdumbbell	device_printf(dev, "REPOSTing\n");
218279487Sdumbbell	x86bios_call(&regs, X86BIOS_PHYSTOSEG(VGA_PCI_BIOS_SHADOW_ADDR + 3),
219279487Sdumbbell	    X86BIOS_PHYSTOOFF(VGA_PCI_BIOS_SHADOW_ADDR + 3));
220279487Sdumbbell
221279487Sdumbbell	x86bios_get_intr(0x10);
222279487Sdumbbell
223279487Sdumbbell	return (0);
224279487Sdumbbell#else
225279487Sdumbbell	return (ENOTSUP);
226279487Sdumbbell#endif
227279487Sdumbbell}
228279487Sdumbbell
229153577Sjhbstatic int
230153577Sjhbvga_pci_probe(device_t dev)
231153577Sjhb{
232153577Sjhb
233153577Sjhb	switch (pci_get_class(dev)) {
234153577Sjhb	case PCIC_DISPLAY:
235153577Sjhb		break;
236153577Sjhb	case PCIC_OLD:
237153577Sjhb		if (pci_get_subclass(dev) != PCIS_OLD_VGA)
238153577Sjhb			return (ENXIO);
239153577Sjhb		break;
240153577Sjhb	default:
241153577Sjhb		return (ENXIO);
242153577Sjhb	}
243198251Sjkim
244198251Sjkim	/* Probe default display. */
245259679Sdumbbell	vga_pci_is_boot_display(dev);
246198251Sjkim
247153577Sjhb	device_set_desc(dev, "VGA-compatible display");
248153646Sjhb	return (BUS_PROBE_GENERIC);
249153577Sjhb}
250153577Sjhb
251153577Sjhbstatic int
252153577Sjhbvga_pci_attach(device_t dev)
253153577Sjhb{
254153577Sjhb
255153577Sjhb	bus_generic_probe(dev);
256153577Sjhb
257153577Sjhb	/* Always create a drm child for now to make it easier on drm. */
258153577Sjhb	device_add_child(dev, "drm", -1);
259235846Skib	device_add_child(dev, "drmn", -1);
260153577Sjhb	bus_generic_attach(dev);
261259679Sdumbbell
262259679Sdumbbell	if (vga_pci_is_boot_display(dev))
263259679Sdumbbell		device_printf(dev, "Boot video device\n");
264259679Sdumbbell
265153577Sjhb	return (0);
266153577Sjhb}
267153577Sjhb
268153577Sjhbstatic int
269153577Sjhbvga_pci_suspend(device_t dev)
270153577Sjhb{
271153577Sjhb
272199002Sjkim	return (bus_generic_suspend(dev));
273153577Sjhb}
274153577Sjhb
275153577Sjhbstatic int
276153577Sjhbvga_pci_resume(device_t dev)
277153577Sjhb{
278153577Sjhb
279153577Sjhb	return (bus_generic_resume(dev));
280153577Sjhb}
281153577Sjhb
282153577Sjhb/* Bus interface. */
283153577Sjhb
284153577Sjhbstatic int
285153577Sjhbvga_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
286153577Sjhb{
287153577Sjhb
288153577Sjhb	return (BUS_READ_IVAR(device_get_parent(dev), dev, which, result));
289153577Sjhb}
290153577Sjhb
291153577Sjhbstatic int
292153577Sjhbvga_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
293153577Sjhb{
294153577Sjhb
295153577Sjhb	return (EINVAL);
296153577Sjhb}
297153577Sjhb
298183194Srnolandstatic int
299183194Srnolandvga_pci_setup_intr(device_t dev, device_t child, struct resource *irq,
300183194Srnoland    int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg,
301183194Srnoland    void **cookiep)
302183194Srnoland{
303183194Srnoland	return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags,
304183194Srnoland	    filter, intr, arg, cookiep));
305183194Srnoland}
306183194Srnoland
307183194Srnolandstatic int
308183194Srnolandvga_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
309183194Srnoland    void *cookie)
310183194Srnoland{
311183194Srnoland	return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie));
312183194Srnoland}
313183194Srnoland
314249315Sjhbstatic struct vga_resource *
315249315Sjhblookup_res(struct vga_pci_softc *sc, int rid)
316249315Sjhb{
317249315Sjhb	int bar;
318249315Sjhb
319249315Sjhb	if (rid == PCIR_BIOS)
320249315Sjhb		return (&sc->vga_bios);
321249315Sjhb	bar = PCI_RID2BAR(rid);
322249315Sjhb	if (bar >= 0 && bar <= PCIR_MAX_BAR_0)
323249315Sjhb		return (&sc->vga_bars[bar]);
324249315Sjhb	return (NULL);
325249315Sjhb}
326249315Sjhb
327153577Sjhbstatic struct resource *
328153577Sjhbvga_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
329153577Sjhb    u_long start, u_long end, u_long count, u_int flags)
330153577Sjhb{
331249315Sjhb	struct vga_resource *vr;
332153577Sjhb
333189373Sjhb	switch (type) {
334189373Sjhb	case SYS_RES_MEMORY:
335189373Sjhb	case SYS_RES_IOPORT:
336189373Sjhb		/*
337189373Sjhb		 * For BARs, we cache the resource so that we only allocate it
338189373Sjhb		 * from the PCI bus once.
339189373Sjhb		 */
340249315Sjhb		vr = lookup_res(device_get_softc(dev), *rid);
341249315Sjhb		if (vr == NULL)
342189373Sjhb			return (NULL);
343249315Sjhb		if (vr->vr_res == NULL)
344249315Sjhb			vr->vr_res = bus_alloc_resource(dev, type, rid, start,
345249315Sjhb			    end, count, flags);
346249315Sjhb		if (vr->vr_res != NULL)
347249315Sjhb			vr->vr_refs++;
348249315Sjhb		return (vr->vr_res);
349189373Sjhb	}
350153577Sjhb	return (bus_alloc_resource(dev, type, rid, start, end, count, flags));
351153577Sjhb}
352153577Sjhb
353153577Sjhbstatic int
354153577Sjhbvga_pci_release_resource(device_t dev, device_t child, int type, int rid,
355153577Sjhb    struct resource *r)
356153577Sjhb{
357249315Sjhb	struct vga_resource *vr;
358249315Sjhb	int error;
359153577Sjhb
360189373Sjhb	switch (type) {
361189373Sjhb	case SYS_RES_MEMORY:
362189373Sjhb	case SYS_RES_IOPORT:
363189373Sjhb		/*
364189373Sjhb		 * For BARs, we release the resource from the PCI bus
365189373Sjhb		 * when the last child reference goes away.
366189373Sjhb		 */
367249315Sjhb		vr = lookup_res(device_get_softc(dev), rid);
368249315Sjhb		if (vr == NULL)
369189373Sjhb			return (EINVAL);
370249315Sjhb		if (vr->vr_res == NULL)
371189373Sjhb			return (EINVAL);
372249315Sjhb		KASSERT(vr->vr_res == r, ("vga_pci resource mismatch"));
373249315Sjhb		if (vr->vr_refs > 1) {
374249315Sjhb			vr->vr_refs--;
375189373Sjhb			return (0);
376189373Sjhb		}
377249315Sjhb		KASSERT(vr->vr_refs > 0,
378189373Sjhb		    ("vga_pci resource reference count underflow"));
379189373Sjhb		error = bus_release_resource(dev, type, rid, r);
380189373Sjhb		if (error == 0) {
381249315Sjhb			vr->vr_res = NULL;
382249315Sjhb			vr->vr_refs = 0;
383189373Sjhb		}
384189373Sjhb		return (error);
385189373Sjhb	}
386189373Sjhb
387153577Sjhb	return (bus_release_resource(dev, type, rid, r));
388153577Sjhb}
389153577Sjhb
390153577Sjhb/* PCI interface. */
391153577Sjhb
392153577Sjhbstatic uint32_t
393153577Sjhbvga_pci_read_config(device_t dev, device_t child, int reg, int width)
394153577Sjhb{
395153577Sjhb
396153577Sjhb	return (pci_read_config(dev, reg, width));
397153577Sjhb}
398153577Sjhb
399153577Sjhbstatic void
400205018Sjhbvga_pci_write_config(device_t dev, device_t child, int reg,
401153577Sjhb    uint32_t val, int width)
402153577Sjhb{
403153577Sjhb
404153577Sjhb	pci_write_config(dev, reg, val, width);
405153577Sjhb}
406153577Sjhb
407153577Sjhbstatic int
408153577Sjhbvga_pci_enable_busmaster(device_t dev, device_t child)
409153577Sjhb{
410153577Sjhb
411153577Sjhb	return (pci_enable_busmaster(dev));
412153577Sjhb}
413153577Sjhb
414153577Sjhbstatic int
415153577Sjhbvga_pci_disable_busmaster(device_t dev, device_t child)
416153577Sjhb{
417153577Sjhb
418153577Sjhb	return (pci_disable_busmaster(dev));
419153577Sjhb}
420153577Sjhb
421153577Sjhbstatic int
422153577Sjhbvga_pci_enable_io(device_t dev, device_t child, int space)
423153577Sjhb{
424153577Sjhb
425153577Sjhb	device_printf(dev, "child %s requested pci_enable_io\n",
426153577Sjhb	    device_get_nameunit(child));
427153577Sjhb	return (pci_enable_io(dev, space));
428153577Sjhb}
429153577Sjhb
430153577Sjhbstatic int
431153577Sjhbvga_pci_disable_io(device_t dev, device_t child, int space)
432153577Sjhb{
433153577Sjhb
434153577Sjhb	device_printf(dev, "child %s requested pci_disable_io\n",
435153577Sjhb	    device_get_nameunit(child));
436153577Sjhb	return (pci_disable_io(dev, space));
437153577Sjhb}
438153577Sjhb
439153577Sjhbstatic int
440183095Sjhbvga_pci_get_vpd_ident(device_t dev, device_t child, const char **identptr)
441183095Sjhb{
442183095Sjhb
443183095Sjhb	return (pci_get_vpd_ident(dev, identptr));
444183095Sjhb}
445183095Sjhb
446183095Sjhbstatic int
447183095Sjhbvga_pci_get_vpd_readonly(device_t dev, device_t child, const char *kw,
448183095Sjhb    const char **vptr)
449183095Sjhb{
450183095Sjhb
451183095Sjhb	return (pci_get_vpd_readonly(dev, kw, vptr));
452183095Sjhb}
453183095Sjhb
454183095Sjhbstatic int
455153577Sjhbvga_pci_set_powerstate(device_t dev, device_t child, int state)
456153577Sjhb{
457153577Sjhb
458153577Sjhb	device_printf(dev, "child %s requested pci_set_powerstate\n",
459153577Sjhb	    device_get_nameunit(child));
460153577Sjhb	return (pci_set_powerstate(dev, state));
461153577Sjhb}
462153577Sjhb
463153577Sjhbstatic int
464153577Sjhbvga_pci_get_powerstate(device_t dev, device_t child)
465153577Sjhb{
466153577Sjhb
467153577Sjhb	device_printf(dev, "child %s requested pci_get_powerstate\n",
468153577Sjhb	    device_get_nameunit(child));
469153577Sjhb	return (pci_get_powerstate(dev));
470153577Sjhb}
471153577Sjhb
472153577Sjhbstatic int
473153577Sjhbvga_pci_assign_interrupt(device_t dev, device_t child)
474153577Sjhb{
475153577Sjhb
476153577Sjhb	device_printf(dev, "child %s requested pci_assign_interrupt\n",
477153577Sjhb	    device_get_nameunit(child));
478153577Sjhb	return (PCI_ASSIGN_INTERRUPT(device_get_parent(dev), dev));
479153577Sjhb}
480153577Sjhb
481153577Sjhbstatic int
482232472Sjhbvga_pci_find_cap(device_t dev, device_t child, int capability,
483232472Sjhb    int *capreg)
484232472Sjhb{
485232472Sjhb
486232472Sjhb	return (pci_find_cap(dev, capability, capreg));
487232472Sjhb}
488232472Sjhb
489232472Sjhbstatic int
490153577Sjhbvga_pci_find_extcap(device_t dev, device_t child, int capability,
491153577Sjhb    int *capreg)
492153577Sjhb{
493153577Sjhb
494153577Sjhb	return (pci_find_extcap(dev, capability, capreg));
495153577Sjhb}
496153577Sjhb
497183095Sjhbstatic int
498232472Sjhbvga_pci_find_htcap(device_t dev, device_t child, int capability,
499232472Sjhb    int *capreg)
500232472Sjhb{
501232472Sjhb
502232472Sjhb	return (pci_find_htcap(dev, capability, capreg));
503232472Sjhb}
504232472Sjhb
505232472Sjhbstatic int
506183095Sjhbvga_pci_alloc_msi(device_t dev, device_t child, int *count)
507183095Sjhb{
508183095Sjhb	struct vga_pci_softc *sc;
509183095Sjhb	int error;
510183095Sjhb
511183095Sjhb	sc = device_get_softc(dev);
512183095Sjhb	if (sc->vga_msi_child != NULL)
513183095Sjhb		return (EBUSY);
514183095Sjhb	error = pci_alloc_msi(dev, count);
515183095Sjhb	if (error == 0)
516183095Sjhb		sc->vga_msi_child = child;
517183095Sjhb	return (error);
518183095Sjhb}
519183095Sjhb
520183095Sjhbstatic int
521183095Sjhbvga_pci_alloc_msix(device_t dev, device_t child, int *count)
522183095Sjhb{
523183095Sjhb	struct vga_pci_softc *sc;
524183095Sjhb	int error;
525183095Sjhb
526183095Sjhb	sc = device_get_softc(dev);
527183095Sjhb	if (sc->vga_msi_child != NULL)
528183095Sjhb		return (EBUSY);
529183095Sjhb	error = pci_alloc_msix(dev, count);
530183095Sjhb	if (error == 0)
531183095Sjhb		sc->vga_msi_child = child;
532183095Sjhb	return (error);
533183095Sjhb}
534183095Sjhb
535183095Sjhbstatic int
536183095Sjhbvga_pci_remap_msix(device_t dev, device_t child, int count,
537183095Sjhb    const u_int *vectors)
538183095Sjhb{
539183095Sjhb	struct vga_pci_softc *sc;
540183095Sjhb
541183095Sjhb	sc = device_get_softc(dev);
542183095Sjhb	if (sc->vga_msi_child != child)
543183095Sjhb		return (ENXIO);
544183095Sjhb	return (pci_remap_msix(dev, count, vectors));
545183095Sjhb}
546183095Sjhb
547183095Sjhbstatic int
548183095Sjhbvga_pci_release_msi(device_t dev, device_t child)
549183095Sjhb{
550183095Sjhb	struct vga_pci_softc *sc;
551183095Sjhb	int error;
552183095Sjhb
553183095Sjhb	sc = device_get_softc(dev);
554183095Sjhb	if (sc->vga_msi_child != child)
555183095Sjhb		return (ENXIO);
556183095Sjhb	error = pci_release_msi(dev);
557183095Sjhb	if (error == 0)
558183095Sjhb		sc->vga_msi_child = NULL;
559183095Sjhb	return (error);
560183095Sjhb}
561183095Sjhb
562183095Sjhbstatic int
563183095Sjhbvga_pci_msi_count(device_t dev, device_t child)
564183095Sjhb{
565183095Sjhb
566183095Sjhb	return (pci_msi_count(dev));
567183095Sjhb}
568183095Sjhb
569183095Sjhbstatic int
570183095Sjhbvga_pci_msix_count(device_t dev, device_t child)
571183095Sjhb{
572183095Sjhb
573183095Sjhb	return (pci_msix_count(dev));
574183095Sjhb}
575183095Sjhb
576249476Skibstatic bus_dma_tag_t
577249476Skibvga_pci_get_dma_tag(device_t bus, device_t child)
578249476Skib{
579249476Skib
580249476Skib	return (bus_get_dma_tag(bus));
581249476Skib}
582249476Skib
583153577Sjhbstatic device_method_t vga_pci_methods[] = {
584153577Sjhb	/* Device interface */
585153577Sjhb	DEVMETHOD(device_probe,		vga_pci_probe),
586153577Sjhb	DEVMETHOD(device_attach,	vga_pci_attach),
587153577Sjhb	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
588153577Sjhb	DEVMETHOD(device_suspend,	vga_pci_suspend),
589153577Sjhb	DEVMETHOD(device_resume,	vga_pci_resume),
590153577Sjhb
591153577Sjhb	/* Bus interface */
592153577Sjhb	DEVMETHOD(bus_read_ivar,	vga_pci_read_ivar),
593153577Sjhb	DEVMETHOD(bus_write_ivar,	vga_pci_write_ivar),
594183194Srnoland	DEVMETHOD(bus_setup_intr,	vga_pci_setup_intr),
595183194Srnoland	DEVMETHOD(bus_teardown_intr,	vga_pci_teardown_intr),
596153577Sjhb	DEVMETHOD(bus_alloc_resource,	vga_pci_alloc_resource),
597153577Sjhb	DEVMETHOD(bus_release_resource,	vga_pci_release_resource),
598153577Sjhb	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
599153577Sjhb	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
600249476Skib	DEVMETHOD(bus_get_dma_tag,	vga_pci_get_dma_tag),
601153577Sjhb
602153577Sjhb	/* PCI interface */
603153577Sjhb	DEVMETHOD(pci_read_config,	vga_pci_read_config),
604153577Sjhb	DEVMETHOD(pci_write_config,	vga_pci_write_config),
605153577Sjhb	DEVMETHOD(pci_enable_busmaster,	vga_pci_enable_busmaster),
606153577Sjhb	DEVMETHOD(pci_disable_busmaster, vga_pci_disable_busmaster),
607153577Sjhb	DEVMETHOD(pci_enable_io,	vga_pci_enable_io),
608153577Sjhb	DEVMETHOD(pci_disable_io,	vga_pci_disable_io),
609183095Sjhb	DEVMETHOD(pci_get_vpd_ident,	vga_pci_get_vpd_ident),
610183095Sjhb	DEVMETHOD(pci_get_vpd_readonly,	vga_pci_get_vpd_readonly),
611153577Sjhb	DEVMETHOD(pci_get_powerstate,	vga_pci_get_powerstate),
612153577Sjhb	DEVMETHOD(pci_set_powerstate,	vga_pci_set_powerstate),
613153577Sjhb	DEVMETHOD(pci_assign_interrupt,	vga_pci_assign_interrupt),
614232472Sjhb	DEVMETHOD(pci_find_cap,		vga_pci_find_cap),
615153577Sjhb	DEVMETHOD(pci_find_extcap,	vga_pci_find_extcap),
616232472Sjhb	DEVMETHOD(pci_find_htcap,	vga_pci_find_htcap),
617183095Sjhb	DEVMETHOD(pci_alloc_msi,	vga_pci_alloc_msi),
618183095Sjhb	DEVMETHOD(pci_alloc_msix,	vga_pci_alloc_msix),
619183095Sjhb	DEVMETHOD(pci_remap_msix,	vga_pci_remap_msix),
620183095Sjhb	DEVMETHOD(pci_release_msi,	vga_pci_release_msi),
621183095Sjhb	DEVMETHOD(pci_msi_count,	vga_pci_msi_count),
622183095Sjhb	DEVMETHOD(pci_msix_count,	vga_pci_msix_count),
623153577Sjhb
624153577Sjhb	{ 0, 0 }
625153577Sjhb};
626153577Sjhb
627153577Sjhbstatic driver_t vga_pci_driver = {
628153577Sjhb	"vgapci",
629153577Sjhb	vga_pci_methods,
630183095Sjhb	sizeof(struct vga_pci_softc),
631153577Sjhb};
632153577Sjhb
633153577Sjhbstatic devclass_t vga_devclass;
634153577Sjhb
635153577SjhbDRIVER_MODULE(vgapci, pci, vga_pci_driver, vga_devclass, 0, 0);
636