Annotation of embedaddon/pciutils/lib/generic.c, revision 1.1
1.1 ! misho 1: /*
! 2: * The PCI Library -- Generic Direct Access Functions
! 3: *
! 4: * Copyright (c) 1997--2000 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: void
! 14: pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus)
! 15: {
! 16: int dev, multi, ht;
! 17: struct pci_dev *t;
! 18:
! 19: a->debug("Scanning bus %02x for devices...\n", bus);
! 20: if (busmap[bus])
! 21: {
! 22: a->warning("Bus %02x seen twice (firmware bug). Ignored.", bus);
! 23: return;
! 24: }
! 25: busmap[bus] = 1;
! 26: t = pci_alloc_dev(a);
! 27: t->bus = bus;
! 28: for (dev=0; dev<32; dev++)
! 29: {
! 30: t->dev = dev;
! 31: multi = 0;
! 32: for (t->func=0; !t->func || multi && t->func<8; t->func++)
! 33: {
! 34: u32 vd = pci_read_long(t, PCI_VENDOR_ID);
! 35: struct pci_dev *d;
! 36:
! 37: if (!vd || vd == 0xffffffff)
! 38: continue;
! 39: ht = pci_read_byte(t, PCI_HEADER_TYPE);
! 40: if (!t->func)
! 41: multi = ht & 0x80;
! 42: ht &= 0x7f;
! 43: d = pci_alloc_dev(a);
! 44: d->bus = t->bus;
! 45: d->dev = t->dev;
! 46: d->func = t->func;
! 47: d->vendor_id = vd & 0xffff;
! 48: d->device_id = vd >> 16U;
! 49: d->known_fields = PCI_FILL_IDENT;
! 50: d->hdrtype = ht;
! 51: pci_link_dev(a, d);
! 52: switch (ht)
! 53: {
! 54: case PCI_HEADER_TYPE_NORMAL:
! 55: break;
! 56: case PCI_HEADER_TYPE_BRIDGE:
! 57: case PCI_HEADER_TYPE_CARDBUS:
! 58: pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS));
! 59: break;
! 60: default:
! 61: a->debug("Device %04x:%02x:%02x.%d has unknown header type %02x.\n", d->domain, d->bus, d->dev, d->func, ht);
! 62: }
! 63: }
! 64: }
! 65: pci_free_dev(t);
! 66: }
! 67:
! 68: void
! 69: pci_generic_scan(struct pci_access *a)
! 70: {
! 71: byte busmap[256];
! 72:
! 73: memset(busmap, 0, sizeof(busmap));
! 74: pci_generic_scan_bus(a, busmap, 0);
! 75: }
! 76:
! 77: int
! 78: pci_generic_fill_info(struct pci_dev *d, int flags)
! 79: {
! 80: struct pci_access *a = d->access;
! 81:
! 82: if ((flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE)) && d->hdrtype < 0)
! 83: d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f;
! 84: if (flags & PCI_FILL_IDENT)
! 85: {
! 86: d->vendor_id = pci_read_word(d, PCI_VENDOR_ID);
! 87: d->device_id = pci_read_word(d, PCI_DEVICE_ID);
! 88: }
! 89: if (flags & PCI_FILL_CLASS)
! 90: d->device_class = pci_read_word(d, PCI_CLASS_DEVICE);
! 91: if (flags & PCI_FILL_IRQ)
! 92: d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE);
! 93: if (flags & PCI_FILL_BASES)
! 94: {
! 95: int cnt = 0, i;
! 96: memset(d->base_addr, 0, sizeof(d->base_addr));
! 97: switch (d->hdrtype)
! 98: {
! 99: case PCI_HEADER_TYPE_NORMAL:
! 100: cnt = 6;
! 101: break;
! 102: case PCI_HEADER_TYPE_BRIDGE:
! 103: cnt = 2;
! 104: break;
! 105: case PCI_HEADER_TYPE_CARDBUS:
! 106: cnt = 1;
! 107: break;
! 108: }
! 109: if (cnt)
! 110: {
! 111: for (i=0; i<cnt; i++)
! 112: {
! 113: u32 x = pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4);
! 114: if (!x || x == (u32) ~0)
! 115: continue;
! 116: if ((x & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
! 117: d->base_addr[i] = x;
! 118: else
! 119: {
! 120: if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != PCI_BASE_ADDRESS_MEM_TYPE_64)
! 121: d->base_addr[i] = x;
! 122: else if (i >= cnt-1)
! 123: a->warning("%04x:%02x:%02x.%d: Invalid 64-bit address seen for BAR %d.", d->domain, d->bus, d->dev, d->func, i);
! 124: else
! 125: {
! 126: u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4);
! 127: #ifdef PCI_HAVE_64BIT_ADDRESS
! 128: d->base_addr[i-1] = x | (((pciaddr_t) y) << 32);
! 129: #else
! 130: if (y)
! 131: a->warning("%04x:%02x:%02x.%d 64-bit device address ignored.", d->domain, d->bus, d->dev, d->func);
! 132: else
! 133: d->base_addr[i-1] = x;
! 134: #endif
! 135: }
! 136: }
! 137: }
! 138: }
! 139: }
! 140: if (flags & PCI_FILL_ROM_BASE)
! 141: {
! 142: int reg = 0;
! 143: d->rom_base_addr = 0;
! 144: switch (d->hdrtype)
! 145: {
! 146: case PCI_HEADER_TYPE_NORMAL:
! 147: reg = PCI_ROM_ADDRESS;
! 148: break;
! 149: case PCI_HEADER_TYPE_BRIDGE:
! 150: reg = PCI_ROM_ADDRESS1;
! 151: break;
! 152: }
! 153: if (reg)
! 154: {
! 155: u32 u = pci_read_long(d, reg);
! 156: if (u != 0xffffffff)
! 157: d->rom_base_addr = u;
! 158: }
! 159: }
! 160: if (flags & (PCI_FILL_CAPS | PCI_FILL_EXT_CAPS))
! 161: flags |= pci_scan_caps(d, flags);
! 162: return flags & ~PCI_FILL_SIZES;
! 163: }
! 164:
! 165: static int
! 166: pci_generic_block_op(struct pci_dev *d, int pos, byte *buf, int len,
! 167: int (*r)(struct pci_dev *d, int pos, byte *buf, int len))
! 168: {
! 169: if ((pos & 1) && len >= 1)
! 170: {
! 171: if (!r(d, pos, buf, 1))
! 172: return 0;
! 173: pos++; buf++; len--;
! 174: }
! 175: if ((pos & 3) && len >= 2)
! 176: {
! 177: if (!r(d, pos, buf, 2))
! 178: return 0;
! 179: pos += 2; buf += 2; len -= 2;
! 180: }
! 181: while (len >= 4)
! 182: {
! 183: if (!r(d, pos, buf, 4))
! 184: return 0;
! 185: pos += 4; buf += 4; len -= 4;
! 186: }
! 187: if (len >= 2)
! 188: {
! 189: if (!r(d, pos, buf, 2))
! 190: return 0;
! 191: pos += 2; buf += 2; len -= 2;
! 192: }
! 193: if (len && !r(d, pos, buf, 1))
! 194: return 0;
! 195: return 1;
! 196: }
! 197:
! 198: int
! 199: pci_generic_block_read(struct pci_dev *d, int pos, byte *buf, int len)
! 200: {
! 201: return pci_generic_block_op(d, pos, buf, len, d->access->methods->read);
! 202: }
! 203:
! 204: int
! 205: pci_generic_block_write(struct pci_dev *d, int pos, byte *buf, int len)
! 206: {
! 207: return pci_generic_block_op(d, pos, buf, len, d->access->methods->write);
! 208: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>