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