File:
[DragonFly] /
src /
sys /
dev /
agp /
agp.c
Revision
1.7:
download - view:
text,
annotated -
select for diffs
Thu Aug 7 21:16:48 2003 UTC (9 years, 9 months ago) by
dillon
Branches:
MAIN
CVS tags:
HEAD
kernel tree reorganization stage 1: Major cvs repository work (not logged as
commits) plus a major reworking of the #include's to accomodate the
relocations.
* CVS repository files manually moved. Old directories left intact
and empty (temporary).
* Reorganize all filesystems into vfs/, most devices into dev/,
sub-divide devices by function.
* Begin to move device-specific architecture files to the device
subdirs rather then throwing them all into, e.g. i386/include
* Reorganize files related to system busses, placing the related code
in a new bus/ directory. Also move cam to bus/cam though this may
not have been the best idea in retrospect.
* Reorganize emulation code and place it in a new emulation/ directory.
* Remove the -I- compiler option in order to allow #include file
localization, rename all config generated X.h files to use_X.h to
clean up the conflicts.
* Remove /usr/src/include (or /usr/include) dependancies during the
kernel build, beyond what is normally needed to compile helper
programs.
* Make config create 'machine' softlinks for architecture specific
directories outside of the standard <arch>/include.
* Bump the config rev.
WARNING! after this commit /usr/include and /usr/src/sys/compile/*
should be regenerated from scratch.
1: /*-
2: * Copyright (c) 2000 Doug Rabson
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24: * SUCH DAMAGE.
25: *
26: * $FreeBSD: src/sys/pci/agp.c,v 1.3.2.4 2002/08/11 19:58:12 alc Exp $
27: * $DragonFly: src/sys/dev/agp/agp.c,v 1.7 2003/08/07 21:16:48 dillon Exp $
28: */
29:
30: #include "opt_bus.h"
31: #include "opt_pci.h"
32:
33: #include <sys/param.h>
34: #include <sys/systm.h>
35: #include <sys/malloc.h>
36: #include <sys/kernel.h>
37: #include <sys/bus.h>
38: #include <sys/conf.h>
39: #include <sys/ioccom.h>
40: #include <sys/agpio.h>
41: #include <sys/lock.h>
42: #include <sys/proc.h>
43:
44: #include <bus/pci/pcivar.h>
45: #include <bus/pci/pcireg.h>
46: #include "agppriv.h"
47: #include "agpvar.h"
48: #include "agpreg.h"
49:
50: #include <vm/vm.h>
51: #include <vm/vm_object.h>
52: #include <vm/vm_page.h>
53: #include <vm/vm_pageout.h>
54: #include <vm/pmap.h>
55:
56: #include <machine/md_var.h>
57: #include <machine/bus.h>
58: #include <machine/resource.h>
59: #include <sys/rman.h>
60:
61: MODULE_VERSION(agp, 1);
62:
63: MALLOC_DEFINE(M_AGP, "agp", "AGP data structures");
64:
65: #define CDEV_MAJOR 148
66: /* agp_drv.c */
67: static d_open_t agp_open;
68: static d_close_t agp_close;
69: static d_ioctl_t agp_ioctl;
70: static d_mmap_t agp_mmap;
71:
72: static struct cdevsw agp_cdevsw = {
73: /* name */ "agp",
74: /* maj */ CDEV_MAJOR,
75: /* flags */ D_TTY,
76: /* port */ NULL,
77: /* autoq */ 0,
78:
79: /* open */ agp_open,
80: /* close */ agp_close,
81: /* read */ noread,
82: /* write */ nowrite,
83: /* ioctl */ agp_ioctl,
84: /* poll */ nopoll,
85: /* mmap */ agp_mmap,
86: /* strategy */ nostrategy,
87: /* dump */ nodump,
88: /* psize */ nopsize
89: };
90:
91: static devclass_t agp_devclass;
92: #define KDEV2DEV(kdev) devclass_get_device(agp_devclass, minor(kdev))
93:
94: /* Helper functions for implementing chipset mini drivers. */
95:
96: void
97: agp_flush_cache()
98: {
99: #ifdef __i386__
100: wbinvd();
101: #endif
102: }
103:
104: u_int8_t
105: agp_find_caps(device_t dev)
106: {
107: u_int32_t status;
108: u_int8_t ptr, next;
109:
110: /*
111: * Check the CAP_LIST bit of the PCI status register first.
112: */
113: status = pci_read_config(dev, PCIR_STATUS, 2);
114: if (!(status & 0x10))
115: return 0;
116:
117: /*
118: * Traverse the capabilities list.
119: */
120: for (ptr = pci_read_config(dev, AGP_CAPPTR, 1);
121: ptr != 0;
122: ptr = next) {
123: u_int32_t capid = pci_read_config(dev, ptr, 4);
124: next = AGP_CAPID_GET_NEXT_PTR(capid);
125:
126: /*
127: * If this capability entry ID is 2, then we are done.
128: */
129: if (AGP_CAPID_GET_CAP_ID(capid) == 2)
130: return ptr;
131: }
132:
133: return 0;
134: }
135:
136: /*
137: * Find an AGP display device (if any).
138: */
139: static device_t
140: agp_find_display(void)
141: {
142: devclass_t pci = devclass_find("pci");
143: device_t bus, dev = 0;
144: device_t *kids;
145: int busnum, numkids, i;
146:
147: for (busnum = 0; busnum < devclass_get_maxunit(pci); busnum++) {
148: bus = devclass_get_device(pci, busnum);
149: if (!bus)
150: continue;
151: device_get_children(bus, &kids, &numkids);
152: for (i = 0; i < numkids; i++) {
153: dev = kids[i];
154: if (pci_get_class(dev) == PCIC_DISPLAY
155: && pci_get_subclass(dev) == PCIS_DISPLAY_VGA)
156: if (agp_find_caps(dev)) {
157: free(kids, M_TEMP);
158: return dev;
159: }
160:
161: }
162: free(kids, M_TEMP);
163: }
164:
165: return 0;
166: }
167:
168: struct agp_gatt *
169: agp_alloc_gatt(device_t dev)
170: {
171: u_int32_t apsize = AGP_GET_APERTURE(dev);
172: u_int32_t entries = apsize >> AGP_PAGE_SHIFT;
173: struct agp_gatt *gatt;
174:
175: if (bootverbose)
176: device_printf(dev,
177: "allocating GATT for aperture of size %dM\n",
178: apsize / (1024*1024));
179:
180: gatt = malloc(sizeof(struct agp_gatt), M_AGP, M_NOWAIT);
181: if (!gatt)
182: return 0;
183:
184: gatt->ag_entries = entries;
185: gatt->ag_virtual = contigmalloc(entries * sizeof(u_int32_t), M_AGP, 0,
186: 0, ~0, PAGE_SIZE, 0);
187: if (!gatt->ag_virtual) {
188: if (bootverbose)
189: device_printf(dev, "contiguous allocation failed\n");
190: free(gatt, M_AGP);
191: return 0;
192: }
193: bzero(gatt->ag_virtual, entries * sizeof(u_int32_t));
194: gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
195: agp_flush_cache();
196:
197: return gatt;
198: }
199:
200: void
201: agp_free_gatt(struct agp_gatt *gatt)
202: {
203: contigfree(gatt->ag_virtual,
204: gatt->ag_entries * sizeof(u_int32_t), M_AGP);
205: free(gatt, M_AGP);
206: }
207:
208: static 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: int
222: agp_generic_attach(device_t dev)
223: {
224: struct agp_softc *sc = device_get_softc(dev);
225: int rid, memsize, i;
226:
227: /*
228: * Find and map the aperture.
229: */
230: rid = AGP_APBASE;
231: sc->as_aperture = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
232: 0, ~0, 1, RF_ACTIVE);
233: if (!sc->as_aperture)
234: return ENOMEM;
235:
236: /*
237: * Work out an upper bound for agp memory allocation. This
238: * uses a heurisitc table from the Linux driver.
239: */
240: memsize = ptoa(Maxmem) >> 20;
241: for (i = 0; i < agp_max_size; i++) {
242: if (memsize <= agp_max[i][0])
243: break;
244: }
245: if (i == agp_max_size) i = agp_max_size - 1;
246: sc->as_maxmem = agp_max[i][1] << 20U;
247:
248: /*
249: * The lock is used to prevent re-entry to
250: * agp_generic_bind_memory() since that function can sleep.
251: */
252: lockinit(&sc->as_lock, PCATCH, "agplk", 0, 0);
253:
254: /*
255: * Initialise stuff for the userland device.
256: */
257: agp_devclass = devclass_find("agp");
258: TAILQ_INIT(&sc->as_memory);
259: sc->as_nextid = 1;
260:
261: sc->as_devnode = make_dev(&agp_cdevsw,
262: device_get_unit(dev),
263: UID_ROOT,
264: GID_WHEEL,
265: 0600,
266: "agpgart");
267:
268: return 0;
269: }
270:
271: int
272: agp_generic_detach(device_t dev)
273: {
274: struct agp_softc *sc = device_get_softc(dev);
275: bus_release_resource(dev, SYS_RES_MEMORY, AGP_APBASE, sc->as_aperture);
276: lockmgr(&sc->as_lock, LK_DRAIN, 0, curthread); /* XXX */
277: destroy_dev(sc->as_devnode);
278: agp_flush_cache();
279: return 0;
280: }
281:
282: int
283: agp_generic_enable(device_t dev, u_int32_t mode)
284: {
285: device_t mdev = agp_find_display();
286: u_int32_t tstatus, mstatus;
287: u_int32_t command;
288: int rq, sba, fw, rate;;
289:
290: if (!mdev) {
291: AGP_DPF("can't find display\n");
292: return ENXIO;
293: }
294:
295: tstatus = pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
296: mstatus = pci_read_config(mdev, agp_find_caps(mdev) + AGP_STATUS, 4);
297:
298: /* Set RQ to the min of mode, tstatus and mstatus */
299: rq = AGP_MODE_GET_RQ(mode);
300: if (AGP_MODE_GET_RQ(tstatus) < rq)
301: rq = AGP_MODE_GET_RQ(tstatus);
302: if (AGP_MODE_GET_RQ(mstatus) < rq)
303: rq = AGP_MODE_GET_RQ(mstatus);
304:
305: /* Set SBA if all three can deal with SBA */
306: sba = (AGP_MODE_GET_SBA(tstatus)
307: & AGP_MODE_GET_SBA(mstatus)
308: & AGP_MODE_GET_SBA(mode));
309:
310: /* Similar for FW */
311: fw = (AGP_MODE_GET_FW(tstatus)
312: & AGP_MODE_GET_FW(mstatus)
313: & AGP_MODE_GET_FW(mode));
314:
315: /* Figure out the max rate */
316: rate = (AGP_MODE_GET_RATE(tstatus)
317: & AGP_MODE_GET_RATE(mstatus)
318: & AGP_MODE_GET_RATE(mode));
319: if (rate & AGP_MODE_RATE_4x)
320: rate = AGP_MODE_RATE_4x;
321: else if (rate & AGP_MODE_RATE_2x)
322: rate = AGP_MODE_RATE_2x;
323: else
324: rate = AGP_MODE_RATE_1x;
325:
326: /* Construct the new mode word and tell the hardware */
327: command = AGP_MODE_SET_RQ(0, rq);
328: command = AGP_MODE_SET_SBA(command, sba);
329: command = AGP_MODE_SET_FW(command, fw);
330: command = AGP_MODE_SET_RATE(command, rate);
331: command = AGP_MODE_SET_AGP(command, 1);
332: pci_write_config(dev, agp_find_caps(dev) + AGP_COMMAND, command, 4);
333: pci_write_config(mdev, agp_find_caps(mdev) + AGP_COMMAND, command, 4);
334:
335: return 0;
336: }
337:
338: struct agp_memory *
339: agp_generic_alloc_memory(device_t dev, int type, vm_size_t size)
340: {
341: struct agp_softc *sc = device_get_softc(dev);
342: struct agp_memory *mem;
343:
344: if ((size & (AGP_PAGE_SIZE - 1)) != 0)
345: return 0;
346:
347: if (sc->as_allocated + size > sc->as_maxmem)
348: return 0;
349:
350: if (type != 0) {
351: printf("agp_generic_alloc_memory: unsupported type %d\n",
352: type);
353: return 0;
354: }
355:
356: mem = malloc(sizeof *mem, M_AGP, M_WAITOK);
357: mem->am_id = sc->as_nextid++;
358: mem->am_size = size;
359: mem->am_type = 0;
360: mem->am_obj = vm_object_allocate(OBJT_DEFAULT, atop(round_page(size)));
361: mem->am_physical = 0;
362: mem->am_offset = 0;
363: mem->am_is_bound = 0;
364: TAILQ_INSERT_TAIL(&sc->as_memory, mem, am_link);
365: sc->as_allocated += size;
366:
367: return mem;
368: }
369:
370: int
371: agp_generic_free_memory(device_t dev, struct agp_memory *mem)
372: {
373: struct agp_softc *sc = device_get_softc(dev);
374:
375: if (mem->am_is_bound)
376: return EBUSY;
377:
378: sc->as_allocated -= mem->am_size;
379: TAILQ_REMOVE(&sc->as_memory, mem, am_link);
380: vm_object_deallocate(mem->am_obj);
381: free(mem, M_AGP);
382: return 0;
383: }
384:
385: int
386: agp_generic_bind_memory(device_t dev, struct agp_memory *mem,
387: vm_offset_t offset)
388: {
389: struct agp_softc *sc = device_get_softc(dev);
390: vm_offset_t i, j, k;
391: vm_page_t m;
392: int error;
393:
394: lockmgr(&sc->as_lock, LK_EXCLUSIVE, 0, curthread); /* XXX */
395:
396: if (mem->am_is_bound) {
397: device_printf(dev, "memory already bound\n");
398: return EINVAL;
399: }
400:
401: if (offset < 0
402: || (offset & (AGP_PAGE_SIZE - 1)) != 0
403: || offset + mem->am_size > AGP_GET_APERTURE(dev)) {
404: device_printf(dev, "binding memory at bad offset %#x\n",
405: (int) offset);
406: return EINVAL;
407: }
408:
409: /*
410: * Bind the individual pages and flush the chipset's
411: * TLB.
412: *
413: * XXX Presumably, this needs to be the pci address on alpha
414: * (i.e. use alpha_XXX_dmamap()). I don't have access to any
415: * alpha AGP hardware to check.
416: */
417: for (i = 0; i < mem->am_size; i += PAGE_SIZE) {
418: /*
419: * Find a page from the object and wire it
420: * down. This page will be mapped using one or more
421: * entries in the GATT (assuming that PAGE_SIZE >=
422: * AGP_PAGE_SIZE. If this is the first call to bind,
423: * the pages will be allocated and zeroed.
424: */
425: m = vm_page_grab(mem->am_obj, OFF_TO_IDX(i),
426: VM_ALLOC_ZERO | VM_ALLOC_RETRY);
427: if ((m->flags & PG_ZERO) == 0)
428: vm_page_zero_fill(m);
429: AGP_DPF("found page pa=%#x\n", VM_PAGE_TO_PHYS(m));
430: vm_page_wire(m);
431:
432: /*
433: * Install entries in the GATT, making sure that if
434: * AGP_PAGE_SIZE < PAGE_SIZE and mem->am_size is not
435: * aligned to PAGE_SIZE, we don't modify too many GATT
436: * entries.
437: */
438: for (j = 0; j < PAGE_SIZE && i + j < mem->am_size;
439: j += AGP_PAGE_SIZE) {
440: vm_offset_t pa = VM_PAGE_TO_PHYS(m) + j;
441: AGP_DPF("binding offset %#x to pa %#x\n",
442: offset + i + j, pa);
443: error = AGP_BIND_PAGE(dev, offset + i + j, pa);
444: if (error) {
445: /*
446: * Bail out. Reverse all the mappings
447: * and unwire the pages.
448: */
449: vm_page_wakeup(m);
450: for (k = 0; k < i + j; k += AGP_PAGE_SIZE)
451: AGP_UNBIND_PAGE(dev, offset + k);
452: for (k = 0; k <= i; k += PAGE_SIZE) {
453: m = vm_page_lookup(mem->am_obj,
454: OFF_TO_IDX(k));
455: vm_page_unwire(m, 0);
456: }
457: lockmgr(&sc->as_lock, LK_RELEASE, 0, curthread); /* XXX */
458: return error;
459: }
460: }
461: vm_page_wakeup(m);
462: }
463:
464: /*
465: * Flush the cpu cache since we are providing a new mapping
466: * for these pages.
467: */
468: agp_flush_cache();
469:
470: /*
471: * Make sure the chipset gets the new mappings.
472: */
473: AGP_FLUSH_TLB(dev);
474:
475: mem->am_offset = offset;
476: mem->am_is_bound = 1;
477:
478: lockmgr(&sc->as_lock, LK_RELEASE, 0, curthread); /* XXX */
479:
480: return 0;
481: }
482:
483: int
484: agp_generic_unbind_memory(device_t dev, struct agp_memory *mem)
485: {
486: struct agp_softc *sc = device_get_softc(dev);
487: vm_page_t m;
488: int i;
489:
490: lockmgr(&sc->as_lock, LK_EXCLUSIVE, 0, curthread); /* XXX */
491:
492: if (!mem->am_is_bound) {
493: device_printf(dev, "memory is not bound\n");
494: return EINVAL;
495: }
496:
497:
498: /*
499: * Unbind the individual pages and flush the chipset's
500: * TLB. Unwire the pages so they can be swapped.
501: */
502: for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
503: AGP_UNBIND_PAGE(dev, mem->am_offset + i);
504: for (i = 0; i < mem->am_size; i += PAGE_SIZE) {
505: m = vm_page_lookup(mem->am_obj, atop(i));
506: vm_page_unwire(m, 0);
507: }
508:
509: agp_flush_cache();
510: AGP_FLUSH_TLB(dev);
511:
512: mem->am_offset = 0;
513: mem->am_is_bound = 0;
514:
515: lockmgr(&sc->as_lock, LK_RELEASE, 0, curthread); /* XXX */
516:
517: return 0;
518: }
519:
520: /* Helper functions for implementing user/kernel api */
521:
522: static int
523: agp_acquire_helper(device_t dev, enum agp_acquire_state state)
524: {
525: struct agp_softc *sc = device_get_softc(dev);
526:
527: if (sc->as_state != AGP_ACQUIRE_FREE)
528: return EBUSY;
529: sc->as_state = state;
530:
531: return 0;
532: }
533:
534: static int
535: agp_release_helper(device_t dev, enum agp_acquire_state state)
536: {
537: struct agp_softc *sc = device_get_softc(dev);
538:
539: if (sc->as_state == AGP_ACQUIRE_FREE)
540: return 0;
541:
542: if (sc->as_state != state)
543: return EBUSY;
544:
545: sc->as_state = AGP_ACQUIRE_FREE;
546: return 0;
547: }
548:
549: static struct agp_memory *
550: agp_find_memory(device_t dev, int id)
551: {
552: struct agp_softc *sc = device_get_softc(dev);
553: struct agp_memory *mem;
554:
555: AGP_DPF("searching for memory block %d\n", id);
556: TAILQ_FOREACH(mem, &sc->as_memory, am_link) {
557: AGP_DPF("considering memory block %d\n", mem->am_id);
558: if (mem->am_id == id)
559: return mem;
560: }
561: return 0;
562: }
563:
564: /* Implementation of the userland ioctl api */
565:
566: static int
567: agp_info_user(device_t dev, agp_info *info)
568: {
569: struct agp_softc *sc = device_get_softc(dev);
570:
571: bzero(info, sizeof *info);
572: info->bridge_id = pci_get_devid(dev);
573: info->agp_mode =
574: pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
575: info->aper_base = rman_get_start(sc->as_aperture);
576: info->aper_size = AGP_GET_APERTURE(dev) >> 20;
577: info->pg_total = info->pg_system = sc->as_maxmem >> AGP_PAGE_SHIFT;
578: info->pg_used = sc->as_allocated >> AGP_PAGE_SHIFT;
579:
580: return 0;
581: }
582:
583: static int
584: agp_setup_user(device_t dev, agp_setup *setup)
585: {
586: return AGP_ENABLE(dev, setup->agp_mode);
587: }
588:
589: static int
590: agp_allocate_user(device_t dev, agp_allocate *alloc)
591: {
592: struct agp_memory *mem;
593:
594: mem = AGP_ALLOC_MEMORY(dev,
595: alloc->type,
596: alloc->pg_count << AGP_PAGE_SHIFT);
597: if (mem) {
598: alloc->key = mem->am_id;
599: alloc->physical = mem->am_physical;
600: return 0;
601: } else {
602: return ENOMEM;
603: }
604: }
605:
606: static int
607: agp_deallocate_user(device_t dev, int id)
608: {
609: struct agp_memory *mem = agp_find_memory(dev, id);;
610:
611: if (mem) {
612: AGP_FREE_MEMORY(dev, mem);
613: return 0;
614: } else {
615: return ENOENT;
616: }
617: }
618:
619: static int
620: agp_bind_user(device_t dev, agp_bind *bind)
621: {
622: struct agp_memory *mem = agp_find_memory(dev, bind->key);
623:
624: if (!mem)
625: return ENOENT;
626:
627: return AGP_BIND_MEMORY(dev, mem, bind->pg_start << AGP_PAGE_SHIFT);
628: }
629:
630: static int
631: agp_unbind_user(device_t dev, agp_unbind *unbind)
632: {
633: struct agp_memory *mem = agp_find_memory(dev, unbind->key);
634:
635: if (!mem)
636: return ENOENT;
637:
638: return AGP_UNBIND_MEMORY(dev, mem);
639: }
640:
641: static int
642: agp_open(dev_t kdev, int oflags, int devtype, struct thread *td)
643: {
644: device_t dev = KDEV2DEV(kdev);
645: struct agp_softc *sc = device_get_softc(dev);
646:
647: if (!sc->as_isopen) {
648: sc->as_isopen = 1;
649: device_busy(dev);
650: }
651:
652: return 0;
653: }
654:
655: static int
656: agp_close(dev_t kdev, int fflag, int devtype, struct thread *td)
657: {
658: device_t dev = KDEV2DEV(kdev);
659: struct agp_softc *sc = device_get_softc(dev);
660: struct agp_memory *mem;
661:
662: /*
663: * Clear the GATT and force release on last close
664: */
665: while ((mem = TAILQ_FIRST(&sc->as_memory)) != 0) {
666: if (mem->am_is_bound)
667: AGP_UNBIND_MEMORY(dev, mem);
668: AGP_FREE_MEMORY(dev, mem);
669: }
670: if (sc->as_state == AGP_ACQUIRE_USER)
671: agp_release_helper(dev, AGP_ACQUIRE_USER);
672: sc->as_isopen = 0;
673: device_unbusy(dev);
674:
675: return 0;
676: }
677:
678: static int
679: agp_ioctl(dev_t kdev, u_long cmd, caddr_t data, int fflag, struct thread *td)
680: {
681: device_t dev = KDEV2DEV(kdev);
682:
683: switch (cmd) {
684: case AGPIOC_INFO:
685: return agp_info_user(dev, (agp_info *) data);
686:
687: case AGPIOC_ACQUIRE:
688: return agp_acquire_helper(dev, AGP_ACQUIRE_USER);
689:
690: case AGPIOC_RELEASE:
691: return agp_release_helper(dev, AGP_ACQUIRE_USER);
692:
693: case AGPIOC_SETUP:
694: return agp_setup_user(dev, (agp_setup *)data);
695:
696: case AGPIOC_ALLOCATE:
697: return agp_allocate_user(dev, (agp_allocate *)data);
698:
699: case AGPIOC_DEALLOCATE:
700: return agp_deallocate_user(dev, *(int *) data);
701:
702: case AGPIOC_BIND:
703: return agp_bind_user(dev, (agp_bind *)data);
704:
705: case AGPIOC_UNBIND:
706: return agp_unbind_user(dev, (agp_unbind *)data);
707:
708: }
709:
710: return EINVAL;
711: }
712:
713: static int
714: agp_mmap(dev_t kdev, vm_offset_t offset, int prot)
715: {
716: device_t dev = KDEV2DEV(kdev);
717: struct agp_softc *sc = device_get_softc(dev);
718:
719: if (offset > AGP_GET_APERTURE(dev))
720: return -1;
721: return atop(rman_get_start(sc->as_aperture) + offset);
722: }
723:
724: /* Implementation of the kernel api */
725:
726: device_t
727: agp_find_device()
728: {
729: if (!agp_devclass)
730: return 0;
731: return devclass_get_device(agp_devclass, 0);
732: }
733:
734: enum agp_acquire_state
735: agp_state(device_t dev)
736: {
737: struct agp_softc *sc = device_get_softc(dev);
738: return sc->as_state;
739: }
740:
741: void
742: agp_get_info(device_t dev, struct agp_info *info)
743: {
744: struct agp_softc *sc = device_get_softc(dev);
745:
746: info->ai_mode =
747: pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
748: info->ai_aperture_base = rman_get_start(sc->as_aperture);
749: info->ai_aperture_size = (rman_get_end(sc->as_aperture)
750: - rman_get_start(sc->as_aperture)) + 1;
751: info->ai_aperture_va = (vm_offset_t) rman_get_virtual(sc->as_aperture);
752: info->ai_memory_allowed = sc->as_maxmem;
753: info->ai_memory_used = sc->as_allocated;
754: }
755:
756: int
757: agp_acquire(device_t dev)
758: {
759: return agp_acquire_helper(dev, AGP_ACQUIRE_KERNEL);
760: }
761:
762: int
763: agp_release(device_t dev)
764: {
765: return agp_release_helper(dev, AGP_ACQUIRE_KERNEL);
766: }
767:
768: int
769: agp_enable(device_t dev, u_int32_t mode)
770: {
771: return AGP_ENABLE(dev, mode);
772: }
773:
774: void *agp_alloc_memory(device_t dev, int type, vm_size_t bytes)
775: {
776: return (void *) AGP_ALLOC_MEMORY(dev, type, bytes);
777: }
778:
779: void agp_free_memory(device_t dev, void *handle)
780: {
781: struct agp_memory *mem = (struct agp_memory *) handle;
782: AGP_FREE_MEMORY(dev, mem);
783: }
784:
785: int agp_bind_memory(device_t dev, void *handle, vm_offset_t offset)
786: {
787: struct agp_memory *mem = (struct agp_memory *) handle;
788: return AGP_BIND_MEMORY(dev, mem, offset);
789: }
790:
791: int agp_unbind_memory(device_t dev, void *handle)
792: {
793: struct agp_memory *mem = (struct agp_memory *) handle;
794: return AGP_UNBIND_MEMORY(dev, mem);
795: }
796:
797: void agp_memory_info(device_t dev, void *handle, struct
798: agp_memory_info *mi)
799: {
800: struct agp_memory *mem = (struct agp_memory *) handle;
801:
802: mi->ami_size = mem->am_size;
803: mi->ami_physical = mem->am_physical;
804: mi->ami_offset = mem->am_offset;
805: mi->ami_is_bound = mem->am_is_bound;
806: }