4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/debug.h>
28 #include <sys/types.h>
29 #include <sys/param.h>
32 #include <sys/errno.h>
33 #include <sys/systm.h>
35 #include <sys/signal.h>
38 #include <sys/ioctl.h>
46 #include <sys/utsname.h>
48 #include <sys/cmn_err.h>
49 #include <sys/vnode.h>
55 #include <sys/devops.h>
56 #include <sys/sunddi.h>
57 #include <sys/ddi_impldefs.h>
58 #include <sys/fs/snode.h>
60 #include <sys/modctl.h>
62 #include <sys/visual_io.h>
64 #include <sys/ddidmareq.h>
65 #include <sys/tnf_probe.h>
66 #include <sys/kstat.h>
67 #include <sys/callb.h>
68 #include <sys/pci_cfgspace.h>
69 #include <sys/gfx_private.h>
71 typedef struct gfxp_pci_bsf
{
81 /* The use of pci_get?/put?_func() depends on misc/pci_autoconfig */
84 gfxp_pci_get_bsf(dev_info_t
*dip
, uint8_t *bus
, uint8_t *dev
, uint8_t *func
)
86 pci_regspec_t
*pci_rp
;
90 /* get "reg" property */
91 rc
= ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, dip
,
92 DDI_PROP_DONTPASS
, "reg", (int **)&pci_rp
,
94 if ((rc
!= DDI_SUCCESS
) || (length
<
95 (sizeof (pci_regspec_t
) / sizeof (int)))) {
99 *bus
= PCI_REG_BUS_G(pci_rp
->pci_phys_hi
);
100 *dev
= PCI_REG_DEV_G(pci_rp
->pci_phys_hi
);
101 *func
= PCI_REG_FUNC_G(pci_rp
->pci_phys_hi
);
104 * free the memory allocated by ddi_prop_lookup_int_array().
106 ddi_prop_free(pci_rp
);
108 return (DDI_SUCCESS
);
112 gfxp_pci_find_bsf(dev_info_t
*dip
, void *arg
)
115 uint8_t bus
, dev
, func
;
116 gfxp_pci_bsf_t
*pci_bsf
;
117 int vendor_id
, device_id
, class_code
;
120 * Look for vendor-id, device-id, class-code to verify
121 * this is some type of PCI child node.
123 vendor_id
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
125 device_id
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
127 class_code
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
129 if ((vendor_id
== -1) || (device_id
== -1) || (class_code
== -1)) {
130 return (DDI_WALK_CONTINUE
);
133 if (gfxp_pci_get_bsf(dip
, &bus
, &dev
, &func
) != DDI_SUCCESS
)
134 return (DDI_WALK_TERMINATE
);
136 pci_bsf
= (gfxp_pci_bsf_t
*)arg
;
138 if ((bus
== pci_bsf
->bus
) && (dev
== pci_bsf
->slot
) &&
139 (func
== pci_bsf
->function
)) {
141 pci_bsf
->vendor
= vendor_id
;
142 pci_bsf
->device
= device_id
;
144 rc
= DDI_WALK_TERMINATE
;
146 rc
= DDI_WALK_CONTINUE
;
153 gfxp_pci_init_handle(uint8_t bus
, uint8_t slot
, uint8_t function
,
154 uint16_t *vendor
, uint16_t *device
)
157 gfxp_pci_bsf_t
*pci_bsf
;
160 * Find a PCI device based on its address, and return a unique handle
161 * to be used in subsequent calls to read from or write to the config
162 * space of this device.
165 if ((pci_bsf
= kmem_zalloc(sizeof (gfxp_pci_bsf_t
), KM_SLEEP
))
171 pci_bsf
->slot
= slot
;
172 pci_bsf
->function
= function
;
174 ddi_walk_devs(ddi_root_node(), gfxp_pci_find_bsf
, pci_bsf
);
176 if (pci_bsf
->found
) {
179 if (vendor
) *vendor
= pci_bsf
->vendor
;
180 if (device
) *device
= pci_bsf
->device
;
183 if (vendor
) *vendor
= 0x0000;
184 if (device
) *device
= 0x0000;
187 kmem_free(pci_bsf
, sizeof (gfxp_pci_bsf_t
));
189 return ((gfxp_acc_handle_t
)dip
);
193 gfxp_pci_read_byte(gfxp_acc_handle_t handle
, uint16_t offset
)
195 dev_info_t
*dip
= (dev_info_t
*)handle
;
197 uint8_t bus
, dev
, func
;
200 return ((uint8_t)~0);
202 if (gfxp_pci_get_bsf(dip
, &bus
, &dev
, &func
) != DDI_SUCCESS
)
203 return ((uint8_t)~0);
205 val
= (*pci_getb_func
)(bus
, dev
, func
, offset
);
210 gfxp_pci_read_word(gfxp_acc_handle_t handle
, uint16_t offset
)
212 dev_info_t
*dip
= (dev_info_t
*)handle
;
214 uint8_t bus
, dev
, func
;
217 return ((uint16_t)~0);
219 if (gfxp_pci_get_bsf(dip
, &bus
, &dev
, &func
) != DDI_SUCCESS
)
220 return ((uint16_t)~0);
222 val
= (*pci_getw_func
)(bus
, dev
, func
, offset
);
227 gfxp_pci_read_dword(gfxp_acc_handle_t handle
, uint16_t offset
)
229 dev_info_t
*dip
= (dev_info_t
*)handle
;
231 uint8_t bus
, dev
, func
;
234 return ((uint32_t)~0);
236 if (gfxp_pci_get_bsf(dip
, &bus
, &dev
, &func
) != DDI_SUCCESS
)
237 return ((uint32_t)~0);
239 val
= (*pci_getl_func
)(bus
, dev
, func
, offset
);
244 gfxp_pci_write_byte(gfxp_acc_handle_t handle
, uint16_t offset
, uint8_t value
)
246 dev_info_t
*dip
= (dev_info_t
*)handle
;
247 uint8_t bus
, dev
, func
;
252 if (gfxp_pci_get_bsf(dip
, &bus
, &dev
, &func
) != DDI_SUCCESS
)
255 (*pci_putb_func
)(bus
, dev
, func
, offset
, value
);
259 gfxp_pci_write_word(gfxp_acc_handle_t handle
, uint16_t offset
, uint16_t value
)
261 dev_info_t
*dip
= (dev_info_t
*)handle
;
262 uint8_t bus
, dev
, func
;
267 if (gfxp_pci_get_bsf(dip
, &bus
, &dev
, &func
) != DDI_SUCCESS
)
270 (*pci_putw_func
)(bus
, dev
, func
, offset
, value
);
274 gfxp_pci_write_dword(gfxp_acc_handle_t handle
, uint16_t offset
, uint32_t value
)
276 dev_info_t
*dip
= (dev_info_t
*)handle
;
277 uint8_t bus
, dev
, func
;
282 if (gfxp_pci_get_bsf(dip
, &bus
, &dev
, &func
) != DDI_SUCCESS
)
285 (*pci_putl_func
)(bus
, dev
, func
, offset
, value
);
289 gfxp_pci_find_vd(dev_info_t
*dip
, void *arg
)
292 gfxp_pci_bsf_t
*pci_bsf
;
293 int vendor_id
, device_id
, class_code
;
296 * Look for vendor-id, device-id, class-code to verify
297 * this is some type of PCI child node.
299 vendor_id
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
301 device_id
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
303 class_code
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
, DDI_PROP_DONTPASS
,
305 if ((vendor_id
== -1) || (device_id
== -1) || (class_code
== -1)) {
306 return (DDI_WALK_CONTINUE
);
309 pci_bsf
= (gfxp_pci_bsf_t
*)arg
;
311 if ((vendor_id
== pci_bsf
->vendor
) && (device_id
== pci_bsf
->device
)) {
313 rc
= DDI_WALK_TERMINATE
;
315 rc
= DDI_WALK_CONTINUE
;
322 gfxp_pci_device_present(uint16_t vendor
, uint16_t device
)
324 gfxp_pci_bsf_t
*pci_bsf
;
328 * Find a PCI device based on its device and vendor id.
331 if ((pci_bsf
= kmem_zalloc(sizeof (gfxp_pci_bsf_t
), KM_SLEEP
)) == NULL
)
334 pci_bsf
->vendor
= vendor
;
335 pci_bsf
->device
= device
;
336 ddi_walk_devs(ddi_root_node(), gfxp_pci_find_vd
, pci_bsf
);
338 if (pci_bsf
->found
) {
344 kmem_free(pci_bsf
, sizeof (gfxp_pci_bsf_t
));