File:
[DragonFly] /
src /
sys /
dev /
agp /
agp.c
Revision
1.8:
download - view:
text,
annotated -
select for diffs
Tue Dec 9 19:40:56 2003 UTC (9 years, 5 months ago) by
dillon
Branches:
MAIN
CVS tags:
HEAD
This patch adds a bunch of stuff from FreeBSD5. It consistantly makes
vendor specific drivers depend on agp, consistantly checks the gart size
!= 0, changes agp_generic_enable to the FreeBSD5 function, initializing
the device as v2 or v3 accordingly, syncs up agpio.h, and adds a couple
PCI Ids from FreeBSD5.
Submitted-by: Craig Dooley <cd5697@albany.edu>
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.8 2003/12/09 19:40:56 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: if (entries == 0) {
181: device_printf(dev, "bad aperture size\n");
182: return NULL;
183: }
184:
185: gatt = malloc(sizeof(struct agp_gatt), M_AGP, M_NOWAIT);
186: if (!gatt)
187: return 0;
188:
189: gatt->ag_entries = entries;
190: gatt->ag_virtual = contigmalloc(entries * sizeof(u_int32_t), M_AGP, 0,
191: 0, ~0, PAGE_SIZE, 0);
192: if (!gatt->ag_virtual) {
193: if (bootverbose)
194: device_printf(dev, "contiguous allocation failed\n");
195: free(gatt, M_AGP);
196: return 0;
197: }
198: bzero(gatt->ag_virtual, entries * sizeof(u_int32_t));
199: gatt->ag_physical = vtophys((vm_offset_t) gatt->ag_virtual);
200: agp_flush_cache();
201:
202: return gatt;
203: }
204:
205: void
206: agp_free_gatt(struct agp_gatt *gatt)
207: {
208: contigfree(gatt->ag_virtual,
209: gatt->ag_entries * sizeof(u_int32_t), M_AGP);
210: free(gatt, M_AGP);
211: }
212:
213: static int agp_max[][2] = {
214: {0, 0},
215: {32, 4},
216: {64, 28},
217: {128, 96},
218: {256, 204},
219: {512, 440},
220: {1024, 942},
221: {2048, 1920},
222: {4096, 3932}
223: };
224: #define agp_max_size (sizeof(agp_max) / sizeof(agp_max[0]))
225:
226: int
227: agp_generic_attach(device_t dev)
228: {
229: struct agp_softc *sc = device_get_softc(dev);
230: int rid, memsize, i;
231:
232: /*
233: * Find and map the aperture.
234: */
235: rid = AGP_APBASE;
236: sc->as_aperture = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
237: 0, ~0, 1, RF_ACTIVE);
238: if (!sc->as_aperture)
239: return ENOMEM;
240:
241: /*
242: * Work out an upper bound for agp memory allocation. This
243: * uses a heurisitc table from the Linux driver.
244: */
245: memsize = ptoa(Maxmem) >> 20;
246: for (i = 0; i < agp_max_size; i++) {
247: if (memsize <= agp_max[i][0])
248: break;
249: }
250: if (i == agp_max_size) i = agp_max_size - 1;
251: sc->as_maxmem = agp_max[i][1] << 20U;
252:
253: /*
254: * The lock is used to prevent re-entry to
255: * agp_generic_bind_memory() since that function can sleep.
256: */
257: lockinit(&sc->as_lock, PCATCH, "agplk", 0, 0);
258:
259: /*
260: * Initialise stuff for the userland device.
261: */
262: agp_devclass = devclass_find("agp");
263: TAILQ_INIT(&sc->as_memory);
264: sc->as_nextid = 1;
265:
266: sc->as_devnode = make_dev(&agp_cdevsw,
267: device_get_unit(dev),
268: UID_ROOT,
269: GID_WHEEL,
270: 0600,
271: "agpgart");
272:
273: return 0;
274: }
275:
276: int
277: agp_generic_detach(device_t dev)
278: {
279: struct agp_softc *sc = device_get_softc(dev);
280: bus_release_resource(dev, SYS_RES_MEMORY, AGP_APBASE, sc->as_aperture);
281: lockmgr(&sc->as_lock, LK_DRAIN, 0, curthread); /* XXX */
282: destroy_dev(sc->as_devnode);
283: agp_flush_cache();
284: return 0;
285: }
286:
287: /*
288: * This does the enable logic for v3, with the same topology
289: * restrictions as in place for v2 -- one bus, one device on the bus.
290: */
291: static int
292: agp_v3_enable(device_t dev, device_t mdev, u_int32_t mode)
293: {
294: u_int32_t tstatus, mstatus;
295: u_int32_t command;
296: int rq, sba, fw, rate, arqsz, cal;
297:
298: tstatus = pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
299: mstatus = pci_read_config(mdev, agp_find_caps(mdev) + AGP_STATUS, 4);
300:
301: /* Set RQ to the min of mode, tstatus and mstatus */
302: rq = AGP_MODE_GET_RQ(mode);
303: if (AGP_MODE_GET_RQ(tstatus) < rq)
304: rq = AGP_MODE_GET_RQ(tstatus);
305: if (AGP_MODE_GET_RQ(mstatus) < rq)
306: rq = AGP_MODE_GET_RQ(mstatus);
307:
308: /*
309: * ARQSZ - Set the value to the maximum one.
310: * Don't allow the mode register to override values.
311: */
312: arqsz = AGP_MODE_GET_ARQSZ(mode);
313: if (AGP_MODE_GET_ARQSZ(tstatus) > rq)
314: rq = AGP_MODE_GET_ARQSZ(tstatus);
315: if (AGP_MODE_GET_ARQSZ(mstatus) > rq)
316: rq = AGP_MODE_GET_ARQSZ(mstatus);
317:
318: /* Calibration cycle - don't allow override by mode register */
319: cal = AGP_MODE_GET_CAL(tstatus);
320: if (AGP_MODE_GET_CAL(mstatus) < cal)
321: cal = AGP_MODE_GET_CAL(mstatus);
322:
323: /* SBA must be supported for AGP v3. */
324: sba = 1;
325:
326: /* Set FW if all three support it. */
327: fw = (AGP_MODE_GET_FW(tstatus)
328: & AGP_MODE_GET_FW(mstatus)
329: & AGP_MODE_GET_FW(mode));
330:
331: /* Figure out the max rate */
332: rate = (AGP_MODE_GET_RATE(tstatus)
333: & AGP_MODE_GET_RATE(mstatus)
334: & AGP_MODE_GET_RATE(mode));
335: if (rate & AGP_MODE_V3_RATE_8x)
336: rate = AGP_MODE_V3_RATE_8x;
337: else
338: rate = AGP_MODE_V3_RATE_4x;
339: if (bootverbose)
340: device_printf(dev, "Setting AGP v3 mode %d\n", rate * 4);
341:
342: pci_write_config(dev, agp_find_caps(dev) + AGP_COMMAND, 0, 4);
343:
344: /* Construct the new mode word and tell the hardware */
345: command = AGP_MODE_SET_RQ(0, rq);
346: command = AGP_MODE_SET_ARQSZ(command, arqsz);
347: command = AGP_MODE_SET_CAL(command, cal);
348: command = AGP_MODE_SET_SBA(command, sba);
349: command = AGP_MODE_SET_FW(command, fw);
350: command = AGP_MODE_SET_RATE(command, rate);
351: command = AGP_MODE_SET_AGP(command, 1);
352: pci_write_config(dev, agp_find_caps(dev) + AGP_COMMAND, command, 4);
353: pci_write_config(mdev, agp_find_caps(mdev) + AGP_COMMAND, command, 4);
354:
355: return 0;
356: }
357:
358: static int
359: agp_v2_enable(device_t dev, device_t mdev, u_int32_t mode)
360: {
361: u_int32_t tstatus, mstatus;
362: u_int32_t command;
363: int rq, sba, fw, rate;
364:
365: tstatus = pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
366: mstatus = pci_read_config(mdev, agp_find_caps(mdev) + AGP_STATUS, 4);
367:
368: /* Set RQ to the min of mode, tstatus and mstatus */
369: rq = AGP_MODE_GET_RQ(mode);
370: if (AGP_MODE_GET_RQ(tstatus) < rq)
371: rq = AGP_MODE_GET_RQ(tstatus);
372: if (AGP_MODE_GET_RQ(mstatus) < rq)
373: rq = AGP_MODE_GET_RQ(mstatus);
374:
375: /* Set SBA if all three can deal with SBA */
376: sba = (AGP_MODE_GET_SBA(tstatus)
377: & AGP_MODE_GET_SBA(mstatus)
378: & AGP_MODE_GET_SBA(mode));
379:
380: /* Similar for FW */
381: fw = (AGP_MODE_GET_FW(tstatus)
382: & AGP_MODE_GET_FW(mstatus)
383: & AGP_MODE_GET_FW(mode));
384:
385: /* Figure out the max rate */
386: rate = (AGP_MODE_GET_RATE(tstatus)
387: & AGP_MODE_GET_RATE(mstatus)
388: & AGP_MODE_GET_RATE(mode));
389: if (rate & AGP_MODE_V2_RATE_4x)
390: rate = AGP_MODE_V2_RATE_4x;
391: else if (rate & AGP_MODE_V2_RATE_2x)
392: rate = AGP_MODE_V2_RATE_2x;
393: else
394: rate = AGP_MODE_V2_RATE_1x;
395: if (bootverbose)
396: device_printf(dev, "Setting AGP v2 mode %d\n", rate);
397:
398: /* Construct the new mode word and tell the hardware */
399: command = AGP_MODE_SET_RQ(0, rq);
400: command = AGP_MODE_SET_SBA(command, sba);
401: command = AGP_MODE_SET_FW(command, fw);
402: command = AGP_MODE_SET_RATE(command, rate);
403: command = AGP_MODE_SET_AGP(command, 1);
404: pci_write_config(dev, agp_find_caps(dev) + AGP_COMMAND, command, 4);
405: pci_write_config(mdev, agp_find_caps(mdev) + AGP_COMMAND, command, 4);
406:
407: return 0;
408: }
409:
410: int
411: agp_generic_enable(device_t dev, u_int32_t mode)
412: {
413: device_t mdev = agp_find_display();
414: u_int32_t tstatus, mstatus;
415:
416: if (!mdev) {
417: AGP_DPF("can't find display\n");
418: return ENXIO;
419: }
420:
421: tstatus = pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
422: mstatus = pci_read_config(mdev, agp_find_caps(mdev) + AGP_STATUS, 4);
423:
424: /*
425: * Check display and bridge for AGP v3 support. AGP v3 allows
426: * more variety in topology than v2, e.g. multiple AGP devices
427: * attached to one bridge, or multiple AGP bridges in one
428: * system. This doesn't attempt to address those situations,
429: * but should work fine for a classic single AGP slot system
430: * with AGP v3.
431: */
432: if (AGP_MODE_GET_MODE_3(tstatus) && AGP_MODE_GET_MODE_3(mstatus))
433: return (agp_v3_enable(dev, mdev, mode));
434: else
435: return (agp_v2_enable(dev, mdev, mode));
436: }
437:
438: struct agp_memory *
439: agp_generic_alloc_memory(device_t dev, int type, vm_size_t size)
440: {
441: struct agp_softc *sc = device_get_softc(dev);
442: struct agp_memory *mem;
443:
444: if ((size & (AGP_PAGE_SIZE - 1)) != 0)
445: return 0;
446:
447: if (sc->as_allocated + size > sc->as_maxmem)
448: return 0;
449:
450: if (type != 0) {
451: printf("agp_generic_alloc_memory: unsupported type %d\n",
452: type);
453: return 0;
454: }
455:
456: mem = malloc(sizeof *mem, M_AGP, M_WAITOK);
457: mem->am_id = sc->as_nextid++;
458: mem->am_size = size;
459: mem->am_type = 0;
460: mem->am_obj = vm_object_allocate(OBJT_DEFAULT, atop(round_page(size)));
461: mem->am_physical = 0;
462: mem->am_offset = 0;
463: mem->am_is_bound = 0;
464: TAILQ_INSERT_TAIL(&sc->as_memory, mem, am_link);
465: sc->as_allocated += size;
466:
467: return mem;
468: }
469:
470: int
471: agp_generic_free_memory(device_t dev, struct agp_memory *mem)
472: {
473: struct agp_softc *sc = device_get_softc(dev);
474:
475: if (mem->am_is_bound)
476: return EBUSY;
477:
478: sc->as_allocated -= mem->am_size;
479: TAILQ_REMOVE(&sc->as_memory, mem, am_link);
480: vm_object_deallocate(mem->am_obj);
481: free(mem, M_AGP);
482: return 0;
483: }
484:
485: int
486: agp_generic_bind_memory(device_t dev, struct agp_memory *mem,
487: vm_offset_t offset)
488: {
489: struct agp_softc *sc = device_get_softc(dev);
490: vm_offset_t i, j, k;
491: vm_page_t m;
492: int error;
493:
494: lockmgr(&sc->as_lock, LK_EXCLUSIVE, 0, curthread); /* XXX */
495:
496: if (mem->am_is_bound) {
497: device_printf(dev, "memory already bound\n");
498: return EINVAL;
499: }
500:
501: if (offset < 0
502: || (offset & (AGP_PAGE_SIZE - 1)) != 0
503: || offset + mem->am_size > AGP_GET_APERTURE(dev)) {
504: device_printf(dev, "binding memory at bad offset %#x\n",
505: (int) offset);
506: return EINVAL;
507: }
508:
509: /*
510: * Bind the individual pages and flush the chipset's
511: * TLB.
512: *
513: * XXX Presumably, this needs to be the pci address on alpha
514: * (i.e. use alpha_XXX_dmamap()). I don't have access to any
515: * alpha AGP hardware to check.
516: */
517: for (i = 0; i < mem->am_size; i += PAGE_SIZE) {
518: /*
519: * Find a page from the object and wire it
520: * down. This page will be mapped using one or more
521: * entries in the GATT (assuming that PAGE_SIZE >=
522: * AGP_PAGE_SIZE. If this is the first call to bind,
523: * the pages will be allocated and zeroed.
524: */
525: m = vm_page_grab(mem->am_obj, OFF_TO_IDX(i),
526: VM_ALLOC_ZERO | VM_ALLOC_RETRY);
527: if ((m->flags & PG_ZERO) == 0)
528: vm_page_zero_fill(m);
529: AGP_DPF("found page pa=%#x\n", VM_PAGE_TO_PHYS(m));
530: vm_page_wire(m);
531:
532: /*
533: * Install entries in the GATT, making sure that if
534: * AGP_PAGE_SIZE < PAGE_SIZE and mem->am_size is not
535: * aligned to PAGE_SIZE, we don't modify too many GATT
536: * entries.
537: */
538: for (j = 0; j < PAGE_SIZE && i + j < mem->am_size;
539: j += AGP_PAGE_SIZE) {
540: vm_offset_t pa = VM_PAGE_TO_PHYS(m) + j;
541: AGP_DPF("binding offset %#x to pa %#x\n",
542: offset + i + j, pa);
543: error = AGP_BIND_PAGE(dev, offset + i + j, pa);
544: if (error) {
545: /*
546: * Bail out. Reverse all the mappings
547: * and unwire the pages.
548: */
549: vm_page_wakeup(m);
550: for (k = 0; k < i + j; k += AGP_PAGE_SIZE)
551: AGP_UNBIND_PAGE(dev, offset + k);
552: for (k = 0; k <= i; k += PAGE_SIZE) {
553: m = vm_page_lookup(mem->am_obj,
554: OFF_TO_IDX(k));
555: vm_page_unwire(m, 0);
556: }
557: lockmgr(&sc->as_lock, LK_RELEASE, 0, curthread); /* XXX */
558: return error;
559: }
560: }
561: vm_page_wakeup(m);
562: }
563:
564: /*
565: * Flush the cpu cache since we are providing a new mapping
566: * for these pages.
567: */
568: agp_flush_cache();
569:
570: /*
571: * Make sure the chipset gets the new mappings.
572: */
573: AGP_FLUSH_TLB(dev);
574:
575: mem->am_offset = offset;
576: mem->am_is_bound = 1;
577:
578: lockmgr(&sc->as_lock, LK_RELEASE, 0, curthread); /* XXX */
579:
580: return 0;
581: }
582:
583: int
584: agp_generic_unbind_memory(device_t dev, struct agp_memory *mem)
585: {
586: struct agp_softc *sc = device_get_softc(dev);
587: vm_page_t m;
588: int i;
589:
590: lockmgr(&sc->as_lock, LK_EXCLUSIVE, 0, curthread); /* XXX */
591:
592: if (!mem->am_is_bound) {
593: device_printf(dev, "memory is not bound\n");
594: return EINVAL;
595: }
596:
597:
598: /*
599: * Unbind the individual pages and flush the chipset's
600: * TLB. Unwire the pages so they can be swapped.
601: */
602: for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
603: AGP_UNBIND_PAGE(dev, mem->am_offset + i);
604: for (i = 0; i < mem->am_size; i += PAGE_SIZE) {
605: m = vm_page_lookup(mem->am_obj, atop(i));
606: vm_page_unwire(m, 0);
607: }
608:
609: agp_flush_cache();
610: AGP_FLUSH_TLB(dev);
611:
612: mem->am_offset = 0;
613: mem->am_is_bound = 0;
614:
615: lockmgr(&sc->as_lock, LK_RELEASE, 0, curthread); /* XXX */
616:
617: return 0;
618: }
619:
620: /* Helper functions for implementing user/kernel api */
621:
622: static int
623: agp_acquire_helper(device_t dev, enum agp_acquire_state state)
624: {
625: struct agp_softc *sc = device_get_softc(dev);
626:
627: if (sc->as_state != AGP_ACQUIRE_FREE)
628: return EBUSY;
629: sc->as_state = state;
630:
631: return 0;
632: }
633:
634: static int
635: agp_release_helper(device_t dev, enum agp_acquire_state state)
636: {
637: struct agp_softc *sc = device_get_softc(dev);
638:
639: if (sc->as_state == AGP_ACQUIRE_FREE)
640: return 0;
641:
642: if (sc->as_state != state)
643: return EBUSY;
644:
645: sc->as_state = AGP_ACQUIRE_FREE;
646: return 0;
647: }
648:
649: static struct agp_memory *
650: agp_find_memory(device_t dev, int id)
651: {
652: struct agp_softc *sc = device_get_softc(dev);
653: struct agp_memory *mem;
654:
655: AGP_DPF("searching for memory block %d\n", id);
656: TAILQ_FOREACH(mem, &sc->as_memory, am_link) {
657: AGP_DPF("considering memory block %d\n", mem->am_id);
658: if (mem->am_id == id)
659: return mem;
660: }
661: return 0;
662: }
663:
664: /* Implementation of the userland ioctl api */
665:
666: static int
667: agp_info_user(device_t dev, agp_info *info)
668: {
669: struct agp_softc *sc = device_get_softc(dev);
670:
671: bzero(info, sizeof *info);
672: info->bridge_id = pci_get_devid(dev);
673: info->agp_mode =
674: pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
675: info->aper_base = rman_get_start(sc->as_aperture);
676: info->aper_size = AGP_GET_APERTURE(dev) >> 20;
677: info->pg_total = info->pg_system = sc->as_maxmem >> AGP_PAGE_SHIFT;
678: info->pg_used = sc->as_allocated >> AGP_PAGE_SHIFT;
679:
680: return 0;
681: }
682:
683: static int
684: agp_setup_user(device_t dev, agp_setup *setup)
685: {
686: return AGP_ENABLE(dev, setup->agp_mode);
687: }
688:
689: static int
690: agp_allocate_user(device_t dev, agp_allocate *alloc)
691: {
692: struct agp_memory *mem;
693:
694: mem = AGP_ALLOC_MEMORY(dev,
695: alloc->type,
696: alloc->pg_count << AGP_PAGE_SHIFT);
697: if (mem) {
698: alloc->key = mem->am_id;
699: alloc->physical = mem->am_physical;
700: return 0;
701: } else {
702: return ENOMEM;
703: }
704: }
705:
706: static int
707: agp_deallocate_user(device_t dev, int id)
708: {
709: struct agp_memory *mem = agp_find_memory(dev, id);;
710:
711: if (mem) {
712: AGP_FREE_MEMORY(dev, mem);
713: return 0;
714: } else {
715: return ENOENT;
716: }
717: }
718:
719: static int
720: agp_bind_user(device_t dev, agp_bind *bind)
721: {
722: struct agp_memory *mem = agp_find_memory(dev, bind->key);
723:
724: if (!mem)
725: return ENOENT;
726:
727: return AGP_BIND_MEMORY(dev, mem, bind->pg_start << AGP_PAGE_SHIFT);
728: }
729:
730: static int
731: agp_unbind_user(device_t dev, agp_unbind *unbind)
732: {
733: struct agp_memory *mem = agp_find_memory(dev, unbind->key);
734:
735: if (!mem)
736: return ENOENT;
737:
738: return AGP_UNBIND_MEMORY(dev, mem);
739: }
740:
741: static int
742: agp_open(dev_t kdev, int oflags, int devtype, struct thread *td)
743: {
744: device_t dev = KDEV2DEV(kdev);
745: struct agp_softc *sc = device_get_softc(dev);
746:
747: if (!sc->as_isopen) {
748: sc->as_isopen = 1;
749: device_busy(dev);
750: }
751:
752: return 0;
753: }
754:
755: static int
756: agp_close(dev_t kdev, int fflag, int devtype, struct thread *td)
757: {
758: device_t dev = KDEV2DEV(kdev);
759: struct agp_softc *sc = device_get_softc(dev);
760: struct agp_memory *mem;
761:
762: /*
763: * Clear the GATT and force release on last close
764: */
765: while ((mem = TAILQ_FIRST(&sc->as_memory)) != 0) {
766: if (mem->am_is_bound)
767: AGP_UNBIND_MEMORY(dev, mem);
768: AGP_FREE_MEMORY(dev, mem);
769: }
770: if (sc->as_state == AGP_ACQUIRE_USER)
771: agp_release_helper(dev, AGP_ACQUIRE_USER);
772: sc->as_isopen = 0;
773: device_unbusy(dev);
774:
775: return 0;
776: }
777:
778: static int
779: agp_ioctl(dev_t kdev, u_long cmd, caddr_t data, int fflag, struct thread *td)
780: {
781: device_t dev = KDEV2DEV(kdev);
782:
783: switch (cmd) {
784: case AGPIOC_INFO:
785: return agp_info_user(dev, (agp_info *) data);
786:
787: case AGPIOC_ACQUIRE:
788: return agp_acquire_helper(dev, AGP_ACQUIRE_USER);
789:
790: case AGPIOC_RELEASE:
791: return agp_release_helper(dev, AGP_ACQUIRE_USER);
792:
793: case AGPIOC_SETUP:
794: return agp_setup_user(dev, (agp_setup *)data);
795:
796: case AGPIOC_ALLOCATE:
797: return agp_allocate_user(dev, (agp_allocate *)data);
798:
799: case AGPIOC_DEALLOCATE:
800: return agp_deallocate_user(dev, *(int *) data);
801:
802: case AGPIOC_BIND:
803: return agp_bind_user(dev, (agp_bind *)data);
804:
805: case AGPIOC_UNBIND:
806: return agp_unbind_user(dev, (agp_unbind *)data);
807:
808: }
809:
810: return EINVAL;
811: }
812:
813: static int
814: agp_mmap(dev_t kdev, vm_offset_t offset, int prot)
815: {
816: device_t dev = KDEV2DEV(kdev);
817: struct agp_softc *sc = device_get_softc(dev);
818:
819: if (offset > AGP_GET_APERTURE(dev))
820: return -1;
821: return atop(rman_get_start(sc->as_aperture) + offset);
822: }
823:
824: /* Implementation of the kernel api */
825:
826: device_t
827: agp_find_device()
828: {
829: if (!agp_devclass)
830: return 0;
831: return devclass_get_device(agp_devclass, 0);
832: }
833:
834: enum agp_acquire_state
835: agp_state(device_t dev)
836: {
837: struct agp_softc *sc = device_get_softc(dev);
838: return sc->as_state;
839: }
840:
841: void
842: agp_get_info(device_t dev, struct agp_info *info)
843: {
844: struct agp_softc *sc = device_get_softc(dev);
845:
846: info->ai_mode =
847: pci_read_config(dev, agp_find_caps(dev) + AGP_STATUS, 4);
848: info->ai_aperture_base = rman_get_start(sc->as_aperture);
849: info->ai_aperture_size = (rman_get_end(sc->as_aperture)
850: - rman_get_start(sc->as_aperture)) + 1;
851: info->ai_aperture_va = (vm_offset_t) rman_get_virtual(sc->as_aperture);
852: info->ai_memory_allowed = sc->as_maxmem;
853: info->ai_memory_used = sc->as_allocated;
854: }
855:
856: int
857: agp_acquire(device_t dev)
858: {
859: return agp_acquire_helper(dev, AGP_ACQUIRE_KERNEL);
860: }
861:
862: int
863: agp_release(device_t dev)
864: {
865: return agp_release_helper(dev, AGP_ACQUIRE_KERNEL);
866: }
867:
868: int
869: agp_enable(device_t dev, u_int32_t mode)
870: {
871: return AGP_ENABLE(dev, mode);
872: }
873:
874: void *agp_alloc_memory(device_t dev, int type, vm_size_t bytes)
875: {
876: return (void *) AGP_ALLOC_MEMORY(dev, type, bytes);
877: }
878:
879: void agp_free_memory(device_t dev, void *handle)
880: {
881: struct agp_memory *mem = (struct agp_memory *) handle;
882: AGP_FREE_MEMORY(dev, mem);
883: }
884:
885: int agp_bind_memory(device_t dev, void *handle, vm_offset_t offset)
886: {
887: struct agp_memory *mem = (struct agp_memory *) handle;
888: return AGP_BIND_MEMORY(dev, mem, offset);
889: }
890:
891: int agp_unbind_memory(device_t dev, void *handle)
892: {
893: struct agp_memory *mem = (struct agp_memory *) handle;
894: return AGP_UNBIND_MEMORY(dev, mem);
895: }
896:
897: void agp_memory_info(device_t dev, void *handle, struct
898: agp_memory_info *mi)
899: {
900: struct agp_memory *mem = (struct agp_memory *) handle;
901:
902: mi->ami_size = mem->am_size;
903: mi->ami_physical = mem->am_physical;
904: mi->ami_offset = mem->am_offset;
905: mi->ami_is_bound = mem->am_is_bound;
906: }