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