xref: /openbsd-src/sys/dev/pci/vga_pci.c (revision 8500990981f885cbe5e6a4958549cacc238b5ae6)
1 /* $OpenBSD: vga_pci.c,v 1.15 2003/10/31 04:10:05 drahn Exp $ */
2 /* $NetBSD: vga_pci.c,v 1.3 1998/06/08 06:55:58 thorpej Exp $ */
3 
4 /*-
5  * Copyright (c) 2000 Doug Rabson
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *	$FreeBSD: src/sys/pci/agp.c,v 1.12 2001/05/19 01:28:07 alfred Exp $
30  */
31 /*
32  * Copyright (c) 2001 Wasabi Systems, Inc.
33  * All rights reserved.
34  *
35  * Written by Frank van der Linden for Wasabi Systems, Inc.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
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
51  *    written permission.
52  *
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.
64  */
65 /*
66  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
67  * All rights reserved.
68  *
69  * Author: Chris G. Demetriou
70  *
71  * Permission to use, copy, modify and distribute this software and
72  * its documentation is hereby granted, provided that both the copyright
73  * notice and this permission notice appear in all copies of the
74  * software, derivative works or modified versions, and any portions
75  * thereof, and that both notices appear in supporting documentation.
76  *
77  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
78  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
79  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
80  *
81  * Carnegie Mellon requests users of this software to return to
82  *
83  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
84  *  School of Computer Science
85  *  Carnegie Mellon University
86  *  Pittsburgh PA 15213-3890
87  *
88  * any improvements or extensions that they make and grant Carnegie the
89  * rights to redistribute these changes.
90  */
91 
92 #include "vga.h"
93 
94 #include <sys/param.h>
95 #include <sys/systm.h>
96 #include <sys/kernel.h>
97 #include <sys/device.h>
98 #include <sys/malloc.h>
99 #include <sys/agpio.h>
100 
101 #include <uvm/uvm.h>
102 
103 #include <machine/bus.h>
104 
105 #include <dev/pci/pcireg.h>
106 #include <dev/pci/pcivar.h>
107 #include <dev/pci/pcidevs.h>
108 
109 #include <dev/ic/mc6845reg.h>
110 #include <dev/ic/pcdisplayvar.h>
111 #include <dev/ic/vgareg.h>
112 #include <dev/ic/vgavar.h>
113 #include <dev/pci/vga_pcivar.h>
114 
115 #ifdef PCIAGP
116 #include <sys/fcntl.h>
117 
118 #include <dev/pci/agpvar.h>
119 #include <dev/pci/agpreg.h>
120 #endif
121 
122 #include <dev/wscons/wsconsio.h>
123 #include <dev/wscons/wsdisplayvar.h>
124 
125 int	vga_pci_match(struct device *, void *, void *);
126 void	vga_pci_attach(struct device *, struct device *, void *);
127 paddr_t	vga_pci_mmap(void* v, off_t off, int prot);
128 
129 struct cfattach vga_pci_ca = {
130 	sizeof(struct vga_pci_softc), vga_pci_match, vga_pci_attach,
131 };
132 
133 #ifdef PCIAGP
134 struct agp_memory *agp_find_memory(struct vga_pci_softc *sc, int id);
135 const struct agp_product *agp_lookup(struct pci_attach_args *pa);
136 
137 struct pci_attach_args	agp_pchb_pa;
138 int	agp_pchb_pa_set = 0;
139 #endif
140 
141 int
142 vga_pci_match(parent, match, aux)
143 	struct device *parent;
144 	void *match;
145 	void *aux;
146 {
147 	struct pci_attach_args *pa = aux;
148 	int potential;
149 
150 	potential = 0;
151 
152 	/*
153 	 * If it's prehistoric/vga or display/vga, we might match.
154 	 * For the console device, this is jut a sanity check.
155 	 */
156 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_PREHISTORIC &&
157 	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_PREHISTORIC_VGA)
158 		potential = 1;
159 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
160 	     PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA)
161 		potential = 1;
162 
163 	if (!potential)
164 		return (0);
165 
166 	/* check whether it is disabled by firmware */
167 	if ((pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG)
168 	    & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
169 	    != (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
170 		return (0);
171 
172 	/* If it's the console, we have a winner! */
173 	if (vga_is_console(pa->pa_iot, WSDISPLAY_TYPE_PCIVGA))
174 		return (1);
175 
176 	/*
177 	 * If we might match, make sure that the card actually looks OK.
178 	 */
179 #ifdef ISA_SPACE_NOT_ACCESSABLE_WITH_PCI_IOT
180 	if (!vga_common_probe(MD_ISA_IOT, MD_ISA_MEMT))
181 		return (0);
182 #else
183 	if (!vga_common_probe(pa->pa_iot, pa->pa_memt))
184 		return (0);
185 #endif
186 
187 	return (1);
188 }
189 
190 void
191 vga_pci_attach(parent, self, aux)
192 	struct device *parent, *self;
193 	void *aux;
194 {
195 #ifndef ISA_SPACE_NOT_ACCESSABLE_WITH_PCI_IOT
196 	struct pci_attach_args *pa = aux;
197 #endif
198 #ifdef PCIAGP
199 	struct vga_pci_softc *sc = (struct vga_pci_softc *)self;
200 	const struct agp_product *ap;
201 	u_int memsize;
202 	int i, ret;
203 #endif
204 
205 #ifdef PCIAGP
206 	ap = agp_lookup(pa);
207 	if (ap) {
208 		static const int agp_max[][2] = {
209 			{0,		0},
210 			{32,		4},
211 			{64,		28},
212 			{128,		96},
213 			{256,		204},
214 			{512,		440},
215 			{1024,		942},
216 			{2048,		1920},
217 			{4096,		3932}
218 		};
219 #define	agp_max_size	 (sizeof(agp_max)/sizeof(agp_max[0]))
220 
221 		/*
222 		 * Work out an upper bound for agp memory allocation. This
223 		 * uses a heurisitc table from the Linux driver.
224 		 */
225 		memsize = ptoa(physmem) >> 20;
226 
227 		for (i = 0; i < agp_max_size && memsize > agp_max[i][0]; i++)
228 			;
229 		if (i == agp_max_size)
230 			i = agp_max_size - 1;
231 		sc->sc_maxmem = agp_max[i][1] << 20;
232 
233 		/*
234 		 * The lock is used to prevent re-entry to
235 		 * agp_generic_bind_memory() since that function can sleep.
236 		 */
237 
238 		lockinit(&sc->sc_lock, PZERO|PCATCH, "agplk", 0, 0);
239 
240 		TAILQ_INIT(&sc->sc_memory);
241 
242 		sc->sc_pcitag = pa->pa_tag;
243 		sc->sc_pc = pa->pa_pc;
244 		sc->sc_id = pa->pa_id;
245 		sc->sc_dmat = pa->pa_dmat;
246 
247 		pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP,
248 		    &sc->sc_capoff, NULL);
249 
250 		ret = (*ap->ap_attach)(sc, pa, &agp_pchb_pa);
251 		if (ret == 0)
252 			printf(": aperture at 0x%lx, size 0x%lx",
253 			    (u_long)sc->sc_apaddr,
254 			    (u_long)AGP_GET_APERTURE(sc));
255 		else {
256 			sc->sc_chipc = NULL;
257 			printf(": AGP GART");
258 		}
259 	}
260 #endif
261 	printf("\n");
262 #ifdef ISA_SPACE_NOT_ACCESSABLE_WITH_PCI_IOT
263 	vga_extended_attach(self, MD_ISA_IOT, ppc_isa_membus_space,
264 	    WSDISPLAY_TYPE_PCIVGA, vga_pci_mmap);
265 #else
266 	vga_common_attach(self, pa->pa_iot, pa->pa_memt,
267 	    WSDISPLAY_TYPE_PCIVGA);
268 #endif
269 }
270 
271 paddr_t
272 vga_pci_mmap(void *v, off_t off, int prot)
273 {
274 #ifdef PCIAGP
275 	struct vga_config* vs = (struct vga_config*) v;
276 	struct vga_pci_softc* sc = (struct vga_pci_softc *)vs->vc_softc;
277 
278 	if (sc->sc_apaddr) {
279 
280 		if (off > AGP_GET_APERTURE(sc))
281 			return (-1);
282 
283 #ifdef __i386__
284 		return i386_btop(sc->sc_apaddr + off);
285 #endif
286 	}
287 #endif
288 #ifdef __pegasos__
289 	/* XXX */
290 		return off;
291 #endif
292 	return -1;
293 }
294 
295 int
296 vga_pci_cnattach(iot, memt, pc, bus, device, function)
297 	bus_space_tag_t iot, memt;
298 	pci_chipset_tag_t pc;
299 	int bus, device, function;
300 {
301 	return (vga_cnattach(iot, memt, WSDISPLAY_TYPE_PCIVGA, 0));
302 }
303 
304 int
305 vga_pci_ioctl(v, cmd, addr, flag, p)
306 	void *v;
307 	u_long cmd;
308 	caddr_t addr;
309 	int flag;
310 	struct proc *p;
311 {
312 	int error = 0;
313 #ifdef PCIAGP
314 	struct vga_config *vc = v;
315 	struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc;
316 	struct agp_memory *mem;
317 	agp_info *info;
318 	agp_setup *setup;
319 	agp_allocate *alloc;
320 	agp_bind *bind;
321 	agp_unbind *unbind;
322 	vsize_t size;
323 
324 	switch (cmd) {
325 	case AGPIOC_INFO:
326 		if (!sc->sc_chipc)
327 			return (ENXIO);
328 	case AGPIOC_ACQUIRE:
329 	case AGPIOC_RELEASE:
330 	case AGPIOC_SETUP:
331 	case AGPIOC_ALLOCATE:
332 	case AGPIOC_DEALLOCATE:
333 	case AGPIOC_BIND:
334 	case AGPIOC_UNBIND:
335 		if (cmd != AGPIOC_INFO && !(flag & FWRITE))
336 			return (EPERM);
337 		break;
338 	}
339 #endif
340 
341 	switch (cmd) {
342 #ifdef PCIAGP
343 	case AGPIOC_INFO:
344 		info = (agp_info *)addr;
345 		bzero(info, sizeof *info);
346 		info->bridge_id = sc->sc_id;
347 		if (sc->sc_capoff != 0)
348 			info->agp_mode = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
349 			    AGP_STATUS + sc->sc_capoff);
350 		else
351 			info->agp_mode = 0; /* i810 doesn't have real AGP */
352 		info->aper_base = sc->sc_apaddr;
353 		info->aper_size = AGP_GET_APERTURE(sc) >> 20;
354 		info->pg_total =
355 		info->pg_system = sc->sc_maxmem >> AGP_PAGE_SHIFT;
356 		info->pg_used = sc->sc_allocated >> AGP_PAGE_SHIFT;
357 		break;
358 
359 	case AGPIOC_ACQUIRE:
360 		if (sc->sc_state != AGP_ACQUIRE_FREE)
361 			error = EBUSY;
362 		else
363 			sc->sc_state = AGP_ACQUIRE_USER;
364 		break;
365 
366 	case AGPIOC_RELEASE:
367 		if (sc->sc_state == AGP_ACQUIRE_FREE)
368 			break;
369 
370 		if (sc->sc_state != AGP_ACQUIRE_USER) {
371 			error = EBUSY;
372 			break;
373 		}
374 
375 		/*
376 		 * Clear out the aperture and free any
377 		 * outstanding memory blocks.
378 		 */
379 		TAILQ_FOREACH(mem, &sc->sc_memory, am_link) {
380 			if (mem->am_is_bound) {
381 				printf("agp_release_helper: mem %d is bound\n",
382 				    mem->am_id);
383 				AGP_UNBIND_MEMORY(sc, mem);
384 			}
385 		}
386 		sc->sc_state = AGP_ACQUIRE_FREE;
387 		break;
388 
389 	case AGPIOC_SETUP:
390 		setup = (agp_setup *)addr;
391 		error = AGP_ENABLE(sc, setup->agp_mode);
392 		break;
393 
394 	case AGPIOC_ALLOCATE:
395 		alloc = (agp_allocate *)addr;
396 		size = alloc->pg_count << AGP_PAGE_SHIFT;
397 		if (sc->sc_allocated + size > sc->sc_maxmem)
398 			error = EINVAL;
399 		else {
400 			mem = AGP_ALLOC_MEMORY(sc, alloc->type, size);
401 			if (mem) {
402 				alloc->key = mem->am_id;
403 				alloc->physical = mem->am_physical;
404 			} else
405 				error = ENOMEM;
406 		}
407 		break;
408 
409 	case AGPIOC_DEALLOCATE:
410 		mem = agp_find_memory(sc, *(int *)addr);
411 		if (mem)
412 			AGP_FREE_MEMORY(sc, mem);
413 		else
414 			error = ENOENT;
415 		break;
416 
417 	case AGPIOC_BIND:
418 		bind = (agp_bind *)addr;
419 		mem = agp_find_memory(sc, bind->key);
420 		if (!mem)
421 			error = ENOENT;
422 		else
423 			error = AGP_BIND_MEMORY(sc, mem,
424 			    bind->pg_start << AGP_PAGE_SHIFT);
425 		break;
426 
427 	case AGPIOC_UNBIND:
428 		unbind = (agp_unbind *)addr;
429 		mem = agp_find_memory(sc, unbind->key);
430 		if (!mem)
431 			error = ENOENT;
432 		else
433 			error = AGP_UNBIND_MEMORY(sc, mem);
434 		break;
435 #endif /* PCIAGP */
436 
437 	default:
438 		error = ENOTTY;
439 	}
440 
441 	return (error);
442 }
443 
444 #ifdef PCIAGP
445 struct agp_memory *
446 agp_find_memory(struct vga_pci_softc *sc, int id)
447 {
448 	struct agp_memory *mem;
449 
450 	AGP_DPF("searching for memory block %d\n", id);
451 	TAILQ_FOREACH(mem, &sc->sc_memory, am_link) {
452 		AGP_DPF("considering memory block %d\n", mem->am_id);
453 		if (mem->am_id == id)
454 			return (mem);
455 	}
456 	return 0;
457 }
458 
459 const struct agp_product *
460 agp_lookup(struct pci_attach_args *pa)
461 {
462 	const struct agp_product *ap;
463 
464 	if (!agp_pchb_pa_set)
465 		return (NULL);
466 	agp_pchb_pa_set = 0;
467 
468 	/* First find the vendor. */
469 	for (ap = agp_products; ap->ap_attach != NULL; ap++)
470 		if (ap->ap_vendor == PCI_VENDOR(pa->pa_id))
471 			break;
472 
473 	if (ap->ap_attach == NULL)
474 		return (NULL);
475 
476 	/* Now find the product within the vendor's domain. */
477 	for (; ap->ap_attach != NULL; ap++) {
478 		/* Ran out of this vendor's section of the table. */
479 		if (ap->ap_vendor != PCI_VENDOR(pa->pa_id))
480 			return (NULL);
481 
482 		if (ap->ap_product == PCI_PRODUCT(pa->pa_id))
483 			break;		/* Exact match. */
484 		if (ap->ap_product == (u_int32_t) -1)
485 			break;		/* Wildcard match. */
486 	}
487 
488 	if (ap->ap_attach == NULL)
489 		ap = NULL;
490 
491 	return (ap);
492 }
493 
494 void
495 pciagp_set_pchb(struct pci_attach_args *pa)
496 {
497 	if (!agp_pchb_pa_set) {
498 		memcpy(&agp_pchb_pa, pa, sizeof *pa);
499 		agp_pchb_pa_set++;
500 	}
501 }
502 
503 int
504 agp_map_aperture(struct vga_pci_softc *sc)
505 {
506 	/*
507 	 * Find and the aperture. Don't map it (yet), this would
508 	 * eat KVA.
509 	 */
510 	if (pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, AGP_APBASE,
511 	    PCI_MAPREG_TYPE_MEM, &sc->sc_apaddr, &sc->sc_apsize,
512 	    &sc->sc_apflags) != 0)
513 		return ENXIO;
514 
515 	return 0;
516 }
517 
518 struct agp_gatt *
519 agp_alloc_gatt(struct vga_pci_softc *sc)
520 {
521 	u_int32_t apsize = AGP_GET_APERTURE(sc);
522 	u_int32_t entries = apsize >> AGP_PAGE_SHIFT;
523 	struct agp_gatt *gatt;
524 	int nseg;
525 
526 	gatt = malloc(sizeof(*gatt), M_DEVBUF, M_NOWAIT);
527 	if (!gatt)
528 		return (NULL);
529 	bzero(gatt, sizeof(*gatt));
530 	gatt->ag_entries = entries;
531 
532 	if (agp_alloc_dmamem(sc->sc_dmat, entries * sizeof(u_int32_t),
533 	    0, &gatt->ag_dmamap, (caddr_t *)&gatt->ag_virtual,
534 	    &gatt->ag_physical, &gatt->ag_dmaseg, 1, &nseg) != 0)
535 		return NULL;
536 
537 	gatt->ag_size = entries * sizeof(u_int32_t);
538 	memset(gatt->ag_virtual, 0, gatt->ag_size);
539 	agp_flush_cache();
540 
541 	return gatt;
542 }
543 
544 void
545 agp_free_gatt(struct vga_pci_softc *sc, struct agp_gatt *gatt)
546 {
547 	agp_free_dmamem(sc->sc_dmat, gatt->ag_size, gatt->ag_dmamap,
548 	    (caddr_t)gatt->ag_virtual, &gatt->ag_dmaseg, 1);
549 	free(gatt, M_DEVBUF);
550 }
551 
552 int
553 agp_generic_detach(struct vga_pci_softc *sc)
554 {
555 	lockmgr(&sc->sc_lock, LK_DRAIN, NULL, curproc);
556 	agp_flush_cache();
557 	return 0;
558 }
559 
560 int
561 agp_generic_enable(struct vga_pci_softc *sc, u_int32_t mode)
562 {
563 	pcireg_t tstatus, mstatus;
564 	pcireg_t command;
565 	int rq, sba, fw, rate, capoff;
566 
567 	if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP,
568 	     &capoff, NULL) == 0) {
569 		printf("agp_generic_enable: not an AGP capable device\n");
570 		return -1;
571 	}
572 
573 	tstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
574 	    sc->sc_capoff + AGP_STATUS);
575 	mstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
576 	    capoff + AGP_STATUS);
577 
578 	/* Set RQ to the min of mode, tstatus and mstatus */
579 	rq = AGP_MODE_GET_RQ(mode);
580 	if (AGP_MODE_GET_RQ(tstatus) < rq)
581 		rq = AGP_MODE_GET_RQ(tstatus);
582 	if (AGP_MODE_GET_RQ(mstatus) < rq)
583 		rq = AGP_MODE_GET_RQ(mstatus);
584 
585 	/* Set SBA if all three can deal with SBA */
586 	sba = (AGP_MODE_GET_SBA(tstatus)
587 	       & AGP_MODE_GET_SBA(mstatus)
588 	       & AGP_MODE_GET_SBA(mode));
589 
590 	/* Similar for FW */
591 	fw = (AGP_MODE_GET_FW(tstatus)
592 	       & AGP_MODE_GET_FW(mstatus)
593 	       & AGP_MODE_GET_FW(mode));
594 
595 	/* Figure out the max rate */
596 	rate = (AGP_MODE_GET_RATE(tstatus)
597 		& AGP_MODE_GET_RATE(mstatus)
598 		& AGP_MODE_GET_RATE(mode));
599 	if (rate & AGP_MODE_RATE_4x)
600 		rate = AGP_MODE_RATE_4x;
601 	else if (rate & AGP_MODE_RATE_2x)
602 		rate = AGP_MODE_RATE_2x;
603 	else
604 		rate = AGP_MODE_RATE_1x;
605 
606 	/* Construct the new mode word and tell the hardware  */
607 	command = AGP_MODE_SET_RQ(0, rq);
608 	command = AGP_MODE_SET_SBA(command, sba);
609 	command = AGP_MODE_SET_FW(command, fw);
610 	command = AGP_MODE_SET_RATE(command, rate);
611 	command = AGP_MODE_SET_AGP(command, 1);
612 	pci_conf_write(sc->sc_pc, sc->sc_pcitag,
613 	    sc->sc_capoff + AGP_COMMAND, command);
614 	pci_conf_write(sc->sc_pc, sc->sc_pcitag, capoff + AGP_COMMAND, command);
615 	return 0;
616 }
617 
618 struct agp_memory *
619 agp_generic_alloc_memory(struct vga_pci_softc *sc, int type, vsize_t size)
620 {
621 	struct agp_memory *mem;
622 
623 	if (type != 0) {
624 		printf("agp_generic_alloc_memory: unsupported type %d\n", type);
625 		return 0;
626 	}
627 
628 	mem = malloc(sizeof *mem, M_DEVBUF, M_WAITOK);
629 	if (mem == NULL)
630 		return NULL;
631 
632 	if (bus_dmamap_create(sc->sc_dmat, size, size / PAGE_SIZE + 1,
633 	    size, 0, BUS_DMA_NOWAIT, &mem->am_dmamap) != 0) {
634 		free(mem, M_DEVBUF);
635 		return NULL;
636 	}
637 
638 	mem->am_id = sc->sc_nextid++;
639 	mem->am_size = size;
640 	mem->am_type = 0;
641 	mem->am_physical = 0;
642 	mem->am_offset = 0;
643 	mem->am_is_bound = 0;
644 	TAILQ_INSERT_TAIL(&sc->sc_memory, mem, am_link);
645 	sc->sc_allocated += size;
646 
647 	return mem;
648 }
649 
650 int
651 agp_generic_free_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
652 {
653 	if (mem->am_is_bound)
654 		return EBUSY;
655 
656 	sc->sc_allocated -= mem->am_size;
657 	TAILQ_REMOVE(&sc->sc_memory, mem, am_link);
658 	bus_dmamap_destroy(sc->sc_dmat, mem->am_dmamap);
659 	free(mem, M_DEVBUF);
660 	return 0;
661 }
662 
663 int
664 agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
665 			off_t offset)
666 {
667 	bus_dma_segment_t *segs, *seg;
668 	bus_size_t done, j;
669 	bus_addr_t pa;
670 	off_t i, k;
671 	int contigpages, nseg, error;
672 
673 	lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL, curproc);
674 
675 	if (mem->am_is_bound) {
676 		printf("AGP: memory already bound\n");
677 		lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
678 		return EINVAL;
679 	}
680 
681 	if (offset < 0
682 	    || (offset & (AGP_PAGE_SIZE - 1)) != 0
683 	    || offset + mem->am_size > AGP_GET_APERTURE(sc)) {
684 		printf("AGP: binding memory at bad offset %#lx\n",
685 			      (unsigned long) offset);
686 		lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
687 		return EINVAL;
688 	}
689 
690 	/*
691 	 * XXXfvdl
692 	 * The memory here needs to be directly accessable from the
693 	 * AGP video card, so it should be allocated using bus_dma.
694 	 * However, it need not be contiguous, since individual pages
695 	 * are translated using the GATT.
696 	 *
697 	 * Using a large chunk of contiguous memory may get in the way
698 	 * of other subsystems that may need one, so we try to be friendly
699 	 * and ask for allocation in chunks of a minimum of 8 pages
700 	 * of contiguous memory on average, falling back to 4, 2 and 1
701 	 * if really needed. Larger chunks are preferred, since allocating
702 	 * a bus_dma_segment per page would be overkill.
703 	 */
704 
705 	for (contigpages = 32; contigpages > 0; contigpages >>= 1) {
706 		nseg = (mem->am_size / (contigpages * PAGE_SIZE)) + 1;
707 		segs = malloc(nseg * sizeof *segs, M_DEVBUF, M_WAITOK);
708 		if (segs == NULL)
709 			return ENOMEM;
710 		if ((error = bus_dmamem_alloc(sc->sc_dmat, mem->am_size, PAGE_SIZE, 0,
711 		    segs, nseg, &mem->am_nseg, BUS_DMA_WAITOK)) != 0) {
712 			free(segs, M_DEVBUF);
713 			AGP_DPF("bus_dmamem_alloc failed %d\n", error);
714 			continue;
715 		}
716 		if ((error = bus_dmamem_map(sc->sc_dmat, segs, mem->am_nseg,
717 		    mem->am_size, &mem->am_virtual, BUS_DMA_WAITOK)) != 0) {
718 			bus_dmamem_free(sc->sc_dmat, segs, mem->am_nseg);
719 			free(segs, M_DEVBUF);
720 			AGP_DPF("bus_dmamem_map failed %d\n", error);
721 			continue;
722 		}
723 		if ((error = bus_dmamap_load(sc->sc_dmat, mem->am_dmamap,
724 		    mem->am_virtual, mem->am_size, NULL,
725 		    BUS_DMA_WAITOK)) != 0) {
726 			bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual,
727 			    mem->am_size);
728 			bus_dmamem_free(sc->sc_dmat, segs, mem->am_nseg);
729 			free(segs, M_DEVBUF);
730 			AGP_DPF("bus_dmamap_load failed %d\n", error);
731 			continue;
732 		}
733 		mem->am_dmaseg = segs;
734 		break;
735 	}
736 
737 	if (contigpages == 0) {
738 		lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
739 		return ENOMEM;
740 	}
741 
742 	/*
743 	 * Bind the individual pages and flush the chipset's
744 	 * TLB.
745 	 */
746 	done = 0;
747 	for (i = 0; i < mem->am_dmamap->dm_nsegs; i++) {
748 		seg = &mem->am_dmamap->dm_segs[i];
749 		/*
750 		 * Install entries in the GATT, making sure that if
751 		 * AGP_PAGE_SIZE < PAGE_SIZE and mem->am_size is not
752 		 * aligned to PAGE_SIZE, we don't modify too many GATT
753 		 * entries.
754 		 */
755 		for (j = 0; j < seg->ds_len && (done + j) < mem->am_size;
756 		     j += AGP_PAGE_SIZE) {
757 			pa = seg->ds_addr + j;
758 			AGP_DPF("binding offset %#lx to pa %#lx\n",
759 				(unsigned long)(offset + done + j),
760 				(unsigned long)pa);
761 			error = AGP_BIND_PAGE(sc, offset + done + j, pa);
762 			if (error) {
763 				/*
764 				 * Bail out. Reverse all the mappings
765 				 * and unwire the pages.
766 				 */
767 				for (k = 0; k < done + j; k += AGP_PAGE_SIZE)
768 					AGP_UNBIND_PAGE(sc, offset + k);
769 
770 				bus_dmamap_unload(sc->sc_dmat, mem->am_dmamap);
771 				bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual,
772 						 mem->am_size);
773 				bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg,
774 						mem->am_nseg);
775 				free(mem->am_dmaseg, M_DEVBUF);
776 				lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
777 				return error;
778 			}
779 		}
780 		done += seg->ds_len;
781 	}
782 
783 	/*
784 	 * Flush the cpu cache since we are providing a new mapping
785 	 * for these pages.
786 	 */
787 	agp_flush_cache();
788 
789 	/*
790 	 * Make sure the chipset gets the new mappings.
791 	 */
792 	AGP_FLUSH_TLB(sc);
793 
794 	mem->am_offset = offset;
795 	mem->am_is_bound = 1;
796 
797 	lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
798 
799 	return 0;
800 }
801 
802 int
803 agp_generic_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
804 {
805 	int i;
806 
807 	lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL, curproc);
808 
809 	if (!mem->am_is_bound) {
810 		printf("AGP: memory is not bound\n");
811 		lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
812 		return EINVAL;
813 	}
814 
815 
816 	/*
817 	 * Unbind the individual pages and flush the chipset's
818 	 * TLB. Unwire the pages so they can be swapped.
819 	 */
820 	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
821 		AGP_UNBIND_PAGE(sc, mem->am_offset + i);
822 
823 	agp_flush_cache();
824 	AGP_FLUSH_TLB(sc);
825 
826 	bus_dmamap_unload(sc->sc_dmat, mem->am_dmamap);
827 	bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual, mem->am_size);
828 	bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg, mem->am_nseg);
829 
830 	free(mem->am_dmaseg, M_DEVBUF);
831 
832 	mem->am_offset = 0;
833 	mem->am_is_bound = 0;
834 
835 	lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
836 
837 	return 0;
838 }
839 
840 int
841 agp_alloc_dmamem(bus_dma_tag_t tag, size_t size, int flags,
842 		 bus_dmamap_t *mapp, caddr_t *vaddr, bus_addr_t *baddr,
843 		 bus_dma_segment_t *seg, int nseg, int *rseg)
844 
845 {
846 	int error, level = 0;
847 
848 	if ((error = bus_dmamem_alloc(tag, size, PAGE_SIZE, 0,
849 			seg, nseg, rseg, BUS_DMA_NOWAIT)) != 0)
850 		goto out;
851 	level++;
852 
853 	if ((error = bus_dmamem_map(tag, seg, *rseg, size, vaddr,
854 			BUS_DMA_NOWAIT | flags)) != 0)
855 		goto out;
856 	level++;
857 
858 	if ((error = bus_dmamap_create(tag, size, *rseg, size, 0,
859 			BUS_DMA_NOWAIT, mapp)) != 0)
860 		goto out;
861 	level++;
862 
863 	if ((error = bus_dmamap_load(tag, *mapp, *vaddr, size, NULL,
864 			BUS_DMA_NOWAIT)) != 0)
865 		goto out;
866 
867 	*baddr = (*mapp)->dm_segs[0].ds_addr;
868 
869 	return 0;
870 out:
871 	switch (level) {
872 	case 3:
873 		bus_dmamap_destroy(tag, *mapp);
874 		/* FALLTHROUGH */
875 	case 2:
876 		bus_dmamem_unmap(tag, *vaddr, size);
877 		/* FALLTHROUGH */
878 	case 1:
879 		bus_dmamem_free(tag, seg, *rseg);
880 		break;
881 	default:
882 		break;
883 	}
884 
885 	return error;
886 }
887 
888 void
889 agp_free_dmamem(bus_dma_tag_t tag, size_t size, bus_dmamap_t map,
890 		caddr_t vaddr, bus_dma_segment_t *seg, int nseg)
891 {
892 
893 	bus_dmamap_unload(tag, map);
894 	bus_dmamap_destroy(tag, map);
895 	bus_dmamem_unmap(tag, vaddr, size);
896 	bus_dmamem_free(tag, seg, nseg);
897 }
898 #endif
899