Annotation of embedaddon/pciutils/lib/generic.c, revision 1.1.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>