8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / uts / intel / io / agpgart / amd64_gart.c
blobb374c875b538172eb6b7e4c26043046a0b7a9171
1 /*
2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 #include <sys/conf.h>
7 #include <sys/ddi.h>
8 #include <sys/sunddi.h>
9 #include <sys/modctl.h>
10 #include <sys/stat.h>
11 #include <sys/sunldi.h>
12 #include <sys/file.h>
13 #include <sys/agpgart.h>
14 #include <sys/agp/agpdefs.h>
15 #include <sys/agp/agpamd64gart_io.h>
17 #define MAX_GART_INSTS 8
18 #define GETSOFTC(instance) ((amd64_gart_softstate_t *) \
19 ddi_get_soft_state(amd64_gart_glob_soft_handle, (instance)));
20 #define DEV2INST(dev) (getminor(dev))
21 #define INST2NODENUM(inst) (inst)
23 int amd64_debug_var = 0;
24 #define AMD64DB_PRINT1(fmt) if (amd64_debug_var == 1) cmn_err fmt
25 #define AMD64DB_PRINT2(fmt) if (amd64_debug_var >= 1) cmn_err fmt
27 typedef struct amd64_gart_softstate {
28 dev_info_t *gsoft_dip;
29 ddi_acc_handle_t gsoft_pcihdl;
30 kmutex_t gsoft_lock;
31 }amd64_gart_softstate_t;
33 static void *amd64_gart_glob_soft_handle;
35 static uint64_t
36 amd64_get_aperbase(amd64_gart_softstate_t *sc)
38 uint32_t value;
39 uint64_t aper_base;
41 /* amd64 aperture base support 40 bits and 32M aligned */
42 value = pci_config_get32(sc->gsoft_pcihdl,
43 AMD64_APERTURE_BASE) & AMD64_APERBASE_MASK;
44 aper_base = (uint64_t)value << AMD64_APERBASE_SHIFT;
45 return (aper_base);
48 static size_t
49 amd64_get_apersize(amd64_gart_softstate_t *sc)
51 uint32_t value;
52 size_t size;
54 value = pci_config_get32(sc->gsoft_pcihdl, AMD64_APERTURE_CONTROL);
56 value = (value & AMD64_APERSIZE_MASK) >> 1;
58 /* aper size = 2^value x 32 */
59 switch (value) {
60 case 0x0:
61 size = 32;
62 break;
63 case 0x1:
64 size = 64;
65 break;
66 case 0x2:
67 size = 128;
68 break;
69 case 0x3:
70 size = 256;
71 break;
72 case 0x4:
73 size = 512;
74 break;
75 case 0x5:
76 size = 1024;
77 break;
78 case 0x6:
79 size = 2048;
80 break;
81 default: /* reserved */
82 size = 0;
85 return (size);
88 static void
89 amd64_invalidate_gtlb(amd64_gart_softstate_t *sc)
91 uint32_t value;
93 value = pci_config_get32(sc->gsoft_pcihdl, AMD64_GART_CACHE_CTL);
94 value |= AMD64_INVALID_CACHE;
96 pci_config_put32(sc->gsoft_pcihdl, AMD64_GART_CACHE_CTL, value);
99 static void
100 amd64_enable_gart(amd64_gart_softstate_t *sc, int enable)
102 uint32_t aper_ctl;
103 uint32_t aper_base;
104 uint32_t gart_ctl;
105 uint32_t gart_base;
107 aper_ctl = pci_config_get32(sc->gsoft_pcihdl, AMD64_APERTURE_CONTROL);
108 AMD64DB_PRINT1((CE_NOTE, "before: aper_ctl = %x", aper_ctl));
109 aper_base = pci_config_get32(sc->gsoft_pcihdl, AMD64_APERTURE_BASE);
110 gart_ctl = pci_config_get32(sc->gsoft_pcihdl, AMD64_GART_CACHE_CTL);
111 gart_base = pci_config_get32(sc->gsoft_pcihdl, AMD64_GART_BASE);
112 #ifdef lint
113 aper_base = aper_base;
114 gart_ctl = gart_ctl;
115 gart_base = gart_base;
116 #endif /* lint */
117 AMD64DB_PRINT1((CE_NOTE, "before: aper_base = %x", aper_base));
118 AMD64DB_PRINT1((CE_NOTE, "before: gart_ctl = %x", gart_ctl));
119 AMD64DB_PRINT1((CE_NOTE, "before: gart_base = %x", gart_base));
120 if (enable) {
121 aper_ctl |= AMD64_GARTEN;
122 aper_ctl &= ~(AMD64_DISGARTCPU | AMD64_DISGARTIO);
123 } else
124 aper_ctl &= (~AMD64_GARTEN);
126 pci_config_put32(sc->gsoft_pcihdl, AMD64_APERTURE_CONTROL, aper_ctl);
129 /*ARGSUSED*/
130 static int
131 amd64_gart_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd,
132 void *arg, void **resultp)
134 amd64_gart_softstate_t *st;
135 int instance, rval = DDI_FAILURE;
136 dev_t dev;
138 switch (cmd) {
139 case DDI_INFO_DEVT2DEVINFO:
140 dev = (dev_t)arg;
141 instance = DEV2INST(dev);
142 st = ddi_get_soft_state(amd64_gart_glob_soft_handle, instance);
143 if (st != NULL) {
144 mutex_enter(&st->gsoft_lock);
145 *resultp = st->gsoft_dip;
146 mutex_exit(&st->gsoft_lock);
147 rval = DDI_SUCCESS;
148 } else {
149 *resultp = NULL;
152 break;
153 case DDI_INFO_DEVT2INSTANCE:
154 dev = (dev_t)arg;
155 instance = DEV2INST(dev);
156 *resultp = (void *)(uintptr_t)instance;
157 rval = DDI_SUCCESS;
158 break;
159 default:
160 break;
163 return (rval);
166 static int
167 amd64_gart_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
169 int instance;
170 amd64_gart_softstate_t *sc;
171 int status;
172 char buf[80];
174 switch (cmd) {
175 default:
176 return (DDI_FAILURE);
178 case DDI_RESUME:
179 /* Nothing special is needed for resume. */
180 return (DDI_SUCCESS);
182 case DDI_ATTACH:
183 break;
186 instance = ddi_get_instance(dip);
188 if (ddi_soft_state_zalloc(amd64_gart_glob_soft_handle, instance) !=
189 DDI_SUCCESS)
190 return (DDI_FAILURE);
192 sc = ddi_get_soft_state(amd64_gart_glob_soft_handle, instance);
193 mutex_init(&sc->gsoft_lock, NULL, MUTEX_DRIVER, NULL);
194 sc->gsoft_dip = dip;
195 status = pci_config_setup(dip, &sc->gsoft_pcihdl);
196 if (status != DDI_SUCCESS) {
197 ddi_soft_state_free(amd64_gart_glob_soft_handle, instance);
198 return (DDI_FAILURE);
200 (void) sprintf(buf, "%s-%d", AMD64GART_NAME, instance);
201 status = ddi_create_minor_node(dip, buf, S_IFCHR,
202 INST2NODENUM(instance), DDI_NT_AGP_CPUGART, 0);
203 if (status != DDI_SUCCESS) {
204 pci_config_teardown(&sc->gsoft_pcihdl);
205 ddi_soft_state_free(amd64_gart_glob_soft_handle, instance);
206 return (DDI_FAILURE);
208 return (DDI_SUCCESS);
211 /*ARGSUSED*/
212 static int
213 amd64_gart_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
215 int instance;
216 amd64_gart_softstate_t *sc;
217 char buf[80];
219 switch (cmd) {
220 default:
221 return (DDI_FAILURE);
223 case DDI_SUSPEND:
224 /* Nothing special is needed for suspend */
225 return (DDI_SUCCESS);
227 case DDI_DETACH:
228 break;
231 instance = ddi_get_instance(dip);
232 sc = ddi_get_soft_state(amd64_gart_glob_soft_handle, instance);
234 (void) sprintf(buf, "%s-%d", AMD64GART_NAME, instance);
235 ddi_remove_minor_node(dip, buf);
236 pci_config_teardown(&sc->gsoft_pcihdl);
237 mutex_destroy(&sc->gsoft_lock);
238 ddi_soft_state_free(amd64_gart_glob_soft_handle, instance);
240 return (DDI_SUCCESS);
243 /*ARGSUSED*/
244 static int
245 amd64_gart_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
246 cred_t *cred, int *rval)
248 int instance;
249 amd64_gart_softstate_t *sc;
250 static char kernel_only[] =
251 "amd64_gart_ioctl: is a kernel only ioctl";
253 if (!(mode & FKIOCTL)) {
254 AMD64DB_PRINT2((CE_CONT, kernel_only));
255 return (ENXIO);
257 instance = DEV2INST(dev);
258 sc = GETSOFTC(instance);
260 if (sc == NULL)
261 return (ENXIO);
262 mutex_enter(&sc->gsoft_lock);
264 switch (cmd) {
265 case AMD64_GET_INFO:
267 amdgart_info_t info;
269 info.cgart_aperbase = amd64_get_aperbase(sc);
270 info.cgart_apersize = amd64_get_apersize(sc);
272 if (ddi_copyout(&info, (void *)data,
273 sizeof (amdgart_info_t), mode)) {
274 mutex_exit(&sc->gsoft_lock);
275 return (EFAULT);
277 break;
279 case AMD64_SET_GART_ADDR:
281 uint32_t addr;
283 if (ddi_copyin((void *)data, &addr, sizeof (uint32_t), mode)) {
284 mutex_exit(&sc->gsoft_lock);
285 return (EFAULT);
288 pci_config_put32(sc->gsoft_pcihdl, AMD64_GART_BASE, addr);
289 amd64_enable_gart(sc, 1);
291 break;
293 case AMD64_FLUSH_GTLB:
295 amd64_invalidate_gtlb(sc);
297 break;
299 case AMD64_CONFIGURE:
301 /* reserved */
302 break;
304 case AMD64_UNCONFIG:
306 amd64_enable_gart(sc, 0);
307 pci_config_put32(sc->gsoft_pcihdl, AMD64_GART_BASE, 0x00000000);
309 break;
311 default:
312 mutex_exit(&sc->gsoft_lock);
313 return (ENXIO);
317 mutex_exit(&sc->gsoft_lock);
319 return (0);
322 /*ARGSUSED*/
323 static int
324 amd64_gart_open(dev_t *dev, int flag, int otyp, cred_t *cred)
326 int instance;
327 amd64_gart_softstate_t *sc;
329 if (!(flag & FKLYR))
330 return (ENXIO);
332 instance = DEV2INST(*dev);
333 sc = GETSOFTC(instance);
335 if (sc == NULL)
336 return (ENXIO);
338 return (0);
341 /*ARGSUSED*/
342 static int
343 amd64_gart_close(dev_t dev, int flag, int otyp, cred_t *cred)
345 int instance;
346 amd64_gart_softstate_t *sc;
348 instance = DEV2INST(dev);
349 sc = GETSOFTC(instance);
351 if (sc == NULL)
352 return (ENXIO);
354 return (0);
357 static struct cb_ops amd64_gart_cb_ops = {
358 amd64_gart_open, /* cb_open() */
359 amd64_gart_close, /* cb_close() */
360 nodev, /* cb_strategy() */
361 nodev, /* cb_print */
362 nodev, /* cb_dump */
363 nodev, /* cb_read() */
364 nodev, /* cb_write() */
365 amd64_gart_ioctl, /* cb_ioctl */
366 nodev, /* cb_devmap */
367 nodev, /* cb_mmap */
368 nodev, /* cb_segmap */
369 nochpoll, /* cb_chpoll */
370 ddi_prop_op, /* cb_prop_op */
371 0, /* cb_stream */
372 D_NEW | D_MP, /* cb_flag */
373 CB_REV, /* cb_ops version? */
374 nodev, /* cb_aread() */
375 nodev, /* cb_awrite() */
378 /* device operations */
379 static struct dev_ops amd64_gart_ops = {
380 DEVO_REV, /* devo_rev */
381 0, /* devo_refcnt */
382 amd64_gart_getinfo, /* devo_getinfo */
383 nulldev, /* devo_identify */
384 nulldev, /* devo_probe */
385 amd64_gart_attach, /* devo_attach */
386 amd64_gart_detach, /* devo_detach */
387 nodev, /* devo_reset */
388 &amd64_gart_cb_ops, /* devo_cb_ops */
389 0, /* devo_bus_ops */
390 0, /* devo_power */
391 ddi_quiesce_not_needed, /* devo_quiesce */
394 static struct modldrv modldrv = {
395 &mod_driverops,
396 "AGP AMD gart driver",
397 &amd64_gart_ops,
400 static struct modlinkage modlinkage = {
401 MODREV_1, /* MODREV_1 is indicated by manual */
402 &modldrv,
403 NULL
408 _init(void)
410 int ret = DDI_SUCCESS;
412 ret = ddi_soft_state_init(&amd64_gart_glob_soft_handle,
413 sizeof (amd64_gart_softstate_t),
414 MAX_GART_INSTS);
416 if (ret)
417 return (ret);
418 if ((ret = mod_install(&modlinkage)) != 0) {
419 ddi_soft_state_fini(&amd64_gart_glob_soft_handle);
420 return (ret);
422 return (DDI_SUCCESS);
426 _info(struct modinfo *modinfop)
428 return (mod_info(&modlinkage, modinfop));
432 _fini(void)
434 int ret;
435 if ((ret = mod_remove(&modlinkage)) == 0) {
436 ddi_soft_state_fini(&amd64_gart_glob_soft_handle);
438 return (ret);