Annotation of embedaddon/pciutils/lib/caps.c, revision 1.1
1.1 ! misho 1: /*
! 2: * The PCI Library -- Capabilities
! 3: *
! 4: * Copyright (c) 2008 Martin Mares <mj@ucw.cz>
! 5: *
! 6: * Can be freely distributed and used under the terms of the GNU GPL.
! 7: */
! 8:
! 9: #include <string.h>
! 10:
! 11: #include "internal.h"
! 12:
! 13: static void
! 14: pci_add_cap(struct pci_dev *d, unsigned int addr, unsigned int id, unsigned int type)
! 15: {
! 16: struct pci_cap *cap = pci_malloc(d->access, sizeof(*cap));
! 17:
! 18: cap->next = d->first_cap;
! 19: d->first_cap = cap;
! 20: cap->addr = addr;
! 21: cap->id = id;
! 22: cap->type = type;
! 23: d->access->debug("%04x:%02x:%02x.%d: Found capability %04x of type %d at %04x\n",
! 24: d->domain, d->bus, d->dev, d->func, id, type, addr);
! 25: }
! 26:
! 27: static void
! 28: pci_scan_trad_caps(struct pci_dev *d)
! 29: {
! 30: word status = pci_read_word(d, PCI_STATUS);
! 31: byte been_there[256];
! 32: int where;
! 33:
! 34: if (!(status & PCI_STATUS_CAP_LIST))
! 35: return;
! 36:
! 37: memset(been_there, 0, 256);
! 38: where = pci_read_byte(d, PCI_CAPABILITY_LIST) & ~3;
! 39: while (where)
! 40: {
! 41: byte id = pci_read_byte(d, where + PCI_CAP_LIST_ID);
! 42: byte next = pci_read_byte(d, where + PCI_CAP_LIST_NEXT) & ~3;
! 43: if (been_there[where]++)
! 44: break;
! 45: if (id == 0xff)
! 46: break;
! 47: pci_add_cap(d, where, id, PCI_CAP_NORMAL);
! 48: where = next;
! 49: }
! 50: }
! 51:
! 52: static void
! 53: pci_scan_ext_caps(struct pci_dev *d)
! 54: {
! 55: byte been_there[0x1000];
! 56: int where = 0x100;
! 57:
! 58: if (!pci_find_cap(d, PCI_CAP_ID_EXP, PCI_CAP_NORMAL))
! 59: return;
! 60:
! 61: memset(been_there, 0, 0x1000);
! 62: do
! 63: {
! 64: u32 header;
! 65: int id;
! 66:
! 67: header = pci_read_long(d, where);
! 68: if (!header || header == 0xffffffff)
! 69: break;
! 70: id = header & 0xffff;
! 71: if (been_there[where]++)
! 72: break;
! 73: pci_add_cap(d, where, id, PCI_CAP_EXTENDED);
! 74: where = (header >> 20) & ~3;
! 75: }
! 76: while (where);
! 77: }
! 78:
! 79: unsigned int
! 80: pci_scan_caps(struct pci_dev *d, unsigned int want_fields)
! 81: {
! 82: if ((want_fields & PCI_FILL_EXT_CAPS) && !(d->known_fields & PCI_FILL_CAPS))
! 83: want_fields |= PCI_FILL_CAPS;
! 84:
! 85: if (want_fields & PCI_FILL_CAPS)
! 86: pci_scan_trad_caps(d);
! 87: if (want_fields & PCI_FILL_EXT_CAPS)
! 88: pci_scan_ext_caps(d);
! 89: return want_fields;
! 90: }
! 91:
! 92: void
! 93: pci_free_caps(struct pci_dev *d)
! 94: {
! 95: struct pci_cap *cap;
! 96:
! 97: while (cap = d->first_cap)
! 98: {
! 99: d->first_cap = cap->next;
! 100: pci_mfree(cap);
! 101: }
! 102: }
! 103:
! 104: struct pci_cap *
! 105: pci_find_cap(struct pci_dev *d, unsigned int id, unsigned int type)
! 106: {
! 107: struct pci_cap *c;
! 108:
! 109: pci_fill_info_v31(d, ((type == PCI_CAP_NORMAL) ? PCI_FILL_CAPS : PCI_FILL_EXT_CAPS));
! 110: for (c=d->first_cap; c; c=c->next)
! 111: if (c->type == type && c->id == id)
! 112: return c;
! 113: return NULL;
! 114: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>