FreeBSD/Linux Kernel Cross Reference
sys/pci/agp_i810.c
1 /*-
2 * Copyright (c) 2000 Doug Rabson
3 * Copyright (c) 2000 Ruslan Ermilov
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 /*
29 * Fixes for 830/845G support: David Dawes <dawes@xfree86.org>
30 * 852GM/855GM/865G support added by David Dawes <dawes@xfree86.org>
31 */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD: releng/6.2/sys/pci/agp_i810.c 159884 2006-06-23 17:10:25Z anholt $");
35
36 #include "opt_bus.h"
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
41 #include <sys/kernel.h>
42 #include <sys/module.h>
43 #include <sys/bus.h>
44 #include <sys/lock.h>
45 #include <sys/mutex.h>
46 #include <sys/proc.h>
47
48 #include <dev/pci/pcivar.h>
49 #include <dev/pci/pcireg.h>
50 #include <pci/agppriv.h>
51 #include <pci/agpreg.h>
52
53 #include <vm/vm.h>
54 #include <vm/vm_object.h>
55 #include <vm/vm_page.h>
56 #include <vm/vm_pageout.h>
57 #include <vm/pmap.h>
58
59 #include <machine/bus.h>
60 #include <machine/resource.h>
61 #include <sys/rman.h>
62
63 MALLOC_DECLARE(M_AGP);
64
65 #define READ1(off) bus_space_read_1(sc->bst, sc->bsh, off)
66 #define READ4(off) bus_space_read_4(sc->bst, sc->bsh, off)
67 #define WRITE4(off,v) bus_space_write_4(sc->bst, sc->bsh, off, v)
68 #define WRITEGTT(off,v) bus_space_write_4(sc->gtt_bst, sc->gtt_bsh, off, v)
69
70 #define CHIP_I810 0 /* i810/i815 */
71 #define CHIP_I830 1 /* 830M/845G */
72 #define CHIP_I855 2 /* 852GM/855GM/865G */
73 #define CHIP_I915 3 /* 915G/915GM */
74
75 struct agp_i810_softc {
76 struct agp_softc agp;
77 u_int32_t initial_aperture; /* aperture size at startup */
78 struct agp_gatt *gatt;
79 int chiptype; /* i810-like or i830 */
80 u_int32_t dcache_size; /* i810 only */
81 u_int32_t stolen; /* number of i830/845 gtt entries for stolen memory */
82 device_t bdev; /* bridge device */
83
84 struct resource *regs; /* memory mapped GC registers */
85 bus_space_tag_t bst; /* bus_space tag */
86 bus_space_handle_t bsh; /* bus_space handle */
87
88 struct resource *gtt; /* memory mapped GATT entries */
89 bus_space_tag_t gtt_bst; /* bus_space tag */
90 bus_space_handle_t gtt_bsh; /* bus_space handle */
91
92 void *argb_cursor; /* contigmalloc area for ARGB cursor */
93 };
94
95 static const char*
96 agp_i810_match(device_t dev)
97 {
98 if (pci_get_class(dev) != PCIC_DISPLAY
99 || pci_get_subclass(dev) != PCIS_DISPLAY_VGA)
100 return NULL;
101
102 switch (pci_get_devid(dev)) {
103 case 0x71218086:
104 return ("Intel 82810 (i810 GMCH) SVGA controller");
105
106 case 0x71238086:
107 return ("Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller");
108
109 case 0x71258086:
110 return ("Intel 82810E (i810E GMCH) SVGA controller");
111
112 case 0x11328086:
113 return ("Intel 82815 (i815 GMCH) SVGA controller");
114
115 case 0x35778086:
116 return ("Intel 82830M (830M GMCH) SVGA controller");
117
118 case 0x25628086:
119 return ("Intel 82845G (845G GMCH) SVGA controller");
120
121 case 0x35828086:
122 switch (pci_read_config(dev, AGP_I85X_CAPID, 1)) {
123 case AGP_I855_GME:
124 return ("Intel 82855GME (855GME GMCH) SVGA controller");
125
126 case AGP_I855_GM:
127 return ("Intel 82855GM (855GM GMCH) SVGA controller");
128
129 case AGP_I852_GME:
130 return ("Intel 82852GME (852GME GMCH) SVGA controller");
131
132 case AGP_I852_GM:
133 return ("Intel 82852GM (852GM GMCH) SVGA controller");
134
135 default:
136 return ("Intel 8285xM (85xGM GMCH) SVGA controller");
137 }
138
139 case 0x25728086:
140 return ("Intel 82865G (865G GMCH) SVGA controller");
141
142 case 0x25828086:
143 return ("Intel 82915G (915G GMCH) SVGA controller");
144
145 case 0x25928086:
146 return ("Intel 82915GM (915GM GMCH) SVGA controller");
147 };
148
149 return NULL;
150 }
151
152 /*
153 * Find bridge device.
154 */
155 static device_t
156 agp_i810_find_bridge(device_t dev)
157 {
158 device_t *children, child;
159 int nchildren, i;
160 u_int32_t devid;
161
162 /*
163 * Calculate bridge device's ID.
164 */
165 devid = pci_get_devid(dev);
166 switch (devid) {
167 case 0x71218086:
168 case 0x71238086:
169 case 0x71258086:
170 devid -= 0x10000;
171 break;
172
173 case 0x11328086:
174 case 0x35778086:
175 case 0x25628086:
176 case 0x35828086:
177 case 0x25728086:
178 case 0x25828086:
179 case 0x25928086:
180 devid -= 0x20000;
181 break;
182 };
183 if (device_get_children(device_get_parent(dev), &children, &nchildren))
184 return 0;
185
186 for (i = 0; i < nchildren; i++) {
187 child = children[i];
188
189 if (pci_get_devid(child) == devid) {
190 free(children, M_TEMP);
191 return child;
192 }
193 }
194 free(children, M_TEMP);
195 return 0;
196 }
197
198 static int
199 agp_i810_probe(device_t dev)
200 {
201 const char *desc;
202
203 if (resource_disabled("agp", device_get_unit(dev)))
204 return (ENXIO);
205 desc = agp_i810_match(dev);
206 if (desc) {
207 device_t bdev;
208 u_int8_t smram;
209 unsigned int gcc1;
210 int devid = pci_get_devid(dev);
211
212 bdev = agp_i810_find_bridge(dev);
213 if (!bdev) {
214 if (bootverbose)
215 printf("I810: can't find bridge device\n");
216 return ENXIO;
217 }
218
219 /*
220 * checking whether internal graphics device has been activated.
221 */
222 switch (devid) {
223 /* i810 */
224 case 0x71218086:
225 case 0x71238086:
226 case 0x71258086:
227 case 0x11328086:
228 smram = pci_read_config(bdev, AGP_I810_SMRAM, 1);
229 if ((smram & AGP_I810_SMRAM_GMS)
230 == AGP_I810_SMRAM_GMS_DISABLED) {
231 if (bootverbose)
232 printf("I810: disabled, not probing\n");
233 return ENXIO;
234 }
235 break;
236
237 /* i830 */
238 case 0x35778086:
239 case 0x35828086:
240 case 0x25628086:
241 case 0x25728086:
242 gcc1 = pci_read_config(bdev, AGP_I830_GCC1, 1);
243 if ((gcc1 & AGP_I830_GCC1_DEV2) == AGP_I830_GCC1_DEV2_DISABLED) {
244 if (bootverbose)
245 printf("I830: disabled, not probing\n");
246 return ENXIO;
247 }
248 break;
249
250 /* i915 */
251 case 0x25828086:
252 case 0x25928086:
253 gcc1 = pci_read_config(bdev, AGP_I915_DEVEN, 4);
254 if ((gcc1 & AGP_I915_DEVEN_D2F0) ==
255 AGP_I915_DEVEN_D2F0_DISABLED) {
256 if (bootverbose)
257 printf("I915: disabled, not probing\n");
258 return ENXIO;
259 }
260 break;
261
262 default:
263 return ENXIO;
264 }
265
266 device_verbose(dev);
267 device_set_desc(dev, desc);
268 return BUS_PROBE_DEFAULT;
269 }
270
271 return ENXIO;
272 }
273
274 static int
275 agp_i810_attach(device_t dev)
276 {
277 struct agp_i810_softc *sc = device_get_softc(dev);
278 struct agp_gatt *gatt;
279 int error, rid;
280
281 sc->bdev = agp_i810_find_bridge(dev);
282 if (!sc->bdev)
283 return ENOENT;
284
285 error = agp_generic_attach(dev);
286 if (error)
287 return error;
288
289 switch (pci_get_devid(dev)) {
290 case 0x71218086:
291 case 0x71238086:
292 case 0x71258086:
293 case 0x11328086:
294 sc->chiptype = CHIP_I810;
295 break;
296 case 0x35778086:
297 case 0x25628086:
298 sc->chiptype = CHIP_I830;
299 break;
300 case 0x35828086:
301 case 0x25728086:
302 sc->chiptype = CHIP_I855;
303 break;
304 case 0x25828086:
305 case 0x25928086:
306 sc->chiptype = CHIP_I915;
307 break;
308 };
309
310 /* Same for i810 and i830 */
311 if (sc->chiptype == CHIP_I915)
312 rid = AGP_I915_MMADR;
313 else
314 rid = AGP_I810_MMADR;
315
316 sc->regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
317 RF_ACTIVE);
318 if (!sc->regs) {
319 agp_generic_detach(dev);
320 return ENODEV;
321 }
322 sc->bst = rman_get_bustag(sc->regs);
323 sc->bsh = rman_get_bushandle(sc->regs);
324
325 if (sc->chiptype == CHIP_I915) {
326 rid = AGP_I915_GTTADR;
327 sc->gtt = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
328 RF_ACTIVE);
329 if (!sc->gtt) {
330 bus_release_resource(dev, SYS_RES_MEMORY,
331 AGP_I810_MMADR, sc->regs);
332 agp_generic_detach(dev);
333 return ENODEV;
334 }
335 sc->gtt_bst = rman_get_bustag(sc->gtt);
336 sc->gtt_bsh = rman_get_bushandle(sc->gtt);
337 }
338
339 sc->initial_aperture = AGP_GET_APERTURE(dev);
340
341 gatt = malloc( sizeof(struct agp_gatt), M_AGP, M_NOWAIT);
342 if (!gatt) {
343 agp_generic_detach(dev);
344 return ENOMEM;
345 }
346 sc->gatt = gatt;
347
348 gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
349
350 if ( sc->chiptype == CHIP_I810 ) {
351 /* Some i810s have on-chip memory called dcache */
352 if (READ1(AGP_I810_DRT) & AGP_I810_DRT_POPULATED)
353 sc->dcache_size = 4 * 1024 * 1024;
354 else
355 sc->dcache_size = 0;
356
357 /* According to the specs the gatt on the i810 must be 64k */
358 gatt->ag_virtual = contigmalloc( 64 * 1024, M_AGP, 0,
359 0, ~0, PAGE_SIZE, 0);
360 if (!gatt->ag_virtual) {
361 if (bootverbose)
362 device_printf(dev, "contiguous allocation failed\n");
363 free(gatt, M_AGP);
364 agp_generic_detach(dev);
365 return ENOMEM;
366 }
367 bzero(gatt->ag_virtual, gatt->ag_entries * sizeof(u_int32_t));
368
369 gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
370 agp_flush_cache();
371 /* Install the GATT. */
372 WRITE4(AGP_I810_PGTBL_CTL, gatt->ag_physical | 1);
373 } else if ( sc->chiptype == CHIP_I830 ) {
374 /* The i830 automatically initializes the 128k gatt on boot. */
375 unsigned int gcc1, pgtblctl;
376
377 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 1);
378 switch (gcc1 & AGP_I830_GCC1_GMS) {
379 case AGP_I830_GCC1_GMS_STOLEN_512:
380 sc->stolen = (512 - 132) * 1024 / 4096;
381 break;
382 case AGP_I830_GCC1_GMS_STOLEN_1024:
383 sc->stolen = (1024 - 132) * 1024 / 4096;
384 break;
385 case AGP_I830_GCC1_GMS_STOLEN_8192:
386 sc->stolen = (8192 - 132) * 1024 / 4096;
387 break;
388 default:
389 sc->stolen = 0;
390 device_printf(dev, "unknown memory configuration, disabling\n");
391 agp_generic_detach(dev);
392 return EINVAL;
393 }
394 if (sc->stolen > 0)
395 device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4);
396 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024);
397
398 /* GATT address is already in there, make sure it's enabled */
399 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
400 pgtblctl |= 1;
401 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
402
403 gatt->ag_physical = pgtblctl & ~1;
404 } else if (sc->chiptype == CHIP_I855 || sc->chiptype == CHIP_I915) { /* CHIP_I855 */
405 unsigned int gcc1, pgtblctl, stolen;
406
407 /* Stolen memory is set up at the beginning of the aperture by
408 * the BIOS, consisting of the GATT followed by 4kb for the BIOS
409 * display.
410 */
411 if (sc->chiptype == CHIP_I855)
412 stolen = 132;
413 else
414 stolen = 260;
415
416 gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1);
417 switch (gcc1 & AGP_I855_GCC1_GMS) {
418 case AGP_I855_GCC1_GMS_STOLEN_1M:
419 sc->stolen = (1024 - stolen) * 1024 / 4096;
420 break;
421 case AGP_I855_GCC1_GMS_STOLEN_4M:
422 sc->stolen = (4096 - stolen) * 1024 / 4096;
423 break;
424 case AGP_I855_GCC1_GMS_STOLEN_8M:
425 sc->stolen = (8192 - stolen) * 1024 / 4096;
426 break;
427 case AGP_I855_GCC1_GMS_STOLEN_16M:
428 sc->stolen = (16384 - stolen) * 1024 / 4096;
429 break;
430 case AGP_I855_GCC1_GMS_STOLEN_32M:
431 sc->stolen = (32768 - stolen) * 1024 / 4096;
432 break;
433 case AGP_I915_GCC1_GMS_STOLEN_48M:
434 sc->stolen = (49152 - stolen) * 1024 / 4096;
435 break;
436 case AGP_I915_GCC1_GMS_STOLEN_64M:
437 sc->stolen = (65536 - stolen) * 1024 / 4096;
438 break;
439 default:
440 sc->stolen = 0;
441 device_printf(dev, "unknown memory configuration, disabling\n");
442 agp_generic_detach(dev);
443 return EINVAL;
444 }
445 if (sc->stolen > 0)
446 device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4);
447 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024);
448
449 /* GATT address is already in there, make sure it's enabled */
450 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
451 pgtblctl |= 1;
452 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
453
454 gatt->ag_physical = pgtblctl & ~1;
455 }
456
457 /* Add a device for the drm to attach to */
458 if (!device_add_child( dev, "drmsub", -1 ))
459 printf("out of memory...\n");
460
461 return bus_generic_attach(dev);
462 }
463
464 static int
465 agp_i810_detach(device_t dev)
466 {
467 struct agp_i810_softc *sc = device_get_softc(dev);
468 int error;
469 device_t child;
470
471 error = agp_generic_detach(dev);
472 if (error)
473 return error;
474
475 /* Clear the GATT base. */
476 if ( sc->chiptype == CHIP_I810 ) {
477 WRITE4(AGP_I810_PGTBL_CTL, 0);
478 } else {
479 unsigned int pgtblctl;
480 pgtblctl = READ4(AGP_I810_PGTBL_CTL);
481 pgtblctl &= ~1;
482 WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
483 }
484
485 /* Put the aperture back the way it started. */
486 AGP_SET_APERTURE(dev, sc->initial_aperture);
487
488 if ( sc->chiptype == CHIP_I810 ) {
489 contigfree(sc->gatt->ag_virtual, 64 * 1024, M_AGP);
490 }
491 free(sc->gatt, M_AGP);
492
493 if (sc->chiptype == CHIP_I915) {
494 bus_release_resource(dev, SYS_RES_MEMORY, AGP_I915_GTTADR,
495 sc->gtt);
496 bus_release_resource(dev, SYS_RES_MEMORY, AGP_I915_MMADR,
497 sc->regs);
498 } else {
499 bus_release_resource(dev, SYS_RES_MEMORY, AGP_I810_MMADR,
500 sc->regs);
501 }
502
503 child = device_find_child( dev, "drmsub", 0 );
504 if (child)
505 device_delete_child( dev, child );
506
507 return 0;
508 }
509
510 static u_int32_t
511 agp_i810_get_aperture(device_t dev)
512 {
513 struct agp_i810_softc *sc = device_get_softc(dev);
514 uint32_t temp;
515 u_int16_t miscc;
516
517 switch (sc->chiptype) {
518 case CHIP_I810:
519 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
520 if ((miscc & AGP_I810_MISCC_WINSIZE) == AGP_I810_MISCC_WINSIZE_32)
521 return 32 * 1024 * 1024;
522 else
523 return 64 * 1024 * 1024;
524 case CHIP_I830:
525 temp = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
526 if ((temp & AGP_I830_GCC1_GMASIZE) == AGP_I830_GCC1_GMASIZE_64)
527 return 64 * 1024 * 1024;
528 else
529 return 128 * 1024 * 1024;
530 case CHIP_I855:
531 return 128 * 1024 * 1024;
532 case CHIP_I915:
533 temp = pci_read_config(dev, AGP_I915_MSAC, 1);
534 if ((temp & AGP_I915_MSAC_GMASIZE) ==
535 AGP_I915_MSAC_GMASIZE_128) {
536 return 128 * 1024 * 1024;
537 } else {
538 return 256 * 1024 * 1024;
539 }
540 }
541
542 return 0;
543 }
544
545 static int
546 agp_i810_set_aperture(device_t dev, u_int32_t aperture)
547 {
548 struct agp_i810_softc *sc = device_get_softc(dev);
549 u_int16_t miscc, gcc1;
550 u_int32_t temp;
551
552 switch (sc->chiptype) {
553 case CHIP_I810:
554 /*
555 * Double check for sanity.
556 */
557 if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) {
558 device_printf(dev, "bad aperture size %d\n", aperture);
559 return EINVAL;
560 }
561
562 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
563 miscc &= ~AGP_I810_MISCC_WINSIZE;
564 if (aperture == 32 * 1024 * 1024)
565 miscc |= AGP_I810_MISCC_WINSIZE_32;
566 else
567 miscc |= AGP_I810_MISCC_WINSIZE_64;
568
569 pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2);
570 break;
571 case CHIP_I830:
572 if (aperture != 64 * 1024 * 1024 &&
573 aperture != 128 * 1024 * 1024) {
574 device_printf(dev, "bad aperture size %d\n", aperture);
575 return EINVAL;
576 }
577 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
578 gcc1 &= ~AGP_I830_GCC1_GMASIZE;
579 if (aperture == 64 * 1024 * 1024)
580 gcc1 |= AGP_I830_GCC1_GMASIZE_64;
581 else
582 gcc1 |= AGP_I830_GCC1_GMASIZE_128;
583
584 pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2);
585 break;
586 case CHIP_I855:
587 if (aperture != 128 * 1024 * 1024) {
588 device_printf(dev, "bad aperture size %d\n", aperture);
589 return EINVAL;
590 }
591 break;
592 case CHIP_I915:
593 temp = pci_read_config(dev, AGP_I915_MSAC, 1);
594 temp &= ~AGP_I915_MSAC_GMASIZE;
595
596 switch (aperture) {
597 case 128 * 1024 * 1024:
598 temp |= AGP_I915_MSAC_GMASIZE_128;
599 break;
600 case 256 * 1024 * 1024:
601 temp |= AGP_I915_MSAC_GMASIZE_256;
602 break;
603 default:
604 device_printf(dev, "bad aperture size %d\n", aperture);
605 return EINVAL;
606 }
607
608 pci_write_config(dev, AGP_I915_MSAC, temp, 1);
609 break;
610 }
611
612 return 0;
613 }
614
615 static int
616 agp_i810_bind_page(device_t dev, int offset, vm_offset_t physical)
617 {
618 struct agp_i810_softc *sc = device_get_softc(dev);
619
620 if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
621 device_printf(dev, "failed: offset is 0x%08x, shift is %d, entries is %d\n", offset, AGP_PAGE_SHIFT, sc->gatt->ag_entries);
622 return EINVAL;
623 }
624
625 if ( sc->chiptype != CHIP_I810 ) {
626 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
627 device_printf(dev, "trying to bind into stolen memory");
628 return EINVAL;
629 }
630 }
631
632 if (sc->chiptype == CHIP_I915) {
633 WRITEGTT((offset >> AGP_PAGE_SHIFT) * 4, physical | 1);
634 } else {
635 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, physical | 1);
636 }
637
638 return 0;
639 }
640
641 static int
642 agp_i810_unbind_page(device_t dev, int offset)
643 {
644 struct agp_i810_softc *sc = device_get_softc(dev);
645
646 if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
647 return EINVAL;
648
649 if ( sc->chiptype != CHIP_I810 ) {
650 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
651 device_printf(dev, "trying to unbind from stolen memory");
652 return EINVAL;
653 }
654 }
655
656 if (sc->chiptype == CHIP_I915) {
657 WRITEGTT((offset >> AGP_PAGE_SHIFT) * 4, 0);
658 } else {
659 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, 0);
660 }
661
662 return 0;
663 }
664
665 /*
666 * Writing via memory mapped registers already flushes all TLBs.
667 */
668 static void
669 agp_i810_flush_tlb(device_t dev)
670 {
671 }
672
673 static int
674 agp_i810_enable(device_t dev, u_int32_t mode)
675 {
676
677 return 0;
678 }
679
680 static struct agp_memory *
681 agp_i810_alloc_memory(device_t dev, int type, vm_size_t size)
682 {
683 struct agp_i810_softc *sc = device_get_softc(dev);
684 struct agp_memory *mem;
685
686 if ((size & (AGP_PAGE_SIZE - 1)) != 0)
687 return 0;
688
689 if (sc->agp.as_allocated + size > sc->agp.as_maxmem)
690 return 0;
691
692 if (type == 1) {
693 /*
694 * Mapping local DRAM into GATT.
695 */
696 if ( sc->chiptype != CHIP_I810 )
697 return 0;
698 if (size != sc->dcache_size)
699 return 0;
700 } else if (type == 2) {
701 /*
702 * Type 2 is the contiguous physical memory type, that hands
703 * back a physical address. This is used for cursors on i810.
704 * Hand back as many single pages with physical as the user
705 * wants, but only allow one larger allocation (ARGB cursor)
706 * for simplicity.
707 */
708 if (size != AGP_PAGE_SIZE) {
709 if (sc->argb_cursor != NULL)
710 return 0;
711
712 /* Allocate memory for ARGB cursor, if we can. */
713 sc->argb_cursor = contigmalloc(size, M_AGP,
714 0, 0, ~0, PAGE_SIZE, 0);
715 if (sc->argb_cursor == NULL)
716 return 0;
717 }
718 }
719
720 mem = malloc(sizeof *mem, M_AGP, M_WAITOK);
721 mem->am_id = sc->agp.as_nextid++;
722 mem->am_size = size;
723 mem->am_type = type;
724 if (type != 1 && (type != 2 || size == AGP_PAGE_SIZE))
725 mem->am_obj = vm_object_allocate(OBJT_DEFAULT,
726 atop(round_page(size)));
727 else
728 mem->am_obj = 0;
729
730 if (type == 2) {
731 if (size == AGP_PAGE_SIZE) {
732 /*
733 * Allocate and wire down the page now so that we can
734 * get its physical address.
735 */
736 vm_page_t m;
737
738 VM_OBJECT_LOCK(mem->am_obj);
739 m = vm_page_grab(mem->am_obj, 0, VM_ALLOC_NOBUSY |
740 VM_ALLOC_WIRED | VM_ALLOC_ZERO | VM_ALLOC_RETRY);
741 VM_OBJECT_UNLOCK(mem->am_obj);
742 mem->am_physical = VM_PAGE_TO_PHYS(m);
743 } else {
744 /* Our allocation is already nicely wired down for us.
745 * Just grab the physical address.
746 */
747 mem->am_physical = vtophys(sc->argb_cursor);
748 }
749 } else {
750 mem->am_physical = 0;
751 }
752
753 mem->am_offset = 0;
754 mem->am_is_bound = 0;
755 TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link);
756 sc->agp.as_allocated += size;
757
758 return mem;
759 }
760
761 static int
762 agp_i810_free_memory(device_t dev, struct agp_memory *mem)
763 {
764 struct agp_i810_softc *sc = device_get_softc(dev);
765
766 if (mem->am_is_bound)
767 return EBUSY;
768
769 if (mem->am_type == 2) {
770 if (mem->am_size == AGP_PAGE_SIZE) {
771 /*
772 * Unwire the page which we wired in alloc_memory.
773 */
774 vm_page_t m;
775
776 VM_OBJECT_LOCK(mem->am_obj);
777 m = vm_page_lookup(mem->am_obj, 0);
778 VM_OBJECT_UNLOCK(mem->am_obj);
779 vm_page_lock_queues();
780 vm_page_unwire(m, 0);
781 vm_page_unlock_queues();
782 } else {
783 contigfree(sc->argb_cursor, mem->am_size, M_AGP);
784 sc->argb_cursor = NULL;
785 }
786 }
787
788 sc->agp.as_allocated -= mem->am_size;
789 TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link);
790 if (mem->am_obj)
791 vm_object_deallocate(mem->am_obj);
792 free(mem, M_AGP);
793 return 0;
794 }
795
796 static int
797 agp_i810_bind_memory(device_t dev, struct agp_memory *mem,
798 vm_offset_t offset)
799 {
800 struct agp_i810_softc *sc = device_get_softc(dev);
801 vm_offset_t i;
802
803 /* Do some sanity checks first. */
804 if (offset < 0 || (offset & (AGP_PAGE_SIZE - 1)) != 0 ||
805 offset + mem->am_size > AGP_GET_APERTURE(dev)) {
806 device_printf(dev, "binding memory at bad offset %#x\n",
807 (int)offset);
808 return EINVAL;
809 }
810
811 if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
812 mtx_lock(&sc->agp.as_lock);
813 if (mem->am_is_bound) {
814 mtx_unlock(&sc->agp.as_lock);
815 return EINVAL;
816 }
817 /* The memory's already wired down, just stick it in the GTT. */
818 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
819 u_int32_t physical = mem->am_physical + i;
820
821 if (sc->chiptype == CHIP_I915) {
822 WRITEGTT(((offset + i) >> AGP_PAGE_SHIFT) * 4,
823 physical | 1);
824 } else {
825 WRITE4(AGP_I810_GTT +
826 ((offset + i) >> AGP_PAGE_SHIFT) * 4,
827 physical | 1);
828 }
829 }
830 agp_flush_cache();
831 mem->am_offset = offset;
832 mem->am_is_bound = 1;
833 mtx_unlock(&sc->agp.as_lock);
834 return 0;
835 }
836
837 if (mem->am_type != 1)
838 return agp_generic_bind_memory(dev, mem, offset);
839
840 if ( sc->chiptype != CHIP_I810 )
841 return EINVAL;
842
843 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
844 WRITE4(AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4,
845 i | 3);
846 }
847
848 return 0;
849 }
850
851 static int
852 agp_i810_unbind_memory(device_t dev, struct agp_memory *mem)
853 {
854 struct agp_i810_softc *sc = device_get_softc(dev);
855 vm_offset_t i;
856
857 if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
858 mtx_lock(&sc->agp.as_lock);
859 if (!mem->am_is_bound) {
860 mtx_unlock(&sc->agp.as_lock);
861 return EINVAL;
862 }
863
864 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
865 vm_offset_t offset = mem->am_offset;
866
867 if (sc->chiptype == CHIP_I915) {
868 WRITEGTT(((offset + i) >> AGP_PAGE_SHIFT) * 4,
869 0);
870 } else {
871 WRITE4(AGP_I810_GTT +
872 ((offset + i) >> AGP_PAGE_SHIFT) * 4, 0);
873 }
874 }
875 agp_flush_cache();
876 mem->am_is_bound = 0;
877 mtx_unlock(&sc->agp.as_lock);
878 return 0;
879 }
880
881 if (mem->am_type != 1)
882 return agp_generic_unbind_memory(dev, mem);
883
884 if ( sc->chiptype != CHIP_I810 )
885 return EINVAL;
886
887 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
888 WRITE4(AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
889
890 return 0;
891 }
892
893 static int
894 agp_i810_print_child(device_t dev, device_t child)
895 {
896 int retval = 0;
897
898 retval += bus_print_child_header(dev, child);
899 retval += printf(": (child of agp_i810.c)");
900 retval += bus_print_child_footer(dev, child);
901
902 return retval;
903 }
904
905 static device_method_t agp_i810_methods[] = {
906 /* Device interface */
907 DEVMETHOD(device_probe, agp_i810_probe),
908 DEVMETHOD(device_attach, agp_i810_attach),
909 DEVMETHOD(device_detach, agp_i810_detach),
910 DEVMETHOD(device_shutdown, bus_generic_shutdown),
911 DEVMETHOD(device_suspend, bus_generic_suspend),
912 DEVMETHOD(device_resume, bus_generic_resume),
913
914 /* AGP interface */
915 DEVMETHOD(agp_get_aperture, agp_i810_get_aperture),
916 DEVMETHOD(agp_set_aperture, agp_i810_set_aperture),
917 DEVMETHOD(agp_bind_page, agp_i810_bind_page),
918 DEVMETHOD(agp_unbind_page, agp_i810_unbind_page),
919 DEVMETHOD(agp_flush_tlb, agp_i810_flush_tlb),
920 DEVMETHOD(agp_enable, agp_i810_enable),
921 DEVMETHOD(agp_alloc_memory, agp_i810_alloc_memory),
922 DEVMETHOD(agp_free_memory, agp_i810_free_memory),
923 DEVMETHOD(agp_bind_memory, agp_i810_bind_memory),
924 DEVMETHOD(agp_unbind_memory, agp_i810_unbind_memory),
925
926 /* bus methods */
927 DEVMETHOD(bus_print_child, agp_i810_print_child),
928 DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
929 DEVMETHOD(bus_release_resource, bus_generic_release_resource),
930 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
931 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
932 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
933 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
934 { 0, 0 }
935 };
936
937 static driver_t agp_i810_driver = {
938 "agp",
939 agp_i810_methods,
940 sizeof(struct agp_i810_softc),
941 };
942
943 static devclass_t agp_devclass;
944
945 DRIVER_MODULE(agp_i810, pci, agp_i810_driver, agp_devclass, 0, 0);
946 MODULE_DEPEND(agp_i810, agp, 1, 1, 1);
947 MODULE_DEPEND(agp_i810, pci, 1, 1, 1);
Cache object: 59a8840eecfe92d270badc34aab49fd8
|