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 **)®s, &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)®spec, &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