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