2 * Copyright (c) 2000 Doug Rabson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * $FreeBSD: src/sys/dev/agp/agp_amd.c,v 1.25 2007/11/12 21:51:36 jhb Exp $
27 * $DragonFly: src/sys/dev/agp/agp_amd.c,v 1.11 2008/01/07 01:34:58 corecode Exp $
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/malloc.h>
35 #include <sys/kernel.h>
40 #include <bus/pci/pcivar.h>
41 #include <bus/pci/pcireg.h>
46 #include <vm/vm_object.h>
49 MALLOC_DECLARE(M_AGP
);
51 #define READ2(off) bus_space_read_2(sc->bst, sc->bsh, off)
52 #define READ4(off) bus_space_read_4(sc->bst, sc->bsh, off)
53 #define WRITE2(off,v) bus_space_write_2(sc->bst, sc->bsh, off, v)
54 #define WRITE4(off,v) bus_space_write_4(sc->bst, sc->bsh, off, v)
58 u_int32_t
*ag_virtual
; /* virtual address of gatt */
59 vm_offset_t ag_physical
;
60 u_int32_t
*ag_vdir
; /* virtual address of page dir */
61 vm_offset_t ag_pdir
; /* physical address of page dir */
64 struct agp_amd_softc
{
66 struct resource
*regs
; /* memory mapped control registers */
67 bus_space_tag_t bst
; /* bus_space tag */
68 bus_space_handle_t bsh
; /* bus_space handle */
69 u_int32_t initial_aperture
; /* aperture size at startup */
70 struct agp_amd_gatt
*gatt
;
73 static struct agp_amd_gatt
*
74 agp_amd_alloc_gatt(device_t dev
)
76 u_int32_t apsize
= AGP_GET_APERTURE(dev
);
77 u_int32_t entries
= apsize
>> AGP_PAGE_SHIFT
;
78 struct agp_amd_gatt
*gatt
;
79 int i
, npages
, pdir_offset
;
83 "allocating GATT for aperture of size %dM\n",
84 apsize
/ (1024*1024));
86 gatt
= kmalloc(sizeof(struct agp_amd_gatt
), M_AGP
, M_INTWAIT
);
89 * The AMD751 uses a page directory to map a non-contiguous
90 * gatt so we don't need to use contigmalloc.
91 * Malloc individual gatt pages and map them into the page
94 gatt
->ag_entries
= entries
;
95 gatt
->ag_virtual
= kmalloc(entries
* sizeof(u_int32_t
),
96 M_AGP
, M_INTWAIT
| M_ZERO
);
99 * Allocate the page directory.
101 gatt
->ag_vdir
= kmalloc(AGP_PAGE_SIZE
, M_AGP
, M_INTWAIT
| M_ZERO
);
103 gatt
->ag_pdir
= vtophys((vm_offset_t
) gatt
->ag_vdir
);
105 device_printf(dev
, "gatt -> ag_pdir %#lx\n",
106 (u_long
)gatt
->ag_pdir
);
108 * Allocate the gatt pages
110 gatt
->ag_entries
= entries
;
112 device_printf(dev
, "allocating GATT for %d AGP page entries\n",
115 gatt
->ag_physical
= vtophys((vm_offset_t
) gatt
->ag_virtual
);
118 * Map the pages of the GATT into the page directory.
120 * The GATT page addresses are mapped into the directory offset by
121 * an amount dependent on the base address of the aperture. This
122 * is and offset into the page directory, not an offset added to
123 * the addresses of the gatt pages.
126 pdir_offset
= pci_read_config(dev
, AGP_AMD751_APBASE
, 4) >> 22;
128 npages
= ((entries
* sizeof(u_int32_t
) + AGP_PAGE_SIZE
- 1)
131 for (i
= 0; i
< npages
; i
++) {
135 va
= ((vm_offset_t
) gatt
->ag_virtual
) + i
* AGP_PAGE_SIZE
;
137 gatt
->ag_vdir
[i
+ pdir_offset
] = pa
| 1;
141 * Make sure the chipset can see everything.
149 agp_amd_free_gatt(struct agp_amd_gatt
*gatt
)
151 kfree(gatt
->ag_virtual
, M_AGP
);
152 kfree(gatt
->ag_vdir
, M_AGP
);
157 agp_amd_match(device_t dev
)
159 if (pci_get_class(dev
) != PCIC_BRIDGE
160 || pci_get_subclass(dev
) != PCIS_BRIDGE_HOST
)
163 if (agp_find_caps(dev
) == 0)
166 switch (pci_get_devid(dev
)) {
168 return ("AMD 751 host to AGP bridge");
170 return ("AMD 761 host to AGP bridge");
172 return ("AMD 762 host to AGP bridge");
179 agp_amd_probe(device_t dev
)
183 if (resource_disabled("agp", device_get_unit(dev
)))
185 desc
= agp_amd_match(dev
);
188 device_set_desc(dev
, desc
);
189 return BUS_PROBE_DEFAULT
;
196 agp_amd_attach(device_t dev
)
198 struct agp_amd_softc
*sc
= device_get_softc(dev
);
199 struct agp_amd_gatt
*gatt
;
202 error
= agp_generic_attach(dev
);
206 rid
= AGP_AMD751_REGISTERS
;
207 sc
->regs
= bus_alloc_resource_any(dev
, SYS_RES_MEMORY
, &rid
,
210 agp_generic_detach(dev
);
214 sc
->bst
= rman_get_bustag(sc
->regs
);
215 sc
->bsh
= rman_get_bushandle(sc
->regs
);
217 sc
->initial_aperture
= AGP_GET_APERTURE(dev
);
218 if (sc
->initial_aperture
== 0) {
219 device_printf(dev
, "bad initial aperture size, disabling\n");
224 gatt
= agp_amd_alloc_gatt(dev
);
229 * Probably contigmalloc failure. Try reducing the
230 * aperture so that the gatt size reduces.
232 if (AGP_SET_APERTURE(dev
, AGP_GET_APERTURE(dev
) / 2))
237 /* Install the gatt. */
238 WRITE4(AGP_AMD751_ATTBASE
, gatt
->ag_pdir
);
240 /* Enable synchronisation between host and agp. */
241 pci_write_config(dev
,
243 AGP_AMD751_MODECTRL_SYNEN
, 1);
245 /* Set indexing mode for two-level and enable page dir cache */
246 pci_write_config(dev
,
247 AGP_AMD751_MODECTRL2
,
248 AGP_AMD751_MODECTRL2_GPDCE
, 1);
250 /* Enable the TLB and flush */
251 WRITE2(AGP_AMD751_STATUS
,
252 READ2(AGP_AMD751_STATUS
) | AGP_AMD751_STATUS_GCE
);
259 agp_amd_detach(device_t dev
)
261 struct agp_amd_softc
*sc
= device_get_softc(dev
);
265 /* Disable the TLB.. */
266 WRITE2(AGP_AMD751_STATUS
,
267 READ2(AGP_AMD751_STATUS
) & ~AGP_AMD751_STATUS_GCE
);
269 /* Disable host-agp sync */
270 pci_write_config(dev
, AGP_AMD751_MODECTRL
, 0x00, 1);
272 /* Clear the GATT base */
273 WRITE4(AGP_AMD751_ATTBASE
, 0);
275 /* Put the aperture back the way it started. */
276 AGP_SET_APERTURE(dev
, sc
->initial_aperture
);
278 agp_amd_free_gatt(sc
->gatt
);
281 bus_release_resource(dev
, SYS_RES_MEMORY
,
282 AGP_AMD751_REGISTERS
, sc
->regs
);
288 agp_amd_get_aperture(device_t dev
)
293 * The aperture size is equal to 32M<<vas.
295 vas
= (pci_read_config(dev
, AGP_AMD751_APCTRL
, 1) & 0x06) >> 1;
296 return (32*1024*1024) << vas
;
300 agp_amd_set_aperture(device_t dev
, u_int32_t aperture
)
305 * Check for a power of two and make sure its within the
306 * programmable range.
308 if (aperture
& (aperture
- 1)
309 || aperture
< 32*1024*1024
310 || aperture
> 2U*1024*1024*1024)
313 vas
= ffs(aperture
/ 32*1024*1024) - 1;
316 * While the size register is bits 1-3 of APCTRL, bit 0 must be
317 * set for the size value to be 'valid'
319 pci_write_config(dev
, AGP_AMD751_APCTRL
,
320 (((pci_read_config(dev
, AGP_AMD751_APCTRL
, 1) & ~0x06)
321 | ((vas
<< 1) | 1))), 1);
327 agp_amd_bind_page(device_t dev
, int offset
, vm_offset_t physical
)
329 struct agp_amd_softc
*sc
= device_get_softc(dev
);
331 if (offset
< 0 || offset
>= (sc
->gatt
->ag_entries
<< AGP_PAGE_SHIFT
))
334 sc
->gatt
->ag_virtual
[offset
>> AGP_PAGE_SHIFT
] = physical
| 1;
336 /* invalidate the cache */
342 agp_amd_unbind_page(device_t dev
, int offset
)
344 struct agp_amd_softc
*sc
= device_get_softc(dev
);
346 if (offset
< 0 || offset
>= (sc
->gatt
->ag_entries
<< AGP_PAGE_SHIFT
))
349 sc
->gatt
->ag_virtual
[offset
>> AGP_PAGE_SHIFT
] = 0;
354 agp_amd_flush_tlb(device_t dev
)
356 struct agp_amd_softc
*sc
= device_get_softc(dev
);
358 /* Set the cache invalidate bit and wait for the chipset to clear */
359 WRITE4(AGP_AMD751_TLBCTRL
, 1);
362 } while (READ4(AGP_AMD751_TLBCTRL
));
365 static device_method_t agp_amd_methods
[] = {
366 /* Device interface */
367 DEVMETHOD(device_probe
, agp_amd_probe
),
368 DEVMETHOD(device_attach
, agp_amd_attach
),
369 DEVMETHOD(device_detach
, agp_amd_detach
),
370 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
371 DEVMETHOD(device_suspend
, bus_generic_suspend
),
372 DEVMETHOD(device_resume
, bus_generic_resume
),
375 DEVMETHOD(agp_get_aperture
, agp_amd_get_aperture
),
376 DEVMETHOD(agp_set_aperture
, agp_amd_set_aperture
),
377 DEVMETHOD(agp_bind_page
, agp_amd_bind_page
),
378 DEVMETHOD(agp_unbind_page
, agp_amd_unbind_page
),
379 DEVMETHOD(agp_flush_tlb
, agp_amd_flush_tlb
),
380 DEVMETHOD(agp_enable
, agp_generic_enable
),
381 DEVMETHOD(agp_alloc_memory
, agp_generic_alloc_memory
),
382 DEVMETHOD(agp_free_memory
, agp_generic_free_memory
),
383 DEVMETHOD(agp_bind_memory
, agp_generic_bind_memory
),
384 DEVMETHOD(agp_unbind_memory
, agp_generic_unbind_memory
),
389 static driver_t agp_amd_driver
= {
392 sizeof(struct agp_amd_softc
),
395 static devclass_t agp_devclass
;
397 DRIVER_MODULE(agp_amd
, pci
, agp_amd_driver
, agp_devclass
, 0, 0);
398 MODULE_DEPEND(agp_amd
, agp
, 1, 1, 1);
399 MODULE_DEPEND(agp_amd
, pci
, 1, 1, 1);