1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2009, Intel Corporation.
24 * All Rights Reserved.
25 */
26
27 /*
28 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
29 * Use is subject to license terms.
30 */
31
32
33 #include <sys/systm.h>
34 #include <sys/conf.h>
35 #include <sys/modctl.h>
36 #include <sys/file.h>
37 #include <sys/stat.h>
38 #include <sys/ddi.h>
39 #include <sys/sunddi.h>
40 #include <sys/sunndi.h>
41 #include <sys/modctl.h>
42 #include <sys/sunldi.h>
43 #include <sys/pci.h>
44 #include <sys/agpgart.h>
45 #include <sys/agp/agpdefs.h>
46 #include <sys/agp/agptarget_io.h>
47
48 int agptarget_debug_var = 0;
49 #define TARGETDB_PRINT2(fmt) if (agptarget_debug_var >= 1) cmn_err fmt
50 #define INST2NODENUM(inst) (inst)
51 #define DEV2INST(dev) (getminor(dev))
52
53 #define I915_IFPADDR 0x60
54 #define I965_IFPADDR 0x70
55
56 #define HIADDR(n) ((uint32_t)(((uint64_t)(n) & \
57 0xFFFFFFFF00000000ULL) >> 32))
58 #define LOADDR(n) ((uint32_t)((uint64_t)(n) & 0x00000000FFFFFFFF))
59
60 typedef struct agp_target_softstate {
61 dev_info_t *tsoft_dip;
62 ddi_acc_handle_t tsoft_pcihdl;
63 uint32_t tsoft_devid;
64 /* The offset of the ACAPID register */
65 off_t tsoft_acaptr;
66 kmutex_t tsoft_lock;
67 int tsoft_gms_off; /* GMS offset in config */
68 uint32_t tsoft_gms;
69 }agp_target_softstate_t;
70
71 /*
72 * To get the pre-allocated graphics mem size using Graphics Mode Select
73 * (GMS) value.
74 */
75 typedef struct gms_mode {
76 uint32_t gm_devid; /* bridge vendor + device id */
77 off_t gm_regoff; /* mode selection register offset */
78 uint32_t gm_mask; /* GMS mask */
79 uint32_t gm_num; /* number of modes in gm_vec */
80 int *gm_vec; /* modes array */
81 } gms_mode_t;
82
83 static void *agptarget_glob_soft_handle;
84
85 #define GETSOFTC(instance) ((agp_target_softstate_t *) \
86 ddi_get_soft_state(agptarget_glob_soft_handle, instance));
87
88 /*
89 * The AMD8151 bridge is the only supported 64 bit hardware
90 */
91 static int
is_64bit_aper(agp_target_softstate_t * softstate)92 is_64bit_aper(agp_target_softstate_t *softstate)
93 {
94 return (softstate->tsoft_devid == AMD_BR_8151);
95 }
96
97 /*
98 * Check if it is an intel bridge
99 */
100 static int
is_intel_br(agp_target_softstate_t * softstate)101 is_intel_br(agp_target_softstate_t *softstate)
102 {
103 return ((softstate->tsoft_devid & VENDOR_ID_MASK) ==
104 INTEL_VENDOR_ID);
105 }
106
107 /*
108 * agp_target_cap_find()
109 *
110 * Description:
111 * This function searches the linked capability list to find the offset
112 * of the AGP capability register. When it was not found, return 0.
113 * This works for standard AGP chipsets, but not for some Intel chipsets,
114 * like the I830M/I830MP/I852PM/I852GME/I855GME. It will return 0 for
115 * these chipsets even if AGP is supported. So the offset of acapid
116 * should be set manually in thoses cases.
117 *
118 * Arguments:
119 * pci_handle ddi acc handle of pci config
120 *
121 * Returns:
122 * 0 No capability pointer register found
123 * nexcap The AGP capability pointer register offset
124 */
125 static off_t
agp_target_cap_find(ddi_acc_handle_t pci_handle)126 agp_target_cap_find(ddi_acc_handle_t pci_handle)
127 {
128 off_t nextcap = 0;
129 uint32_t ncapid = 0;
130 uint8_t value = 0;
131
132 /* Check if this device supports the capability pointer */
133 value = (uint8_t)(pci_config_get16(pci_handle, PCI_CONF_STAT)
134 & PCI_CONF_CAP_MASK);
135
136 if (!value)
137 return (0);
138 /* Get the offset of the first capability pointer from CAPPTR */
139 nextcap = (off_t)(pci_config_get8(pci_handle, AGP_CONF_CAPPTR));
140
141 /* Check the AGP capability from the first capability pointer */
142 while (nextcap) {
143 ncapid = pci_config_get32(pci_handle, nextcap);
144 /*
145 * AGP3.0 rev1.0 127 the capid was assigned by the PCI SIG,
146 * 845 data sheet page 69
147 */
148 if ((ncapid & PCI_CONF_CAPID_MASK) ==
149 AGP_CAP_ID) /* The AGP cap was found */
150 break;
151
152 nextcap = (off_t)((ncapid & PCI_CONF_NCAPID_MASK) >> 8);
153 }
154
155 return (nextcap);
156
157 }
158
159 /*
160 * agp_target_get_aperbase()
161 *
162 * Description:
163 * This function gets the AGP aperture base address from the AGP target
164 * register, the AGP aperture base register was programmed by the BIOS.
165 *
166 * Arguments:
167 * softstate driver soft state pointer
168 *
169 * Returns:
170 * aper_base AGP aperture base address
171 *
172 * Notes:
173 * If a 64bit bridge device is available, the AGP aperture base address
174 * can be 64 bit.
175 */
176 static uint64_t
agp_target_get_apbase(agp_target_softstate_t * softstate)177 agp_target_get_apbase(agp_target_softstate_t *softstate)
178 {
179 uint64_t aper_base;
180
181 if (is_intel_br(softstate)) {
182 aper_base = pci_config_get32(softstate->tsoft_pcihdl,
183 AGP_CONF_APERBASE) & AGP_32_APERBASE_MASK;
184 } else if (is_64bit_aper(softstate)) {
185 aper_base = pci_config_get64(softstate->tsoft_pcihdl,
186 AGP_CONF_APERBASE);
187 /* 32-bit or 64-bit aperbase base pointer */
188 if ((aper_base & AGP_APER_TYPE_MASK) == 0)
189 aper_base &= AGP_32_APERBASE_MASK;
190 else
191 aper_base &= AGP_64_APERBASE_MASK;
192 }
193
194 return (aper_base);
195 }
196
197 /*
198 * agp_target_get_apsize()
199 *
200 * Description:
201 * This function gets the AGP aperture size by reading the AGP aperture
202 * size register.
203 * Arguments:
204 * softstate driver soft state pointer
205 *
206 * Return:
207 * size The AGP aperture size in megabytes
208 * 0 an unexpected error
209 */
210 static size_t
agp_target_get_apsize(agp_target_softstate_t * softstate)211 agp_target_get_apsize(agp_target_softstate_t *softstate)
212 {
213 off_t cap;
214 uint16_t value;
215 size_t size, regsize;
216
217 ASSERT(softstate->tsoft_acaptr);
218 cap = softstate->tsoft_acaptr;
219
220 if (is_intel_br(softstate)) {
221 /* extend this value to 16 bit for later tests */
222 value = (uint16_t)pci_config_get8(softstate->tsoft_pcihdl,
223 cap + AGP_CONF_APERSIZE) | AGP_APER_SIZE_MASK;
224 } else if (is_64bit_aper(softstate)) {
225 value = pci_config_get16(softstate->tsoft_pcihdl,
226 cap + AGP_CONF_APERSIZE);
227 }
228
229 if (value & AGP_APER_128M_MASK) {
230 switch (value & AGP_APER_128M_MASK) {
231 case AGP_APER_4M:
232 size = 4; /* 4M */
233 break;
234 case AGP_APER_8M:
235 size = 8; /* 8M */
236 break;
237 case AGP_APER_16M:
238 size = 16; /* 16M */
239 break;
240 case AGP_APER_32M:
241 size = 32; /* 32M */
242 break;
243 case AGP_APER_64M:
244 size = 64; /* 64M */
245 break;
246 case AGP_APER_128M:
247 size = 128; /* 128M */
248 break;
249 default:
250 size = 0; /* not true */
251 }
252 } else {
253 switch (value & AGP_APER_4G_MASK) {
254 case AGP_APER_256M:
255 size = 256; /* 256 M */
256 break;
257 case AGP_APER_512M:
258 size = 512; /* 512 M */
259 break;
260 case AGP_APER_1024M:
261 size = 1024; /* 1024 M */
262 break;
263 case AGP_APER_2048M:
264 size = 2048; /* 2048 M */
265 break;
266 case AGP_APER_4G:
267 size = 4096; /* 4096 M */
268 break;
269 default:
270 size = 0; /* not true */
271 }
272 }
273 /*
274 * In some cases, there is no APSIZE register, so the size value
275 * of 256M could be wrong. Check the value by reading the size of
276 * the first register which was set in the PCI configuration space.
277 */
278 if (size == 256) {
279 if (ddi_dev_regsize(softstate->tsoft_dip,
280 AGP_TARGET_BAR1, (off_t *)®size) == DDI_FAILURE)
281 return (0);
282
283 if (MB2BYTES(size) != regsize) {
284 TARGETDB_PRINT2((CE_WARN,
285 "APSIZE 256M doesn't match regsize %lx",
286 regsize));
287 TARGETDB_PRINT2((CE_WARN, "Use regsize instead"));
288 size = BYTES2MB(regsize);
289 }
290 }
291
292 return (size);
293 }
294
295 static void
agp_target_set_gartaddr(agp_target_softstate_t * softstate,uint32_t gartaddr)296 agp_target_set_gartaddr(agp_target_softstate_t *softstate, uint32_t gartaddr)
297 {
298 ASSERT(softstate->tsoft_acaptr);
299
300 /* Disable the GTLB for Intel chipsets */
301 pci_config_put16(softstate->tsoft_pcihdl,
302 softstate->tsoft_acaptr + AGP_CONF_CONTROL, 0x0000);
303
304 pci_config_put32(softstate->tsoft_pcihdl,
305 softstate->tsoft_acaptr + AGP_CONF_ATTBASE,
306 gartaddr & AGP_ATTBASE_MASK);
307 }
308
309 /*
310 * Pre-allocated graphics memory for every type of Intel north bridge, mem size
311 * are specified in kbytes.
312 */
313 #define GMS_MB(n) ((n) * 1024)
314 #define GMS_SHIFT 4
315 #define GMS_SIZE(a) (sizeof (a) / sizeof (int))
316
317 /*
318 * Since value zero always means "No memory pre-allocated", value of (GMS - 1)
319 * is used to index these arrays, i.e. gms_xxx[1] contains the mem size (in kb)
320 * that GMS value 0x1 corresponding to.
321 *
322 * Assuming all "reserved" GMS value as zero bytes of pre-allocated graphics
323 * memory, unless some special BIOS settings exist.
324 */
325 static int gms_810[12] = {0, 0, 0, 0, 0, 0, 0, 512, 0, 0, 0, GMS_MB(1)};
326 static int gms_830_845[4] = {0, 512, GMS_MB(1), GMS_MB(8)};
327 static int gms_855GM[5] = {GMS_MB(1), GMS_MB(4), GMS_MB(8), GMS_MB(16),
328 GMS_MB(32)};
329 /* There is no modes for 16M in datasheet, but some BIOS add it. */
330 static int gms_865_915GM[4] = {GMS_MB(1), 0, GMS_MB(8), GMS_MB(16)};
331 static int gms_915_945_965[3] = {GMS_MB(1), 0, GMS_MB(8)};
332 static int gms_965GM[7] = {GMS_MB(1), GMS_MB(4), GMS_MB(8), GMS_MB(16),
333 GMS_MB(32), GMS_MB(48), GMS_MB(64)};
334 static int gms_X33[9] = {GMS_MB(1), GMS_MB(4), GMS_MB(8), GMS_MB(16),
335 GMS_MB(32), GMS_MB(48), GMS_MB(64), GMS_MB(128), GMS_MB(256)};
336 static int gms_G4X[13] = {0, 0, 0, 0,
337 GMS_MB(32), GMS_MB(48), GMS_MB(64), GMS_MB(128), GMS_MB(256),
338 GMS_MB(96), GMS_MB(160), GMS_MB(224), GMS_MB(352)};
339
340 static gms_mode_t gms_modes[] = {
341 {INTEL_BR_810, I810_CONF_SMRAM, I810_GMS_MASK,
342 GMS_SIZE(gms_810), gms_810},
343 {INTEL_BR_810DC, I810_CONF_SMRAM, I810_GMS_MASK,
344 GMS_SIZE(gms_810), gms_810},
345 {INTEL_BR_810E, I810_CONF_SMRAM, I810_GMS_MASK,
346 GMS_SIZE(gms_810), gms_810},
347 {INTEL_BR_830M, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
348 GMS_SIZE(gms_830_845), gms_830_845},
349 {INTEL_BR_845, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
350 GMS_SIZE(gms_830_845), gms_830_845},
351 {INTEL_BR_855GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
352 GMS_SIZE(gms_855GM), gms_855GM},
353 {INTEL_BR_865, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
354 GMS_SIZE(gms_865_915GM), gms_865_915GM},
355 {INTEL_BR_915GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
356 GMS_SIZE(gms_865_915GM), gms_865_915GM},
357 {INTEL_BR_915, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
358 GMS_SIZE(gms_915_945_965), gms_915_945_965},
359 {INTEL_BR_945, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
360 GMS_SIZE(gms_915_945_965), gms_915_945_965},
361 {INTEL_BR_945GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
362 GMS_SIZE(gms_915_945_965), gms_915_945_965},
363 {INTEL_BR_945GME, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
364 GMS_SIZE(gms_915_945_965), gms_915_945_965},
365 {INTEL_BR_946GZ, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
366 GMS_SIZE(gms_915_945_965), gms_915_945_965},
367 {INTEL_BR_965G1, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
368 GMS_SIZE(gms_915_945_965), gms_915_945_965},
369 {INTEL_BR_965G2, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
370 GMS_SIZE(gms_915_945_965), gms_915_945_965},
371 {INTEL_BR_965Q, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
372 GMS_SIZE(gms_915_945_965), gms_915_945_965},
373 {INTEL_BR_965GM, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
374 GMS_SIZE(gms_965GM), gms_965GM},
375 {INTEL_BR_965GME, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
376 GMS_SIZE(gms_965GM), gms_965GM},
377 {INTEL_BR_Q35, I8XX_CONF_GC, IX33_GC_MODE_MASK,
378 GMS_SIZE(gms_X33), gms_X33},
379 {INTEL_BR_G33, I8XX_CONF_GC, IX33_GC_MODE_MASK,
380 GMS_SIZE(gms_X33), gms_X33},
381 {INTEL_BR_Q33, I8XX_CONF_GC, IX33_GC_MODE_MASK,
382 GMS_SIZE(gms_X33), gms_X33},
383 {INTEL_BR_GM45, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
384 GMS_SIZE(gms_965GM), gms_965GM},
385 {INTEL_BR_EL, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
386 GMS_SIZE(gms_G4X), gms_G4X},
387 {INTEL_BR_Q45, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
388 GMS_SIZE(gms_G4X), gms_G4X},
389 {INTEL_BR_G45, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
390 GMS_SIZE(gms_G4X), gms_G4X},
391 {INTEL_BR_G41, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
392 GMS_SIZE(gms_G4X), gms_G4X},
393 {INTEL_BR_IGDNG_D, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
394 GMS_SIZE(gms_G4X), gms_G4X},
395 {INTEL_BR_IGDNG_M, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
396 GMS_SIZE(gms_G4X), gms_G4X},
397 {INTEL_BR_IGDNG_MA, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
398 GMS_SIZE(gms_G4X), gms_G4X},
399 {INTEL_BR_IGDNG_MC2, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
400 GMS_SIZE(gms_G4X), gms_G4X},
401 {INTEL_BR_B43, I8XX_CONF_GC, I8XX_GC_MODE_MASK,
402 GMS_SIZE(gms_G4X), gms_G4X}
403 };
404 static int
get_chip_gms(uint32_t devid)405 get_chip_gms(uint32_t devid)
406 {
407 int num_modes;
408 int i;
409
410 num_modes = (sizeof (gms_modes) / sizeof (gms_mode_t));
411
412 for (i = 0; i < num_modes; i++) {
413 if (gms_modes[i].gm_devid == devid)
414 break;
415 }
416
417 return ((i == num_modes) ? -1 : i);
418 }
419
420 /* Returns the size (kbytes) of pre-allocated graphics memory */
421 static size_t
i8xx_biosmem_detect(agp_target_softstate_t * softstate)422 i8xx_biosmem_detect(agp_target_softstate_t *softstate)
423 {
424 uint8_t memval;
425 size_t kbytes;
426 int gms_off;
427
428 kbytes = 0;
429 gms_off = softstate->tsoft_gms_off;
430
431 /* fetch the GMS value from DRAM controller */
432 memval = pci_config_get8(softstate->tsoft_pcihdl,
433 gms_modes[gms_off].gm_regoff);
434 TARGETDB_PRINT2((CE_NOTE, "i8xx_biosmem_detect: memval = %x", memval));
435 memval = (memval & gms_modes[gms_off].gm_mask) >> GMS_SHIFT;
436 /* assuming zero byte for 0 or "reserved" GMS values */
437 if (memval == 0 || memval > gms_modes[gms_off].gm_num) {
438 TARGETDB_PRINT2((CE_WARN, "i8xx_biosmem_detect: "
439 "devid = %x, GMS = %x. assuming zero byte of "
440 "pre-allocated memory",
441 gms_modes[gms_off].gm_devid, memval));
442 goto done;
443 }
444 memval--; /* use (GMS_value - 1) as index */
445 kbytes = (gms_modes[gms_off].gm_vec)[memval];
446
447 done:
448 TARGETDB_PRINT2((CE_NOTE,
449 "i8xx_biosmem_detect: %ldKB BIOS pre-allocated memory detected",
450 kbytes));
451 return (kbytes);
452 }
453
454 /*ARGSUSED*/
agptarget_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** resultp)455 static int agptarget_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd,
456 void *arg, void **resultp)
457 {
458 agp_target_softstate_t *st;
459 int instance, rval = DDI_FAILURE;
460 dev_t dev;
461
462 switch (cmd) {
463 case DDI_INFO_DEVT2DEVINFO:
464 dev = (dev_t)arg;
465 instance = DEV2INST(dev);
466 st = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
467 if (st != NULL) {
468 mutex_enter(&st->tsoft_lock);
469 *resultp = st->tsoft_dip;
470 mutex_exit(&st->tsoft_lock);
471 rval = DDI_SUCCESS;
472 } else
473 *resultp = NULL;
474
475 break;
476 case DDI_INFO_DEVT2INSTANCE:
477 dev = (dev_t)arg;
478 instance = DEV2INST(dev);
479 *resultp = (void *)(uintptr_t)instance;
480 rval = DDI_SUCCESS;
481 default:
482 break;
483 }
484
485 return (rval);
486 }
487
488 static int
intel_br_resume(agp_target_softstate_t * softstate)489 intel_br_resume(agp_target_softstate_t *softstate)
490 {
491 int gms_off;
492
493 gms_off = softstate->tsoft_gms_off;
494
495 /*
496 * We recover the gmch graphics control register here
497 */
498 pci_config_put16(softstate->tsoft_pcihdl,
499 gms_modes[gms_off].gm_regoff, softstate->tsoft_gms);
500
501 return (DDI_SUCCESS);
502 }
503 static int
intel_br_suspend(agp_target_softstate_t * softstate)504 intel_br_suspend(agp_target_softstate_t *softstate)
505 {
506 int gms_off;
507
508 gms_off = softstate->tsoft_gms_off;
509 softstate->tsoft_gms = pci_config_get16(softstate->tsoft_pcihdl,
510 gms_modes[gms_off].gm_regoff);
511
512 return (DDI_SUCCESS);
513 }
514
515 static int
agp_target_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)516 agp_target_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
517 {
518 agp_target_softstate_t *softstate;
519 int instance;
520 int status;
521
522 instance = ddi_get_instance(dip);
523
524 switch (cmd) {
525 case DDI_ATTACH:
526 break;
527 case DDI_RESUME:
528 softstate =
529 ddi_get_soft_state(agptarget_glob_soft_handle, instance);
530 return (intel_br_resume(softstate));
531 default:
532 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
533 "only attach and resume ops are supported"));
534 return (DDI_FAILURE);
535 }
536
537 if (ddi_soft_state_zalloc(agptarget_glob_soft_handle,
538 instance) != DDI_SUCCESS) {
539 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
540 "soft state zalloc failed"));
541 return (DDI_FAILURE);
542 }
543
544 softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
545 mutex_init(&softstate->tsoft_lock, NULL, MUTEX_DRIVER, NULL);
546 softstate->tsoft_dip = dip;
547 status = pci_config_setup(dip, &softstate->tsoft_pcihdl);
548 if (status != DDI_SUCCESS) {
549 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
550 "pci config setup failed"));
551 ddi_soft_state_free(agptarget_glob_soft_handle,
552 instance);
553 return (DDI_FAILURE);
554 }
555
556 softstate->tsoft_devid = pci_config_get32(softstate->tsoft_pcihdl,
557 PCI_CONF_VENID);
558 softstate->tsoft_gms_off = get_chip_gms(softstate->tsoft_devid);
559 if (softstate->tsoft_gms_off < 0) {
560 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
561 "read gms offset failed"));
562 pci_config_teardown(&softstate->tsoft_pcihdl);
563 ddi_soft_state_free(agptarget_glob_soft_handle,
564 instance);
565 return (DDI_FAILURE);
566 }
567 softstate->tsoft_acaptr = agp_target_cap_find(softstate->tsoft_pcihdl);
568 if (softstate->tsoft_acaptr == 0) {
569 /* Make a correction for some Intel chipsets */
570 if (is_intel_br(softstate))
571 softstate->tsoft_acaptr = AGP_CAP_OFF_DEF;
572 else {
573 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
574 "Not a supposed corretion"));
575 pci_config_teardown(&softstate->tsoft_pcihdl);
576 ddi_soft_state_free(agptarget_glob_soft_handle,
577 instance);
578 return (DDI_FAILURE);
579 }
580 }
581
582 status = ddi_create_minor_node(dip, AGPTARGET_NAME, S_IFCHR,
583 INST2NODENUM(instance), DDI_NT_AGP_TARGET, 0);
584
585 if (status != DDI_SUCCESS) {
586 TARGETDB_PRINT2((CE_WARN, "agp_target_attach:"
587 "Create minor node failed"));
588 pci_config_teardown(&softstate->tsoft_pcihdl);
589 ddi_soft_state_free(agptarget_glob_soft_handle, instance);
590 return (DDI_FAILURE);
591 }
592
593 return (DDI_SUCCESS);
594 }
595
596 /*ARGSUSED*/
597 static int
agp_target_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)598 agp_target_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
599 {
600 int instance;
601 agp_target_softstate_t *softstate;
602
603 instance = ddi_get_instance(dip);
604 softstate = ddi_get_soft_state(agptarget_glob_soft_handle, instance);
605
606 if (cmd == DDI_SUSPEND) {
607 /* get GMS modes list entry */
608 return (intel_br_suspend(softstate));
609 }
610
611 if (cmd != DDI_DETACH) {
612 TARGETDB_PRINT2((CE_WARN, "agp_target_detach:"
613 "only detach and suspend ops are supported"));
614 return (DDI_FAILURE);
615 }
616
617 ddi_remove_minor_node(dip, AGPTARGET_NAME);
618 pci_config_teardown(&softstate->tsoft_pcihdl);
619 mutex_destroy(&softstate->tsoft_lock);
620 ddi_soft_state_free(agptarget_glob_soft_handle, instance);
621 return (DDI_SUCCESS);
622 }
623
624 /*ARGSUSED*/
625 static int
agp_target_ioctl(dev_t dev,int cmd,intptr_t data,int mode,cred_t * cred,int * rval)626 agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
627 cred_t *cred, int *rval)
628 {
629 int instance = DEV2INST(dev);
630 agp_target_softstate_t *st;
631 static char kernel_only[] =
632 "amd64_gart_ioctl: is a kernel only ioctl";
633
634 if (!(mode & FKIOCTL)) {
635 TARGETDB_PRINT2((CE_CONT, kernel_only));
636 return (ENXIO);
637 }
638 st = GETSOFTC(instance);
639
640 if (st == NULL)
641 return (ENXIO);
642
643 mutex_enter(&st->tsoft_lock);
644
645 switch (cmd) {
646 case CHIP_DETECT:
647 {
648 int type = 0;
649
650 if (is_intel_br(st))
651 type = CHIP_IS_INTEL;
652 else if (is_64bit_aper(st))
653 type = CHIP_IS_AMD;
654 else {
655 type = 0;
656 TARGETDB_PRINT2((CE_WARN, "Unknown bridge!"));
657 }
658
659 if (ddi_copyout(&type, (void *)data, sizeof (int), mode)) {
660 mutex_exit(&st->tsoft_lock);
661 return (EFAULT);
662 }
663
664 break;
665 }
666 case I8XX_GET_PREALLOC_SIZE:
667 {
668 size_t prealloc_size;
669
670 if (!is_intel_br(st)) {
671 mutex_exit(&st->tsoft_lock);
672 return (EINVAL);
673 }
674
675 prealloc_size = i8xx_biosmem_detect(st);
676 if (ddi_copyout(&prealloc_size, (void *)data,
677 sizeof (size_t), mode)) {
678 mutex_exit(&st->tsoft_lock);
679 return (EFAULT);
680 }
681
682 break;
683 }
684 case AGP_TARGET_GETINFO:
685 {
686 i_agp_info_t info;
687 uint32_t value;
688 off_t cap;
689
690 ASSERT(st->tsoft_acaptr);
691
692 cap = st->tsoft_acaptr;
693 value = pci_config_get32(st->tsoft_pcihdl, cap);
694 info.iagp_ver.agpv_major = (uint16_t)((value >> 20) & 0xf);
695 info.iagp_ver.agpv_minor = (uint16_t)((value >> 16) & 0xf);
696 info.iagp_devid = st->tsoft_devid;
697 info.iagp_mode = pci_config_get32(st->tsoft_pcihdl,
698 cap + AGP_CONF_STATUS);
699 info.iagp_aperbase = agp_target_get_apbase(st);
700 info.iagp_apersize = agp_target_get_apsize(st);
701
702 if (ddi_copyout(&info, (void *)data,
703 sizeof (i_agp_info_t), mode)) {
704 mutex_exit(&st->tsoft_lock);
705 return (EFAULT);
706 }
707 break;
708
709 }
710 /*
711 * This ioctl is only for Intel AGP chipsets.
712 * It is not necessary for the AMD8151 AGP bridge, because
713 * this register in the AMD8151 does not control any hardware.
714 * It is only provided for compatibility with an Intel AGP bridge.
715 * Please refer to the <<AMD8151 data sheet>> page 24,
716 * AGP device GART pointer.
717 */
718 case AGP_TARGET_SET_GATTADDR:
719 {
720 uint32_t gartaddr;
721
722 if (ddi_copyin((void *)data, &gartaddr,
723 sizeof (uint32_t), mode)) {
724 mutex_exit(&st->tsoft_lock);
725 return (EFAULT);
726 }
727
728 agp_target_set_gartaddr(st, gartaddr);
729 break;
730 }
731 case AGP_TARGET_SETCMD:
732 {
733 uint32_t command;
734
735 if (ddi_copyin((void *)data, &command,
736 sizeof (uint32_t), mode)) {
737 mutex_exit(&st->tsoft_lock);
738 return (EFAULT);
739 }
740
741 ASSERT(st->tsoft_acaptr);
742
743 pci_config_put32(st->tsoft_pcihdl,
744 st->tsoft_acaptr + AGP_CONF_COMMAND,
745 command);
746 break;
747
748 }
749 case AGP_TARGET_FLUSH_GTLB:
750 {
751 uint16_t value;
752
753 ASSERT(st->tsoft_acaptr);
754
755 value = pci_config_get16(st->tsoft_pcihdl,
756 st->tsoft_acaptr + AGP_CONF_CONTROL);
757 value &= ~AGPCTRL_GTLBEN;
758 pci_config_put16(st->tsoft_pcihdl,
759 st->tsoft_acaptr + AGP_CONF_CONTROL, value);
760 value |= AGPCTRL_GTLBEN;
761 pci_config_put16(st->tsoft_pcihdl,
762 st->tsoft_acaptr + AGP_CONF_CONTROL, value);
763
764 break;
765 }
766 case AGP_TARGET_CONFIGURE:
767 {
768 uint8_t value;
769
770 ASSERT(st->tsoft_acaptr);
771
772 /*
773 * In Intel agp bridges, agp misc register offset
774 * is indexed from 0 instead of capability register.
775 * AMD agp bridges have no such misc register
776 * to control the aperture access, and they have
777 * similar regsiters in CPU gart devices instead.
778 */
779
780 if (is_intel_br(st)) {
781 value = pci_config_get8(st->tsoft_pcihdl,
782 st->tsoft_acaptr + AGP_CONF_MISC);
783 value |= AGP_MISC_APEN;
784 pci_config_put8(st->tsoft_pcihdl,
785 st->tsoft_acaptr + AGP_CONF_MISC, value);
786 }
787 break;
788
789 }
790 case AGP_TARGET_UNCONFIG:
791 {
792 uint32_t value1;
793 uint8_t value2;
794
795 ASSERT(st->tsoft_acaptr);
796
797 pci_config_put16(st->tsoft_pcihdl,
798 st->tsoft_acaptr + AGP_CONF_CONTROL, 0x0);
799
800 if (is_intel_br(st)) {
801 value2 = pci_config_get8(st->tsoft_pcihdl,
802 st->tsoft_acaptr + AGP_CONF_MISC);
803 value2 &= ~AGP_MISC_APEN;
804 pci_config_put8(st->tsoft_pcihdl,
805 st->tsoft_acaptr + AGP_CONF_MISC, value2);
806 }
807
808 value1 = pci_config_get32(st->tsoft_pcihdl,
809 st->tsoft_acaptr + AGP_CONF_COMMAND);
810 value1 &= ~AGPCMD_AGPEN;
811 pci_config_put32(st->tsoft_pcihdl,
812 st->tsoft_acaptr + AGP_CONF_COMMAND,
813 value1);
814
815 pci_config_put32(st->tsoft_pcihdl,
816 st->tsoft_acaptr + AGP_CONF_ATTBASE, 0x0);
817
818 break;
819 }
820
821 case INTEL_CHIPSET_FLUSH_SETUP:
822 case INTEL_CHIPSET_FLUSH:
823 case INTEL_CHIPSET_FLUSH_FREE:
824 break;
825 default:
826 mutex_exit(&st->tsoft_lock);
827 return (ENXIO);
828 } /* end switch */
829
830 mutex_exit(&st->tsoft_lock);
831
832 return (0);
833 }
834
835 /*ARGSUSED*/
836 static int
agp_target_open(dev_t * devp,int flag,int otyp,cred_t * cred)837 agp_target_open(dev_t *devp, int flag, int otyp, cred_t *cred)
838 {
839 int instance = DEV2INST(*devp);
840 agp_target_softstate_t *st;
841
842 if (!(flag & FKLYR))
843 return (ENXIO);
844
845 st = GETSOFTC(instance);
846
847 if (st == NULL)
848 return (ENXIO);
849
850 return (0);
851 }
852
853 /*ARGSUSED*/
854 static int
agp_target_close(dev_t dev,int flag,int otyp,cred_t * cred)855 agp_target_close(dev_t dev, int flag, int otyp, cred_t *cred)
856 {
857 int instance = DEV2INST(dev);
858 agp_target_softstate_t *st;
859
860 st = GETSOFTC(instance);
861
862 if (st == NULL)
863 return (ENXIO);
864
865 return (0);
866 }
867
868 static struct cb_ops agp_target_cb_ops = {
869 agp_target_open, /* cb_open */
870 agp_target_close, /* cb_close */
871 nodev, /* cb_strategy */
872 nodev, /* cb_print */
873 nodev, /* cb_dump */
874 nodev, /* cb_read() */
875 nodev, /* cb_write() */
876 agp_target_ioctl, /* cb_ioctl */
877 nodev, /* cb_devmap */
878 nodev, /* cb_mmap */
879 nodev, /* cb_segmap */
880 nochpoll, /* cb_chpoll */
881 ddi_prop_op, /* cb_prop_op */
882 0, /* cb_stream */
883 D_NEW | D_MP, /* cb_flag */
884 CB_REV, /* cb_ops version? */
885 nodev, /* cb_aread() */
886 nodev, /* cb_awrite() */
887 };
888
889 /* device operations */
890 static struct dev_ops agp_target_ops = {
891 DEVO_REV, /* devo_rev */
892 0, /* devo_refcnt */
893 agptarget_getinfo, /* devo_getinfo */
894 nulldev, /* devo_identify */
895 nulldev, /* devo_probe */
896 agp_target_attach, /* devo_attach */
897 agp_target_detach, /* devo_detach */
898 nodev, /* devo_reset */
899 &agp_target_cb_ops, /* devo_cb_ops */
900 0, /* devo_bus_ops */
901 0, /* devo_power */
902 ddi_quiesce_not_needed, /* devo_quiesce */
903 };
904
905 static struct modldrv modldrv = {
906 &mod_driverops,
907 "AGP target driver",
908 &agp_target_ops,
909 };
910
911 static struct modlinkage modlinkage = {
912 MODREV_1, /* MODREV_1 is indicated by manual */
913 {&modldrv, NULL, NULL, NULL}
914 };
915
916 int
_init(void)917 _init(void)
918 {
919 int ret;
920
921 ret = ddi_soft_state_init(&agptarget_glob_soft_handle,
922 sizeof (agp_target_softstate_t), 1);
923
924 if (ret)
925 goto err1;
926
927 if ((ret = mod_install(&modlinkage)) != 0) {
928 goto err2;
929 }
930
931 return (DDI_SUCCESS);
932 err2:
933 ddi_soft_state_fini(&agptarget_glob_soft_handle);
934 err1:
935 return (ret);
936 }
937
938 int
_info(struct modinfo * modinfop)939 _info(struct modinfo *modinfop)
940 {
941 return (mod_info(&modlinkage, modinfop));
942 }
943
944 int
_fini(void)945 _fini(void)
946 {
947 int ret;
948
949 if ((ret = mod_remove(&modlinkage)) == 0) {
950 ddi_soft_state_fini(&agptarget_glob_soft_handle);
951 }
952 return (ret);
953 }
954