xref: /openbsd-src/sys/dev/pci/vga_pci.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /* $OpenBSD: vga_pci.c,v 1.14 2002/07/15 13:23:48 mickey 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 	if (!vga_common_probe(pa->pa_iot, pa->pa_memt))
180 		return (0);
181 
182 	return (1);
183 }
184 
185 void
186 vga_pci_attach(parent, self, aux)
187 	struct device *parent, *self;
188 	void *aux;
189 {
190 	struct pci_attach_args *pa = aux;
191 #ifdef PCIAGP
192 	struct vga_pci_softc *sc = (struct vga_pci_softc *)self;
193 	const struct agp_product *ap;
194 	u_int memsize;
195 	int i, ret;
196 #endif
197 
198 #ifdef PCIAGP
199 	ap = agp_lookup(pa);
200 	if (ap) {
201 		static const int agp_max[][2] = {
202 			{0,		0},
203 			{32,		4},
204 			{64,		28},
205 			{128,		96},
206 			{256,		204},
207 			{512,		440},
208 			{1024,		942},
209 			{2048,		1920},
210 			{4096,		3932}
211 		};
212 #define	agp_max_size	 (sizeof(agp_max)/sizeof(agp_max[0]))
213 
214 		/*
215 		 * Work out an upper bound for agp memory allocation. This
216 		 * uses a heurisitc table from the Linux driver.
217 		 */
218 		memsize = ptoa(physmem) >> 20;
219 
220 		for (i = 0; i < agp_max_size && memsize > agp_max[i][0]; i++)
221 			;
222 		if (i == agp_max_size)
223 			i = agp_max_size - 1;
224 		sc->sc_maxmem = agp_max[i][1] << 20;
225 
226 		/*
227 		 * The lock is used to prevent re-entry to
228 		 * agp_generic_bind_memory() since that function can sleep.
229 		 */
230 
231 		lockinit(&sc->sc_lock, PZERO|PCATCH, "agplk", 0, 0);
232 
233 		TAILQ_INIT(&sc->sc_memory);
234 
235 		sc->sc_pcitag = pa->pa_tag;
236 		sc->sc_pc = pa->pa_pc;
237 		sc->sc_id = pa->pa_id;
238 		sc->sc_dmat = pa->pa_dmat;
239 
240 		pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP,
241 		    &sc->sc_capoff, NULL);
242 
243 		ret = (*ap->ap_attach)(sc, pa, &agp_pchb_pa);
244 		if (ret == 0)
245 			printf(": aperture at 0x%lx, size 0x%lx",
246 			    (u_long)sc->sc_apaddr,
247 			    (u_long)AGP_GET_APERTURE(sc));
248 		else {
249 			sc->sc_chipc = NULL;
250 			printf(": AGP GART");
251 		}
252 	}
253 #endif
254 	printf("\n");
255 	vga_common_attach(self, pa->pa_iot, pa->pa_memt,
256 	    WSDISPLAY_TYPE_PCIVGA);
257 }
258 
259 paddr_t
260 vga_pci_mmap(void *v, off_t off, int prot)
261 {
262 #ifdef PCIAGP
263 	struct vga_config* vs = (struct vga_config*) v;
264 	struct vga_pci_softc* sc = (struct vga_pci_softc *)vs->vc_softc;
265 
266 	if (sc->sc_apaddr) {
267 
268 		if (off > AGP_GET_APERTURE(sc))
269 			return (-1);
270 
271 #ifdef __i386__
272 		return i386_btop(sc->sc_apaddr + off);
273 #endif
274 	}
275 #endif
276 	return -1;
277 }
278 
279 int
280 vga_pci_cnattach(iot, memt, pc, bus, device, function)
281 	bus_space_tag_t iot, memt;
282 	pci_chipset_tag_t pc;
283 	int bus, device, function;
284 {
285 	return (vga_cnattach(iot, memt, WSDISPLAY_TYPE_PCIVGA, 0));
286 }
287 
288 int
289 vga_pci_ioctl(v, cmd, addr, flag, p)
290 	void *v;
291 	u_long cmd;
292 	caddr_t addr;
293 	int flag;
294 	struct proc *p;
295 {
296 	int error = 0;
297 #ifdef PCIAGP
298 	struct vga_config *vc = v;
299 	struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc;
300 	struct agp_memory *mem;
301 	agp_info *info;
302 	agp_setup *setup;
303 	agp_allocate *alloc;
304 	agp_bind *bind;
305 	agp_unbind *unbind;
306 	vsize_t size;
307 
308 	switch (cmd) {
309 	case AGPIOC_INFO:
310 		if (!sc->sc_chipc)
311 			return (ENXIO);
312 	case AGPIOC_ACQUIRE:
313 	case AGPIOC_RELEASE:
314 	case AGPIOC_SETUP:
315 	case AGPIOC_ALLOCATE:
316 	case AGPIOC_DEALLOCATE:
317 	case AGPIOC_BIND:
318 	case AGPIOC_UNBIND:
319 		if (cmd != AGPIOC_INFO && !(flag & FWRITE))
320 			return (EPERM);
321 		break;
322 	}
323 #endif
324 
325 	switch (cmd) {
326 #ifdef PCIAGP
327 	case AGPIOC_INFO:
328 		info = (agp_info *)addr;
329 		bzero(info, sizeof *info);
330 		info->bridge_id = sc->sc_id;
331 		if (sc->sc_capoff != 0)
332 			info->agp_mode = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
333 			    AGP_STATUS + sc->sc_capoff);
334 		else
335 			info->agp_mode = 0; /* i810 doesn't have real AGP */
336 		info->aper_base = sc->sc_apaddr;
337 		info->aper_size = AGP_GET_APERTURE(sc) >> 20;
338 		info->pg_total =
339 		info->pg_system = sc->sc_maxmem >> AGP_PAGE_SHIFT;
340 		info->pg_used = sc->sc_allocated >> AGP_PAGE_SHIFT;
341 		break;
342 
343 	case AGPIOC_ACQUIRE:
344 		if (sc->sc_state != AGP_ACQUIRE_FREE)
345 			error = EBUSY;
346 		else
347 			sc->sc_state = AGP_ACQUIRE_USER;
348 		break;
349 
350 	case AGPIOC_RELEASE:
351 		if (sc->sc_state == AGP_ACQUIRE_FREE)
352 			break;
353 
354 		if (sc->sc_state != AGP_ACQUIRE_USER) {
355 			error = EBUSY;
356 			break;
357 		}
358 
359 		/*
360 		 * Clear out the aperture and free any
361 		 * outstanding memory blocks.
362 		 */
363 		TAILQ_FOREACH(mem, &sc->sc_memory, am_link) {
364 			if (mem->am_is_bound) {
365 				printf("agp_release_helper: mem %d is bound\n",
366 				    mem->am_id);
367 				AGP_UNBIND_MEMORY(sc, mem);
368 			}
369 		}
370 		sc->sc_state = AGP_ACQUIRE_FREE;
371 		break;
372 
373 	case AGPIOC_SETUP:
374 		setup = (agp_setup *)addr;
375 		error = AGP_ENABLE(sc, setup->agp_mode);
376 		break;
377 
378 	case AGPIOC_ALLOCATE:
379 		alloc = (agp_allocate *)addr;
380 		size = alloc->pg_count << AGP_PAGE_SHIFT;
381 		if (sc->sc_allocated + size > sc->sc_maxmem)
382 			error = EINVAL;
383 		else {
384 			mem = AGP_ALLOC_MEMORY(sc, alloc->type, size);
385 			if (mem) {
386 				alloc->key = mem->am_id;
387 				alloc->physical = mem->am_physical;
388 			} else
389 				error = ENOMEM;
390 		}
391 		break;
392 
393 	case AGPIOC_DEALLOCATE:
394 		mem = agp_find_memory(sc, *(int *)addr);
395 		if (mem)
396 			AGP_FREE_MEMORY(sc, mem);
397 		else
398 			error = ENOENT;
399 		break;
400 
401 	case AGPIOC_BIND:
402 		bind = (agp_bind *)addr;
403 		mem = agp_find_memory(sc, bind->key);
404 		if (!mem)
405 			error = ENOENT;
406 		else
407 			error = AGP_BIND_MEMORY(sc, mem,
408 			    bind->pg_start << AGP_PAGE_SHIFT);
409 		break;
410 
411 	case AGPIOC_UNBIND:
412 		unbind = (agp_unbind *)addr;
413 		mem = agp_find_memory(sc, unbind->key);
414 		if (!mem)
415 			error = ENOENT;
416 		else
417 			error = AGP_UNBIND_MEMORY(sc, mem);
418 		break;
419 #endif /* PCIAGP */
420 
421 	default:
422 		error = ENOTTY;
423 	}
424 
425 	return (error);
426 }
427 
428 #ifdef PCIAGP
429 struct agp_memory *
430 agp_find_memory(struct vga_pci_softc *sc, int id)
431 {
432 	struct agp_memory *mem;
433 
434 	AGP_DPF("searching for memory block %d\n", id);
435 	TAILQ_FOREACH(mem, &sc->sc_memory, am_link) {
436 		AGP_DPF("considering memory block %d\n", mem->am_id);
437 		if (mem->am_id == id)
438 			return (mem);
439 	}
440 	return 0;
441 }
442 
443 const struct agp_product *
444 agp_lookup(struct pci_attach_args *pa)
445 {
446 	const struct agp_product *ap;
447 
448 	if (!agp_pchb_pa_set)
449 		return (NULL);
450 	agp_pchb_pa_set = 0;
451 
452 	/* First find the vendor. */
453 	for (ap = agp_products; ap->ap_attach != NULL; ap++)
454 		if (ap->ap_vendor == PCI_VENDOR(pa->pa_id))
455 			break;
456 
457 	if (ap->ap_attach == NULL)
458 		return (NULL);
459 
460 	/* Now find the product within the vendor's domain. */
461 	for (; ap->ap_attach != NULL; ap++) {
462 		/* Ran out of this vendor's section of the table. */
463 		if (ap->ap_vendor != PCI_VENDOR(pa->pa_id))
464 			return (NULL);
465 
466 		if (ap->ap_product == PCI_PRODUCT(pa->pa_id))
467 			break;		/* Exact match. */
468 		if (ap->ap_product == (u_int32_t) -1)
469 			break;		/* Wildcard match. */
470 	}
471 
472 	if (ap->ap_attach == NULL)
473 		ap = NULL;
474 
475 	return (ap);
476 }
477 
478 void
479 pciagp_set_pchb(struct pci_attach_args *pa)
480 {
481 	if (!agp_pchb_pa_set) {
482 		memcpy(&agp_pchb_pa, pa, sizeof *pa);
483 		agp_pchb_pa_set++;
484 	}
485 }
486 
487 int
488 agp_map_aperture(struct vga_pci_softc *sc)
489 {
490 	/*
491 	 * Find and the aperture. Don't map it (yet), this would
492 	 * eat KVA.
493 	 */
494 	if (pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, AGP_APBASE,
495 	    PCI_MAPREG_TYPE_MEM, &sc->sc_apaddr, &sc->sc_apsize,
496 	    &sc->sc_apflags) != 0)
497 		return ENXIO;
498 
499 	return 0;
500 }
501 
502 struct agp_gatt *
503 agp_alloc_gatt(struct vga_pci_softc *sc)
504 {
505 	u_int32_t apsize = AGP_GET_APERTURE(sc);
506 	u_int32_t entries = apsize >> AGP_PAGE_SHIFT;
507 	struct agp_gatt *gatt;
508 	int nseg;
509 
510 	gatt = malloc(sizeof(*gatt), M_DEVBUF, M_NOWAIT);
511 	if (!gatt)
512 		return (NULL);
513 	bzero(gatt, sizeof(*gatt));
514 	gatt->ag_entries = entries;
515 
516 	if (agp_alloc_dmamem(sc->sc_dmat, entries * sizeof(u_int32_t),
517 	    0, &gatt->ag_dmamap, (caddr_t *)&gatt->ag_virtual,
518 	    &gatt->ag_physical, &gatt->ag_dmaseg, 1, &nseg) != 0)
519 		return NULL;
520 
521 	gatt->ag_size = entries * sizeof(u_int32_t);
522 	memset(gatt->ag_virtual, 0, gatt->ag_size);
523 	agp_flush_cache();
524 
525 	return gatt;
526 }
527 
528 void
529 agp_free_gatt(struct vga_pci_softc *sc, struct agp_gatt *gatt)
530 {
531 	agp_free_dmamem(sc->sc_dmat, gatt->ag_size, gatt->ag_dmamap,
532 	    (caddr_t)gatt->ag_virtual, &gatt->ag_dmaseg, 1);
533 	free(gatt, M_DEVBUF);
534 }
535 
536 int
537 agp_generic_detach(struct vga_pci_softc *sc)
538 {
539 	lockmgr(&sc->sc_lock, LK_DRAIN, NULL, curproc);
540 	agp_flush_cache();
541 	return 0;
542 }
543 
544 int
545 agp_generic_enable(struct vga_pci_softc *sc, u_int32_t mode)
546 {
547 	pcireg_t tstatus, mstatus;
548 	pcireg_t command;
549 	int rq, sba, fw, rate, capoff;
550 
551 	if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP,
552 	     &capoff, NULL) == 0) {
553 		printf("agp_generic_enable: not an AGP capable device\n");
554 		return -1;
555 	}
556 
557 	tstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
558 	    sc->sc_capoff + AGP_STATUS);
559 	mstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
560 	    capoff + AGP_STATUS);
561 
562 	/* Set RQ to the min of mode, tstatus and mstatus */
563 	rq = AGP_MODE_GET_RQ(mode);
564 	if (AGP_MODE_GET_RQ(tstatus) < rq)
565 		rq = AGP_MODE_GET_RQ(tstatus);
566 	if (AGP_MODE_GET_RQ(mstatus) < rq)
567 		rq = AGP_MODE_GET_RQ(mstatus);
568 
569 	/* Set SBA if all three can deal with SBA */
570 	sba = (AGP_MODE_GET_SBA(tstatus)
571 	       & AGP_MODE_GET_SBA(mstatus)
572 	       & AGP_MODE_GET_SBA(mode));
573 
574 	/* Similar for FW */
575 	fw = (AGP_MODE_GET_FW(tstatus)
576 	       & AGP_MODE_GET_FW(mstatus)
577 	       & AGP_MODE_GET_FW(mode));
578 
579 	/* Figure out the max rate */
580 	rate = (AGP_MODE_GET_RATE(tstatus)
581 		& AGP_MODE_GET_RATE(mstatus)
582 		& AGP_MODE_GET_RATE(mode));
583 	if (rate & AGP_MODE_RATE_4x)
584 		rate = AGP_MODE_RATE_4x;
585 	else if (rate & AGP_MODE_RATE_2x)
586 		rate = AGP_MODE_RATE_2x;
587 	else
588 		rate = AGP_MODE_RATE_1x;
589 
590 	/* Construct the new mode word and tell the hardware  */
591 	command = AGP_MODE_SET_RQ(0, rq);
592 	command = AGP_MODE_SET_SBA(command, sba);
593 	command = AGP_MODE_SET_FW(command, fw);
594 	command = AGP_MODE_SET_RATE(command, rate);
595 	command = AGP_MODE_SET_AGP(command, 1);
596 	pci_conf_write(sc->sc_pc, sc->sc_pcitag,
597 	    sc->sc_capoff + AGP_COMMAND, command);
598 	pci_conf_write(sc->sc_pc, sc->sc_pcitag, capoff + AGP_COMMAND, command);
599 	return 0;
600 }
601 
602 struct agp_memory *
603 agp_generic_alloc_memory(struct vga_pci_softc *sc, int type, vsize_t size)
604 {
605 	struct agp_memory *mem;
606 
607 	if (type != 0) {
608 		printf("agp_generic_alloc_memory: unsupported type %d\n", type);
609 		return 0;
610 	}
611 
612 	mem = malloc(sizeof *mem, M_DEVBUF, M_WAITOK);
613 	if (mem == NULL)
614 		return NULL;
615 
616 	if (bus_dmamap_create(sc->sc_dmat, size, size / PAGE_SIZE + 1,
617 	    size, 0, BUS_DMA_NOWAIT, &mem->am_dmamap) != 0) {
618 		free(mem, M_DEVBUF);
619 		return NULL;
620 	}
621 
622 	mem->am_id = sc->sc_nextid++;
623 	mem->am_size = size;
624 	mem->am_type = 0;
625 	mem->am_physical = 0;
626 	mem->am_offset = 0;
627 	mem->am_is_bound = 0;
628 	TAILQ_INSERT_TAIL(&sc->sc_memory, mem, am_link);
629 	sc->sc_allocated += size;
630 
631 	return mem;
632 }
633 
634 int
635 agp_generic_free_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
636 {
637 	if (mem->am_is_bound)
638 		return EBUSY;
639 
640 	sc->sc_allocated -= mem->am_size;
641 	TAILQ_REMOVE(&sc->sc_memory, mem, am_link);
642 	bus_dmamap_destroy(sc->sc_dmat, mem->am_dmamap);
643 	free(mem, M_DEVBUF);
644 	return 0;
645 }
646 
647 int
648 agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
649 			off_t offset)
650 {
651 	bus_dma_segment_t *segs, *seg;
652 	bus_size_t done, j;
653 	bus_addr_t pa;
654 	off_t i, k;
655 	int contigpages, nseg, error;
656 
657 	lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL, curproc);
658 
659 	if (mem->am_is_bound) {
660 		printf("AGP: memory already bound\n");
661 		lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
662 		return EINVAL;
663 	}
664 
665 	if (offset < 0
666 	    || (offset & (AGP_PAGE_SIZE - 1)) != 0
667 	    || offset + mem->am_size > AGP_GET_APERTURE(sc)) {
668 		printf("AGP: binding memory at bad offset %#lx\n",
669 			      (unsigned long) offset);
670 		lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
671 		return EINVAL;
672 	}
673 
674 	/*
675 	 * XXXfvdl
676 	 * The memory here needs to be directly accessable from the
677 	 * AGP video card, so it should be allocated using bus_dma.
678 	 * However, it need not be contiguous, since individual pages
679 	 * are translated using the GATT.
680 	 *
681 	 * Using a large chunk of contiguous memory may get in the way
682 	 * of other subsystems that may need one, so we try to be friendly
683 	 * and ask for allocation in chunks of a minimum of 8 pages
684 	 * of contiguous memory on average, falling back to 4, 2 and 1
685 	 * if really needed. Larger chunks are preferred, since allocating
686 	 * a bus_dma_segment per page would be overkill.
687 	 */
688 
689 	for (contigpages = 32; contigpages > 0; contigpages >>= 1) {
690 		nseg = (mem->am_size / (contigpages * PAGE_SIZE)) + 1;
691 		segs = malloc(nseg * sizeof *segs, M_DEVBUF, M_WAITOK);
692 		if (segs == NULL)
693 			return ENOMEM;
694 		if ((error = bus_dmamem_alloc(sc->sc_dmat, mem->am_size, PAGE_SIZE, 0,
695 		    segs, nseg, &mem->am_nseg, BUS_DMA_WAITOK)) != 0) {
696 			free(segs, M_DEVBUF);
697 			AGP_DPF("bus_dmamem_alloc failed %d\n", error);
698 			continue;
699 		}
700 		if ((error = bus_dmamem_map(sc->sc_dmat, segs, mem->am_nseg,
701 		    mem->am_size, &mem->am_virtual, BUS_DMA_WAITOK)) != 0) {
702 			bus_dmamem_free(sc->sc_dmat, segs, mem->am_nseg);
703 			free(segs, M_DEVBUF);
704 			AGP_DPF("bus_dmamem_map failed %d\n", error);
705 			continue;
706 		}
707 		if ((error = bus_dmamap_load(sc->sc_dmat, mem->am_dmamap,
708 		    mem->am_virtual, mem->am_size, NULL,
709 		    BUS_DMA_WAITOK)) != 0) {
710 			bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual,
711 			    mem->am_size);
712 			bus_dmamem_free(sc->sc_dmat, segs, mem->am_nseg);
713 			free(segs, M_DEVBUF);
714 			AGP_DPF("bus_dmamap_load failed %d\n", error);
715 			continue;
716 		}
717 		mem->am_dmaseg = segs;
718 		break;
719 	}
720 
721 	if (contigpages == 0) {
722 		lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
723 		return ENOMEM;
724 	}
725 
726 	/*
727 	 * Bind the individual pages and flush the chipset's
728 	 * TLB.
729 	 */
730 	done = 0;
731 	for (i = 0; i < mem->am_dmamap->dm_nsegs; i++) {
732 		seg = &mem->am_dmamap->dm_segs[i];
733 		/*
734 		 * Install entries in the GATT, making sure that if
735 		 * AGP_PAGE_SIZE < PAGE_SIZE and mem->am_size is not
736 		 * aligned to PAGE_SIZE, we don't modify too many GATT
737 		 * entries.
738 		 */
739 		for (j = 0; j < seg->ds_len && (done + j) < mem->am_size;
740 		     j += AGP_PAGE_SIZE) {
741 			pa = seg->ds_addr + j;
742 			AGP_DPF("binding offset %#lx to pa %#lx\n",
743 				(unsigned long)(offset + done + j),
744 				(unsigned long)pa);
745 			error = AGP_BIND_PAGE(sc, offset + done + j, pa);
746 			if (error) {
747 				/*
748 				 * Bail out. Reverse all the mappings
749 				 * and unwire the pages.
750 				 */
751 				for (k = 0; k < done + j; k += AGP_PAGE_SIZE)
752 					AGP_UNBIND_PAGE(sc, offset + k);
753 
754 				bus_dmamap_unload(sc->sc_dmat, mem->am_dmamap);
755 				bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual,
756 						 mem->am_size);
757 				bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg,
758 						mem->am_nseg);
759 				free(mem->am_dmaseg, M_DEVBUF);
760 				lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
761 				return error;
762 			}
763 		}
764 		done += seg->ds_len;
765 	}
766 
767 	/*
768 	 * Flush the cpu cache since we are providing a new mapping
769 	 * for these pages.
770 	 */
771 	agp_flush_cache();
772 
773 	/*
774 	 * Make sure the chipset gets the new mappings.
775 	 */
776 	AGP_FLUSH_TLB(sc);
777 
778 	mem->am_offset = offset;
779 	mem->am_is_bound = 1;
780 
781 	lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
782 
783 	return 0;
784 }
785 
786 int
787 agp_generic_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
788 {
789 	int i;
790 
791 	lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL, curproc);
792 
793 	if (!mem->am_is_bound) {
794 		printf("AGP: memory is not bound\n");
795 		lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
796 		return EINVAL;
797 	}
798 
799 
800 	/*
801 	 * Unbind the individual pages and flush the chipset's
802 	 * TLB. Unwire the pages so they can be swapped.
803 	 */
804 	for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
805 		AGP_UNBIND_PAGE(sc, mem->am_offset + i);
806 
807 	agp_flush_cache();
808 	AGP_FLUSH_TLB(sc);
809 
810 	bus_dmamap_unload(sc->sc_dmat, mem->am_dmamap);
811 	bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual, mem->am_size);
812 	bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg, mem->am_nseg);
813 
814 	free(mem->am_dmaseg, M_DEVBUF);
815 
816 	mem->am_offset = 0;
817 	mem->am_is_bound = 0;
818 
819 	lockmgr(&sc->sc_lock, LK_RELEASE, NULL, curproc);
820 
821 	return 0;
822 }
823 
824 int
825 agp_alloc_dmamem(bus_dma_tag_t tag, size_t size, int flags,
826 		 bus_dmamap_t *mapp, caddr_t *vaddr, bus_addr_t *baddr,
827 		 bus_dma_segment_t *seg, int nseg, int *rseg)
828 
829 {
830 	int error, level = 0;
831 
832 	if ((error = bus_dmamem_alloc(tag, size, PAGE_SIZE, 0,
833 			seg, nseg, rseg, BUS_DMA_NOWAIT)) != 0)
834 		goto out;
835 	level++;
836 
837 	if ((error = bus_dmamem_map(tag, seg, *rseg, size, vaddr,
838 			BUS_DMA_NOWAIT | flags)) != 0)
839 		goto out;
840 	level++;
841 
842 	if ((error = bus_dmamap_create(tag, size, *rseg, size, 0,
843 			BUS_DMA_NOWAIT, mapp)) != 0)
844 		goto out;
845 	level++;
846 
847 	if ((error = bus_dmamap_load(tag, *mapp, *vaddr, size, NULL,
848 			BUS_DMA_NOWAIT)) != 0)
849 		goto out;
850 
851 	*baddr = (*mapp)->dm_segs[0].ds_addr;
852 
853 	return 0;
854 out:
855 	switch (level) {
856 	case 3:
857 		bus_dmamap_destroy(tag, *mapp);
858 		/* FALLTHROUGH */
859 	case 2:
860 		bus_dmamem_unmap(tag, *vaddr, size);
861 		/* FALLTHROUGH */
862 	case 1:
863 		bus_dmamem_free(tag, seg, *rseg);
864 		break;
865 	default:
866 		break;
867 	}
868 
869 	return error;
870 }
871 
872 void
873 agp_free_dmamem(bus_dma_tag_t tag, size_t size, bus_dmamap_t map,
874 		caddr_t vaddr, bus_dma_segment_t *seg, int nseg)
875 {
876 
877 	bus_dmamap_unload(tag, map);
878 	bus_dmamap_destroy(tag, map);
879 	bus_dmamem_unmap(tag, vaddr, size);
880 	bus_dmamem_free(tag, seg, nseg);
881 }
882 #endif
883