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 2009 Sun Microsystems, Inc. All rights reserved.
29 * Use is subject to license terms.
30 */
31
32 /*
33 * Misc module for AGP master device support
34 */
35
36 #include <sys/modctl.h>
37 #include <sys/pci.h>
38 #include <sys/stat.h>
39 #include <sys/file.h>
40 #include <sys/types.h>
41 #include <sys/dditypes.h>
42 #include <sys/sunddi.h>
43 #include <sys/agpgart.h>
44 #include <sys/agp/agpdefs.h>
45 #include <sys/agp/agpmaster_io.h>
46
47 #define PGTBL_CTL 0x2020 /* Page table control register */
48 #define I8XX_FB_BAR 1
49 #define I8XX_MMIO_BAR 2
50 #define I8XX_PTE_OFFSET 0x10000
51 #define I915_MMADR 1 /* mem-mapped registers BAR */
52 #define I915_GMADR 3 /* graphics mem BAR */
53 #define I915_GTTADDR 4 /* GTT BAR */
54 #define I965_GTTMMADR 1 /* mem-mapped registers BAR + GTT */
55 /* In 965 1MB GTTMMADR, GTT reside in the latter 512KB */
56 #define I965_GTT_OFFSET 0x80000
57 #define GM45_GTT_OFFSET 0x200000
58 #define GTT_SIZE_MASK 0xe
59 #define GTT_512KB (0 << 1)
60 #define GTT_256KB (1 << 1)
61 #define GTT_128KB (2 << 1)
62 #define GTT_1MB (3 << 1)
63 #define GTT_2MB (4 << 1)
64 #define GTT_1_5MB (5 << 1)
65
66 #define MMIO_BASE(x) (x)->agpm_data.agpm_gtt.gtt_mmio_base
67 #define MMIO_HANDLE(x) (x)->agpm_data.agpm_gtt.gtt_mmio_handle
68 #define GTT_HANDLE(x) (x)->agpm_data.agpm_gtt.gtt_handle
69 /* Base address of GTT */
70 #define GTT_ADDR(x) (x)->agpm_data.agpm_gtt.gtt_addr
71 /* Graphics memory base address */
72 #define APER_BASE(x) (x)->agpm_data.agpm_gtt.gtt_info.igd_aperbase
73
74 #define AGPM_WRITE(x, off, val) \
75 ddi_put32(MMIO_HANDLE(x), (uint32_t *)(MMIO_BASE(x) + (off)), (val));
76
77 #define AGPM_READ(x, off) \
78 ddi_get32(MMIO_HANDLE(x), (uint32_t *)(MMIO_BASE(x) + (off)));
79
80 #ifdef DEBUG
81 #define CONFIRM(value) ASSERT(value)
82 #else
83 #define CONFIRM(value) if (!(value)) return (EINVAL)
84 #endif
85
86 int agpm_debug = 0;
87 #define AGPM_DEBUG(args) if (agpm_debug >= 1) cmn_err args
88
89 /*
90 * Whether it is a Intel integrated graphics card
91 */
92 #define IS_IGD(agpmaster) ((agpmaster->agpm_dev_type == DEVICE_IS_I810) || \
93 (agpmaster->agpm_dev_type == DEVICE_IS_I830))
94
95 static struct modlmisc modlmisc = {
96 &mod_miscops, "AGP master interfaces"
97 };
98
99 static struct modlinkage modlinkage = {
100 MODREV_1, (void *)&modlmisc, NULL
101 };
102
103 static ddi_device_acc_attr_t i8xx_dev_access = {
104 DDI_DEVICE_ATTR_V0,
105 DDI_NEVERSWAP_ACC,
106 DDI_STRICTORDER_ACC
107 };
108
109 static off_t agpmaster_cap_find(ddi_acc_handle_t);
110 static int detect_i8xx_device(agp_master_softc_t *);
111 static int detect_agp_devcice(agp_master_softc_t *, ddi_acc_handle_t);
112 static int i8xx_add_to_gtt(gtt_impl_t *, igd_gtt_seg_t);
113 static void i8xx_remove_from_gtt(gtt_impl_t *, igd_gtt_seg_t);
114
115 int
_init(void)116 _init(void)
117 {
118 int err;
119
120 if ((err = mod_install(&modlinkage)) != 0)
121 return (err);
122
123 return (0);
124 }
125
126 int
_fini(void)127 _fini(void)
128 {
129 int err;
130
131 if ((err = mod_remove(&modlinkage)) != 0)
132 return (err);
133
134 return (0);
135 }
136
137 int
_info(struct modinfo * modinfop)138 _info(struct modinfo *modinfop)
139 {
140 return (mod_info(&modlinkage, modinfop));
141 }
142
143 /*
144 * Minor node is not removed here, since the caller (xx_attach) is
145 * responsible for removing all nodes.
146 */
147 void
agpmaster_detach(agp_master_softc_t ** master_softcp)148 agpmaster_detach(agp_master_softc_t **master_softcp)
149 {
150 agp_master_softc_t *master_softc;
151
152 ASSERT(master_softcp);
153 master_softc = *master_softcp;
154
155 /* intel integrated device */
156 if (IS_IGD(master_softc) &&
157 ((MMIO_HANDLE(master_softc) != NULL) ||
158 (GTT_HANDLE(master_softc) != NULL))) {
159 /*
160 * for some chipsets, mmap handle is shared between both mmio
161 * and GTT table.
162 */
163 if ((GTT_HANDLE(master_softc) != MMIO_HANDLE(master_softc)) &&
164 (GTT_HANDLE(master_softc) != NULL))
165 ddi_regs_map_free(>T_HANDLE(master_softc));
166 if (MMIO_HANDLE(master_softc) != NULL)
167 ddi_regs_map_free(&MMIO_HANDLE(master_softc));
168 }
169
170 kmem_free(master_softc, sizeof (agp_master_softc_t));
171 master_softc = NULL;
172
173 return;
174
175 }
176
177 /*
178 * 965 has a fixed GTT table size (512KB), so check to see the actual aperture
179 * size. Aperture size = GTT table size * 1024.
180 */
181 static off_t
i965_apersize(agp_master_softc_t * agpmaster)182 i965_apersize(agp_master_softc_t *agpmaster)
183 {
184 off_t apersize;
185
186 apersize = AGPM_READ(agpmaster, PGTBL_CTL);
187 AGPM_DEBUG((CE_NOTE, "i965_apersize: PGTBL_CTL = %lx", apersize));
188 switch (apersize & GTT_SIZE_MASK) {
189 case GTT_2MB:
190 apersize = 2048;
191 break;
192 case GTT_1_5MB:
193 apersize = 1536;
194 break;
195 case GTT_1MB:
196 apersize = 1024;
197 break;
198 case GTT_512KB:
199 apersize = 512;
200 break;
201 case GTT_256KB:
202 apersize = 256;
203 break;
204 case GTT_128KB:
205 apersize = 128;
206 break;
207 default:
208 apersize = 0;
209 AGPM_DEBUG((CE_WARN,
210 "i965_apersize: invalid GTT size in PGTBL_CTL"));
211 }
212 return (apersize);
213 }
214
215 /*
216 * For Intel 3 series, we need to get GTT size from the GGMS field in GMCH
217 * Graphics Control Register. Return aperture size in MB.
218 */
219 static off_t
i3XX_apersize(ddi_acc_handle_t pci_acc_hdl)220 i3XX_apersize(ddi_acc_handle_t pci_acc_hdl)
221 {
222 uint16_t value;
223 off_t apersize;
224
225 /*
226 * Get the value of configuration register MGGC "Mirror of Dev0 GMCH
227 * Graphics Control" from Internal Graphics #2 (Device2:Function0).
228 */
229 value = pci_config_get16(pci_acc_hdl, I8XX_CONF_GC);
230 AGPM_DEBUG((CE_NOTE, "i3XX_apersize: MGGC = 0x%x", value));
231 /* computing aperture size using the pre-allocated GTT size */
232 switch (value & IX33_GGMS_MASK) {
233 case IX33_GGMS_1M:
234 apersize = 1024;
235 break;
236 case IX33_GGMS_2M:
237 apersize = 2048;
238 break;
239 default:
240 apersize = 0; /* no memory pre-allocated */
241 AGPM_DEBUG((CE_WARN,
242 "i3XX_apersize: no memory allocated for GTT"));
243 }
244 AGPM_DEBUG((CE_NOTE, "i3xx_apersize: apersize = %ldM", apersize));
245 return (apersize);
246 }
247
248 #define CHECK_STATUS(status) \
249 if (status != DDI_SUCCESS) { \
250 AGPM_DEBUG((CE_WARN, \
251 "set_gtt_mmio: regs_map_setup error")); \
252 return (-1); \
253 }
254 /*
255 * Set gtt_addr, gtt_mmio_base, igd_apersize, igd_aperbase and igd_devid
256 * according to chipset.
257 */
258 static int
set_gtt_mmio(dev_info_t * devi,agp_master_softc_t * agpmaster,ddi_acc_handle_t pci_acc_hdl)259 set_gtt_mmio(dev_info_t *devi, agp_master_softc_t *agpmaster,
260 ddi_acc_handle_t pci_acc_hdl)
261 {
262 off_t apersize; /* size of graphics mem (MB) == GTT size (KB) */
263 uint32_t value;
264 off_t gmadr_off; /* GMADR offset in PCI config space */
265 int status;
266
267 if (IS_INTEL_X33(agpmaster->agpm_id)) {
268 /* Intel 3 series are similar with 915/945 series */
269 status = ddi_regs_map_setup(devi, I915_GTTADDR,
270 >T_ADDR(agpmaster), 0, 0, &i8xx_dev_access,
271 >T_HANDLE(agpmaster));
272 CHECK_STATUS(status);
273
274 status = ddi_regs_map_setup(devi, I915_MMADR,
275 &MMIO_BASE(agpmaster), 0, 0, &i8xx_dev_access,
276 &MMIO_HANDLE(agpmaster));
277 CHECK_STATUS(status);
278
279 gmadr_off = I915_CONF_GMADR;
280 /* Different computing method used in getting aperture size. */
281 apersize = i3XX_apersize(pci_acc_hdl);
282 } else if (IS_INTEL_965(agpmaster->agpm_id)) {
283 status = ddi_regs_map_setup(devi, I965_GTTMMADR,
284 &MMIO_BASE(agpmaster), 0, 0, &i8xx_dev_access,
285 &MMIO_HANDLE(agpmaster));
286 CHECK_STATUS(status);
287 if ((agpmaster->agpm_id == INTEL_IGD_GM45) ||
288 IS_INTEL_G4X(agpmaster->agpm_id))
289 GTT_ADDR(agpmaster) =
290 MMIO_BASE(agpmaster) + GM45_GTT_OFFSET;
291 else
292 GTT_ADDR(agpmaster) =
293 MMIO_BASE(agpmaster) + I965_GTT_OFFSET;
294 GTT_HANDLE(agpmaster) = MMIO_HANDLE(agpmaster);
295
296 gmadr_off = I915_CONF_GMADR;
297 apersize = i965_apersize(agpmaster);
298 } else if (IS_INTEL_915(agpmaster->agpm_id)) {
299 /* I915/945 series */
300 status = ddi_regs_map_setup(devi, I915_GTTADDR,
301 >T_ADDR(agpmaster), 0, 0, &i8xx_dev_access,
302 >T_HANDLE(agpmaster));
303 CHECK_STATUS(status);
304
305 status = ddi_regs_map_setup(devi, I915_MMADR,
306 &MMIO_BASE(agpmaster), 0, 0, &i8xx_dev_access,
307 &MMIO_HANDLE(agpmaster));
308 CHECK_STATUS(status);
309
310 gmadr_off = I915_CONF_GMADR;
311 status = ddi_dev_regsize(devi, I915_GMADR, &apersize);
312 apersize = BYTES2MB(apersize);
313 } else {
314 /* I8XX series */
315 status = ddi_regs_map_setup(devi, I8XX_MMIO_BAR,
316 &MMIO_BASE(agpmaster), 0, 0, &i8xx_dev_access,
317 &MMIO_HANDLE(agpmaster));
318 CHECK_STATUS(status);
319
320 GTT_ADDR(agpmaster) = MMIO_BASE(agpmaster) + I8XX_PTE_OFFSET;
321 GTT_HANDLE(agpmaster) = MMIO_HANDLE(agpmaster);
322 gmadr_off = I8XX_CONF_GMADR;
323 status = ddi_dev_regsize(devi, I8XX_FB_BAR, &apersize);
324 apersize = BYTES2MB(apersize);
325 CHECK_STATUS(status);
326 }
327
328 /*
329 * If memory size is smaller than a certain value, it means
330 * the register set number for graphics memory range might
331 * be wrong
332 */
333 if (status != DDI_SUCCESS || apersize < 4) {
334 AGPM_DEBUG((CE_WARN,
335 "set_gtt_mmio: error in getting graphics memory"));
336 return (-1);
337 }
338
339 agpmaster->agpm_data.agpm_gtt.gtt_info.igd_apersize = apersize;
340
341 /* get graphics memory base address from GMADR */
342 value = pci_config_get32(pci_acc_hdl, gmadr_off);
343 APER_BASE(agpmaster) = value & GTT_BASE_MASK;
344 AGPM_DEBUG((CE_NOTE, "set_gtt_mmio: aperbase = 0x%x, apersize = %ldM, "
345 "gtt_addr = %p, mmio_base = %p", APER_BASE(agpmaster), apersize,
346 (void *)GTT_ADDR(agpmaster), (void *)MMIO_BASE(agpmaster)));
347 return (0);
348 }
349
350 /*
351 * Try to initialize agp master.
352 * 0 is returned if the device is successfully initialized. AGP master soft
353 * state is returned in master_softcp if needed.
354 * Otherwise -1 is returned and *master_softcp is set to NULL.
355 */
356 int
agpmaster_attach(dev_info_t * devi,agp_master_softc_t ** master_softcp,ddi_acc_handle_t pci_acc_hdl,minor_t minor)357 agpmaster_attach(dev_info_t *devi, agp_master_softc_t **master_softcp,
358 ddi_acc_handle_t pci_acc_hdl, minor_t minor)
359 {
360 int instance;
361 int status;
362 agp_master_softc_t *agpmaster;
363 char buf[80];
364
365
366 ASSERT(pci_acc_hdl);
367 *master_softcp = NULL;
368 agpmaster = (agp_master_softc_t *)
369 kmem_zalloc(sizeof (agp_master_softc_t), KM_SLEEP);
370
371 agpmaster->agpm_id =
372 pci_config_get32(pci_acc_hdl, PCI_CONF_VENID);
373 agpmaster->agpm_acc_hdl = pci_acc_hdl;
374
375 if (!detect_i8xx_device(agpmaster)) {
376 /* Intel 8XX, 915, 945 and 965 series */
377 if (set_gtt_mmio(devi, agpmaster, pci_acc_hdl) != 0)
378 goto fail;
379 } else if (detect_agp_devcice(agpmaster, pci_acc_hdl)) {
380 /* non IGD or AGP devices, AMD64 gart */
381 AGPM_DEBUG((CE_WARN,
382 "agpmaster_attach: neither IGD or AGP devices exists"));
383 agpmaster_detach(&agpmaster);
384 return (0);
385 }
386
387 agpmaster->agpm_data.agpm_gtt.gtt_info.igd_devid =
388 agpmaster->agpm_id;
389
390 /* create minor node for IGD or AGP device */
391 instance = ddi_get_instance(devi);
392
393 (void) sprintf(buf, "%s%d", AGPMASTER_NAME, instance);
394 status = ddi_create_minor_node(devi, buf, S_IFCHR, minor,
395 DDI_NT_AGP_MASTER, 0);
396
397 if (status != DDI_SUCCESS) {
398 AGPM_DEBUG((CE_WARN,
399 "agpmaster_attach: create agpmaster node failed"));
400 goto fail;
401 }
402
403 *master_softcp = agpmaster;
404 return (0);
405 fail:
406 agpmaster_detach(&agpmaster);
407 return (-1);
408 }
409
410 /*
411 * Currently, it handles ioctl requests related with agp master device for
412 * layered driver (agpgart) only.
413 */
414 /*ARGSUSED*/
415 int
agpmaster_ioctl(dev_t dev,int cmd,intptr_t data,int mode,cred_t * cred,int * rval,agp_master_softc_t * softc)416 agpmaster_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *cred,
417 int *rval, agp_master_softc_t *softc)
418 {
419 uint32_t base;
420 uint32_t addr;
421 igd_gtt_seg_t seg;
422 agp_info_t info;
423 uint32_t value;
424 off_t cap;
425 uint32_t command;
426 static char kernel_only[] =
427 "agpmaster_ioctl: %s is a kernel only ioctl";
428
429 CONFIRM(softc);
430
431 switch (cmd) {
432 case DEVICE_DETECT:
433 if (!(mode & FKIOCTL)) {
434 AGPM_DEBUG((CE_CONT, kernel_only, "DEVICE_DETECT"));
435 return (ENXIO);
436 }
437
438 if (ddi_copyout(&softc->agpm_dev_type,
439 (void *)data, sizeof (int), mode))
440 return (EFAULT);
441 break;
442 case AGP_MASTER_SETCMD:
443 if (!(mode & FKIOCTL)) {
444 AGPM_DEBUG((CE_CONT, kernel_only, "AGP_MASTER_SETCMD"));
445 return (ENXIO);
446 }
447
448 CONFIRM(softc->agpm_dev_type == DEVICE_IS_AGP);
449 CONFIRM(softc->agpm_data.agpm_acaptr);
450
451 if (ddi_copyin((void *)data, &command,
452 sizeof (uint32_t), mode))
453 return (EFAULT);
454
455 pci_config_put32(softc->agpm_acc_hdl,
456 softc->agpm_data.agpm_acaptr + AGP_CONF_COMMAND,
457 command);
458 break;
459 case AGP_MASTER_GETINFO:
460 if (!(mode & FKIOCTL)) {
461 AGPM_DEBUG((CE_CONT, kernel_only,
462 "AGP_MASTER_GETINFO"));
463 return (ENXIO);
464 }
465
466 CONFIRM(softc->agpm_dev_type == DEVICE_IS_AGP);
467 CONFIRM(softc->agpm_data.agpm_acaptr);
468
469 cap = softc->agpm_data.agpm_acaptr;
470 value = pci_config_get32(softc->agpm_acc_hdl, cap);
471 info.agpi_version.agpv_major = (uint16_t)((value >> 20) & 0xf);
472 info.agpi_version.agpv_minor = (uint16_t)((value >> 16) & 0xf);
473 info.agpi_devid = softc->agpm_id;
474 info.agpi_mode = pci_config_get32(
475 softc->agpm_acc_hdl, cap + AGP_CONF_STATUS);
476
477 if (ddi_copyout(&info, (void *)data,
478 sizeof (agp_info_t), mode))
479 return (EFAULT);
480 break;
481 case I810_SET_GTT_BASE:
482 if (!(mode & FKIOCTL)) {
483 AGPM_DEBUG((CE_CONT, kernel_only, "I810_SET_GTT_ADDR"));
484 return (ENXIO);
485 }
486
487 CONFIRM(softc->agpm_dev_type == DEVICE_IS_I810);
488
489 if (ddi_copyin((void *)data, &base, sizeof (uint32_t), mode))
490 return (EFAULT);
491
492 /* enables page table */
493 addr = (base & GTT_BASE_MASK) | GTT_TABLE_VALID;
494
495 AGPM_WRITE(softc, PGTBL_CTL, addr);
496 break;
497 case I8XX_GET_INFO:
498 if (!(mode & FKIOCTL)) {
499 AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_GET_INFO"));
500 return (ENXIO);
501 }
502
503 CONFIRM(IS_IGD(softc));
504
505 if (ddi_copyout(&softc->agpm_data.agpm_gtt.gtt_info,
506 (void *)data, sizeof (igd_info_t), mode))
507 return (EFAULT);
508 break;
509 case I8XX_ADD2GTT:
510 if (!(mode & FKIOCTL)) {
511 AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_ADD2GTT"));
512 return (ENXIO);
513 }
514
515 CONFIRM(IS_IGD(softc));
516
517 if (ddi_copyin((void *)data, &seg,
518 sizeof (igd_gtt_seg_t), mode))
519 return (EFAULT);
520
521 if (i8xx_add_to_gtt(&softc->agpm_data.agpm_gtt, seg))
522 return (EINVAL);
523 break;
524 case I8XX_REM_GTT:
525 if (!(mode & FKIOCTL)) {
526 AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_REM_GTT"));
527 return (ENXIO);
528 }
529
530 CONFIRM(IS_IGD(softc));
531
532 if (ddi_copyin((void *)data, &seg,
533 sizeof (igd_gtt_seg_t), mode))
534 return (EFAULT);
535
536 i8xx_remove_from_gtt(&softc->agpm_data.agpm_gtt, seg);
537 break;
538 case I8XX_UNCONFIG:
539 if (!(mode & FKIOCTL)) {
540 AGPM_DEBUG((CE_CONT, kernel_only, "I8XX_UNCONFIG"));
541 return (ENXIO);
542 }
543
544 CONFIRM(IS_IGD(softc));
545
546 if (softc->agpm_dev_type == DEVICE_IS_I810)
547 AGPM_WRITE(softc, PGTBL_CTL, 0);
548 /*
549 * may need to clear all gtt entries here for i830 series,
550 * but may not be necessary
551 */
552 break;
553 }
554 return (0);
555 }
556
557 /*
558 * If AGP cap pointer is successfully found, none-zero value is returned.
559 * Otherwise 0 is returned.
560 */
561 static off_t
agpmaster_cap_find(ddi_acc_handle_t acc_handle)562 agpmaster_cap_find(ddi_acc_handle_t acc_handle)
563 {
564 off_t nextcap;
565 uint32_t ncapid;
566 uint8_t value;
567
568 /* check if this device supports capibility pointer */
569 value = (uint8_t)(pci_config_get16(acc_handle, PCI_CONF_STAT)
570 & PCI_CONF_CAP_MASK);
571
572 if (!value)
573 return (0);
574 /* get the offset of the first capability pointer from CAPPTR */
575 nextcap = (off_t)(pci_config_get8(acc_handle, AGP_CONF_CAPPTR));
576
577 /* check AGP capability from the first capability pointer */
578 while (nextcap) {
579 ncapid = pci_config_get32(acc_handle, nextcap);
580 if ((ncapid & PCI_CONF_CAPID_MASK)
581 == AGP_CAP_ID) /* find AGP cap */
582 break;
583
584 nextcap = (off_t)((ncapid & PCI_CONF_NCAPID_MASK) >> 8);
585 }
586
587 return (nextcap);
588
589 }
590
591 /*
592 * If i8xx device is successfully detected, 0 is returned.
593 * Otherwise -1 is returned.
594 */
595 static int
detect_i8xx_device(agp_master_softc_t * master_softc)596 detect_i8xx_device(agp_master_softc_t *master_softc)
597 {
598
599 switch (master_softc->agpm_id) {
600 case INTEL_IGD_810:
601 case INTEL_IGD_810DC:
602 case INTEL_IGD_810E:
603 case INTEL_IGD_815:
604 master_softc->agpm_dev_type = DEVICE_IS_I810;
605 break;
606 case INTEL_IGD_830M:
607 case INTEL_IGD_845G:
608 case INTEL_IGD_855GM:
609 case INTEL_IGD_865G:
610 case INTEL_IGD_915:
611 case INTEL_IGD_915GM:
612 case INTEL_IGD_945:
613 case INTEL_IGD_945GM:
614 case INTEL_IGD_945GME:
615 case INTEL_IGD_946GZ:
616 case INTEL_IGD_965G1:
617 case INTEL_IGD_965G2:
618 case INTEL_IGD_965GM:
619 case INTEL_IGD_965GME:
620 case INTEL_IGD_965Q:
621 case INTEL_IGD_Q35:
622 case INTEL_IGD_G33:
623 case INTEL_IGD_Q33:
624 case INTEL_IGD_GM45:
625 case INTEL_IGD_EL:
626 case INTEL_IGD_Q45:
627 case INTEL_IGD_G45:
628 case INTEL_IGD_G41:
629 case INTEL_IGD_IGDNG_D:
630 case INTEL_IGD_IGDNG_M:
631 case INTEL_IGD_B43:
632 master_softc->agpm_dev_type = DEVICE_IS_I830;
633 break;
634 default: /* unknown id */
635 return (-1);
636 }
637
638 return (0);
639 }
640
641 /*
642 * If agp master is successfully detected, 0 is returned.
643 * Otherwise -1 is returned.
644 */
645 static int
detect_agp_devcice(agp_master_softc_t * master_softc,ddi_acc_handle_t acc_handle)646 detect_agp_devcice(agp_master_softc_t *master_softc,
647 ddi_acc_handle_t acc_handle)
648 {
649 off_t cap;
650
651 cap = agpmaster_cap_find(acc_handle);
652 if (cap) {
653 master_softc->agpm_dev_type = DEVICE_IS_AGP;
654 master_softc->agpm_data.agpm_acaptr = cap;
655 return (0);
656 } else {
657 return (-1);
658 }
659
660 }
661
662 /*
663 * Please refer to GART and GTT entry format table in agpdefs.h for
664 * intel GTT entry format.
665 */
666 static int
phys2entry(uint32_t type,uint32_t physaddr,uint32_t * entry)667 phys2entry(uint32_t type, uint32_t physaddr, uint32_t *entry)
668 {
669 uint32_t value;
670
671 switch (type) {
672 case AGP_PHYSICAL:
673 case AGP_NORMAL:
674 value = (physaddr & GTT_PTE_MASK) | GTT_PTE_VALID;
675 break;
676 default:
677 return (-1);
678 }
679
680 *entry = value;
681
682 return (0);
683 }
684
685 static int
i8xx_add_to_gtt(gtt_impl_t * gtt,igd_gtt_seg_t seg)686 i8xx_add_to_gtt(gtt_impl_t *gtt, igd_gtt_seg_t seg)
687 {
688 int i;
689 uint32_t *paddr;
690 uint32_t entry;
691 uint32_t maxpages;
692
693 maxpages = gtt->gtt_info.igd_apersize;
694 maxpages = GTT_MB_TO_PAGES(maxpages);
695
696 paddr = seg.igs_phyaddr;
697
698 /* check if gtt max page number is reached */
699 if ((seg.igs_pgstart + seg.igs_npage) > maxpages)
700 return (-1);
701
702 paddr = seg.igs_phyaddr;
703 for (i = seg.igs_pgstart; i < (seg.igs_pgstart + seg.igs_npage);
704 i++, paddr++) {
705 if (phys2entry(seg.igs_type, *paddr, &entry))
706 return (-1);
707 ddi_put32(gtt->gtt_handle,
708 (uint32_t *)(gtt->gtt_addr + i * sizeof (uint32_t)),
709 entry);
710 }
711
712 return (0);
713 }
714
715 static void
i8xx_remove_from_gtt(gtt_impl_t * gtt,igd_gtt_seg_t seg)716 i8xx_remove_from_gtt(gtt_impl_t *gtt, igd_gtt_seg_t seg)
717 {
718 int i;
719 uint32_t maxpages;
720
721 maxpages = gtt->gtt_info.igd_apersize;
722 maxpages = GTT_MB_TO_PAGES(maxpages);
723
724 /* check if gtt max page number is reached */
725 if ((seg.igs_pgstart + seg.igs_npage) > maxpages)
726 return;
727
728 for (i = seg.igs_pgstart; i < (seg.igs_pgstart + seg.igs_npage); i++) {
729 ddi_put32(gtt->gtt_handle,
730 (uint32_t *)(gtt->gtt_addr + i * sizeof (uint32_t)), 0);
731 }
732 }
733