xref: /gfx-drm/usr/src/uts/common/io/drm/drm_sun_pci.c (revision 47dc10d7)
1 /*
2  * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /*
25  * Copyright (c) 2012 Intel Corporation.  All rights reserved.
26  */
27 
28 #include <sys/types.h>
29 #include <sys/errno.h>
30 #include <sys/conf.h>
31 #include <sys/kmem.h>
32 #include <sys/visual_io.h>
33 #include <sys/fbio.h>
34 #include <sys/ddi.h>
35 #include <sys/sunddi.h>
36 #include <sys/stat.h>
37 #include <sys/file.h>
38 #include <sys/open.h>
39 #include <sys/modctl.h>
40 #include <sys/pci.h>
41 #include <sys/kd.h>
42 #include <sys/ddi_impldefs.h>
43 #include <sys/sunldi.h>
44 #include <sys/mkdev.h>
45 #include "drmP.h"
46 #include <sys/agpgart.h>
47 #include <sys/agp/agpdefs.h>
48 #include <sys/agp/agpmaster_io.h>
49 
50 #define	PCI_BUS(x)   (((x) & 0xff0000) >> 16)
51 #define	PCI_SLOT(x)  (((x)>>11) & 0x1f)
52 #define	PCI_FUNC(x)  (((x) & 0x700) >> 8)
53 
54 struct pci_dev *
pci_dev_create(struct drm_device * dev)55 pci_dev_create(struct drm_device *dev)
56 {
57 	dev_info_t *dip = dev->devinfo;
58 	pci_regspec_t *regspec;
59 	struct pci_dev *pdev;
60 	int *regs, ret, len, i;
61 	uint_t nregs = 0;
62 
63 	pdev = kmem_zalloc(sizeof(struct pci_dev), KM_NOSLEEP);
64 	if (!pdev)
65 		return (NULL);
66 
67 	/* access handle */
68 	ret = pci_config_setup(dip, &pdev->pci_cfg_acc_handle);
69 	if (ret != DDI_SUCCESS) {
70 		DRM_ERROR("pci_config_setup() failed");
71 		goto err_setup;
72 	}
73 
74 	/* XXX Fix domain number (alpha hoses) */
75 	pdev->domain = 0;
76 
77 	/* bus, slot, func */
78 	ret = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
79 	    DDI_PROP_DONTPASS, "reg", (int **)&regs, &nregs);
80 	if (ret != DDI_PROP_SUCCESS) {
81 		DRM_ERROR("ddi_prop_lookup_int_array() failed");
82 		goto err_info;
83 	}
84 	pdev->bus = (int)PCI_BUS(regs[0]);
85 	pdev->slot = (int)PCI_SLOT(regs[0]);
86 	pdev->func = (int)PCI_FUNC(regs[0]);
87 	ddi_prop_free(regs);
88 
89 	/* irq */
90 	ret = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
91 	    DDI_PROP_DONTPASS, "interrupts", -1);
92 	if (ret == -1) {
93 		DRM_ERROR("ddi_prop_get_int() failed");
94 		goto err_irq;
95 	}
96 	if (ret > 0)
97 		pdev->irq = pci_config_get8(pdev->pci_cfg_acc_handle, PCI_CONF_ILINE);
98 
99 	if (ddi_intr_hilevel(dip, 0) != 0) {
100 		DRM_ERROR("high-level interrupts are not supported");
101 		goto err_irq;
102 	}
103 
104 	if (ddi_get_iblock_cookie(dip, (uint_t)0,
105 	    &pdev->intr_block) != DDI_SUCCESS) {
106 		DRM_ERROR("cannot get iblock cookie");
107 		goto err_irq;
108 	}
109 
110 	/* regions */
111 	ret = ddi_getlongprop(DDI_DEV_T_ANY, dip,
112 	    DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&regspec, &len);
113 	if (ret != DDI_PROP_SUCCESS) {
114 		DRM_ERROR("ddi_getlongprop() failed");
115 		goto err_regions;
116 	}
117 	for (i = 0; i < PCI_CONFIG_REGION_NUMS; i++) {
118 		pdev->regions[i].start =
119 		    (unsigned long)regspec[i].pci_phys_low;
120 		pdev->regions[i].size =
121 		    (unsigned long)regspec[i].pci_size_low;
122 	}
123 	kmem_free(regspec, (size_t)len);
124 
125 	/* vendor, device */
126 	pdev->vendor = ddi_prop_get_int(DDI_DEV_T_ANY,
127 	    dev->devinfo, DDI_PROP_DONTPASS, "vendor-id", 0);
128 	pdev->device = ddi_prop_get_int(DDI_DEV_T_ANY,
129 	    dev->devinfo, DDI_PROP_DONTPASS, "device-id", 0);
130 
131 	pdev->dev = dev;
132 	return pdev;
133 
134 err_regions:
135 err_irq:
136 err_info:
137 	pci_config_teardown(&pdev->pci_cfg_acc_handle);
138 err_setup:
139 	kmem_free(pdev, sizeof(struct pci_dev));
140 	return (NULL);
141 }
142 
pci_dev_destroy(struct pci_dev * pdev)143 void pci_dev_destroy(struct pci_dev *pdev)
144 {
145 	pci_config_teardown(&pdev->pci_cfg_acc_handle);
146 	kmem_free(pdev, sizeof(struct pci_dev));
147 }
148 
pci_read_config_byte(struct pci_dev * pdev,int where,u8 * val)149 void pci_read_config_byte(struct pci_dev *pdev, int where, u8 *val)
150 {
151 	*val = pci_config_get8(pdev->pci_cfg_acc_handle, where);
152 }
153 
pci_read_config_word(struct pci_dev * pdev,int where,u16 * val)154 void pci_read_config_word(struct pci_dev *pdev, int where, u16 *val)
155 {
156 	*val = pci_config_get16(pdev->pci_cfg_acc_handle, where);
157 }
158 
pci_read_config_dword(struct pci_dev * pdev,int where,u32 * val)159 void pci_read_config_dword(struct pci_dev *pdev, int where, u32 *val)
160 {
161 	*val = pci_config_get32(pdev->pci_cfg_acc_handle, where);
162 }
163 
pci_write_config_byte(struct pci_dev * pdev,int where,u8 val)164 void pci_write_config_byte(struct pci_dev *pdev, int where, u8 val)
165 {
166 	pci_config_put8(pdev->pci_cfg_acc_handle, where, val);
167 }
168 
pci_write_config_word(struct pci_dev * pdev,int where,u16 val)169 void pci_write_config_word(struct pci_dev *pdev, int where, u16 val)
170 {
171 	pci_config_put16(pdev->pci_cfg_acc_handle, where, val);
172 }
173 
pci_write_config_dword(struct pci_dev * pdev,int where,u32 val)174 void pci_write_config_dword(struct pci_dev *pdev, int where, u32 val)
175 {
176 	pci_config_put32(pdev->pci_cfg_acc_handle, where, val);
177 }
178 
179 /* LINTED */
pci_map_rom(struct pci_dev * pdev,size_t * size)180 u8* pci_map_rom(struct pci_dev *pdev, size_t *size)
181 {
182 	u32 base;
183 
184 	base = 0xC0000;
185 	*size = 0x20000;
186 
187 	return (u8*)drm_sun_ioremap(base, *size, DRM_MEM_UNCACHED);
188 }
189 
190 /* LINTED */
pci_unmap_rom(struct pci_dev * pdev,u8 * base)191 void pci_unmap_rom(struct pci_dev *pdev, u8 *base)
192 {
193 	iounmap(base);
194 }
195 
pci_find_capability(struct pci_dev * pdev,int capid)196 int pci_find_capability(struct pci_dev *pdev, int capid)
197 {
198 	uint8_t cap = 0;
199 	uint16_t caps_ptr;
200 
201 	/* has capabilities list ? */
202 	if ((pci_config_get16(pdev->pci_cfg_acc_handle,
203 	    PCI_CONF_STAT) & PCI_CONF_CAP_MASK) == 0)
204 		return (0);
205 
206 	caps_ptr = pci_config_get8(
207 	    pdev->pci_cfg_acc_handle, PCI_CONF_CAP_PTR);
208 	while (caps_ptr != PCI_CAP_NEXT_PTR_NULL) {
209 		cap = pci_config_get32(
210 		    pdev->pci_cfg_acc_handle, caps_ptr);
211 		if ((cap & PCI_CONF_CAPID_MASK) == capid)
212 			return (cap);
213 		caps_ptr = pci_config_get8(
214 		    pdev->pci_cfg_acc_handle,
215 		    caps_ptr + PCI_CAP_NEXT_PTR);
216 	}
217 
218 	return (0);
219 }
220