2 * Copyright (c) 2005 Eric Anholt
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 * Based on reading the Linux 2.6.8.1 driver by Dave Jones.
28 * $FreeBSD: src/sys/dev/agp/agp_ati.c,v 1.5 2007/11/12 21:51:36 jhb Exp $
29 * $DragonFly: src/sys/dev/agp/agp_ati.c,v 1.3 2008/01/07 01:34:58 corecode Exp $
32 #include <sys/cdefs.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/kernel.h>
40 #include <sys/module.h>
45 #include <bus/pci/pcivar.h>
46 #include <bus/pci/pcireg.h>
51 #include <vm/vm_object.h>
56 MALLOC_DECLARE(M_AGP
);
58 #define READ4(off) bus_space_read_4(sc->bst, sc->bsh, off)
59 #define WRITE4(off,v) bus_space_write_4(sc->bst, sc->bsh, off, v)
61 struct agp_ati_softc
{
63 struct resource
*regs
; /* memory mapped control registers */
64 bus_space_tag_t bst
; /* bus_space tag */
65 bus_space_handle_t bsh
; /* bus_space handle */
66 u_int32_t initial_aperture
; /* aperture size at startup */
71 u_int32_t
*ag_virtual
; /* virtual address of gatt */
72 u_int32_t
*ag_vdir
; /* virtual address of page dir */
73 vm_offset_t ag_pdir
; /* physical address of page dir */
78 agp_ati_match(device_t dev
)
80 if (pci_get_class(dev
) != PCIC_BRIDGE
||
81 pci_get_subclass(dev
) != PCIS_BRIDGE_HOST
)
84 if (agp_find_caps(dev
) == 0)
87 switch (pci_get_devid(dev
)) {
89 return ("ATI RS100 AGP bridge");
91 return ("ATI RS200 AGP bridge");
93 return ("ATI RS200M AGP bridge");
95 return ("ATI RS250 AGP bridge");
97 return ("ATI RS300_100 AGP bridge");
99 return ("ATI RS300_133 AGP bridge");
101 return ("ATI RS300_166 AGP bridge");
103 return ("ATI RS300_200 AGP bridge");
110 agp_ati_probe(device_t dev
)
114 desc
= agp_ati_match(dev
);
117 device_set_desc(dev
, desc
);
125 agp_ati_alloc_gatt(device_t dev
)
127 struct agp_ati_softc
*sc
= device_get_softc(dev
);
128 u_int32_t apsize
= AGP_GET_APERTURE(dev
);
129 u_int32_t entries
= apsize
>> AGP_PAGE_SHIFT
;
130 u_int32_t apbase_offset
;
133 /* Alloc the GATT -- pointers to pages of AGP memory */
134 sc
->ag_entries
= entries
;
135 sc
->ag_virtual
= kmalloc(entries
* sizeof(u_int32_t
), M_AGP
,
137 if (sc
->ag_virtual
== NULL
) {
139 device_printf(dev
, "aperture allocation failed\n");
143 /* Alloc the page directory -- pointers to each page of the GATT */
144 sc
->ag_vdir
= kmalloc(AGP_PAGE_SIZE
, M_AGP
, M_NOWAIT
| M_ZERO
);
145 if (sc
->ag_vdir
== NULL
) {
147 device_printf(dev
, "pagedir allocation failed\n");
148 kfree(sc
->ag_virtual
, M_AGP
);
151 sc
->ag_pdir
= vtophys((vm_offset_t
)sc
->ag_vdir
);
153 apbase_offset
= pci_read_config(dev
, AGP_APBASE
, 4) >> 22;
154 /* Fill in the pagedir's pointers to GATT pages */
155 for (i
= 0; i
< sc
->ag_entries
/ 1024; i
++) {
159 va
= ((vm_offset_t
)sc
->ag_virtual
) + i
* AGP_PAGE_SIZE
;
161 sc
->ag_vdir
[apbase_offset
+ i
] = pa
| 1;
165 * Make sure the chipset can see everything.
174 agp_ati_attach(device_t dev
)
176 struct agp_ati_softc
*sc
= device_get_softc(dev
);
179 u_int32_t apsize_reg
, agpmode_reg
;
181 error
= agp_generic_attach(dev
);
185 switch (pci_get_devid(dev
)) {
186 case 0xcab01002: /* ATI RS100 AGP bridge */
187 case 0xcab21002: /* ATI RS200 AGP bridge */
188 case 0xcbb21002: /* ATI RS200M AGP bridge */
189 case 0xcab31002: /* ATI RS250 AGP bridge */
191 apsize_reg
= ATI_RS100_APSIZE
;
192 agpmode_reg
= ATI_RS100_IG_AGPMODE
;
194 case 0x58301002: /* ATI RS300_100 AGP bridge */
195 case 0x58311002: /* ATI RS300_133 AGP bridge */
196 case 0x58321002: /* ATI RS300_166 AGP bridge */
197 case 0x58331002: /* ATI RS300_200 AGP bridge */
199 apsize_reg
= ATI_RS300_APSIZE
;
200 agpmode_reg
= ATI_RS300_IG_AGPMODE
;
203 /* Unknown chipset */
207 rid
= ATI_GART_MMADDR
;
208 sc
->regs
= bus_alloc_resource_any(dev
, SYS_RES_MEMORY
, &rid
, RF_ACTIVE
);
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 if (agp_ati_alloc_gatt(dev
) == 0)
228 * Probably contigmalloc failure. Try reducing the
229 * aperture so that the gatt size reduces.
231 if (AGP_SET_APERTURE(dev
, AGP_GET_APERTURE(dev
) / 2))
235 temp
= pci_read_config(dev
, apsize_reg
, 4);
236 pci_write_config(dev
, apsize_reg
, temp
| 1, 4);
238 pci_write_config(dev
, agpmode_reg
, 0x20000, 4);
240 WRITE4(ATI_GART_FEATURE_ID
, 0x00060000);
242 temp
= pci_read_config(dev
, 4, 4); /* XXX: Magic reg# */
243 pci_write_config(dev
, 4, temp
| (1 << 14), 4);
245 WRITE4(ATI_GART_BASE
, sc
->ag_pdir
);
253 agp_ati_detach(device_t dev
)
255 struct agp_ati_softc
*sc
= device_get_softc(dev
);
256 u_int32_t apsize_reg
, temp
;
261 apsize_reg
= ATI_RS300_APSIZE
;
263 apsize_reg
= ATI_RS100_APSIZE
;
265 /* Clear the GATT base */
266 WRITE4(ATI_GART_BASE
, 0);
268 /* Put the aperture back the way it started. */
269 AGP_SET_APERTURE(dev
, sc
->initial_aperture
);
271 temp
= pci_read_config(dev
, apsize_reg
, 4);
272 pci_write_config(dev
, apsize_reg
, temp
& ~1, 4);
274 kfree(sc
->ag_vdir
, M_AGP
);
275 kfree(sc
->ag_virtual
, M_AGP
);
277 bus_release_resource(dev
, SYS_RES_MEMORY
, ATI_GART_MMADDR
, sc
->regs
);
284 agp_ati_get_aperture(device_t dev
)
286 struct agp_ati_softc
*sc
= device_get_softc(dev
);
290 size_value
= pci_read_config(dev
, ATI_RS300_APSIZE
, 4);
292 size_value
= pci_read_config(dev
, ATI_RS100_APSIZE
, 4);
294 size_value
= (size_value
& 0x0000000e) >> 1;
295 size_value
= (32 * 1024 * 1024) << size_value
;
301 agp_ati_set_aperture(device_t dev
, u_int32_t aperture
)
303 struct agp_ati_softc
*sc
= device_get_softc(dev
);
305 u_int32_t apsize_reg
;
308 apsize_reg
= ATI_RS300_APSIZE
;
310 apsize_reg
= ATI_RS100_APSIZE
;
312 size_value
= pci_read_config(dev
, apsize_reg
, 4);
314 size_value
&= ~0x0000000e;
315 size_value
|= (ffs(aperture
/ (32 * 1024 * 1024)) - 1) << 1;
317 pci_write_config(dev
, apsize_reg
, size_value
, 4);
323 agp_ati_bind_page(device_t dev
, int offset
, vm_offset_t physical
)
325 struct agp_ati_softc
*sc
= device_get_softc(dev
);
327 if (offset
< 0 || offset
>= (sc
->ag_entries
<< AGP_PAGE_SHIFT
))
330 sc
->ag_virtual
[offset
>> AGP_PAGE_SHIFT
] = physical
| 1;
336 agp_ati_unbind_page(device_t dev
, int offset
)
338 struct agp_ati_softc
*sc
= device_get_softc(dev
);
340 if (offset
< 0 || offset
>= (sc
->ag_entries
<< AGP_PAGE_SHIFT
))
343 sc
->ag_virtual
[offset
>> AGP_PAGE_SHIFT
] = 0;
348 agp_ati_flush_tlb(device_t dev
)
350 struct agp_ati_softc
*sc
= device_get_softc(dev
);
352 /* Set the cache invalidate bit and wait for the chipset to clear */
353 WRITE4(ATI_GART_CACHE_CNTRL
, 1);
354 (void)READ4(ATI_GART_CACHE_CNTRL
);
357 static device_method_t agp_ati_methods
[] = {
358 /* Device interface */
359 DEVMETHOD(device_probe
, agp_ati_probe
),
360 DEVMETHOD(device_attach
, agp_ati_attach
),
361 DEVMETHOD(device_detach
, agp_ati_detach
),
362 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
363 DEVMETHOD(device_suspend
, bus_generic_suspend
),
364 DEVMETHOD(device_resume
, bus_generic_resume
),
367 DEVMETHOD(agp_get_aperture
, agp_ati_get_aperture
),
368 DEVMETHOD(agp_set_aperture
, agp_ati_set_aperture
),
369 DEVMETHOD(agp_bind_page
, agp_ati_bind_page
),
370 DEVMETHOD(agp_unbind_page
, agp_ati_unbind_page
),
371 DEVMETHOD(agp_flush_tlb
, agp_ati_flush_tlb
),
372 DEVMETHOD(agp_enable
, agp_generic_enable
),
373 DEVMETHOD(agp_alloc_memory
, agp_generic_alloc_memory
),
374 DEVMETHOD(agp_free_memory
, agp_generic_free_memory
),
375 DEVMETHOD(agp_bind_memory
, agp_generic_bind_memory
),
376 DEVMETHOD(agp_unbind_memory
, agp_generic_unbind_memory
),
381 static driver_t agp_ati_driver
= {
384 sizeof(struct agp_ati_softc
),
387 static devclass_t agp_devclass
;
389 DRIVER_MODULE(agp_ati
, pci
, agp_ati_driver
, agp_devclass
, 0, 0);
390 MODULE_DEPEND(agp_ati
, agp
, 1, 1, 1);
391 MODULE_DEPEND(agp_ati
, pci
, 1, 1, 1);