93da821bfdccbb297779e77d60422b18b2752929
[dragonfly.git] / sys / dev / agp / 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  *      $FreeBSD: src/sys/pci/agp_i810.c,v 1.40 2007/07/13 16:28:12 anholt Exp $
28  *      $DragonFly: src/sys/dev/agp/agp_i810.c,v 1.12 2007/09/12 08:31:43 hasso Exp $
29  */
30
31 /*
32  * Fixes for 830/845G support: David Dawes <dawes@xfree86.org>
33  * 852GM/855GM/865G support added by David Dawes <dawes@xfree86.org>
34  */
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/bus.h>
43 #include <sys/lock.h>
44 #include <sys/rman.h>
45
46 #include <bus/pci/pcivar.h>
47 #include <bus/pci/pcireg.h>
48 #include "agppriv.h"
49 #include "agpreg.h"
50
51 #include <vm/vm.h>
52 #include <vm/vm_object.h>
53 #include <vm/vm_page.h>
54 #include <vm/vm_pageout.h>
55 #include <vm/pmap.h>
56
57 #include <machine/md_var.h>
58
59 #define bus_read_1(r, o) \
60                    bus_space_read_1((r)->r_bustag, (r)->r_bushandle, (o))
61 #define bus_read_4(r, o) \
62                    bus_space_read_4((r)->r_bustag, (r)->r_bushandle, (o))
63 #define bus_write_4(r, o, v) \
64                     bus_space_write_4((r)->r_bustag, (r)->r_bushandle, (o), (v))
65
66 MALLOC_DECLARE(M_AGP);
67
68 enum {
69         CHIP_I810,      /* i810/i815 */
70         CHIP_I830,      /* 830M/845G */
71         CHIP_I855,      /* 852GM/855GM/865G */
72         CHIP_I915,      /* 915G/915GM */
73         CHIP_I965,      /* G965 */
74         CHIP_G33,       /* G33/Q33/Q35 */
75 };
76
77 /* The i810 through i855 have the registers at BAR 1, and the GATT gets
78  * allocated by us.  The i915 has registers in BAR 0 and the GATT is at the
79  * start of the stolen memory, and should only be accessed by the OS through
80  * BAR 3.  The G965 has registers and GATT in the same BAR (0) -- first 512KB
81  * is registers, second 512KB is GATT.
82  */
83 static struct resource_spec agp_i810_res_spec[] = {
84         { SYS_RES_MEMORY, AGP_I810_MMADR, RF_ACTIVE | RF_SHAREABLE },
85         { -1, 0 }
86 };
87
88 static struct resource_spec agp_i915_res_spec[] = {
89         { SYS_RES_MEMORY, AGP_I915_MMADR, RF_ACTIVE | RF_SHAREABLE },
90         { SYS_RES_MEMORY, AGP_I915_GTTADR, RF_ACTIVE | RF_SHAREABLE },
91         { -1, 0 }
92 };
93
94 static struct resource_spec agp_i965_res_spec[] = {
95         { SYS_RES_MEMORY, AGP_I965_GTTMMADR, RF_ACTIVE | RF_SHAREABLE },
96         { -1, 0 }
97 };
98
99 struct agp_i810_softc {
100         struct agp_softc agp;
101         u_int32_t initial_aperture;     /* aperture size at startup */
102         struct agp_gatt *gatt;
103         int chiptype;                   /* i810-like or i830 */
104         u_int32_t dcache_size;          /* i810 only */
105         u_int32_t stolen;               /* number of i830/845 gtt entries for stolen memory */
106         device_t bdev;                  /* bridge device */
107
108         void *argb_cursor;              /* contigmalloc area for ARGB cursor */
109
110         struct resource_spec * sc_res_spec;
111         struct resource *sc_res[2];
112 };
113
114 /* For adding new devices, devid is the id of the graphics controller
115  * (pci:0:2:0, for example).  The placeholder (usually at pci:0:2:1) for the
116  * second head should never be added.  The bridge_offset is the offset to
117  * subtract from devid to get the id of the hostb that the device is on.
118  */
119 static const struct agp_i810_match {
120         int devid;
121         int chiptype;
122         int bridge_offset;
123         char *name;
124 } agp_i810_matches[] = {
125         {0x71218086, CHIP_I810, 0x00010000,
126             "Intel 82810 (i810 GMCH) SVGA controller"},
127         {0x71238086, CHIP_I810, 0x00010000,
128             "Intel 82810-DC100 (i810-DC100 GMCH) SVGA controller"},
129         {0x71258086, CHIP_I810, 0x00010000,
130             "Intel 82810E (i810E GMCH) SVGA controller"},
131         {0x11328086, CHIP_I810, 0x00020000,
132             "Intel 82815 (i815 GMCH) SVGA controller"},
133         {0x35778086, CHIP_I830, 0x00020000,
134             "Intel 82830M (830M GMCH) SVGA controller"},
135         {0x35828086, CHIP_I855, 0x00020000,
136             "Intel 82852/5"},
137         {0x25728086, CHIP_I855, 0x00020000,
138             "Intel 82865G (865G GMCH) SVGA controller"},
139         {0x25828086, CHIP_I915, 0x00020000,
140             "Intel 82915G (915G GMCH) SVGA controller"},
141         {0x25928086, CHIP_I915, 0x00020000,
142             "Intel 82915GM (915GM GMCH) SVGA controller"},
143         {0x27728086, CHIP_I915, 0x00020000,
144             "Intel 82945G (945G GMCH) SVGA controller"},
145         {0x27A28086, CHIP_I915, 0x00020000,
146             "Intel 82945GM (945GM GMCH) SVGA controller"},
147         {0x27A28086, CHIP_I915, 0x00020000,
148             "Intel 945GME SVGA controller"},
149         {0x29728086, CHIP_I965, 0x00020000,
150             "Intel 946GZ SVGA controller"},
151         {0x29828086, CHIP_I965, 0x00020000,
152             "Intel G965 SVGA controller"},
153         {0x29928086, CHIP_I965, 0x00020000,
154             "Intel Q965 SVGA controller"},
155         {0x29a28086, CHIP_I965, 0x00020000,
156             "Intel G965 SVGA controller"},
157 /*
158         {0x29b28086, CHIP_G33, 0x00020000,
159             "Intel Q35 SVGA controller"},
160         {0x29c28086, CHIP_G33, 0x00020000,
161             "Intel G33 SVGA controller"},
162         {0x29d28086, CHIP_G33, 0x00020000,
163             "Intel Q33 SVGA controller"},
164 */
165         {0x2a028086, CHIP_I965, 0x00020000,
166             "Intel GM965 SVGA controller"},
167         {0x2a128086, CHIP_I965, 0x00020000,
168             "Intel GME965 SVGA controller"},
169         {0, 0, 0, NULL}
170 };
171
172 static const struct agp_i810_match*
173 agp_i810_match(device_t dev)
174 {
175         int i, devid;
176
177         if (pci_get_class(dev) != PCIC_DISPLAY
178             || pci_get_subclass(dev) != PCIS_DISPLAY_VGA)
179                 return NULL;
180
181         devid = pci_get_devid(dev);
182         for (i = 0; agp_i810_matches[i].devid != 0; i++) {
183                 if (agp_i810_matches[i].devid == devid)
184                     break;
185         }
186         if (agp_i810_matches[i].devid == 0)
187                 return NULL;
188         else
189                 return &agp_i810_matches[i];
190 }
191
192 /*
193  * Find bridge device.
194  */
195 static device_t
196 agp_i810_find_bridge(device_t dev)
197 {
198         device_t *children, child;
199         int nchildren, i;
200         u_int32_t devid;
201         const struct agp_i810_match *match;
202   
203         match = agp_i810_match(dev);
204         devid = match->devid - match->bridge_offset;
205
206         if (device_get_children(device_get_parent(dev), &children, &nchildren))
207                 return 0;
208
209         for (i = 0; i < nchildren; i++) {
210                 child = children[i];
211
212                 if (pci_get_devid(child) == devid) {
213                         kfree(children, M_TEMP);
214                         return child;
215                 }
216         }
217         kfree(children, M_TEMP);
218         return 0;
219 }
220
221 static void
222 agp_i810_identify(driver_t *driver, device_t parent)
223 {
224
225         if (device_find_child(parent, "agp", -1) == NULL &&
226             agp_i810_match(parent))
227                 device_add_child(parent, "agp", -1);
228 }
229
230 static int
231 agp_i810_probe(device_t dev)
232 {
233         device_t bdev;
234         const struct agp_i810_match *match;
235         u_int8_t smram;
236         int gcc1, deven;
237
238         if (resource_disabled("agp", device_get_unit(dev)))
239                 return (ENXIO);
240         match = agp_i810_match(dev);
241         if (match == NULL)
242                 return ENXIO;
243
244         bdev = agp_i810_find_bridge(dev);
245         if (!bdev) {
246                 if (bootverbose)
247                         kprintf("I810: can't find bridge device\n");
248                 return ENXIO;
249         }
250
251         /*
252          * checking whether internal graphics device has been activated.
253          */
254         switch (match->chiptype) {
255         case CHIP_I810:
256                 smram = pci_read_config(bdev, AGP_I810_SMRAM, 1);
257                 if ((smram & AGP_I810_SMRAM_GMS) ==
258                     AGP_I810_SMRAM_GMS_DISABLED) {
259                         if (bootverbose)
260                                 kprintf("I810: disabled, not probing\n");
261                         return ENXIO;
262                 }
263                 break;
264         case CHIP_I830:
265         case CHIP_I855:
266                 gcc1 = pci_read_config(bdev, AGP_I830_GCC1, 1);
267                 if ((gcc1 & AGP_I830_GCC1_DEV2) ==
268                     AGP_I830_GCC1_DEV2_DISABLED) {
269                         if (bootverbose)
270                                 kprintf("I830: disabled, not probing\n");
271                         return ENXIO;
272                 }
273                 break;
274         case CHIP_I915:
275         case CHIP_I965:
276         case CHIP_G33:
277                 deven = pci_read_config(bdev, AGP_I915_DEVEN, 4);
278                 if ((deven & AGP_I915_DEVEN_D2F0) ==
279                     AGP_I915_DEVEN_D2F0_DISABLED) {
280                         if (bootverbose)
281                                 kprintf("I915: disabled, not probing\n");
282                         return ENXIO;
283                 }
284                 break;
285         }
286
287         device_verbose(dev);
288         if (match->devid == 0x35828086) {
289                 switch (pci_read_config(dev, AGP_I85X_CAPID, 1)) {
290                 case AGP_I855_GME:
291                         device_set_desc(dev,
292                             "Intel 82855GME (855GME GMCH) SVGA controller");
293                         break;
294                 case AGP_I855_GM:
295                         device_set_desc(dev,
296                             "Intel 82855GM (855GM GMCH) SVGA controller");
297                         break;
298                 case AGP_I852_GME:
299                         device_set_desc(dev,
300                             "Intel 82852GME (852GME GMCH) SVGA controller");
301                         break;
302                 case AGP_I852_GM:
303                         device_set_desc(dev,
304                             "Intel 82852GM (852GM GMCH) SVGA controller");
305                         break;
306                 default:
307                         device_set_desc(dev,
308                             "Intel 8285xM (85xGM GMCH) SVGA controller");
309                         break;
310                 }
311         } else {
312                 device_set_desc(dev, match->name);
313         }
314
315         return BUS_PROBE_DEFAULT;
316 }
317
318 static void
319 agp_i810_dump_regs(device_t dev)
320 {
321         struct agp_i810_softc *sc = device_get_softc(dev);
322
323         device_printf(dev, "AGP_I810_PGTBL_CTL: %08x\n",
324             bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL));
325
326         switch (sc->chiptype) {
327         case CHIP_I810:
328                 device_printf(dev, "AGP_I810_MISCC: 0x%04x\n",
329                     pci_read_config(sc->bdev, AGP_I810_MISCC, 2));
330                 break;
331         case CHIP_I830:
332                 device_printf(dev, "AGP_I830_GCC1: 0x%02x\n",
333                     pci_read_config(sc->bdev, AGP_I830_GCC1, 1));
334                 break;
335         case CHIP_I855:
336                 device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
337                     pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
338                 break;
339         case CHIP_I915:
340         case CHIP_I965:
341         case CHIP_G33:
342                 device_printf(dev, "AGP_I855_GCC1: 0x%02x\n",
343                     pci_read_config(sc->bdev, AGP_I855_GCC1, 1));
344                 device_printf(dev, "AGP_I915_MSAC: 0x%02x\n",
345                     pci_read_config(sc->bdev, AGP_I915_MSAC, 1));
346                 break;
347         }
348         device_printf(dev, "Aperture resource size: %d bytes\n",
349             AGP_GET_APERTURE(dev));
350 }
351
352 static int
353 agp_i810_attach(device_t dev)
354 {
355         struct agp_i810_softc *sc = device_get_softc(dev);
356         struct agp_gatt *gatt;
357         const struct agp_i810_match *match;
358         int error;
359
360         sc->bdev = agp_i810_find_bridge(dev);
361         if (!sc->bdev)
362                 return ENOENT;
363
364         match = agp_i810_match(dev);
365         sc->chiptype = match->chiptype;
366
367         switch (sc->chiptype) {
368         case CHIP_I810:
369         case CHIP_I830:
370         case CHIP_I855:
371                 sc->sc_res_spec = agp_i810_res_spec;
372                 agp_set_aperture_resource(dev, AGP_APBASE);
373                 break;
374         case CHIP_I915:
375         case CHIP_G33:
376                 sc->sc_res_spec = agp_i915_res_spec;
377                 agp_set_aperture_resource(dev, AGP_I915_GMADR);
378                 break;
379         case CHIP_I965:
380                 sc->sc_res_spec = agp_i965_res_spec;
381                 agp_set_aperture_resource(dev, AGP_I915_GMADR);
382                 break;
383         }
384
385         error = agp_generic_attach(dev);
386         if (error)
387                 return error;
388
389         if (sc->chiptype != CHIP_I965 && sc->chiptype != CHIP_G33 &&
390             ptoa((vm_paddr_t)Maxmem) > 0xfffffffful)
391         {
392                 device_printf(dev, "agp_i810.c does not support physical "
393                     "memory above 4GB.\n");
394                 return ENOENT;
395         }
396
397         if (bus_alloc_resources(dev, sc->sc_res_spec, sc->sc_res)) {
398                 agp_generic_detach(dev);
399                 return ENODEV;
400         }
401
402         sc->initial_aperture = AGP_GET_APERTURE(dev);
403         if (sc->initial_aperture == 0) {
404                 device_printf(dev, "bad initial aperture size, disabling\n");
405                 return ENXIO;
406         }
407
408         gatt = kmalloc( sizeof(struct agp_gatt), M_AGP, M_INTWAIT);
409         sc->gatt = gatt;
410
411         gatt->ag_entries = AGP_GET_APERTURE(dev) >> AGP_PAGE_SHIFT;
412
413         if ( sc->chiptype == CHIP_I810 ) {
414                 /* Some i810s have on-chip memory called dcache */
415                 if (bus_read_1(sc->sc_res[0], AGP_I810_DRT) &
416                     AGP_I810_DRT_POPULATED)
417                         sc->dcache_size = 4 * 1024 * 1024;
418                 else
419                         sc->dcache_size = 0;
420
421                 /* According to the specs the gatt on the i810 must be 64k */
422                 gatt->ag_virtual = contigmalloc( 64 * 1024, M_AGP, 0, 
423                                         0, ~0, PAGE_SIZE, 0);
424                 if (!gatt->ag_virtual) {
425                         if (bootverbose)
426                                 device_printf(dev, "contiguous allocation failed\n");
427                         bus_release_resources(dev, sc->sc_res_spec,
428                             sc->sc_res);
429                         kfree(gatt, M_AGP);
430                         agp_generic_detach(dev);
431                         return ENOMEM;
432                 }
433                 bzero(gatt->ag_virtual, gatt->ag_entries * sizeof(u_int32_t));
434         
435                 gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
436                 agp_flush_cache();
437                 /* Install the GATT. */
438                 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL,
439                     gatt->ag_physical | 1);
440         } else if ( sc->chiptype == CHIP_I830 ) {
441                 /* The i830 automatically initializes the 128k gatt on boot. */
442                 unsigned int gcc1, pgtblctl;
443                 
444                 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 1);
445                 switch (gcc1 & AGP_I830_GCC1_GMS) {
446                         case AGP_I830_GCC1_GMS_STOLEN_512:
447                                 sc->stolen = (512 - 132) * 1024 / 4096;
448                                 break;
449                         case AGP_I830_GCC1_GMS_STOLEN_1024: 
450                                 sc->stolen = (1024 - 132) * 1024 / 4096;
451                                 break;
452                         case AGP_I830_GCC1_GMS_STOLEN_8192: 
453                                 sc->stolen = (8192 - 132) * 1024 / 4096;
454                                 break;
455                         default:
456                                 sc->stolen = 0;
457                                 device_printf(dev, "unknown memory configuration, disabling\n");
458                                 bus_release_resources(dev, sc->sc_res_spec,
459                                     sc->sc_res);
460                                 kfree(gatt, M_AGP);
461                                 agp_generic_detach(dev);
462                                 return EINVAL;
463                 }
464                 if (sc->stolen > 0) {
465                         device_printf(dev, "detected %dk stolen memory\n",
466                             sc->stolen * 4);
467                 }
468                 device_printf(dev, "aperture size is %dM\n",
469                     sc->initial_aperture / 1024 / 1024);
470
471                 /* GATT address is already in there, make sure it's enabled */
472                 pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
473                 pgtblctl |= 1;
474                 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
475
476                 gatt->ag_physical = pgtblctl & ~1;
477         } else if (sc->chiptype == CHIP_I855 || sc->chiptype == CHIP_I915 ||
478             sc->chiptype == CHIP_I965 || sc->chiptype == CHIP_G33) {
479                 unsigned int gcc1, pgtblctl, stolen, gtt_size;
480
481                 /* Stolen memory is set up at the beginning of the aperture by
482                  * the BIOS, consisting of the GATT followed by 4kb for the
483                  * BIOS display.
484                  */
485                 switch (sc->chiptype) {
486                 case CHIP_I855:
487                         gtt_size = 128;
488                         break;
489                 case CHIP_I915:
490                         gtt_size = 256;
491                         break;
492                 case CHIP_I965:
493                 case CHIP_G33:
494                         switch (bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL) &
495                             AGP_I810_PGTBL_SIZE_MASK) {
496                         case AGP_I810_PGTBL_SIZE_128KB:
497                                 gtt_size = 128;
498                                 break;
499                         case AGP_I810_PGTBL_SIZE_256KB:
500                                 gtt_size = 256;
501                                 break;
502                         case AGP_I810_PGTBL_SIZE_512KB:
503                                 gtt_size = 512;
504                                 break;
505                         default:
506                                 device_printf(dev, "Bad PGTBL size\n");
507                                 bus_release_resources(dev, sc->sc_res_spec,
508                                     sc->sc_res);
509                                 kfree(gatt, M_AGP);
510                                 agp_generic_detach(dev);
511                                 return EINVAL;
512                         }
513                         break;
514                 default:
515                         device_printf(dev, "Bad chiptype\n");
516                         bus_release_resources(dev, sc->sc_res_spec,
517                             sc->sc_res);
518                         kfree(gatt, M_AGP);
519                         agp_generic_detach(dev);
520                         return EINVAL;
521                 }
522
523                 /* GCC1 is called MGGC on i915+ */
524                 gcc1 = pci_read_config(sc->bdev, AGP_I855_GCC1, 1);
525                 switch (gcc1 & AGP_I855_GCC1_GMS) {
526                 case AGP_I855_GCC1_GMS_STOLEN_1M:
527                         stolen = 1024;
528                         break;
529                 case AGP_I855_GCC1_GMS_STOLEN_4M:
530                         stolen = 4096;
531                         break;
532                 case AGP_I855_GCC1_GMS_STOLEN_8M:
533                         stolen = 8192;
534                         break;
535                 case AGP_I855_GCC1_GMS_STOLEN_16M:
536                         stolen = 16384;
537                         break;
538                 case AGP_I855_GCC1_GMS_STOLEN_32M:
539                         stolen = 32768;
540                         break;
541                 case AGP_I915_GCC1_GMS_STOLEN_48M:
542                         stolen = 49152;
543                         break;
544                 case AGP_I915_GCC1_GMS_STOLEN_64M:
545                         stolen = 65536;
546                         break;
547                 case AGP_G33_GCC1_GMS_STOLEN_128M:
548                         stolen = 128 * 1024;
549                         break;
550                 case AGP_G33_GCC1_GMS_STOLEN_256M:
551                         stolen = 256 * 1024;
552                         break;
553                 default:
554                         device_printf(dev, "unknown memory configuration, "
555                             "disabling\n");
556                         bus_release_resources(dev, sc->sc_res_spec,
557                             sc->sc_res);
558                         kfree(gatt, M_AGP);
559                         agp_generic_detach(dev);
560                         return EINVAL;
561                 }
562                 sc->stolen = (stolen - gtt_size - 4) * 1024 / 4096;
563                 if (sc->stolen > 0)
564                         device_printf(dev, "detected %dk stolen memory\n", sc->stolen * 4);
565                 device_printf(dev, "aperture size is %dM\n", sc->initial_aperture / 1024 / 1024);
566
567                 /* GATT address is already in there, make sure it's enabled */
568                 pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
569                 pgtblctl |= 1;
570                 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
571
572                 gatt->ag_physical = pgtblctl & ~1;
573         }
574
575         if (0)
576                 agp_i810_dump_regs(dev);
577
578         return 0;
579 }
580
581 static int
582 agp_i810_detach(device_t dev)
583 {
584         struct agp_i810_softc *sc = device_get_softc(dev);
585         int error;
586
587         error = agp_generic_detach(dev);
588         if (error)
589                 return error;
590
591         /* Clear the GATT base. */
592         if ( sc->chiptype == CHIP_I810 ) {
593                 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, 0);
594         } else {
595                 unsigned int pgtblctl;
596                 pgtblctl = bus_read_4(sc->sc_res[0], AGP_I810_PGTBL_CTL);
597                 pgtblctl &= ~1;
598                 bus_write_4(sc->sc_res[0], AGP_I810_PGTBL_CTL, pgtblctl);
599         }
600
601         /* Put the aperture back the way it started. */
602         AGP_SET_APERTURE(dev, sc->initial_aperture);
603
604         if ( sc->chiptype == CHIP_I810 ) {
605                 contigfree(sc->gatt->ag_virtual, 64 * 1024, M_AGP);
606         }
607         kfree(sc->gatt, M_AGP);
608
609         bus_release_resources(dev, sc->sc_res_spec, sc->sc_res);
610
611         return 0;
612 }
613
614 /**
615  * Sets the PCI resource size of the aperture on i830-class and below chipsets,
616  * while returning failure on later chipsets when an actual change is
617  * requested.
618  *
619  * This whole function is likely bogus, as the kernel would probably need to
620  * reconfigure the placement of the AGP aperture if a larger size is requested,
621  * which doesn't happen currently.
622  */
623 static int
624 agp_i810_set_aperture(device_t dev, u_int32_t aperture)
625 {
626         struct agp_i810_softc *sc = device_get_softc(dev);
627         u_int16_t miscc, gcc1;
628
629         switch (sc->chiptype) {
630         case CHIP_I810:
631                 /*
632                  * Double check for sanity.
633                  */
634                 if (aperture != 32 * 1024 * 1024 && aperture != 64 * 1024 * 1024) {
635                         device_printf(dev, "bad aperture size %d\n", aperture);
636                         return EINVAL;
637                 }
638
639                 miscc = pci_read_config(sc->bdev, AGP_I810_MISCC, 2);
640                 miscc &= ~AGP_I810_MISCC_WINSIZE;
641                 if (aperture == 32 * 1024 * 1024)
642                         miscc |= AGP_I810_MISCC_WINSIZE_32;
643                 else
644                         miscc |= AGP_I810_MISCC_WINSIZE_64;
645         
646                 pci_write_config(sc->bdev, AGP_I810_MISCC, miscc, 2);
647                 break;
648         case CHIP_I830:
649                 if (aperture != 64 * 1024 * 1024 &&
650                     aperture != 128 * 1024 * 1024) {
651                         device_printf(dev, "bad aperture size %d\n", aperture);
652                         return EINVAL;
653                 }
654                 gcc1 = pci_read_config(sc->bdev, AGP_I830_GCC1, 2);
655                 gcc1 &= ~AGP_I830_GCC1_GMASIZE;
656                 if (aperture == 64 * 1024 * 1024)
657                         gcc1 |= AGP_I830_GCC1_GMASIZE_64;
658                 else
659                         gcc1 |= AGP_I830_GCC1_GMASIZE_128;
660
661                 pci_write_config(sc->bdev, AGP_I830_GCC1, gcc1, 2);
662                 break;
663         case CHIP_I855:
664         case CHIP_I915:
665         case CHIP_I965:
666         case CHIP_G33:
667                 return agp_generic_set_aperture(dev, aperture);
668         }
669
670         return 0;
671 }
672
673 /**
674  * Writes a GTT entry mapping the page at the given offset from the beginning
675  * of the aperture to the given physical address.
676  */
677 static void
678 agp_i810_write_gtt_entry(device_t dev, int offset, vm_offset_t physical,
679     int enabled)
680 {
681         struct agp_i810_softc *sc = device_get_softc(dev);
682         u_int32_t pte;
683
684         pte = (u_int32_t)physical | 1;
685         if (sc->chiptype == CHIP_I965 || sc->chiptype == CHIP_G33) {
686                 pte |= (physical & 0x0000000f00000000ull) >> 28;
687         } else {
688                 /* If we do actually have memory above 4GB on an older system,
689                  * crash cleanly rather than scribble on system memory,
690                  * so we know we need to fix it.
691                  */
692                 KASSERT((pte & 0x0000000f00000000ull) == 0,
693                     (">4GB physical address in agp"));
694         }
695
696         switch (sc->chiptype) {
697         case CHIP_I810:
698         case CHIP_I830:
699         case CHIP_I855:
700                 bus_write_4(sc->sc_res[0],
701                     AGP_I810_GTT + (offset >> AGP_PAGE_SHIFT) * 4, pte);
702                 break;
703         case CHIP_I915:
704         case CHIP_G33:
705                 bus_write_4(sc->sc_res[1],
706                     (offset >> AGP_PAGE_SHIFT) * 4, pte);
707                 break;
708         case CHIP_I965:
709                 bus_write_4(sc->sc_res[0],
710                     (offset >> AGP_PAGE_SHIFT) * 4 + (512 * 1024), pte);
711                 break;
712         }
713 }
714
715 static int
716 agp_i810_bind_page(device_t dev, int offset, vm_offset_t physical)
717 {
718         struct agp_i810_softc *sc = device_get_softc(dev);
719
720         if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
721                 device_printf(dev, "failed: offset is 0x%08x, shift is %d, entries is %d\n", offset, AGP_PAGE_SHIFT, sc->gatt->ag_entries);
722                 return EINVAL;
723         }
724
725         if ( sc->chiptype != CHIP_I810 ) {
726                 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
727                         device_printf(dev, "trying to bind into stolen memory");
728                         return EINVAL;
729                 }
730         }
731
732         agp_i810_write_gtt_entry(dev, offset, physical, 1);
733
734         return 0;
735 }
736
737 static int
738 agp_i810_unbind_page(device_t dev, int offset)
739 {
740         struct agp_i810_softc *sc = device_get_softc(dev);
741
742         if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
743                 return EINVAL;
744
745         if ( sc->chiptype != CHIP_I810 ) {
746                 if ( (offset >> AGP_PAGE_SHIFT) < sc->stolen ) {
747                         device_printf(dev, "trying to unbind from stolen memory");
748                         return EINVAL;
749                 }
750         }
751
752         agp_i810_write_gtt_entry(dev, offset, 0, 0);
753
754         return 0;
755 }
756
757 /*
758  * Writing via memory mapped registers already flushes all TLBs.
759  */
760 static void
761 agp_i810_flush_tlb(device_t dev)
762 {
763 }
764
765 static int
766 agp_i810_enable(device_t dev, u_int32_t mode)
767 {
768
769         return 0;
770 }
771
772 static struct agp_memory *
773 agp_i810_alloc_memory(device_t dev, int type, vm_size_t size)
774 {
775         struct agp_i810_softc *sc = device_get_softc(dev);
776         struct agp_memory *mem;
777
778         if ((size & (AGP_PAGE_SIZE - 1)) != 0)
779                 return 0;
780
781         if (sc->agp.as_allocated + size > sc->agp.as_maxmem)
782                 return 0;
783
784         if (type == 1) {
785                 /*
786                  * Mapping local DRAM into GATT.
787                  */
788                 if ( sc->chiptype != CHIP_I810 )
789                         return 0;
790                 if (size != sc->dcache_size)
791                         return 0;
792         } else if (type == 2) {
793                 /*
794                  * Type 2 is the contiguous physical memory type, that hands
795                  * back a physical address.  This is used for cursors on i810.
796                  * Hand back as many single pages with physical as the user
797                  * wants, but only allow one larger allocation (ARGB cursor)
798                  * for simplicity.
799                  */
800                 if (size != AGP_PAGE_SIZE) {
801                         if (sc->argb_cursor != NULL)
802                                 return 0;
803
804                         /* Allocate memory for ARGB cursor, if we can. */
805                         sc->argb_cursor = contigmalloc(size, M_AGP,
806                            0, 0, ~0, PAGE_SIZE, 0);
807                         if (sc->argb_cursor == NULL)
808                                 return 0;
809                 }
810         }
811
812         mem = kmalloc(sizeof *mem, M_AGP, M_INTWAIT);
813         mem->am_id = sc->agp.as_nextid++;
814         mem->am_size = size;
815         mem->am_type = type;
816         if (type != 1 && (type != 2 || size == AGP_PAGE_SIZE))
817                 mem->am_obj = vm_object_allocate(OBJT_DEFAULT,
818                                                  atop(round_page(size)));
819         else
820                 mem->am_obj = 0;
821
822         if (type == 2) {
823                 if (size == AGP_PAGE_SIZE) {
824                         /*
825                          * Allocate and wire down the page now so that we can
826                          * get its physical address.
827                          */
828                         vm_page_t m;
829         
830                         m = vm_page_grab(mem->am_obj, 0, 
831                                          VM_ALLOC_NORMAL|VM_ALLOC_ZERO|VM_ALLOC_RETRY);
832                         if ((m->flags & PG_ZERO) == 0)
833                                 vm_page_zero_fill(m);
834                         vm_page_wire(m);
835                         mem->am_physical = VM_PAGE_TO_PHYS(m);
836                         vm_page_wakeup(m);
837                 } else {
838                         /* Our allocation is already nicely wired down for us.
839                          * Just grab the physical address.
840                          */
841                         mem->am_physical = vtophys(sc->argb_cursor);
842                 }
843         } else {
844                 mem->am_physical = 0;
845         }
846
847         mem->am_offset = 0;
848         mem->am_is_bound = 0;
849         TAILQ_INSERT_TAIL(&sc->agp.as_memory, mem, am_link);
850         sc->agp.as_allocated += size;
851
852         return mem;
853 }
854
855 static int
856 agp_i810_free_memory(device_t dev, struct agp_memory *mem)
857 {
858         struct agp_i810_softc *sc = device_get_softc(dev);
859
860         if (mem->am_is_bound)
861                 return EBUSY;
862
863         if (mem->am_type == 2) {
864                 if (mem->am_size == AGP_PAGE_SIZE) {
865                         /*
866                          * Unwire the page which we wired in alloc_memory.
867                          */
868                         vm_page_t m = vm_page_lookup(mem->am_obj, 0);
869                         vm_page_unwire(m, 0);
870                 } else {
871                         contigfree(sc->argb_cursor, mem->am_size, M_AGP);
872                         sc->argb_cursor = NULL;
873                 }
874         }
875
876         sc->agp.as_allocated -= mem->am_size;
877         TAILQ_REMOVE(&sc->agp.as_memory, mem, am_link);
878         if (mem->am_obj)
879                 vm_object_deallocate(mem->am_obj);
880         kfree(mem, M_AGP);
881         return 0;
882 }
883
884 static int
885 agp_i810_bind_memory(device_t dev, struct agp_memory *mem,
886                      vm_offset_t offset)
887 {
888         struct agp_i810_softc *sc = device_get_softc(dev);
889         vm_offset_t i;
890
891         /* Do some sanity checks first. */
892         if (offset < 0 || (offset & (AGP_PAGE_SIZE - 1)) != 0 ||
893             offset + mem->am_size > AGP_GET_APERTURE(dev)) {
894                 device_printf(dev, "binding memory at bad offset %#x\n",
895                     (int)offset);
896                 return EINVAL;
897         }
898
899         if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
900                 lockmgr(&sc->agp.as_lock, LK_EXCLUSIVE);
901                 if (mem->am_is_bound) {
902                         lockmgr(&sc->agp.as_lock, LK_RELEASE);
903                         return EINVAL;
904                 }
905                 /* The memory's already wired down, just stick it in the GTT. */
906                 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
907                         agp_i810_write_gtt_entry(dev, offset + i,
908                             mem->am_physical + i, 1);
909                 }
910                 agp_flush_cache();
911                 mem->am_offset = offset;
912                 mem->am_is_bound = 1;
913                 lockmgr(&sc->agp.as_lock, LK_RELEASE);
914                 return 0;
915         }
916
917         if (mem->am_type != 1)
918                 return agp_generic_bind_memory(dev, mem, offset);
919
920         if ( sc->chiptype != CHIP_I810 )
921                 return EINVAL;
922
923         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
924                 bus_write_4(sc->sc_res[0],
925                     AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, i | 3);
926         }
927
928         return 0;
929 }
930
931 static int
932 agp_i810_unbind_memory(device_t dev, struct agp_memory *mem)
933 {
934         struct agp_i810_softc *sc = device_get_softc(dev);
935         vm_offset_t i;
936
937         if (mem->am_type == 2 && mem->am_size != AGP_PAGE_SIZE) {
938                 lockmgr(&sc->agp.as_lock, LK_EXCLUSIVE);
939                 if (!mem->am_is_bound) {
940                         lockmgr(&sc->agp.as_lock, LK_RELEASE);
941                         return EINVAL;
942                 }
943
944                 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
945                         agp_i810_write_gtt_entry(dev, mem->am_offset + i,
946                             0, 0);
947                 }
948                 agp_flush_cache();
949                 mem->am_is_bound = 0;
950                 lockmgr(&sc->agp.as_lock, LK_RELEASE);
951                 return 0;
952         }
953
954         if (mem->am_type != 1)
955                 return agp_generic_unbind_memory(dev, mem);
956
957         if ( sc->chiptype != CHIP_I810 )
958                 return EINVAL;
959
960         for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE) {
961                 bus_write_4(sc->sc_res[0],
962                     AGP_I810_GTT + (i >> AGP_PAGE_SHIFT) * 4, 0);
963         }
964
965         return 0;
966 }
967
968 static device_method_t agp_i810_methods[] = {
969         /* Device interface */
970         DEVMETHOD(device_identify,      agp_i810_identify),
971         DEVMETHOD(device_probe,         agp_i810_probe),
972         DEVMETHOD(device_attach,        agp_i810_attach),
973         DEVMETHOD(device_detach,        agp_i810_detach),
974
975         /* AGP interface */
976         DEVMETHOD(agp_get_aperture,     agp_generic_get_aperture),
977         DEVMETHOD(agp_set_aperture,     agp_i810_set_aperture),
978         DEVMETHOD(agp_bind_page,        agp_i810_bind_page),
979         DEVMETHOD(agp_unbind_page,      agp_i810_unbind_page),
980         DEVMETHOD(agp_flush_tlb,        agp_i810_flush_tlb),
981         DEVMETHOD(agp_enable,           agp_i810_enable),
982         DEVMETHOD(agp_alloc_memory,     agp_i810_alloc_memory),
983         DEVMETHOD(agp_free_memory,      agp_i810_free_memory),
984         DEVMETHOD(agp_bind_memory,      agp_i810_bind_memory),
985         DEVMETHOD(agp_unbind_memory,    agp_i810_unbind_memory),
986
987         { 0, 0 }
988 };
989
990 static driver_t agp_i810_driver = {
991         "agp",
992         agp_i810_methods,
993         sizeof(struct agp_i810_softc),
994 };
995
996 static devclass_t agp_devclass;
997
998 DRIVER_MODULE(agp_i810, pci, agp_i810_driver, agp_devclass, 0, 0);
999 MODULE_DEPEND(agp_i810, agp, 1, 1, 1);
1000 MODULE_DEPEND(agp_i810, pci, 1, 1, 1);