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