Annotation of sys/dev/pci/agp_i810.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: agp_i810.c,v 1.15 2007/08/04 19:40:25 reyk Exp $ */
2: /* $NetBSD: agp_i810.c,v 1.15 2003/01/31 00:07:39 thorpej Exp $ */
3:
4: /*-
5: * Copyright (c) 2000 Doug Rabson
6: * Copyright (c) 2000 Ruslan Ermilov
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28: * SUCH DAMAGE.
29: *
30: * $FreeBSD: src/sys/pci/agp_i810.c,v 1.4 2001/07/05 21:28:47 jhb Exp $
31: */
32:
33:
34: #include <sys/param.h>
35: #include <sys/systm.h>
36: #include <sys/malloc.h>
37: #include <sys/kernel.h>
38: #include <sys/lock.h>
39: #include <sys/proc.h>
40: #include <sys/device.h>
41: #include <sys/conf.h>
42: #include <sys/agpio.h>
43:
44: #include <dev/pci/pcivar.h>
45: #include <dev/pci/pcireg.h>
46: #include <dev/pci/pcidevs.h>
47: #include <dev/pci/agpvar.h>
48: #include <dev/pci/agpreg.h>
49: #include <dev/pci/vga_pcivar.h>
50:
51: #include <machine/bus.h>
52:
53: #define READ1(off) bus_space_read_1(isc->bst, isc->bsh, off)
54: #define READ4(off) bus_space_read_4(isc->bst, isc->bsh, off)
55: #define WRITE4(off,v) bus_space_write_4(isc->bst, isc->bsh, off, v)
56: #define WRITEGTT(off,v) bus_space_write_4(isc->gtt_bst, isc->gtt_bsh, off, v)
57:
58: #define WRITE_GATT(off, v) agp_i810_write_gatt(isc, off, v)
59:
60: enum {
61: CHIP_I810 = 0, /* i810/i815 */
62: CHIP_I830 = 1, /* i830/i845 */
63: CHIP_I855 = 2, /* i852GM/i855GM/i865G */
64: CHIP_I915 = 3, /* i915G/i915GM */
65: CHIP_I965 = 4 /* i965/i965GM */
66: };
67:
68: struct agp_i810_softc {
69: struct agp_gatt *gatt;
70: int chiptype; /* i810-like or i830 */
71: u_int32_t dcache_size; /* i810 only */
72: u_int32_t stolen; /* number of i830/845 gtt entries
73: for stolen memory */
74: bus_space_tag_t bst; /* bus_space tag */
75: bus_space_handle_t bsh; /* bus_space handle */
76: bus_size_t bsz; /* bus_space size */
77: bus_space_tag_t gtt_bst; /* GATT bus_space tag */
78: bus_space_handle_t gtt_bsh; /* GATT bus_space handle */
79: struct pci_attach_args bridge_pa;
80: };
81:
82: u_int32_t agp_i810_get_aperture(struct vga_pci_softc *);
83: int agp_i810_set_aperture(struct vga_pci_softc *, u_int32_t);
84: int agp_i810_bind_page(struct vga_pci_softc *, off_t, bus_addr_t);
85: int agp_i810_unbind_page(struct vga_pci_softc *, off_t);
86: void agp_i810_flush_tlb(struct vga_pci_softc *);
87: int agp_i810_enable(struct vga_pci_softc *, u_int32_t mode);
88: struct agp_memory *
89: agp_i810_alloc_memory(struct vga_pci_softc *, int, vsize_t);
90: int agp_i810_free_memory(struct vga_pci_softc *, struct agp_memory *);
91: int agp_i810_bind_memory(struct vga_pci_softc *, struct agp_memory *,
92: off_t);
93: int agp_i810_unbind_memory(struct vga_pci_softc *, struct agp_memory *);
94: void agp_i810_write_gatt(struct agp_i810_softc *, bus_size_t, u_int32_t);
95:
96: struct agp_methods agp_i810_methods = {
97: agp_i810_get_aperture,
98: agp_i810_set_aperture,
99: agp_i810_bind_page,
100: agp_i810_unbind_page,
101: agp_i810_flush_tlb,
102: agp_i810_enable,
103: agp_i810_alloc_memory,
104: agp_i810_free_memory,
105: agp_i810_bind_memory,
106: agp_i810_unbind_memory,
107: };
108:
109: int
110: agp_i810_attach(struct vga_pci_softc *sc, struct pci_attach_args *pa,
111: struct pci_attach_args *pchb_pa)
112: {
113: struct agp_i810_softc *isc;
114: struct agp_gatt *gatt;
115: bus_addr_t mmaddr, gmaddr;
116: int error;
117: u_int memtype = 0;
118:
119: isc = malloc(sizeof *isc, M_DEVBUF, M_NOWAIT);
120: if (isc == NULL) {
121: printf(": can't allocate chipset-specific softc\n");
122: return (ENOMEM);
123: }
124: memset(isc, 0, sizeof *isc);
125: sc->sc_chipc = isc;
126: sc->sc_methods = &agp_i810_methods;
127: memcpy(&isc->bridge_pa, pchb_pa, sizeof *pchb_pa);
128:
129: switch (PCI_PRODUCT(pa->pa_id)) {
130: case PCI_PRODUCT_INTEL_82810_GC:
131: case PCI_PRODUCT_INTEL_82810_DC100_GC:
132: case PCI_PRODUCT_INTEL_82810E_GC:
133: case PCI_PRODUCT_INTEL_82815_FULL_GRAPH:
134: isc->chiptype = CHIP_I810;
135: break;
136: case PCI_PRODUCT_INTEL_82830MP_IV:
137: case PCI_PRODUCT_INTEL_82845G_IGD:
138: isc->chiptype = CHIP_I830;
139: break;
140: case PCI_PRODUCT_INTEL_82852GM_AGP:
141: case PCI_PRODUCT_INTEL_82865_IGD:
142: isc->chiptype = CHIP_I855;
143: break;
144: case PCI_PRODUCT_INTEL_82915G_IV:
145: case PCI_PRODUCT_INTEL_82915GM_IGD:
146: case PCI_PRODUCT_INTEL_82945G_IGD_1:
147: case PCI_PRODUCT_INTEL_82945GM_IGD:
148: isc->chiptype = CHIP_I915;
149: break;
150: case PCI_PRODUCT_INTEL_82965_IGD_1:
151: case PCI_PRODUCT_INTEL_82965GM_IGD_1:
152: isc->chiptype = CHIP_I965;
153: break;
154: }
155:
156: switch (isc->chiptype) {
157: case CHIP_I915:
158: gmaddr = AGP_I915_GMADR;
159: mmaddr = AGP_I915_MMADR;
160: break;
161: case CHIP_I965:
162: gmaddr = AGP_I965_GMADR;
163: mmaddr = AGP_I965_MMADR;
164: memtype = PCI_MAPREG_MEM_TYPE_64BIT;
165: break;
166: default:
167: gmaddr = AGP_APBASE;
168: mmaddr = AGP_I810_MMADR;
169: break;
170: }
171:
172: error = agp_map_aperture(sc, gmaddr, memtype);
173: if (error != 0) {
174: printf(": can't map aperture\n");
175: free(isc, M_DEVBUF);
176: return (error);
177: }
178:
179: error = pci_mapreg_map(pa, mmaddr, memtype, 0,
180: &isc->bst, &isc->bsh, NULL, &isc->bsz, 0);
181: if (error != 0) {
182: printf(": can't map mmadr registers\n");
183: return (error);
184: }
185:
186: if (isc->chiptype == CHIP_I915) {
187: error = pci_mapreg_map(pa, AGP_I915_GTTADR, memtype,
188: 0, &isc->gtt_bst, &isc->gtt_bsh, NULL, NULL, 0);
189: if (error != 0) {
190: printf(": can't map gatt registers\n");
191: agp_generic_detach(sc);
192: return (error);
193: }
194: }
195:
196: gatt = malloc(sizeof(struct agp_gatt), M_DEVBUF, M_NOWAIT);
197: if (!gatt) {
198: agp_generic_detach(sc);
199: return (ENOMEM);
200: }
201: isc->gatt = gatt;
202:
203: gatt->ag_entries = AGP_GET_APERTURE(sc) >> AGP_PAGE_SHIFT;
204:
205: if (isc->chiptype == CHIP_I810) {
206: int dummyseg;
207: /* Some i810s have on-chip memory called dcache */
208: if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
209: isc->dcache_size = 4 * 1024 * 1024;
210: else
211: isc->dcache_size = 0;
212:
213: /* According to the specs the gatt on the i810 must be 64k */
214: if (agp_alloc_dmamem(sc->sc_dmat, 64 * 1024,
215: 0, &gatt->ag_dmamap, (caddr_t *)&gatt->ag_virtual,
216: &gatt->ag_physical, &gatt->ag_dmaseg, 1, &dummyseg) != 0) {
217: free(gatt, M_DEVBUF);
218: agp_generic_detach(sc);
219: return (ENOMEM);
220: }
221:
222: gatt->ag_size = gatt->ag_entries * sizeof(u_int32_t);
223: memset(gatt->ag_virtual, 0, gatt->ag_size);
224:
225: agp_flush_cache();
226: /* Install the GATT. */
227: WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
228: } else if (isc->chiptype == CHIP_I830) {
229: /* The i830 automatically initializes the 128k gatt on boot. */
230: pcireg_t reg;
231: u_int32_t pgtblctl;
232: u_int16_t gcc1;
233:
234: reg = pci_conf_read(isc->bridge_pa.pa_pc,
235: isc->bridge_pa.pa_tag, AGP_I830_GCC1);
236: gcc1 = (u_int16_t)(reg >> 16);
237: switch (gcc1 & AGP_I830_GCC1_GMS) {
238: case AGP_I830_GCC1_GMS_STOLEN_512:
239: isc->stolen = (512 - 132) * 1024 / 4096;
240: break;
241: case AGP_I830_GCC1_GMS_STOLEN_1024:
242: isc->stolen = (1024 - 132) * 1024 / 4096;
243: break;
244: case AGP_I830_GCC1_GMS_STOLEN_8192:
245: isc->stolen = (8192 - 132) * 1024 / 4096;
246: break;
247: default:
248: isc->stolen = 0;
249: printf(
250: ": unknown memory configuration, disabling\n");
251: agp_generic_detach(sc);
252: return (EINVAL);
253: }
254: #ifdef DEBUG
255: if (isc->stolen > 0) {
256: printf(": detected %dk stolen memory",
257: isc->stolen * 4);
258: }
259: #endif
260:
261: /* GATT address is already in there, make sure it's enabled */
262: pgtblctl = READ4(AGP_I810_PGTBL_CTL);
263: pgtblctl |= 1;
264: WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
265:
266: gatt->ag_physical = pgtblctl & ~1;
267: } else if (isc->chiptype == CHIP_I915) {
268: /* The 915G automatically initializes the 256k gatt on boot. */
269: pcireg_t reg;
270: u_int32_t pgtblctl;
271: u_int16_t gcc1;
272:
273: reg = pci_conf_read(isc->bridge_pa.pa_pc,
274: isc->bridge_pa.pa_tag, AGP_I855_GCC1);
275: gcc1 = (u_int16_t)(reg >> 16);
276: switch (gcc1 & AGP_I855_GCC1_GMS) {
277: case AGP_I855_GCC1_GMS_STOLEN_1M:
278: isc->stolen = (1024 - 260) * 1024 / 4096;
279: break;
280: case AGP_I855_GCC1_GMS_STOLEN_4M:
281: isc->stolen = (4096 - 260) * 1024 / 4096;
282: break;
283: case AGP_I855_GCC1_GMS_STOLEN_8M:
284: isc->stolen = (8192 - 260) * 1024 / 4096;
285: break;
286: case AGP_I855_GCC1_GMS_STOLEN_16M:
287: isc->stolen = (16384 - 260) * 1024 / 4096;
288: break;
289: case AGP_I855_GCC1_GMS_STOLEN_32M:
290: isc->stolen = (32768 - 260) * 1024 / 4096;
291: break;
292: case AGP_I915_GCC1_GMS_STOLEN_48M:
293: isc->stolen = (49152 - 260) * 1024 / 4096;
294: break;
295: case AGP_I915_GCC1_GMS_STOLEN_64M:
296: isc->stolen = (65536 - 260) * 1024 / 4096;
297: break;
298: default:
299: isc->stolen = 0;
300: printf(
301: ": unknown memory configuration, disabling\n");
302: agp_generic_detach(sc);
303: return (EINVAL);
304: }
305: #ifdef DEBUG
306: if (isc->stolen > 0) {
307: printf(": detected %dk stolen memory",
308: isc->stolen * 4);
309: }
310: #endif
311:
312: /* GATT address is already in there, make sure it's enabled */
313: pgtblctl = READ4(AGP_I810_PGTBL_CTL);
314: pgtblctl |= 1;
315: WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
316:
317: gatt->ag_physical = pgtblctl & ~1;
318: } else if (isc->chiptype == CHIP_I965) {
319: pcireg_t reg;
320: u_int32_t pgtblctl;
321: u_int16_t gcc1;
322: u_int32_t gttsize;
323:
324: switch (READ4(AGP_I810_PGTBL_CTL) &
325: AGP_I810_PGTBL_SIZE_MASK) {
326: case AGP_I810_PGTBL_SIZE_512KB:
327: gttsize = 512 + 4;
328: break;
329: case AGP_I810_PGTBL_SIZE_256KB:
330: gttsize = 256 + 4;
331: break;
332: case AGP_I810_PGTBL_SIZE_128KB:
333: default:
334: gttsize = 128 + 4;
335: break;
336: }
337:
338: reg = pci_conf_read(isc->bridge_pa.pa_pc,
339: isc->bridge_pa.pa_tag, AGP_I855_GCC1);
340: gcc1 = (u_int16_t)(reg >> 16);
341: switch (gcc1 & AGP_I855_GCC1_GMS) {
342: case AGP_I855_GCC1_GMS_STOLEN_1M:
343: isc->stolen = (1024 - gttsize) * 1024 / 4096;
344: break;
345: case AGP_I855_GCC1_GMS_STOLEN_4M:
346: isc->stolen = (4096 - gttsize) * 1024 / 4096;
347: break;
348: case AGP_I855_GCC1_GMS_STOLEN_8M:
349: isc->stolen = (8192 - gttsize) * 1024 / 4096;
350: break;
351: case AGP_I855_GCC1_GMS_STOLEN_16M:
352: isc->stolen = (16384 - gttsize) * 1024 / 4096;
353: break;
354: case AGP_I855_GCC1_GMS_STOLEN_32M:
355: isc->stolen = (32768 - gttsize) * 1024 / 4096;
356: break;
357: case AGP_I915_GCC1_GMS_STOLEN_48M:
358: isc->stolen = (49152 - gttsize) * 1024 / 4096;
359: break;
360: case AGP_I915_GCC1_GMS_STOLEN_64M:
361: isc->stolen = (65536 - gttsize) * 1024 / 4096;
362: break;
363: case AGP_G33_GCC1_GMS_STOLEN_128M:
364: isc->stolen = (131072 - gttsize) * 1024 / 4096;
365: break;
366: case AGP_G33_GCC1_GMS_STOLEN_256M:
367: isc->stolen = (262144 - gttsize) * 1024 / 4096;
368: break;
369: default:
370: isc->stolen = 0;
371: printf(": unknown memory configuration 0x%x, "
372: "disabling\n", reg);
373: agp_generic_detach(sc);
374: return (EINVAL);
375: }
376: #ifdef DEBUG
377: if (isc->stolen > 0) {
378: printf(": detected %dk stolen memory",
379: isc->stolen * 4);
380: }
381: #endif
382:
383: /* GATT address is already in there, make sure it's enabled */
384: pgtblctl = READ4(AGP_I810_PGTBL_CTL);
385: pgtblctl |= 1;
386: WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
387:
388: gatt->ag_physical = pgtblctl & ~1;
389: } else { /* CHIP_I855 */
390: /* The 855GM automatically initializes the 128k gatt on boot. */
391: pcireg_t reg;
392: u_int32_t pgtblctl;
393: u_int16_t gcc1;
394:
395: reg = pci_conf_read(isc->bridge_pa.pa_pc,
396: isc->bridge_pa.pa_tag, AGP_I855_GCC1);
397: gcc1 = (u_int16_t)(reg >> 16);
398: switch (gcc1 & AGP_I855_GCC1_GMS) {
399: case AGP_I855_GCC1_GMS_STOLEN_1M:
400: isc->stolen = (1024 - 132) * 1024 / 4096;
401: break;
402: case AGP_I855_GCC1_GMS_STOLEN_4M:
403: isc->stolen = (4096 - 132) * 1024 / 4096;
404: break;
405: case AGP_I855_GCC1_GMS_STOLEN_8M:
406: isc->stolen = (8192 - 132) * 1024 / 4096;
407: break;
408: case AGP_I855_GCC1_GMS_STOLEN_16M:
409: isc->stolen = (16384 - 132) * 1024 / 4096;
410: break;
411: case AGP_I855_GCC1_GMS_STOLEN_32M:
412: isc->stolen = (32768 - 132) * 1024 / 4096;
413: break;
414: default:
415: isc->stolen = 0;
416: printf(
417: ": unknown memory configuration, disabling\n");
418: agp_generic_detach(sc);
419: return (EINVAL);
420: }
421: #ifdef DEBUG
422: if (isc->stolen > 0) {
423: printf(": detected %dk stolen memory",
424: isc->stolen * 4);
425: }
426: #endif
427:
428: /* GATT address is already in there, make sure it's enabled */
429: pgtblctl = READ4(AGP_I810_PGTBL_CTL);
430: pgtblctl |= 1;
431: WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
432:
433: gatt->ag_physical = pgtblctl & ~1;
434: }
435:
436: /*
437: * Make sure the chipset can see everything.
438: */
439: agp_flush_cache();
440:
441: return (0);
442: }
443:
444: u_int32_t
445: agp_i810_get_aperture(struct vga_pci_softc *sc)
446: {
447: struct agp_i810_softc *isc = sc->sc_chipc;
448: pcireg_t reg;
449:
450: if (isc->chiptype == CHIP_I810) {
451: u_int16_t miscc;
452:
453: reg = pci_conf_read(isc->bridge_pa.pa_pc,
454: isc->bridge_pa.pa_tag, AGP_I810_SMRAM);
455: miscc = (u_int16_t)(reg >> 16);
456: if ((miscc & AGP_I810_MISCC_WINSIZE) ==
457: AGP_I810_MISCC_WINSIZE_32)
458: return (32 * 1024 * 1024);
459: else
460: return (64 * 1024 * 1024);
461: } else if (isc->chiptype == CHIP_I830) {
462: u_int16_t gcc1;
463:
464: reg = pci_conf_read(isc->bridge_pa.pa_pc,
465: isc->bridge_pa.pa_tag, AGP_I830_GCC0);
466: gcc1 = (u_int16_t)(reg >> 16);
467: if ((gcc1 & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
468: return (64 * 1024 * 1024);
469: else
470: return (128 * 1024 * 1024);
471: } else if (isc->chiptype == CHIP_I915) {
472: reg = pci_conf_read(isc->bridge_pa.pa_pc,
473: isc->bridge_pa.pa_tag, AGP_I915_MSAC);
474: if ((reg & AGP_I915_MSAC_GMASIZE) == AGP_I915_MSAC_GMASIZE_128) {
475: return (128 * 1024 * 1024);
476: } else {
477: return (256 * 1024 * 1024);
478: }
479: } else if (isc->chiptype == CHIP_I965) {
480: reg = pci_conf_read(isc->bridge_pa.pa_pc,
481: isc->bridge_pa.pa_tag, AGP_I965_MSAC);
482: switch (reg & AGP_I965_MSAC_GMASIZE) {
483: case AGP_I965_MSAC_GMASIZE_128:
484: return (128 * 1024 * 1024);
485: case AGP_I965_MSAC_GMASIZE_256:
486: return (256 * 1024 * 1024);
487: case AGP_I965_MSAC_GMASIZE_512:
488: return (512 * 1024 * 1024);
489: }
490: }
491:
492: /* CHIP_I855 */
493: return (128 * 1024 * 1024);
494: }
495:
496: int
497: agp_i810_set_aperture(struct vga_pci_softc *sc, u_int32_t aperture)
498: {
499: struct agp_i810_softc *isc = sc->sc_chipc;
500: pcireg_t reg;
501:
502: if (isc->chiptype == CHIP_I810) {
503: u_int16_t miscc;
504:
505: /*
506: * Double check for sanity.
507: */
508: if (aperture != (32 * 1024 * 1024) &&
509: aperture != (64 * 1024 * 1024)) {
510: printf("agp: bad aperture size %d\n", aperture);
511: return (EINVAL);
512: }
513:
514: reg = pci_conf_read(isc->bridge_pa.pa_pc,
515: isc->bridge_pa.pa_tag, AGP_I810_SMRAM);
516: miscc = (u_int16_t)(reg >> 16);
517: miscc &= ~AGP_I810_MISCC_WINSIZE;
518: if (aperture == 32 * 1024 * 1024)
519: miscc |= AGP_I810_MISCC_WINSIZE_32;
520: else
521: miscc |= AGP_I810_MISCC_WINSIZE_64;
522:
523: reg &= 0x0000ffff;
524: reg |= ((pcireg_t)miscc) << 16;
525: pci_conf_write(isc->bridge_pa.pa_pc,
526: isc->bridge_pa.pa_tag, AGP_I810_SMRAM, reg);
527: } else if (isc->chiptype == CHIP_I830) {
528: u_int16_t gcc1;
529:
530: if (aperture != (64 * 1024 * 1024) &&
531: aperture != (128 * 1024 * 1024)) {
532: printf("agp: bad aperture size %d\n", aperture);
533: return (EINVAL);
534: }
535: reg = pci_conf_read(isc->bridge_pa.pa_pc,
536: isc->bridge_pa.pa_tag, AGP_I830_GCC0);
537: gcc1 = (u_int16_t)(reg >> 16);
538: gcc1 &= ~AGP_I830_GCC1_GMASIZE;
539: if (aperture == 64 * 1024 * 1024)
540: gcc1 |= AGP_I830_GCC1_GMASIZE_64;
541: else
542: gcc1 |= AGP_I830_GCC1_GMASIZE_128;
543:
544: reg &= 0x0000ffff;
545: reg |= ((pcireg_t)gcc1) << 16;
546: pci_conf_write(isc->bridge_pa.pa_pc,
547: isc->bridge_pa.pa_tag, AGP_I830_GCC0, reg);
548: } else if (isc->chiptype == CHIP_I915) {
549: if (aperture != (128 * 1024 * 1024) &&
550: aperture != (256 * 1024 * 1024)) {
551: printf("agp: bad aperture size %d\n", aperture);
552: return (EINVAL);
553: }
554: reg = pci_conf_read(isc->bridge_pa.pa_pc,
555: isc->bridge_pa.pa_tag, AGP_I915_MSAC);
556: reg &= ~AGP_I915_MSAC_GMASIZE;
557: if (aperture == (128 * 1024 * 1024))
558: reg |= AGP_I915_MSAC_GMASIZE_128;
559: else
560: reg |= AGP_I915_MSAC_GMASIZE_256;
561: pci_conf_write(isc->bridge_pa.pa_pc,
562: isc->bridge_pa.pa_tag, AGP_I915_MSAC, reg);
563: } else if (isc->chiptype == CHIP_I965) {
564: reg = pci_conf_read(isc->bridge_pa.pa_pc,
565: isc->bridge_pa.pa_tag, AGP_I965_MSAC);
566: reg &= ~AGP_I965_MSAC_GMASIZE;
567: switch (aperture) {
568: case (128 * 1024 * 1024):
569: reg |= AGP_I965_MSAC_GMASIZE_128;
570: break;
571: case (256 * 1024 * 1024):
572: reg |= AGP_I965_MSAC_GMASIZE_256;
573: break;
574: case (512 * 1024 * 1024):
575: reg |= AGP_I965_MSAC_GMASIZE_512;
576: break;
577: default:
578: printf("agp: bad aperture size %d\n", aperture);
579: return (EINVAL);
580: }
581: pci_conf_write(isc->bridge_pa.pa_pc,
582: isc->bridge_pa.pa_tag, AGP_I965_MSAC, reg);
583: } else { /* CHIP_I855 */
584: if (aperture != (128 * 1024 * 1024)) {
585: printf("agp: bad aperture size %d\n", aperture);
586: return (EINVAL);
587: }
588: }
589:
590: return (0);
591: }
592:
593: int
594: agp_i810_bind_page(struct vga_pci_softc *sc, off_t offset, bus_addr_t physical)
595: {
596: struct agp_i810_softc *isc = sc->sc_chipc;
597:
598: if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
599: #ifdef DEBUG
600: printf("agp: failed: offset 0x%08x, shift %d, entries %d\n",
601: (int)offset, AGP_PAGE_SHIFT,
602: isc->gatt->ag_entries);
603: #endif
604: return (EINVAL);
605: }
606:
607: if (isc->chiptype != CHIP_I810) {
608: if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) {
609: #ifdef DEBUG
610: printf("agp: trying to bind into stolen memory\n");
611: #endif
612: return (EINVAL);
613: }
614: }
615:
616: WRITE_GATT(offset, physical);
617: return (0);
618: }
619:
620: int
621: agp_i810_unbind_page(struct vga_pci_softc *sc, off_t offset)
622: {
623: struct agp_i810_softc *isc = sc->sc_chipc;
624:
625: if (offset < 0 || offset >= (isc->gatt->ag_entries << AGP_PAGE_SHIFT))
626: return (EINVAL);
627:
628: if (isc->chiptype != CHIP_I810 ) {
629: if ((offset >> AGP_PAGE_SHIFT) < isc->stolen) {
630: #ifdef DEBUG
631: printf("agp: trying to unbind from stolen memory\n");
632: #endif
633: return (EINVAL);
634: }
635: }
636:
637: WRITE_GATT(offset, 0);
638: return (0);
639: }
640:
641: /*
642: * Writing via memory mapped registers already flushes all TLBs.
643: */
644: void
645: agp_i810_flush_tlb(struct vga_pci_softc *sc)
646: {
647: }
648:
649: int
650: agp_i810_enable(struct vga_pci_softc *sc, u_int32_t mode)
651: {
652: return (0);
653: }
654:
655: struct agp_memory *
656: agp_i810_alloc_memory(struct vga_pci_softc *sc, int type, vsize_t size)
657: {
658: struct agp_i810_softc *isc = sc->sc_chipc;
659: struct agp_memory *mem;
660: int error;
661:
662: if ((size & (AGP_PAGE_SIZE - 1)) != 0)
663: return 0;
664:
665: if (type == 1) {
666: /*
667: * Mapping local DRAM into GATT.
668: */
669: if (isc->chiptype != CHIP_I810 )
670: return (NULL);
671: if (size != isc->dcache_size)
672: return (NULL);
673: } else if (type == 2) {
674: /*
675: * Bogus mapping of 1 or 4 pages for the hardware cursor.
676: */
677: if (size != AGP_PAGE_SIZE && size != 4 * AGP_PAGE_SIZE) {
678: printf("agp: trying to map %lu for hw cursor\n", size);
679: return (NULL);
680: }
681: }
682:
683: mem = malloc(sizeof *mem, M_DEVBUF, M_WAITOK);
684: bzero(mem, sizeof *mem);
685: mem->am_id = sc->sc_nextid++;
686: mem->am_size = size;
687: mem->am_type = type;
688:
689: if (type == 2) {
690: /*
691: * Allocate and wire down the pages now so that we can
692: * get their physical address.
693: */
694: mem->am_dmaseg = malloc(sizeof *mem->am_dmaseg, M_DEVBUF,
695: M_WAITOK);
696: if (mem->am_dmaseg == NULL) {
697: free(mem, M_DEVBUF);
698: return (NULL);
699: }
700: if ((error = agp_alloc_dmamem(sc->sc_dmat, size, 0,
701: &mem->am_dmamap, &mem->am_virtual, &mem->am_physical,
702: mem->am_dmaseg, 1, &mem->am_nseg)) != 0) {
703: free(mem->am_dmaseg, M_DEVBUF);
704: free(mem, M_DEVBUF);
705: printf("agp: agp_alloc_dmamem(%d)\n", error);
706: return (NULL);
707: }
708: } else if (type != 1) {
709: if ((error = bus_dmamap_create(sc->sc_dmat, size,
710: size / PAGE_SIZE + 1, size, 0, BUS_DMA_NOWAIT,
711: &mem->am_dmamap)) != 0) {
712: free(mem, M_DEVBUF);
713: printf("agp: bus_dmamap_create(%d)\n", error);
714: return (NULL);
715: }
716: }
717:
718: TAILQ_INSERT_TAIL(&sc->sc_memory, mem, am_link);
719: sc->sc_allocated += size;
720:
721: return (mem);
722: }
723:
724: int
725: agp_i810_free_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
726: {
727: if (mem->am_is_bound)
728: return (EBUSY);
729:
730: if (mem->am_type == 2) {
731: agp_free_dmamem(sc->sc_dmat, mem->am_size, mem->am_dmamap,
732: mem->am_virtual, mem->am_dmaseg, mem->am_nseg);
733: free(mem->am_dmaseg, M_DEVBUF);
734: }
735:
736: sc->sc_allocated -= mem->am_size;
737: TAILQ_REMOVE(&sc->sc_memory, mem, am_link);
738: free(mem, M_DEVBUF);
739: return (0);
740: }
741:
742: int
743: agp_i810_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
744: off_t offset)
745: {
746: struct agp_i810_softc *isc = sc->sc_chipc;
747: u_int32_t regval, i;
748:
749: /*
750: * XXX evil hack: the PGTBL_CTL appearently gets overwritten by the
751: * X server for mysterious reasons which leads to crashes if we write
752: * to the GTT through the MMIO window.
753: * Until the issue is solved, simply restore it.
754: */
755: regval = bus_space_read_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL);
756: if (regval != (isc->gatt->ag_physical | 1)) {
757: #if DEBUG
758: printf("agp_i810_bind_memory: PGTBL_CTL is 0x%x - fixing\n",
759: regval);
760: #endif
761: bus_space_write_4(isc->bst, isc->bsh, AGP_I810_PGTBL_CTL,
762: isc->gatt->ag_physical | 1);
763: }
764:
765: if (mem->am_type == 2) {
766: for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
767: WRITE_GATT(offset + i, mem->am_physical + i);
768: }
769: mem->am_offset = offset;
770: mem->am_is_bound = 1;
771: return (0);
772: }
773:
774: if (mem->am_type != 1)
775: return (agp_generic_bind_memory(sc, mem, offset));
776:
777: if (isc->chiptype != CHIP_I810)
778: return (EINVAL);
779:
780: for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
781: WRITE4(AGP_I810_GTT +
782: (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4, i | 3);
783: }
784: mem->am_is_bound = 1;
785: return (0);
786: }
787:
788: int
789: agp_i810_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
790: {
791: struct agp_i810_softc *isc = sc->sc_chipc;
792: u_int32_t i;
793:
794: if (mem->am_type == 2) {
795: for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
796: WRITE_GATT(mem->am_offset + i, 0);
797: }
798: mem->am_offset = 0;
799: mem->am_is_bound = 0;
800: return (0);
801: }
802:
803: if (mem->am_type != 1)
804: return (agp_generic_unbind_memory(sc, mem));
805:
806: if (isc->chiptype != CHIP_I810)
807: return (EINVAL);
808:
809: for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
810: WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
811: mem->am_is_bound = 0;
812: return (0);
813: }
814:
815: void
816: agp_i810_write_gatt(struct agp_i810_softc *isc, bus_size_t off, u_int32_t v)
817: {
818: u_int32_t d;
819:
820:
821: d = v | 1;
822:
823: if (isc->chiptype == CHIP_I915)
824: WRITEGTT((u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, v ? d : 0);
825: else if (isc->chiptype == CHIP_I965) {
826: d |= (v & 0x0000000f00000000ULL) >> 28;
827: WRITE4(AGP_I965_GTT +
828: (u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, v ? d : 0);
829: } else
830: WRITE4(AGP_I810_GTT +
831: (u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, v ? d : 0);
832: }
CVSweb