xref: /netbsd-src/sys/external/bsd/drm2/pci/drmfb_pci.c (revision 6c7d0f6b02eab93ec01ea191aedaf13e622a2527)
1*6c7d0f6bSriastradh /*	$NetBSD: drmfb_pci.c,v 1.5 2021/12/19 10:37:32 riastradh Exp $	*/
2894a903bSriastradh 
3894a903bSriastradh /*-
4894a903bSriastradh  * Copyright (c) 2014 The NetBSD Foundation, Inc.
5894a903bSriastradh  * All rights reserved.
6894a903bSriastradh  *
7894a903bSriastradh  * This code is derived from software contributed to The NetBSD Foundation
8894a903bSriastradh  * by Taylor R. Campbell.
9894a903bSriastradh  *
10894a903bSriastradh  * Redistribution and use in source and binary forms, with or without
11894a903bSriastradh  * modification, are permitted provided that the following conditions
12894a903bSriastradh  * are met:
13894a903bSriastradh  * 1. Redistributions of source code must retain the above copyright
14894a903bSriastradh  *    notice, this list of conditions and the following disclaimer.
15894a903bSriastradh  * 2. Redistributions in binary form must reproduce the above copyright
16894a903bSriastradh  *    notice, this list of conditions and the following disclaimer in the
17894a903bSriastradh  *    documentation and/or other materials provided with the distribution.
18894a903bSriastradh  *
19894a903bSriastradh  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20894a903bSriastradh  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21894a903bSriastradh  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22894a903bSriastradh  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23894a903bSriastradh  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24894a903bSriastradh  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25894a903bSriastradh  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26894a903bSriastradh  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27894a903bSriastradh  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28894a903bSriastradh  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29894a903bSriastradh  * POSSIBILITY OF SUCH DAMAGE.
30894a903bSriastradh  */
31894a903bSriastradh 
32894a903bSriastradh /*
33894a903bSriastradh  * drmfb_pci: drmfb hooks for PCI devices.
34894a903bSriastradh  */
35894a903bSriastradh 
36894a903bSriastradh #include <sys/cdefs.h>
37*6c7d0f6bSriastradh __KERNEL_RCSID(0, "$NetBSD: drmfb_pci.c,v 1.5 2021/12/19 10:37:32 riastradh Exp $");
388d3bbbe0Sriastradh 
398d3bbbe0Sriastradh #ifdef _KERNEL_OPT
408d3bbbe0Sriastradh #include "vga.h"
418d3bbbe0Sriastradh #endif
42894a903bSriastradh 
43894a903bSriastradh #include <sys/types.h>
44894a903bSriastradh #include <sys/device.h>
45894a903bSriastradh #include <sys/errno.h>
46894a903bSriastradh #include <sys/systm.h>
47894a903bSriastradh 
48894a903bSriastradh #include <dev/pci/pciio.h>
49894a903bSriastradh #include <dev/pci/pcireg.h>
50894a903bSriastradh #include <dev/pci/pcivar.h>
51894a903bSriastradh #include <dev/pci/wsdisplay_pci.h>
52894a903bSriastradh 
538d3bbbe0Sriastradh #if NVGA > 0
548d3bbbe0Sriastradh /*
558d3bbbe0Sriastradh  * XXX All we really need is vga_is_console from vgavar.h, but the
568d3bbbe0Sriastradh  * header files are missing their own dependencies, so we need to
578d3bbbe0Sriastradh  * explicitly drag in the other crap.
588d3bbbe0Sriastradh  */
598d3bbbe0Sriastradh #include <dev/ic/mc6845reg.h>
608d3bbbe0Sriastradh #include <dev/ic/pcdisplayvar.h>
618d3bbbe0Sriastradh #include <dev/ic/vgareg.h>
628d3bbbe0Sriastradh #include <dev/ic/vgavar.h>
638d3bbbe0Sriastradh #endif
648d3bbbe0Sriastradh 
65*6c7d0f6bSriastradh #include <linux/pci.h>
66*6c7d0f6bSriastradh 
67f21b21b0Sriastradh #include <drm/drm_device.h>
68894a903bSriastradh #include <drm/drm_fb_helper.h>
69894a903bSriastradh 
700dc9dda4Schristos #include <drm/drmfb.h>
710dc9dda4Schristos #include <drm/drmfb_pci.h>
72894a903bSriastradh 
73894a903bSriastradh /*
74894a903bSriastradh  * drmfb_pci_mmap: Implementation of drmfb_params::dp_mmap.  Don't use
75894a903bSriastradh  * this for dp_mmapfb -- how to get at the framebuffer is device-
76894a903bSriastradh  * specific.
77894a903bSriastradh  */
78894a903bSriastradh paddr_t
drmfb_pci_mmap(struct drmfb_softc * sc,off_t offset,int prot)79894a903bSriastradh drmfb_pci_mmap(struct drmfb_softc *sc, off_t offset, int prot)
80894a903bSriastradh {
81894a903bSriastradh 	struct drm_device *const dev = sc->sc_da.da_fb_helper->dev;
82894a903bSriastradh 	const struct pci_attach_args *const pa = &dev->pdev->pd_pa;
83894a903bSriastradh 	unsigned i;
84894a903bSriastradh 
85894a903bSriastradh 	for (i = 0; PCI_BAR(i) <= PCI_MAPREG_ROM; i++) {
86894a903bSriastradh 		pcireg_t type;
87894a903bSriastradh 		bus_addr_t addr;
88894a903bSriastradh 		bus_size_t size;
89894a903bSriastradh 		int flags;
90894a903bSriastradh 
91894a903bSriastradh 		/* Interrogate the BAR.  */
92894a903bSriastradh 		if (!pci_mapreg_probe(pa->pa_pc, pa->pa_tag, PCI_BAR(i),
93894a903bSriastradh 			&type))
94894a903bSriastradh 			continue;
95894a903bSriastradh 		if (PCI_MAPREG_TYPE(type) != PCI_MAPREG_TYPE_MEM)
96894a903bSriastradh 			continue;
97894a903bSriastradh 		if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PCI_BAR(i), type,
98894a903bSriastradh 			&addr, &size, &flags))
99894a903bSriastradh 			continue;
100894a903bSriastradh 
101894a903bSriastradh 		/* Try to map it if it's in range.  */
102894a903bSriastradh 		if ((addr <= offset) && (offset < (addr + size)))
103894a903bSriastradh 			return bus_space_mmap(pa->pa_memt, addr,
104894a903bSriastradh 			    (offset - addr), prot, flags);
105894a903bSriastradh 
106894a903bSriastradh 		/* Skip a slot if this was a 64-bit BAR.  */
107894a903bSriastradh 		if ((PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_MEM) &&
108894a903bSriastradh 		    (PCI_MAPREG_MEM_TYPE(type) == PCI_MAPREG_MEM_TYPE_64BIT))
109894a903bSriastradh 			i += 1;
110894a903bSriastradh 	}
111894a903bSriastradh 
112894a903bSriastradh 	/* Failure!  */
113894a903bSriastradh 	return -1;
114894a903bSriastradh }
115894a903bSriastradh 
116894a903bSriastradh /*
117894a903bSriastradh  * drmfb_pci_ioctl: Implementation of drmfb_params::dp_ioctl.  Provides:
118894a903bSriastradh  *
119894a903bSriastradh  * - WSDISPLAY_GET_BUSID
120894a903bSriastradh  * - WSDISPLAY_GTYPE
121894a903bSriastradh  *
122894a903bSriastradh  * Additionally allows access to PCI registers.
123894a903bSriastradh  *
124894a903bSriastradh  * XXX Do we need to provide access to PCI registers?  I can't find
125894a903bSriastradh  * anything that uses this functionality, and as is it is very
126894a903bSriastradh  * dangerous.
127894a903bSriastradh  */
128894a903bSriastradh int
drmfb_pci_ioctl(struct drmfb_softc * sc,unsigned long cmd,void * data,int flag,struct lwp * l)129894a903bSriastradh drmfb_pci_ioctl(struct drmfb_softc *sc, unsigned long cmd, void *data,
130894a903bSriastradh     int flag, struct lwp *l)
131894a903bSriastradh {
132894a903bSriastradh 	struct drm_device *const dev = sc->sc_da.da_fb_helper->dev;
133894a903bSriastradh 	struct pci_attach_args *const pa = &dev->pdev->pd_pa;
134894a903bSriastradh 
135894a903bSriastradh 	switch (cmd) {
136894a903bSriastradh 	/* PCI config read/write passthrough.  */
137894a903bSriastradh 	case PCI_IOC_CFGREAD:
138894a903bSriastradh 	case PCI_IOC_CFGWRITE:
139894a903bSriastradh 		return pci_devioctl(pa->pa_pc, pa->pa_tag, cmd, data, flag, l);
140894a903bSriastradh 
141894a903bSriastradh 	/* PCI-specific wsdisplay ioctls.  */
142894a903bSriastradh 	case WSDISPLAYIO_GET_BUSID:
143894a903bSriastradh 		return wsdisplayio_busid_pci(dev->dev, pa->pa_pc, pa->pa_tag,
144894a903bSriastradh 		    data);
145894a903bSriastradh 	case WSDISPLAYIO_GTYPE:
146894a903bSriastradh 		*(unsigned int *)data = WSDISPLAY_TYPE_PCIVGA;
147894a903bSriastradh 		return 0;
148894a903bSriastradh 
149894a903bSriastradh 	default:
150894a903bSriastradh 		return EPASSTHROUGH;
151894a903bSriastradh 	}
152894a903bSriastradh }
1538d3bbbe0Sriastradh 
1548d3bbbe0Sriastradh bool
drmfb_pci_is_vga_console(struct drm_device * dev)1558d3bbbe0Sriastradh drmfb_pci_is_vga_console(struct drm_device *dev)
1568d3bbbe0Sriastradh {
1578d3bbbe0Sriastradh 
1588d3bbbe0Sriastradh #if NVGA > 0
1598d3bbbe0Sriastradh 	return vga_is_console(dev->pdev->pd_pa.pa_iot, -1);
1608d3bbbe0Sriastradh #else
1618d3bbbe0Sriastradh 	return false;
1628d3bbbe0Sriastradh #endif
1638d3bbbe0Sriastradh }
164