xref: /onnv-gate/usr/src/uts/i86pc/io/gfx_private/gfxp_pci.c (revision 945:8a803989ced9)
1*945Srugrat /*
2*945Srugrat  * CDDL HEADER START
3*945Srugrat  *
4*945Srugrat  * The contents of this file are subject to the terms of the
5*945Srugrat  * Common Development and Distribution License, Version 1.0 only
6*945Srugrat  * (the "License").  You may not use this file except in compliance
7*945Srugrat  * with the License.
8*945Srugrat  *
9*945Srugrat  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*945Srugrat  * or http://www.opensolaris.org/os/licensing.
11*945Srugrat  * See the License for the specific language governing permissions
12*945Srugrat  * and limitations under the License.
13*945Srugrat  *
14*945Srugrat  * When distributing Covered Code, include this CDDL HEADER in each
15*945Srugrat  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*945Srugrat  * If applicable, add the following below this CDDL HEADER, with the
17*945Srugrat  * fields enclosed by brackets "[]" replaced with your own identifying
18*945Srugrat  * information: Portions Copyright [yyyy] [name of copyright owner]
19*945Srugrat  *
20*945Srugrat  * CDDL HEADER END
21*945Srugrat  */
22*945Srugrat /*
23*945Srugrat  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*945Srugrat  * Use is subject to license terms.
25*945Srugrat  */
26*945Srugrat 
27*945Srugrat #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*945Srugrat 
29*945Srugrat #include <sys/debug.h>
30*945Srugrat #include <sys/types.h>
31*945Srugrat #include <sys/param.h>
32*945Srugrat #include <sys/time.h>
33*945Srugrat #include <sys/buf.h>
34*945Srugrat #include <sys/errno.h>
35*945Srugrat #include <sys/systm.h>
36*945Srugrat #include <sys/conf.h>
37*945Srugrat #include <sys/signal.h>
38*945Srugrat #include <sys/file.h>
39*945Srugrat #include <sys/uio.h>
40*945Srugrat #include <sys/ioctl.h>
41*945Srugrat #include <sys/map.h>
42*945Srugrat #include <sys/proc.h>
43*945Srugrat #include <sys/user.h>
44*945Srugrat #include <sys/mman.h>
45*945Srugrat #include <sys/cred.h>
46*945Srugrat #include <sys/open.h>
47*945Srugrat #include <sys/stat.h>
48*945Srugrat #include <sys/utsname.h>
49*945Srugrat #include <sys/kmem.h>
50*945Srugrat #include <sys/cmn_err.h>
51*945Srugrat #include <sys/vnode.h>
52*945Srugrat #include <vm/page.h>
53*945Srugrat #include <vm/as.h>
54*945Srugrat #include <vm/hat.h>
55*945Srugrat #include <vm/seg.h>
56*945Srugrat #include <sys/ddi.h>
57*945Srugrat #include <sys/devops.h>
58*945Srugrat #include <sys/sunddi.h>
59*945Srugrat #include <sys/ddi_impldefs.h>
60*945Srugrat #include <sys/fs/snode.h>
61*945Srugrat #include <sys/pci.h>
62*945Srugrat #include <sys/modctl.h>
63*945Srugrat #include <sys/uio.h>
64*945Srugrat #include <sys/visual_io.h>
65*945Srugrat #include <sys/fbio.h>
66*945Srugrat #include <sys/ddidmareq.h>
67*945Srugrat #include <sys/tnf_probe.h>
68*945Srugrat #include <sys/kstat.h>
69*945Srugrat #include <sys/callb.h>
70*945Srugrat #include <sys/pci_cfgspace.h>
71*945Srugrat #include "gfx_private.h"
72*945Srugrat 
73*945Srugrat typedef struct gfxp_pci_bsf {
74*945Srugrat 	uint16_t	vendor;
75*945Srugrat 	uint16_t	device;
76*945Srugrat 	uint8_t		bus;
77*945Srugrat 	uint8_t		slot;
78*945Srugrat 	uint8_t		function;
79*945Srugrat 	uint8_t		found;
80*945Srugrat 	dev_info_t	*dip;
81*945Srugrat } gfxp_pci_bsf_t;
82*945Srugrat 
83*945Srugrat /* The use of pci_get?/put?_func() depends on misc/pci_autoconfig */
84*945Srugrat 
85*945Srugrat static int
gfxp_pci_get_bsf(dev_info_t * dip,uint8_t * bus,uint8_t * dev,uint8_t * func)86*945Srugrat gfxp_pci_get_bsf(dev_info_t *dip, uint8_t *bus, uint8_t *dev, uint8_t *func)
87*945Srugrat {
88*945Srugrat 	pci_regspec_t   *pci_rp;
89*945Srugrat 	uint32_t	length;
90*945Srugrat 	int	rc;
91*945Srugrat 
92*945Srugrat 	/* get "reg" property */
93*945Srugrat 	rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
94*945Srugrat 		DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
95*945Srugrat 		(uint_t *)&length);
96*945Srugrat 	if ((rc != DDI_SUCCESS) || (length <
97*945Srugrat 			(sizeof (pci_regspec_t) / sizeof (int)))) {
98*945Srugrat 		return (DDI_FAILURE);
99*945Srugrat 	}
100*945Srugrat 
101*945Srugrat 	*bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
102*945Srugrat 	*dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
103*945Srugrat 	*func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
104*945Srugrat 
105*945Srugrat 	/*
106*945Srugrat 	 * free the memory allocated by ddi_prop_lookup_int_array().
107*945Srugrat 	 */
108*945Srugrat 	ddi_prop_free(pci_rp);
109*945Srugrat 
110*945Srugrat 	return (DDI_SUCCESS);
111*945Srugrat }
112*945Srugrat 
113*945Srugrat static int
gfxp_pci_find_bsf(dev_info_t * dip,void * arg)114*945Srugrat gfxp_pci_find_bsf(dev_info_t *dip, void *arg)
115*945Srugrat {
116*945Srugrat 	int	rc;
117*945Srugrat 	uint8_t bus, dev, func;
118*945Srugrat 	gfxp_pci_bsf_t    *pci_bsf;
119*945Srugrat 	int vendor_id, device_id, class_code;
120*945Srugrat 
121*945Srugrat 	/*
122*945Srugrat 	 * Look for vendor-id, device-id, class-code to verify
123*945Srugrat 	 * this is some type of PCI child node.
124*945Srugrat 	 */
125*945Srugrat 	vendor_id = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
126*945Srugrat 				"vendor-id", -1);
127*945Srugrat 	device_id = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
128*945Srugrat 				"device-id", -1);
129*945Srugrat 	class_code = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
130*945Srugrat 				"class-code", -1);
131*945Srugrat 	if ((vendor_id == -1) || (device_id == -1) || (class_code == -1)) {
132*945Srugrat 		return (DDI_WALK_CONTINUE);
133*945Srugrat 	}
134*945Srugrat 
135*945Srugrat 	if (gfxp_pci_get_bsf(dip, &bus, &dev, &func) != DDI_SUCCESS)
136*945Srugrat 		return (DDI_WALK_TERMINATE);
137*945Srugrat 
138*945Srugrat 	pci_bsf = (gfxp_pci_bsf_t *)arg;
139*945Srugrat 
140*945Srugrat 	if ((bus == pci_bsf->bus) && (dev == pci_bsf->slot) &&
141*945Srugrat 		(func == pci_bsf->function)) {
142*945Srugrat 		pci_bsf->dip = dip;
143*945Srugrat 		pci_bsf->vendor = vendor_id;
144*945Srugrat 		pci_bsf->device = device_id;
145*945Srugrat 		pci_bsf->found = 1;
146*945Srugrat 		rc = DDI_WALK_TERMINATE;
147*945Srugrat 	} else {
148*945Srugrat 		rc = DDI_WALK_CONTINUE;
149*945Srugrat 	}
150*945Srugrat 
151*945Srugrat 	return (rc);
152*945Srugrat }
153*945Srugrat 
154*945Srugrat gfxp_acc_handle_t
gfxp_pci_init_handle(uint8_t bus,uint8_t slot,uint8_t function,uint16_t * vendor,uint16_t * device)155*945Srugrat gfxp_pci_init_handle(uint8_t bus, uint8_t slot, uint8_t function,
156*945Srugrat 	uint16_t *vendor, uint16_t *device)
157*945Srugrat {
158*945Srugrat 	dev_info_t	*dip;
159*945Srugrat 	gfxp_pci_bsf_t	*pci_bsf;
160*945Srugrat 
161*945Srugrat 	/*
162*945Srugrat 	 * Find a PCI device based on its address, and return a unique handle
163*945Srugrat 	 * to be used in subsequent calls to read from or write to the config
164*945Srugrat 	 * space of this device.
165*945Srugrat 	 */
166*945Srugrat 
167*945Srugrat 	if ((pci_bsf = kmem_zalloc(sizeof (gfxp_pci_bsf_t), KM_SLEEP))
168*945Srugrat 			== NULL) {
169*945Srugrat 		return (NULL);
170*945Srugrat 	}
171*945Srugrat 
172*945Srugrat 	pci_bsf->bus = bus;
173*945Srugrat 	pci_bsf->slot = slot;
174*945Srugrat 	pci_bsf->function = function;
175*945Srugrat 
176*945Srugrat 	ddi_walk_devs(ddi_root_node(), gfxp_pci_find_bsf, pci_bsf);
177*945Srugrat 
178*945Srugrat 	if (pci_bsf->found) {
179*945Srugrat 		dip = pci_bsf->dip;
180*945Srugrat 
181*945Srugrat 		if (vendor) *vendor = pci_bsf->vendor;
182*945Srugrat 		if (device) *device = pci_bsf->device;
183*945Srugrat 	} else {
184*945Srugrat 		dip = NULL;
185*945Srugrat 		if (vendor) *vendor = 0x0000;
186*945Srugrat 		if (device) *device = 0x0000;
187*945Srugrat 	}
188*945Srugrat 
189*945Srugrat 	kmem_free(pci_bsf, sizeof (gfxp_pci_bsf_t));
190*945Srugrat 
191*945Srugrat 	return ((gfxp_acc_handle_t)dip);
192*945Srugrat }
193*945Srugrat 
194*945Srugrat uint8_t
gfxp_pci_read_byte(gfxp_acc_handle_t handle,uint16_t offset)195*945Srugrat gfxp_pci_read_byte(gfxp_acc_handle_t handle, uint16_t offset)
196*945Srugrat {
197*945Srugrat 	dev_info_t	*dip = (dev_info_t *)handle;
198*945Srugrat 	uint8_t	val;
199*945Srugrat 	uint8_t	bus, dev, func;
200*945Srugrat 
201*945Srugrat 	if (dip == NULL)
202*945Srugrat 		return ((uint8_t)~0);
203*945Srugrat 
204*945Srugrat 	if (gfxp_pci_get_bsf(dip, &bus, &dev, &func) != DDI_SUCCESS)
205*945Srugrat 		return ((uint8_t)~0);
206*945Srugrat 
207*945Srugrat 	val = (*pci_getb_func)(bus, dev, func, offset);
208*945Srugrat 	return (val);
209*945Srugrat }
210*945Srugrat 
211*945Srugrat uint16_t
gfxp_pci_read_word(gfxp_acc_handle_t handle,uint16_t offset)212*945Srugrat gfxp_pci_read_word(gfxp_acc_handle_t handle, uint16_t offset)
213*945Srugrat {
214*945Srugrat 	dev_info_t	*dip = (dev_info_t *)handle;
215*945Srugrat 	uint16_t	val;
216*945Srugrat 	uint8_t 	bus, dev, func;
217*945Srugrat 
218*945Srugrat 	if (dip == NULL)
219*945Srugrat 		return ((uint16_t)~0);
220*945Srugrat 
221*945Srugrat 	if (gfxp_pci_get_bsf(dip, &bus, &dev, &func) != DDI_SUCCESS)
222*945Srugrat 		return ((uint16_t)~0);
223*945Srugrat 
224*945Srugrat 	val = (*pci_getw_func)(bus, dev, func, offset);
225*945Srugrat 	return (val);
226*945Srugrat }
227*945Srugrat 
228*945Srugrat uint32_t
gfxp_pci_read_dword(gfxp_acc_handle_t handle,uint16_t offset)229*945Srugrat gfxp_pci_read_dword(gfxp_acc_handle_t handle, uint16_t offset)
230*945Srugrat {
231*945Srugrat 	dev_info_t	*dip = (dev_info_t *)handle;
232*945Srugrat 	uint32_t	val;
233*945Srugrat 	uint8_t		bus, dev, func;
234*945Srugrat 
235*945Srugrat 	if (dip == NULL)
236*945Srugrat 		return ((uint32_t)~0);
237*945Srugrat 
238*945Srugrat 	if (gfxp_pci_get_bsf(dip, &bus, &dev, &func) != DDI_SUCCESS)
239*945Srugrat 		return ((uint32_t)~0);
240*945Srugrat 
241*945Srugrat 	val = (*pci_getl_func)(bus, dev, func, offset);
242*945Srugrat 	return (val);
243*945Srugrat }
244*945Srugrat 
245*945Srugrat void
gfxp_pci_write_byte(gfxp_acc_handle_t handle,uint16_t offset,uint8_t value)246*945Srugrat gfxp_pci_write_byte(gfxp_acc_handle_t handle, uint16_t offset, uint8_t value)
247*945Srugrat {
248*945Srugrat 	dev_info_t	*dip = (dev_info_t *)handle;
249*945Srugrat 	uint8_t		bus, dev, func;
250*945Srugrat 
251*945Srugrat 	if (dip == NULL)
252*945Srugrat 		return;
253*945Srugrat 
254*945Srugrat 	if (gfxp_pci_get_bsf(dip, &bus, &dev, &func) != DDI_SUCCESS)
255*945Srugrat 		return;
256*945Srugrat 
257*945Srugrat 	(*pci_putb_func)(bus, dev, func, offset, value);
258*945Srugrat }
259*945Srugrat 
260*945Srugrat void
gfxp_pci_write_word(gfxp_acc_handle_t handle,uint16_t offset,uint16_t value)261*945Srugrat gfxp_pci_write_word(gfxp_acc_handle_t handle, uint16_t offset, uint16_t value)
262*945Srugrat {
263*945Srugrat 	dev_info_t	*dip = (dev_info_t *)handle;
264*945Srugrat 	uint8_t		bus, dev, func;
265*945Srugrat 
266*945Srugrat 	if (dip == NULL)
267*945Srugrat 		return;
268*945Srugrat 
269*945Srugrat 	if (gfxp_pci_get_bsf(dip, &bus, &dev, &func) != DDI_SUCCESS)
270*945Srugrat 		return;
271*945Srugrat 
272*945Srugrat 	(*pci_putw_func)(bus, dev, func, offset, value);
273*945Srugrat }
274*945Srugrat 
275*945Srugrat void
gfxp_pci_write_dword(gfxp_acc_handle_t handle,uint16_t offset,uint32_t value)276*945Srugrat gfxp_pci_write_dword(gfxp_acc_handle_t handle, uint16_t offset, uint32_t value)
277*945Srugrat {
278*945Srugrat 	dev_info_t	*dip = (dev_info_t *)handle;
279*945Srugrat 	uint8_t		bus, dev, func;
280*945Srugrat 
281*945Srugrat 	if (dip == NULL)
282*945Srugrat 		return;
283*945Srugrat 
284*945Srugrat 	if (gfxp_pci_get_bsf(dip, &bus, &dev, &func) != DDI_SUCCESS)
285*945Srugrat 		return;
286*945Srugrat 
287*945Srugrat 	(*pci_putl_func)(bus, dev, func, offset, value);
288*945Srugrat }
289*945Srugrat 
290*945Srugrat static int
gfxp_pci_find_vd(dev_info_t * dip,void * arg)291*945Srugrat gfxp_pci_find_vd(dev_info_t *dip, void *arg)
292*945Srugrat {
293*945Srugrat 	int		rc;
294*945Srugrat 	gfxp_pci_bsf_t	*pci_bsf;
295*945Srugrat 	int		vendor_id, device_id, class_code;
296*945Srugrat 
297*945Srugrat 	/*
298*945Srugrat 	 * Look for vendor-id, device-id, class-code to verify
299*945Srugrat 	 * this is some type of PCI child node.
300*945Srugrat 	 */
301*945Srugrat 	vendor_id = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
302*945Srugrat 			"vendor-id", -1);
303*945Srugrat 	device_id = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
304*945Srugrat 			"device-id", -1);
305*945Srugrat 	class_code = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
306*945Srugrat 			"class-code", -1);
307*945Srugrat 	if ((vendor_id == -1) || (device_id == -1) || (class_code == -1)) {
308*945Srugrat 		return (DDI_WALK_CONTINUE);
309*945Srugrat 	}
310*945Srugrat 
311*945Srugrat 	pci_bsf = (gfxp_pci_bsf_t *)arg;
312*945Srugrat 
313*945Srugrat 	if ((vendor_id == pci_bsf->vendor) && (device_id == pci_bsf->device)) {
314*945Srugrat 		pci_bsf->found = 1;
315*945Srugrat 		rc = DDI_WALK_TERMINATE;
316*945Srugrat 	} else {
317*945Srugrat 		rc = DDI_WALK_CONTINUE;
318*945Srugrat 	}
319*945Srugrat 
320*945Srugrat 	return (rc);
321*945Srugrat }
322*945Srugrat 
323*945Srugrat int
gfxp_pci_device_present(uint16_t vendor,uint16_t device)324*945Srugrat gfxp_pci_device_present(uint16_t vendor, uint16_t device)
325*945Srugrat {
326*945Srugrat 	gfxp_pci_bsf_t	*pci_bsf;
327*945Srugrat 	int		rv;
328*945Srugrat 
329*945Srugrat 	/*
330*945Srugrat 	 * Find a PCI device based on its device and vendor id.
331*945Srugrat 	 */
332*945Srugrat 
333*945Srugrat 	if ((pci_bsf = kmem_zalloc(sizeof (gfxp_pci_bsf_t), KM_SLEEP)) == NULL)
334*945Srugrat 	    return (0);
335*945Srugrat 
336*945Srugrat 	pci_bsf->vendor = vendor;
337*945Srugrat 	pci_bsf->device = device;
338*945Srugrat 	ddi_walk_devs(ddi_root_node(), gfxp_pci_find_vd, pci_bsf);
339*945Srugrat 
340*945Srugrat 	if (pci_bsf->found) {
341*945Srugrat 		rv = 1;
342*945Srugrat 	} else {
343*945Srugrat 		rv = 0;
344*945Srugrat 	}
345*945Srugrat 
346*945Srugrat 	kmem_free(pci_bsf, sizeof (gfxp_pci_bsf_t));
347*945Srugrat 
348*945Srugrat 	return (rv);
349*945Srugrat }
350