1 /* $NetBSD: agp.c,v 1.65 2009/01/27 08:39:33 markd Exp $ */
4 * Copyright (c) 2000 Doug Rabson
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * $FreeBSD: src/sys/pci/agp.c,v 1.12 2001/05/19 01:28:07 alfred Exp $
32 * Copyright (c) 2001 Wasabi Systems, Inc.
33 * All rights reserved.
35 * Written by Frank van der Linden for Wasabi Systems, Inc.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed for the NetBSD Project by
48 * Wasabi Systems, Inc.
49 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
50 * or promote products derived from this software without specific prior
53 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63 * POSSIBILITY OF SUCH DAMAGE.
67 #include <sys/cdefs.h>
68 __KERNEL_RCSID(0, "$NetBSD: agp.c,v 1.65 2009/01/27 08:39:33 markd Exp $");
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/malloc.h>
73 #include <sys/kernel.h>
74 #include <sys/device.h>
76 #include <sys/ioctl.h>
77 #include <sys/fcntl.h>
78 #include <sys/agpio.h>
80 #include <sys/mutex.h>
82 #include <uvm/uvm_extern.h>
84 #include <dev/pci/pcireg.h>
85 #include <dev/pci/pcivar.h>
86 #include <dev/pci/agpvar.h>
87 #include <dev/pci/agpreg.h>
88 #include <dev/pci/pcidevs.h>
92 MALLOC_DEFINE(M_AGP
, "AGP", "AGP memory");
94 /* Helper functions for implementing chipset mini drivers. */
95 /* XXXfvdl get rid of this one. */
97 extern struct cfdriver agp_cd
;
99 static int agp_info_user(struct agp_softc
*, agp_info
*);
100 static int agp_setup_user(struct agp_softc
*, agp_setup
*);
101 static int agp_allocate_user(struct agp_softc
*, agp_allocate
*);
102 static int agp_deallocate_user(struct agp_softc
*, int);
103 static int agp_bind_user(struct agp_softc
*, agp_bind
*);
104 static int agp_unbind_user(struct agp_softc
*, agp_unbind
*);
105 static int agpdev_match(struct pci_attach_args
*);
106 static bool agp_resume(device_t
, pmf_qual_t
);
110 #include "agp_i810.h"
111 #include "agp_intel.h"
114 #include "agp_amd64.h"
116 const struct agp_product
{
119 int (*ap_match
)(const struct pci_attach_args
*);
120 int (*ap_attach
)(device_t
, device_t
, void *);
123 { PCI_VENDOR_ALI
, PCI_PRODUCT_ALI_M1689
,
124 agp_amd64_match
, agp_amd64_attach
},
128 { PCI_VENDOR_ALI
, -1,
129 NULL
, agp_ali_attach
},
133 { PCI_VENDOR_AMD
, PCI_PRODUCT_AMD_AGP8151_DEV
,
134 agp_amd64_match
, agp_amd64_attach
},
138 { PCI_VENDOR_AMD
, -1,
139 agp_amd_match
, agp_amd_attach
},
143 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82810_MCH
,
144 NULL
, agp_i810_attach
},
145 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82810_DC100_MCH
,
146 NULL
, agp_i810_attach
},
147 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82810E_MCH
,
148 NULL
, agp_i810_attach
},
149 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82815_FULL_HUB
,
150 NULL
, agp_i810_attach
},
151 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82840_HB
,
152 NULL
, agp_i810_attach
},
153 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82830MP_IO_1
,
154 NULL
, agp_i810_attach
},
155 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82845G_DRAM
,
156 NULL
, agp_i810_attach
},
157 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82855GM_MCH
,
158 NULL
, agp_i810_attach
},
159 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82865_HB
,
160 NULL
, agp_i810_attach
},
161 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82915G_HB
,
162 NULL
, agp_i810_attach
},
163 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82915GM_HB
,
164 NULL
, agp_i810_attach
},
165 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82945P_MCH
,
166 NULL
, agp_i810_attach
},
167 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82945GM_HB
,
168 NULL
, agp_i810_attach
},
169 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82945GME_HB
,
170 NULL
, agp_i810_attach
},
171 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82965Q_HB
,
172 NULL
, agp_i810_attach
},
173 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82965PM_HB
,
174 NULL
, agp_i810_attach
},
175 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82965G_HB
,
176 NULL
, agp_i810_attach
},
177 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82Q35_HB
,
178 NULL
, agp_i810_attach
},
179 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82G33_HB
,
180 NULL
, agp_i810_attach
},
181 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82Q33_HB
,
182 NULL
, agp_i810_attach
},
183 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82G35_HB
,
184 NULL
, agp_i810_attach
},
185 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82946GZ_HB
,
186 NULL
, agp_i810_attach
},
187 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82GM45_HB
,
188 NULL
, agp_i810_attach
},
189 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82IGD_E_HB
,
190 NULL
, agp_i810_attach
},
191 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82Q45_HB
,
192 NULL
, agp_i810_attach
},
193 { PCI_VENDOR_INTEL
, PCI_PRODUCT_INTEL_82G45_HB
,
194 NULL
, agp_i810_attach
},
198 { PCI_VENDOR_INTEL
, -1,
199 NULL
, agp_intel_attach
},
203 { PCI_VENDOR_NVIDIA
, PCI_PRODUCT_NVIDIA_NFORCE3_PCHB
,
204 agp_amd64_match
, agp_amd64_attach
},
205 { PCI_VENDOR_NVIDIA
, PCI_PRODUCT_NVIDIA_NFORCE3_250_PCHB
,
206 agp_amd64_match
, agp_amd64_attach
},
210 { PCI_VENDOR_SIS
, PCI_PRODUCT_SIS_755
,
211 agp_amd64_match
, agp_amd64_attach
},
212 { PCI_VENDOR_SIS
, PCI_PRODUCT_SIS_760
,
213 agp_amd64_match
, agp_amd64_attach
},
217 { PCI_VENDOR_SIS
, -1,
218 NULL
, agp_sis_attach
},
222 { PCI_VENDOR_VIATECH
, PCI_PRODUCT_VIATECH_K8M800_0
,
223 agp_amd64_match
, agp_amd64_attach
},
224 { PCI_VENDOR_VIATECH
, PCI_PRODUCT_VIATECH_K8T890_0
,
225 agp_amd64_match
, agp_amd64_attach
},
226 { PCI_VENDOR_VIATECH
, PCI_PRODUCT_VIATECH_K8HTB_0
,
227 agp_amd64_match
, agp_amd64_attach
},
228 { PCI_VENDOR_VIATECH
, PCI_PRODUCT_VIATECH_K8HTB
,
229 agp_amd64_match
, agp_amd64_attach
},
233 { PCI_VENDOR_VIATECH
, -1,
234 NULL
, agp_via_attach
},
241 static const struct agp_product
*
242 agp_lookup(const struct pci_attach_args
*pa
)
244 const struct agp_product
*ap
;
246 /* First find the vendor. */
247 for (ap
= agp_products
; ap
->ap_attach
!= NULL
; ap
++) {
248 if (PCI_VENDOR(pa
->pa_id
) == ap
->ap_vendor
)
252 if (ap
->ap_attach
== NULL
)
255 /* Now find the product within the vendor's domain. */
256 for (; ap
->ap_attach
!= NULL
; ap
++) {
257 if (PCI_VENDOR(pa
->pa_id
) != ap
->ap_vendor
) {
258 /* Ran out of this vendor's section of the table. */
261 if (ap
->ap_product
== PCI_PRODUCT(pa
->pa_id
)) {
265 if (ap
->ap_product
== (uint32_t) -1) {
266 /* Wildcard match. */
271 if (ap
->ap_attach
== NULL
)
274 /* Now let the product-specific driver filter the match. */
275 if (ap
->ap_match
!= NULL
&& (*ap
->ap_match
)(pa
) == 0)
282 agpmatch(device_t parent
, cfdata_t match
, void *aux
)
284 struct agpbus_attach_args
*apa
= aux
;
285 struct pci_attach_args
*pa
= &apa
->apa_pci_args
;
287 if (agp_lookup(pa
) == NULL
)
293 static const int agp_max
[][2] = {
304 #define agp_max_size (sizeof(agp_max) / sizeof(agp_max[0]))
307 agpattach(device_t parent
, device_t self
, void *aux
)
309 struct agpbus_attach_args
*apa
= aux
;
310 struct pci_attach_args
*pa
= &apa
->apa_pci_args
;
311 struct agp_softc
*sc
= device_private(self
);
312 const struct agp_product
*ap
;
318 aprint_naive(": AGP controller\n");
321 sc
->as_dmat
= pa
->pa_dmat
;
322 sc
->as_pc
= pa
->pa_pc
;
323 sc
->as_tag
= pa
->pa_tag
;
324 sc
->as_id
= pa
->pa_id
;
327 * Work out an upper bound for agp memory allocation. This
328 * uses a heuristic table from the Linux driver.
330 memsize
= ptoa(physmem
) >> 20;
331 for (i
= 0; i
< agp_max_size
; i
++) {
332 if (memsize
<= agp_max
[i
][0])
335 if (i
== agp_max_size
)
336 i
= agp_max_size
- 1;
337 sc
->as_maxmem
= agp_max
[i
][1] << 20U;
340 * The mutex is used to prevent re-entry to
341 * agp_generic_bind_memory() since that function can sleep.
343 mutex_init(&sc
->as_mtx
, MUTEX_DEFAULT
, IPL_NONE
);
345 TAILQ_INIT(&sc
->as_memory
);
347 ret
= (*ap
->ap_attach
)(parent
, self
, pa
);
349 aprint_normal(": aperture at 0x%lx, size 0x%lx\n",
350 (unsigned long)sc
->as_apaddr
,
351 (unsigned long)AGP_GET_APERTURE(sc
));
355 if (!device_pmf_is_registered(self
)) {
356 if (!pmf_device_register(self
, NULL
, agp_resume
))
357 aprint_error_dev(self
, "couldn't establish power "
362 CFATTACH_DECL_NEW(agp
, sizeof(struct agp_softc
),
363 agpmatch
, agpattach
, NULL
, NULL
);
366 agp_map_aperture(struct pci_attach_args
*pa
, struct agp_softc
*sc
, int reg
)
369 * Find the aperture. Don't map it (yet), this would
372 if (pci_mapreg_info(pa
->pa_pc
, pa
->pa_tag
, reg
,
373 PCI_MAPREG_TYPE_MEM
, &sc
->as_apaddr
, &sc
->as_apsize
,
374 &sc
->as_apflags
) != 0)
377 sc
->as_apt
= pa
->pa_memt
;
383 agp_alloc_gatt(struct agp_softc
*sc
)
385 u_int32_t apsize
= AGP_GET_APERTURE(sc
);
386 u_int32_t entries
= apsize
>> AGP_PAGE_SHIFT
;
387 struct agp_gatt
*gatt
;
391 gatt
= malloc(sizeof(struct agp_gatt
), M_AGP
, M_NOWAIT
);
394 gatt
->ag_entries
= entries
;
396 if (agp_alloc_dmamem(sc
->as_dmat
, entries
* sizeof(u_int32_t
),
397 0, &gatt
->ag_dmamap
, &virtual, &gatt
->ag_physical
,
398 &gatt
->ag_dmaseg
, 1, &dummyseg
) != 0) {
402 gatt
->ag_virtual
= (uint32_t *)virtual;
404 gatt
->ag_size
= entries
* sizeof(u_int32_t
);
405 memset(gatt
->ag_virtual
, 0, gatt
->ag_size
);
412 agp_free_gatt(struct agp_softc
*sc
, struct agp_gatt
*gatt
)
414 agp_free_dmamem(sc
->as_dmat
, gatt
->ag_size
, gatt
->ag_dmamap
,
415 (void *)gatt
->ag_virtual
, &gatt
->ag_dmaseg
, 1);
421 agp_generic_detach(struct agp_softc
*sc
)
423 mutex_destroy(&sc
->as_mtx
);
429 agpdev_match(struct pci_attach_args
*pa
)
431 if (PCI_CLASS(pa
->pa_class
) == PCI_CLASS_DISPLAY
&&
432 PCI_SUBCLASS(pa
->pa_class
) == PCI_SUBCLASS_DISPLAY_VGA
)
433 if (pci_get_capability(pa
->pa_pc
, pa
->pa_tag
, PCI_CAP_AGP
,
441 agp_generic_enable(struct agp_softc
*sc
, u_int32_t mode
)
443 struct pci_attach_args pa
;
444 pcireg_t tstatus
, mstatus
;
446 int rq
, sba
, fw
, rate
, capoff
;
448 if (pci_find_device(&pa
, agpdev_match
) == 0 ||
449 pci_get_capability(pa
.pa_pc
, pa
.pa_tag
, PCI_CAP_AGP
,
450 &capoff
, NULL
) == 0) {
451 aprint_error_dev(sc
->as_dev
, "can't find display\n");
455 tstatus
= pci_conf_read(sc
->as_pc
, sc
->as_tag
,
456 sc
->as_capoff
+ AGP_STATUS
);
457 mstatus
= pci_conf_read(pa
.pa_pc
, pa
.pa_tag
,
458 capoff
+ AGP_STATUS
);
460 /* Set RQ to the min of mode, tstatus and mstatus */
461 rq
= AGP_MODE_GET_RQ(mode
);
462 if (AGP_MODE_GET_RQ(tstatus
) < rq
)
463 rq
= AGP_MODE_GET_RQ(tstatus
);
464 if (AGP_MODE_GET_RQ(mstatus
) < rq
)
465 rq
= AGP_MODE_GET_RQ(mstatus
);
467 /* Set SBA if all three can deal with SBA */
468 sba
= (AGP_MODE_GET_SBA(tstatus
)
469 & AGP_MODE_GET_SBA(mstatus
)
470 & AGP_MODE_GET_SBA(mode
));
473 fw
= (AGP_MODE_GET_FW(tstatus
)
474 & AGP_MODE_GET_FW(mstatus
)
475 & AGP_MODE_GET_FW(mode
));
477 /* Figure out the max rate */
478 rate
= (AGP_MODE_GET_RATE(tstatus
)
479 & AGP_MODE_GET_RATE(mstatus
)
480 & AGP_MODE_GET_RATE(mode
));
481 if (rate
& AGP_MODE_RATE_4x
)
482 rate
= AGP_MODE_RATE_4x
;
483 else if (rate
& AGP_MODE_RATE_2x
)
484 rate
= AGP_MODE_RATE_2x
;
486 rate
= AGP_MODE_RATE_1x
;
488 /* Construct the new mode word and tell the hardware */
489 command
= AGP_MODE_SET_RQ(0, rq
);
490 command
= AGP_MODE_SET_SBA(command
, sba
);
491 command
= AGP_MODE_SET_FW(command
, fw
);
492 command
= AGP_MODE_SET_RATE(command
, rate
);
493 command
= AGP_MODE_SET_AGP(command
, 1);
494 pci_conf_write(sc
->as_pc
, sc
->as_tag
,
495 sc
->as_capoff
+ AGP_COMMAND
, command
);
496 pci_conf_write(pa
.pa_pc
, pa
.pa_tag
, capoff
+ AGP_COMMAND
, command
);
502 agp_generic_alloc_memory(struct agp_softc
*sc
, int type
, vsize_t size
)
504 struct agp_memory
*mem
;
506 if ((size
& (AGP_PAGE_SIZE
- 1)) != 0)
509 if (sc
->as_allocated
+ size
> sc
->as_maxmem
)
513 printf("agp_generic_alloc_memory: unsupported type %d\n",
518 mem
= malloc(sizeof *mem
, M_AGP
, M_WAITOK
);
522 if (bus_dmamap_create(sc
->as_dmat
, size
, size
/ PAGE_SIZE
+ 1,
523 size
, 0, BUS_DMA_NOWAIT
, &mem
->am_dmamap
) != 0) {
528 mem
->am_id
= sc
->as_nextid
++;
531 mem
->am_physical
= 0;
533 mem
->am_is_bound
= 0;
534 TAILQ_INSERT_TAIL(&sc
->as_memory
, mem
, am_link
);
535 sc
->as_allocated
+= size
;
541 agp_generic_free_memory(struct agp_softc
*sc
, struct agp_memory
*mem
)
543 if (mem
->am_is_bound
)
546 sc
->as_allocated
-= mem
->am_size
;
547 TAILQ_REMOVE(&sc
->as_memory
, mem
, am_link
);
548 bus_dmamap_destroy(sc
->as_dmat
, mem
->am_dmamap
);
554 agp_generic_bind_memory(struct agp_softc
*sc
, struct agp_memory
*mem
,
560 bus_dma_segment_t
*segs
, *seg
;
562 int contigpages
, nseg
;
564 mutex_enter(&sc
->as_mtx
);
566 if (mem
->am_is_bound
) {
567 aprint_error_dev(sc
->as_dev
, "memory already bound\n");
568 mutex_exit(&sc
->as_mtx
);
573 || (offset
& (AGP_PAGE_SIZE
- 1)) != 0
574 || offset
+ mem
->am_size
> AGP_GET_APERTURE(sc
)) {
575 aprint_error_dev(sc
->as_dev
,
576 "binding memory at bad offset %#lx\n",
577 (unsigned long) offset
);
578 mutex_exit(&sc
->as_mtx
);
584 * The memory here needs to be directly accessable from the
585 * AGP video card, so it should be allocated using bus_dma.
586 * However, it need not be contiguous, since individual pages
587 * are translated using the GATT.
589 * Using a large chunk of contiguous memory may get in the way
590 * of other subsystems that may need one, so we try to be friendly
591 * and ask for allocation in chunks of a minimum of 8 pages
592 * of contiguous memory on average, falling back to 4, 2 and 1
593 * if really needed. Larger chunks are preferred, since allocating
594 * a bus_dma_segment per page would be overkill.
597 for (contigpages
= 8; contigpages
> 0; contigpages
>>= 1) {
598 nseg
= (mem
->am_size
/ (contigpages
* PAGE_SIZE
)) + 1;
599 segs
= malloc(nseg
* sizeof *segs
, M_AGP
, M_WAITOK
);
601 mutex_exit(&sc
->as_mtx
);
604 if (bus_dmamem_alloc(sc
->as_dmat
, mem
->am_size
, PAGE_SIZE
, 0,
605 segs
, nseg
, &mem
->am_nseg
,
607 BUS_DMA_NOWAIT
: BUS_DMA_WAITOK
) != 0) {
611 if (bus_dmamem_map(sc
->as_dmat
, segs
, mem
->am_nseg
,
612 mem
->am_size
, &mem
->am_virtual
, BUS_DMA_WAITOK
) != 0) {
613 bus_dmamem_free(sc
->as_dmat
, segs
, mem
->am_nseg
);
617 if (bus_dmamap_load(sc
->as_dmat
, mem
->am_dmamap
,
618 mem
->am_virtual
, mem
->am_size
, NULL
, BUS_DMA_WAITOK
) != 0) {
619 bus_dmamem_unmap(sc
->as_dmat
, mem
->am_virtual
,
621 bus_dmamem_free(sc
->as_dmat
, segs
, mem
->am_nseg
);
625 mem
->am_dmaseg
= segs
;
629 if (contigpages
== 0) {
630 mutex_exit(&sc
->as_mtx
);
636 * Bind the individual pages and flush the chipset's
640 for (i
= 0; i
< mem
->am_dmamap
->dm_nsegs
; i
++) {
641 seg
= &mem
->am_dmamap
->dm_segs
[i
];
643 * Install entries in the GATT, making sure that if
644 * AGP_PAGE_SIZE < PAGE_SIZE and mem->am_size is not
645 * aligned to PAGE_SIZE, we don't modify too many GATT
648 for (j
= 0; j
< seg
->ds_len
&& (done
+ j
) < mem
->am_size
;
649 j
+= AGP_PAGE_SIZE
) {
650 pa
= seg
->ds_addr
+ j
;
651 AGP_DPF(("binding offset %#lx to pa %#lx\n",
652 (unsigned long)(offset
+ done
+ j
),
654 error
= AGP_BIND_PAGE(sc
, offset
+ done
+ j
, pa
);
657 * Bail out. Reverse all the mappings
658 * and unwire the pages.
660 for (k
= 0; k
< done
+ j
; k
+= AGP_PAGE_SIZE
)
661 AGP_UNBIND_PAGE(sc
, offset
+ k
);
663 bus_dmamap_unload(sc
->as_dmat
, mem
->am_dmamap
);
664 bus_dmamem_unmap(sc
->as_dmat
, mem
->am_virtual
,
666 bus_dmamem_free(sc
->as_dmat
, mem
->am_dmaseg
,
668 free(mem
->am_dmaseg
, M_AGP
);
669 mutex_exit(&sc
->as_mtx
);
677 * Flush the CPU cache since we are providing a new mapping
683 * Make sure the chipset gets the new mappings.
687 mem
->am_offset
= offset
;
688 mem
->am_is_bound
= 1;
690 mutex_exit(&sc
->as_mtx
);
696 agp_generic_unbind_memory(struct agp_softc
*sc
, struct agp_memory
*mem
)
700 mutex_enter(&sc
->as_mtx
);
702 if (!mem
->am_is_bound
) {
703 aprint_error_dev(sc
->as_dev
, "memory is not bound\n");
704 mutex_exit(&sc
->as_mtx
);
710 * Unbind the individual pages and flush the chipset's
711 * TLB. Unwire the pages so they can be swapped.
713 for (i
= 0; i
< mem
->am_size
; i
+= AGP_PAGE_SIZE
)
714 AGP_UNBIND_PAGE(sc
, mem
->am_offset
+ i
);
719 bus_dmamap_unload(sc
->as_dmat
, mem
->am_dmamap
);
720 bus_dmamem_unmap(sc
->as_dmat
, mem
->am_virtual
, mem
->am_size
);
721 bus_dmamem_free(sc
->as_dmat
, mem
->am_dmaseg
, mem
->am_nseg
);
723 free(mem
->am_dmaseg
, M_AGP
);
726 mem
->am_is_bound
= 0;
728 mutex_exit(&sc
->as_mtx
);
733 /* Helper functions for implementing user/kernel api */
736 agp_acquire_helper(struct agp_softc
*sc
, enum agp_acquire_state state
)
738 if (sc
->as_state
!= AGP_ACQUIRE_FREE
)
740 sc
->as_state
= state
;
746 agp_release_helper(struct agp_softc
*sc
, enum agp_acquire_state state
)
749 if (sc
->as_state
== AGP_ACQUIRE_FREE
)
752 if (sc
->as_state
!= state
)
755 sc
->as_state
= AGP_ACQUIRE_FREE
;
759 static struct agp_memory
*
760 agp_find_memory(struct agp_softc
*sc
, int id
)
762 struct agp_memory
*mem
;
764 AGP_DPF(("searching for memory block %d\n", id
));
765 TAILQ_FOREACH(mem
, &sc
->as_memory
, am_link
) {
766 AGP_DPF(("considering memory block %d\n", mem
->am_id
));
767 if (mem
->am_id
== id
)
773 /* Implementation of the userland ioctl api */
776 agp_info_user(struct agp_softc
*sc
, agp_info
*info
)
778 memset(info
, 0, sizeof *info
);
779 info
->bridge_id
= sc
->as_id
;
780 if (sc
->as_capoff
!= 0)
781 info
->agp_mode
= pci_conf_read(sc
->as_pc
, sc
->as_tag
,
782 sc
->as_capoff
+ AGP_STATUS
);
784 info
->agp_mode
= 0; /* i810 doesn't have real AGP */
785 info
->aper_base
= sc
->as_apaddr
;
786 info
->aper_size
= AGP_GET_APERTURE(sc
) >> 20;
787 info
->pg_total
= info
->pg_system
= sc
->as_maxmem
>> AGP_PAGE_SHIFT
;
788 info
->pg_used
= sc
->as_allocated
>> AGP_PAGE_SHIFT
;
794 agp_setup_user(struct agp_softc
*sc
, agp_setup
*setup
)
796 return AGP_ENABLE(sc
, setup
->agp_mode
);
800 agp_allocate_user(struct agp_softc
*sc
, agp_allocate
*alloc
)
802 struct agp_memory
*mem
;
804 mem
= AGP_ALLOC_MEMORY(sc
,
806 alloc
->pg_count
<< AGP_PAGE_SHIFT
);
808 alloc
->key
= mem
->am_id
;
809 alloc
->physical
= mem
->am_physical
;
817 agp_deallocate_user(struct agp_softc
*sc
, int id
)
819 struct agp_memory
*mem
= agp_find_memory(sc
, id
);
822 AGP_FREE_MEMORY(sc
, mem
);
830 agp_bind_user(struct agp_softc
*sc
, agp_bind
*bind
)
832 struct agp_memory
*mem
= agp_find_memory(sc
, bind
->key
);
837 return AGP_BIND_MEMORY(sc
, mem
, bind
->pg_start
<< AGP_PAGE_SHIFT
);
841 agp_unbind_user(struct agp_softc
*sc
, agp_unbind
*unbind
)
843 struct agp_memory
*mem
= agp_find_memory(sc
, unbind
->key
);
848 return AGP_UNBIND_MEMORY(sc
, mem
);
852 agpopen(dev_t dev
, int oflags
, int devtype
, struct lwp
*l
)
854 struct agp_softc
*sc
= device_lookup_private(&agp_cd
, AGPUNIT(dev
));
859 if (sc
->as_chipc
== NULL
)
871 agpclose(dev_t dev
, int fflag
, int devtype
, struct lwp
*l
)
873 struct agp_softc
*sc
= device_lookup_private(&agp_cd
, AGPUNIT(dev
));
874 struct agp_memory
*mem
;
880 * Clear the GATT and force release on last close
882 if (sc
->as_state
== AGP_ACQUIRE_USER
) {
883 while ((mem
= TAILQ_FIRST(&sc
->as_memory
))) {
884 if (mem
->am_is_bound
) {
885 printf("agpclose: mem %d is bound\n",
887 AGP_UNBIND_MEMORY(sc
, mem
);
890 * XXX it is not documented, but if the protocol allows
891 * allocate->acquire->bind, it would be possible that
892 * memory ranges are allocated by the kernel here,
893 * which we shouldn't free. We'd have to keep track of
894 * the memory range's owner.
895 * The kernel API is unsed yet, so we get away with
898 AGP_FREE_MEMORY(sc
, mem
);
900 agp_release_helper(sc
, AGP_ACQUIRE_USER
);
908 agpioctl(dev_t dev
, u_long cmd
, void *data
, int fflag
, struct lwp
*l
)
910 struct agp_softc
*sc
= device_lookup_private(&agp_cd
, AGPUNIT(dev
));
915 if ((fflag
& FWRITE
) == 0 && cmd
!= AGPIOC_INFO
)
920 return agp_info_user(sc
, (agp_info
*) data
);
923 return agp_acquire_helper(sc
, AGP_ACQUIRE_USER
);
926 return agp_release_helper(sc
, AGP_ACQUIRE_USER
);
929 return agp_setup_user(sc
, (agp_setup
*)data
);
931 case AGPIOC_ALLOCATE
:
932 return agp_allocate_user(sc
, (agp_allocate
*)data
);
934 case AGPIOC_DEALLOCATE
:
935 return agp_deallocate_user(sc
, *(int *) data
);
938 return agp_bind_user(sc
, (agp_bind
*)data
);
941 return agp_unbind_user(sc
, (agp_unbind
*)data
);
949 agpmmap(dev_t dev
, off_t offset
, int prot
)
951 struct agp_softc
*sc
= device_lookup_private(&agp_cd
, AGPUNIT(dev
));
956 if (offset
> AGP_GET_APERTURE(sc
))
959 return (bus_space_mmap(sc
->as_apt
, sc
->as_apaddr
, offset
, prot
,
960 BUS_SPACE_MAP_LINEAR
));
963 const struct cdevsw agp_cdevsw
= {
964 agpopen
, agpclose
, noread
, nowrite
, agpioctl
,
965 nostop
, notty
, nopoll
, agpmmap
, nokqfilter
, D_OTHER
968 /* Implementation of the kernel api */
971 agp_find_device(int unit
)
973 return device_lookup_private(&agp_cd
, unit
);
976 enum agp_acquire_state
977 agp_state(void *devcookie
)
979 struct agp_softc
*sc
= devcookie
;
985 agp_get_info(void *devcookie
, struct agp_info
*info
)
987 struct agp_softc
*sc
= devcookie
;
989 info
->ai_mode
= pci_conf_read(sc
->as_pc
, sc
->as_tag
,
990 sc
->as_capoff
+ AGP_STATUS
);
991 info
->ai_aperture_base
= sc
->as_apaddr
;
992 info
->ai_aperture_size
= sc
->as_apsize
; /* XXXfvdl inconsistent */
993 info
->ai_memory_allowed
= sc
->as_maxmem
;
994 info
->ai_memory_used
= sc
->as_allocated
;
998 agp_acquire(void *dev
)
1000 return agp_acquire_helper(dev
, AGP_ACQUIRE_KERNEL
);
1004 agp_release(void *dev
)
1006 return agp_release_helper(dev
, AGP_ACQUIRE_KERNEL
);
1010 agp_enable(void *dev
, u_int32_t mode
)
1012 struct agp_softc
*sc
= dev
;
1014 return AGP_ENABLE(sc
, mode
);
1018 agp_alloc_memory(void *dev
, int type
, vsize_t bytes
)
1020 struct agp_softc
*sc
= dev
;
1022 return (void *)AGP_ALLOC_MEMORY(sc
, type
, bytes
);
1026 agp_free_memory(void *dev
, void *handle
)
1028 struct agp_softc
*sc
= dev
;
1029 struct agp_memory
*mem
= handle
;
1031 AGP_FREE_MEMORY(sc
, mem
);
1035 agp_bind_memory(void *dev
, void *handle
, off_t offset
)
1037 struct agp_softc
*sc
= dev
;
1038 struct agp_memory
*mem
= handle
;
1040 return AGP_BIND_MEMORY(sc
, mem
, offset
);
1044 agp_unbind_memory(void *dev
, void *handle
)
1046 struct agp_softc
*sc
= dev
;
1047 struct agp_memory
*mem
= handle
;
1049 return AGP_UNBIND_MEMORY(sc
, mem
);
1053 agp_memory_info(void *dev
, void *handle
, struct agp_memory_info
*mi
)
1055 struct agp_memory
*mem
= handle
;
1057 mi
->ami_size
= mem
->am_size
;
1058 mi
->ami_physical
= mem
->am_physical
;
1059 mi
->ami_offset
= mem
->am_offset
;
1060 mi
->ami_is_bound
= mem
->am_is_bound
;
1064 agp_alloc_dmamem(bus_dma_tag_t tag
, size_t size
, int flags
,
1065 bus_dmamap_t
*mapp
, void **vaddr
, bus_addr_t
*baddr
,
1066 bus_dma_segment_t
*seg
, int nseg
, int *rseg
)
1069 int error
, level
= 0;
1071 if ((error
= bus_dmamem_alloc(tag
, size
, PAGE_SIZE
, 0,
1072 seg
, nseg
, rseg
, BUS_DMA_NOWAIT
)) != 0)
1076 if ((error
= bus_dmamem_map(tag
, seg
, *rseg
, size
, vaddr
,
1077 BUS_DMA_NOWAIT
| flags
)) != 0)
1081 if ((error
= bus_dmamap_create(tag
, size
, *rseg
, size
, 0,
1082 BUS_DMA_NOWAIT
, mapp
)) != 0)
1086 if ((error
= bus_dmamap_load(tag
, *mapp
, *vaddr
, size
, NULL
,
1087 BUS_DMA_NOWAIT
)) != 0)
1090 *baddr
= (*mapp
)->dm_segs
[0].ds_addr
;
1096 bus_dmamap_destroy(tag
, *mapp
);
1099 bus_dmamem_unmap(tag
, *vaddr
, size
);
1102 bus_dmamem_free(tag
, seg
, *rseg
);
1112 agp_free_dmamem(bus_dma_tag_t tag
, size_t size
, bus_dmamap_t map
,
1113 void *vaddr
, bus_dma_segment_t
*seg
, int nseg
)
1115 bus_dmamap_unload(tag
, map
);
1116 bus_dmamap_destroy(tag
, map
);
1117 bus_dmamem_unmap(tag
, vaddr
, size
);
1118 bus_dmamem_free(tag
, seg
, nseg
);
1122 agp_resume(device_t dv
, pmf_qual_t qual
)