This source file includes following definitions.
- agp_attach
- agp_mmap
- agp_ioctl
- agp_close
- agp_find_memory
- agp_lookup
- pciagp_set_pchb
- agp_map_aperture
- agp_alloc_gatt
- agp_free_gatt
- agp_generic_detach
- agp_generic_enable
- agp_generic_alloc_memory
- agp_generic_free_memory
- agp_generic_bind_memory
- agp_generic_unbind_memory
- agp_alloc_dmamem
- agp_free_dmamem
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include <sys/param.h>
31 #include <sys/malloc.h>
32 #include <sys/agpio.h>
33 #include <sys/fcntl.h>
34 #include <sys/ioctl.h>
35
36 #include <uvm/uvm.h>
37
38 #include <dev/pci/pcivar.h>
39
40 #include <dev/ic/mc6845reg.h>
41 #include <dev/ic/pcdisplayvar.h>
42 #include <dev/ic/vgareg.h>
43 #include <dev/ic/vgavar.h>
44
45 #include <dev/pci/agpvar.h>
46 #include <dev/pci/agpreg.h>
47
48 struct agp_memory *agp_find_memory(struct vga_pci_softc *sc, int id);
49 const struct agp_product *agp_lookup(struct pci_attach_args *pa);
50
51 struct pci_attach_args agp_pchb_pa;
52 int agp_pchb_pa_set = 0;
53
54 void
55 agp_attach(struct device *parent, struct device *self, void *aux)
56 {
57 struct pci_attach_args *pa = aux;
58 struct vga_pci_softc *sc = (struct vga_pci_softc *)self;
59 const struct agp_product *ap;
60 u_int memsize;
61 int i, ret;
62
63 ap = agp_lookup(pa);
64 if (ap) {
65 static const int agp_max[][2] = {
66 {0, 0},
67 {32, 4},
68 {64, 28},
69 {128, 96},
70 {256, 204},
71 {512, 440},
72 {1024, 942},
73 {2048, 1920},
74 {4096, 3932}
75 };
76 #define agp_max_size (sizeof(agp_max)/sizeof(agp_max[0]))
77
78
79
80
81
82 memsize = ptoa(physmem) >> 20;
83
84 for (i = 0; i < agp_max_size && memsize > agp_max[i][0]; i++)
85 ;
86 if (i == agp_max_size)
87 i = agp_max_size - 1;
88 sc->sc_maxmem = agp_max[i][1] << 20;
89
90
91
92
93
94
95 lockinit(&sc->sc_lock, PZERO|PCATCH, "agplk", 0, 0);
96
97 TAILQ_INIT(&sc->sc_memory);
98
99 sc->sc_pcitag = pa->pa_tag;
100 sc->sc_pc = pa->pa_pc;
101 sc->sc_id = pa->pa_id;
102 sc->sc_dmat = pa->pa_dmat;
103
104 pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP,
105 &sc->sc_capoff, NULL);
106
107 ret = (*ap->ap_attach)(sc, pa, &agp_pchb_pa);
108 if (ret == 0)
109 printf(": aperture at 0x%lx, size 0x%lx",
110 (u_long)sc->sc_apaddr,
111 (u_long)AGP_GET_APERTURE(sc));
112 else {
113 sc->sc_chipc = NULL;
114 printf(": AGP GART");
115 }
116 }
117 }
118
119 paddr_t
120 agp_mmap(void *v, off_t off, int prot)
121 {
122 struct vga_config* vs = (struct vga_config*) v;
123 struct vga_pci_softc* sc = (struct vga_pci_softc *)vs->vc_softc;
124
125 if (sc->sc_apaddr) {
126
127 if (off > AGP_GET_APERTURE(sc))
128 return (-1);
129
130 return atop(sc->sc_apaddr + off);
131 }
132 return -1;
133 }
134
135 int
136 agp_ioctl(void *v, u_long cmd, caddr_t addr, int flag, struct proc *pb)
137 {
138 struct vga_config *vc = v;
139 struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc;
140 struct agp_memory *mem;
141 agp_info *info;
142 agp_setup *setup;
143 agp_allocate *alloc;
144 agp_bind *bind;
145 agp_unbind *unbind;
146 vsize_t size;
147 int error = 0;
148
149 if (sc->sc_methods == NULL || sc->sc_chipc == NULL)
150 return (ENXIO);
151
152 switch (cmd) {
153 case AGPIOC_INFO:
154 if (!sc->sc_chipc)
155 return (ENXIO);
156 case AGPIOC_ACQUIRE:
157 case AGPIOC_RELEASE:
158 case AGPIOC_SETUP:
159 case AGPIOC_ALLOCATE:
160 case AGPIOC_DEALLOCATE:
161 case AGPIOC_BIND:
162 case AGPIOC_UNBIND:
163 if (cmd != AGPIOC_INFO && !(flag & FWRITE))
164 return (EPERM);
165 break;
166 }
167 switch(cmd) {
168 case AGPIOC_INFO:
169 info = (agp_info *)addr;
170 bzero(info, sizeof *info);
171 info->bridge_id = sc->sc_id;
172 if (sc->sc_capoff != 0)
173 info->agp_mode = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
174 AGP_STATUS + sc->sc_capoff);
175 else
176 info->agp_mode = 0;
177 info->aper_base = sc->sc_apaddr;
178 info->aper_size = AGP_GET_APERTURE(sc) >> 20;
179 info->pg_total =
180 info->pg_system = sc->sc_maxmem >> AGP_PAGE_SHIFT;
181 info->pg_used = sc->sc_allocated >> AGP_PAGE_SHIFT;
182 break;
183
184 case AGPIOC_ACQUIRE:
185 if (sc->sc_state != AGP_ACQUIRE_FREE)
186 error = EBUSY;
187 else
188 sc->sc_state = AGP_ACQUIRE_USER;
189 break;
190
191 case AGPIOC_RELEASE:
192 if (sc->sc_state == AGP_ACQUIRE_FREE)
193 break;
194
195 if (sc->sc_state != AGP_ACQUIRE_USER) {
196 error = EBUSY;
197 break;
198 }
199
200
201
202
203
204 TAILQ_FOREACH(mem, &sc->sc_memory, am_link) {
205 if (mem->am_is_bound) {
206 printf("agp_release_helper: mem %d is bound\n",
207 mem->am_id);
208 AGP_UNBIND_MEMORY(sc, mem);
209 }
210 }
211 sc->sc_state = AGP_ACQUIRE_FREE;
212 break;
213
214 case AGPIOC_SETUP:
215 setup = (agp_setup *)addr;
216 error = AGP_ENABLE(sc, setup->agp_mode);
217 break;
218
219 case AGPIOC_ALLOCATE:
220 alloc = (agp_allocate *)addr;
221 size = alloc->pg_count << AGP_PAGE_SHIFT;
222 if (sc->sc_allocated + size > sc->sc_maxmem)
223 error = EINVAL;
224 else {
225 mem = AGP_ALLOC_MEMORY(sc, alloc->type, size);
226 if (mem) {
227 alloc->key = mem->am_id;
228 alloc->physical = mem->am_physical;
229 } else
230 error = ENOMEM;
231 }
232 break;
233
234 case AGPIOC_DEALLOCATE:
235 mem = agp_find_memory(sc, *(int *)addr);
236 if (mem)
237 AGP_FREE_MEMORY(sc, mem);
238 else
239 error = ENOENT;
240 break;
241
242 case AGPIOC_BIND:
243 bind = (agp_bind *)addr;
244 mem = agp_find_memory(sc, bind->key);
245 if (!mem)
246 error = ENOENT;
247 else
248 error = AGP_BIND_MEMORY(sc, mem,
249 bind->pg_start << AGP_PAGE_SHIFT);
250 break;
251
252 case AGPIOC_UNBIND:
253 unbind = (agp_unbind *)addr;
254 mem = agp_find_memory(sc, unbind->key);
255 if (!mem)
256 error = ENOENT;
257 else
258 error = AGP_UNBIND_MEMORY(sc, mem);
259 break;
260 default:
261 error = ENOTTY;
262 }
263
264 return (error);
265 }
266
267 #ifdef notyet
268 void
269 agp_close(void *v)
270 {
271 struct vga_config *vc = v;
272 struct vga_pci_softc *sc = (struct vga_pci_softc *)vc->vc_softc;
273 struct agp_memory *mem;
274
275
276
277
278
279 TAILQ_FOREACH(mem, &sc->sc_memory, am_link) {
280 if (mem->am_is_bound) {
281 AGP_UNBIND_MEMORY(sc, mem);
282 }
283 }
284
285 while (!TAILQ_EMPTY(&sc->sc_memory)) {
286 mem = TAILQ_FIRST(&sc->sc_memory);
287 AGP_FREE_MEMORY(sc, mem);
288 }
289
290 sc->sc_state = AGP_ACQUIRE_FREE;
291 }
292 #endif
293
294 struct agp_memory *
295 agp_find_memory(struct vga_pci_softc *sc, int id)
296 {
297 struct agp_memory *mem;
298
299 AGP_DPF("searching for memory block %d\n", id);
300 TAILQ_FOREACH(mem, &sc->sc_memory, am_link) {
301 AGP_DPF("considering memory block %d\n", mem->am_id);
302 if (mem->am_id == id)
303 return (mem);
304 }
305 return 0;
306 }
307
308 const struct agp_product *
309 agp_lookup(struct pci_attach_args *pa)
310 {
311 const struct agp_product *ap;
312
313 if (!agp_pchb_pa_set)
314 return (NULL);
315 agp_pchb_pa_set = 0;
316
317
318 for (ap = agp_products; ap->ap_attach != NULL; ap++)
319 if (ap->ap_vendor == PCI_VENDOR(pa->pa_id))
320 break;
321
322 if (ap->ap_attach == NULL)
323 return (NULL);
324
325
326 for (; ap->ap_attach != NULL; ap++) {
327
328 if (ap->ap_vendor != PCI_VENDOR(pa->pa_id))
329 return (NULL);
330
331 if (ap->ap_product == PCI_PRODUCT(pa->pa_id))
332 break;
333 if (ap->ap_product == (u_int32_t) -1)
334 break;
335 }
336
337 if (ap->ap_attach == NULL)
338 ap = NULL;
339
340 return (ap);
341 }
342
343 void
344 pciagp_set_pchb(struct pci_attach_args *pa)
345 {
346 if (!agp_pchb_pa_set) {
347 memcpy(&agp_pchb_pa, pa, sizeof *pa);
348 agp_pchb_pa_set++;
349 }
350 }
351
352 int
353 agp_map_aperture(struct vga_pci_softc *sc, u_int32_t bar, u_int32_t memtype)
354 {
355
356
357
358
359 if (pci_mapreg_info(sc->sc_pc, sc->sc_pcitag, bar,
360 memtype, &sc->sc_apaddr, &sc->sc_apsize,
361 &sc->sc_apflags) != 0)
362 return ENXIO;
363
364 return 0;
365 }
366
367 struct agp_gatt *
368 agp_alloc_gatt(struct vga_pci_softc *sc)
369 {
370 u_int32_t apsize = AGP_GET_APERTURE(sc);
371 u_int32_t entries = apsize >> AGP_PAGE_SHIFT;
372 struct agp_gatt *gatt;
373 int nseg;
374
375 gatt = malloc(sizeof(*gatt), M_DEVBUF, M_NOWAIT);
376 if (!gatt)
377 return (NULL);
378 bzero(gatt, sizeof(*gatt));
379 gatt->ag_entries = entries;
380
381 if (agp_alloc_dmamem(sc->sc_dmat, entries * sizeof(u_int32_t),
382 0, &gatt->ag_dmamap, (caddr_t *)&gatt->ag_virtual,
383 &gatt->ag_physical, &gatt->ag_dmaseg, 1, &nseg) != 0)
384 return NULL;
385
386 gatt->ag_size = entries * sizeof(u_int32_t);
387 memset(gatt->ag_virtual, 0, gatt->ag_size);
388 agp_flush_cache();
389
390 return gatt;
391 }
392
393 void
394 agp_free_gatt(struct vga_pci_softc *sc, struct agp_gatt *gatt)
395 {
396 agp_free_dmamem(sc->sc_dmat, gatt->ag_size, gatt->ag_dmamap,
397 (caddr_t)gatt->ag_virtual, &gatt->ag_dmaseg, 1);
398 free(gatt, M_DEVBUF);
399 }
400
401 int
402 agp_generic_detach(struct vga_pci_softc *sc)
403 {
404 lockmgr(&sc->sc_lock, LK_DRAIN, NULL);
405 agp_flush_cache();
406 return 0;
407 }
408
409 int
410 agp_generic_enable(struct vga_pci_softc *sc, u_int32_t mode)
411 {
412 pcireg_t tstatus, mstatus;
413 pcireg_t command;
414 int rq, sba, fw, rate, capoff;
415
416 if (pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP,
417 &capoff, NULL) == 0) {
418 printf("agp_generic_enable: not an AGP capable device\n");
419 return -1;
420 }
421
422 tstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
423 sc->sc_capoff + AGP_STATUS);
424 mstatus = pci_conf_read(sc->sc_pc, sc->sc_pcitag,
425 capoff + AGP_STATUS);
426
427
428 rq = AGP_MODE_GET_RQ(mode);
429 if (AGP_MODE_GET_RQ(tstatus) < rq)
430 rq = AGP_MODE_GET_RQ(tstatus);
431 if (AGP_MODE_GET_RQ(mstatus) < rq)
432 rq = AGP_MODE_GET_RQ(mstatus);
433
434
435 sba = (AGP_MODE_GET_SBA(tstatus)
436 & AGP_MODE_GET_SBA(mstatus)
437 & AGP_MODE_GET_SBA(mode));
438
439
440 fw = (AGP_MODE_GET_FW(tstatus)
441 & AGP_MODE_GET_FW(mstatus)
442 & AGP_MODE_GET_FW(mode));
443
444
445 rate = (AGP_MODE_GET_RATE(tstatus)
446 & AGP_MODE_GET_RATE(mstatus)
447 & AGP_MODE_GET_RATE(mode));
448 if (rate & AGP_MODE_RATE_4x)
449 rate = AGP_MODE_RATE_4x;
450 else if (rate & AGP_MODE_RATE_2x)
451 rate = AGP_MODE_RATE_2x;
452 else
453 rate = AGP_MODE_RATE_1x;
454
455
456 command = AGP_MODE_SET_RQ(0, rq);
457 command = AGP_MODE_SET_SBA(command, sba);
458 command = AGP_MODE_SET_FW(command, fw);
459 command = AGP_MODE_SET_RATE(command, rate);
460 command = AGP_MODE_SET_AGP(command, 1);
461 pci_conf_write(sc->sc_pc, sc->sc_pcitag,
462 sc->sc_capoff + AGP_COMMAND, command);
463 pci_conf_write(sc->sc_pc, sc->sc_pcitag, capoff + AGP_COMMAND, command);
464 return 0;
465 }
466
467 struct agp_memory *
468 agp_generic_alloc_memory(struct vga_pci_softc *sc, int type, vsize_t size)
469 {
470 struct agp_memory *mem;
471
472 if (type != 0) {
473 printf("agp_generic_alloc_memory: unsupported type %d\n", type);
474 return 0;
475 }
476
477 mem = malloc(sizeof *mem, M_DEVBUF, M_WAITOK);
478 if (mem == NULL)
479 return NULL;
480 bzero(mem, sizeof *mem);
481
482 if (bus_dmamap_create(sc->sc_dmat, size, size / PAGE_SIZE + 1,
483 size, 0, BUS_DMA_NOWAIT, &mem->am_dmamap) != 0) {
484 free(mem, M_DEVBUF);
485 return NULL;
486 }
487
488 mem->am_id = sc->sc_nextid++;
489 mem->am_size = size;
490 TAILQ_INSERT_TAIL(&sc->sc_memory, mem, am_link);
491 sc->sc_allocated += size;
492
493 return mem;
494 }
495
496 int
497 agp_generic_free_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
498 {
499 if (mem->am_is_bound)
500 return EBUSY;
501
502 sc->sc_allocated -= mem->am_size;
503 TAILQ_REMOVE(&sc->sc_memory, mem, am_link);
504 bus_dmamap_destroy(sc->sc_dmat, mem->am_dmamap);
505 free(mem, M_DEVBUF);
506 return 0;
507 }
508
509 int
510 agp_generic_bind_memory(struct vga_pci_softc *sc, struct agp_memory *mem,
511 off_t offset)
512 {
513 bus_dma_segment_t *segs, *seg;
514 bus_size_t done, j;
515 bus_addr_t pa;
516 off_t i, k;
517 int nseg, error;
518
519 lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL);
520
521 if (mem->am_is_bound) {
522 printf("AGP: memory already bound\n");
523 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
524 return EINVAL;
525 }
526
527 if (offset < 0
528 || (offset & (AGP_PAGE_SIZE - 1)) != 0
529 || offset + mem->am_size > AGP_GET_APERTURE(sc)) {
530 printf("AGP: binding memory at bad offset %#lx\n",
531 (unsigned long) offset);
532 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
533 return EINVAL;
534 }
535
536
537
538
539
540
541
542
543 nseg = (mem->am_size + PAGE_SIZE - 1) / PAGE_SIZE;
544 segs = malloc(nseg * sizeof *segs, M_DEVBUF, M_WAITOK);
545 if (segs == NULL) {
546 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
547 AGP_DPF("malloc segs (%u) failed\n",
548 nseg * sizeof *segs);
549 return ENOMEM;
550 }
551 if ((error = bus_dmamem_alloc(sc->sc_dmat, mem->am_size, PAGE_SIZE, 0,
552 segs, nseg, &mem->am_nseg, BUS_DMA_WAITOK)) != 0) {
553 free(segs, M_DEVBUF);
554 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
555 AGP_DPF("bus_dmamem_alloc failed %d\n", error);
556 return error;
557 }
558 if ((error = bus_dmamem_map(sc->sc_dmat, segs, mem->am_nseg,
559 mem->am_size, &mem->am_virtual, BUS_DMA_WAITOK)) != 0) {
560 bus_dmamem_free(sc->sc_dmat, segs, mem->am_nseg);
561 free(segs, M_DEVBUF);
562 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
563 AGP_DPF("bus_dmamem_map failed %d\n", error);
564 return error;
565 }
566 if ((error = bus_dmamap_load(sc->sc_dmat, mem->am_dmamap,
567 mem->am_virtual, mem->am_size, NULL,
568 BUS_DMA_WAITOK)) != 0) {
569 bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual,
570 mem->am_size);
571 bus_dmamem_free(sc->sc_dmat, segs, mem->am_nseg);
572 free(segs, M_DEVBUF);
573 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
574 AGP_DPF("bus_dmamap_load failed %d\n", error);
575 return error;
576 }
577 mem->am_dmaseg = segs;
578
579
580
581
582
583 done = 0;
584 for (i = 0; i < mem->am_dmamap->dm_nsegs; i++) {
585 seg = &mem->am_dmamap->dm_segs[i];
586
587
588
589
590
591
592 for (j = 0; j < seg->ds_len && (done + j) < mem->am_size;
593 j += AGP_PAGE_SIZE) {
594 pa = seg->ds_addr + j;
595 AGP_DPF("binding offset %#lx to pa %#lx\n",
596 (unsigned long)(offset + done + j),
597 (unsigned long)pa);
598 error = AGP_BIND_PAGE(sc, offset + done + j, pa);
599 if (error) {
600
601
602
603
604 for (k = 0; k < done + j; k += AGP_PAGE_SIZE)
605 AGP_UNBIND_PAGE(sc, offset + k);
606
607 bus_dmamap_unload(sc->sc_dmat, mem->am_dmamap);
608 bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual,
609 mem->am_size);
610 bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg,
611 mem->am_nseg);
612 free(mem->am_dmaseg, M_DEVBUF);
613 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
614 AGP_DPF("AGP_BIND_PAGE failed %d\n", error);
615 return error;
616 }
617 }
618 done += seg->ds_len;
619 }
620
621
622
623
624
625 agp_flush_cache();
626
627
628
629
630 AGP_FLUSH_TLB(sc);
631
632 mem->am_offset = offset;
633 mem->am_is_bound = 1;
634
635 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
636
637 return 0;
638 }
639
640 int
641 agp_generic_unbind_memory(struct vga_pci_softc *sc, struct agp_memory *mem)
642 {
643 int i;
644
645 lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL);
646
647 if (!mem->am_is_bound) {
648 printf("AGP: memory is not bound\n");
649 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
650 return EINVAL;
651 }
652
653
654
655
656
657
658 for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
659 AGP_UNBIND_PAGE(sc, mem->am_offset + i);
660
661 agp_flush_cache();
662 AGP_FLUSH_TLB(sc);
663
664 bus_dmamap_unload(sc->sc_dmat, mem->am_dmamap);
665 bus_dmamem_unmap(sc->sc_dmat, mem->am_virtual, mem->am_size);
666 bus_dmamem_free(sc->sc_dmat, mem->am_dmaseg, mem->am_nseg);
667
668 free(mem->am_dmaseg, M_DEVBUF);
669
670 mem->am_offset = 0;
671 mem->am_is_bound = 0;
672
673 lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
674
675 return 0;
676 }
677
678 int
679 agp_alloc_dmamem(bus_dma_tag_t tag, size_t size, int flags,
680 bus_dmamap_t *mapp, caddr_t *vaddr, bus_addr_t *baddr,
681 bus_dma_segment_t *seg, int nseg, int *rseg)
682
683 {
684 int error, level = 0;
685
686 if ((error = bus_dmamem_alloc(tag, size, PAGE_SIZE, 0,
687 seg, nseg, rseg, BUS_DMA_NOWAIT)) != 0)
688 goto out;
689 level++;
690
691 if ((error = bus_dmamem_map(tag, seg, *rseg, size, vaddr,
692 BUS_DMA_NOWAIT | flags)) != 0)
693 goto out;
694 level++;
695
696 if ((error = bus_dmamap_create(tag, size, *rseg, size, 0,
697 BUS_DMA_NOWAIT, mapp)) != 0)
698 goto out;
699 level++;
700
701 if ((error = bus_dmamap_load(tag, *mapp, *vaddr, size, NULL,
702 BUS_DMA_NOWAIT)) != 0)
703 goto out;
704
705 *baddr = (*mapp)->dm_segs[0].ds_addr;
706
707 return 0;
708 out:
709 switch (level) {
710 case 3:
711 bus_dmamap_destroy(tag, *mapp);
712
713 case 2:
714 bus_dmamem_unmap(tag, *vaddr, size);
715
716 case 1:
717 bus_dmamem_free(tag, seg, *rseg);
718 break;
719 default:
720 break;
721 }
722
723 return error;
724 }
725
726 void
727 agp_free_dmamem(bus_dma_tag_t tag, size_t size, bus_dmamap_t map,
728 caddr_t vaddr, bus_dma_segment_t *seg, int nseg)
729 {
730
731 bus_dmamap_unload(tag, map);
732 bus_dmamap_destroy(tag, map);
733 bus_dmamem_unmap(tag, vaddr, size);
734 bus_dmamem_free(tag, seg, nseg);
735 }