]> git.ipfire.org Git - thirdparty/pciutils.git/blob - lib/generic.c
Rewrote the PCI Utilities. All PCI configuration space access has been
[thirdparty/pciutils.git] / lib / generic.c
1 /*
2 * $Id: generic.c,v 1.1 1999/01/22 21:05:24 mj Exp $
3 *
4 * The PCI Library -- Generic Direct Access Functions
5 *
6 * Copyright (c) 1997--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
7 *
8 * Can be freely distributed and used under the terms of the GNU GPL.
9 */
10
11 #include <string.h>
12
13 #include "internal.h"
14
15 static void
16 pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus)
17 {
18 int dev, multi, ht;
19 struct pci_dev *t = pci_alloc_dev(a);
20
21 a->debug("Scanning bus %02x for devices...\n", bus);
22 if (busmap[bus])
23 {
24 a->warning("Bus %02x seen twice (firmware bug). Ignored.", bus);
25 return;
26 }
27 busmap[bus] = 1;
28 t->bus = bus;
29 for(dev=0; dev<32; dev++)
30 {
31 t->dev = dev;
32 multi = 0;
33 for(t->func=0; t->func<8; t->func++)
34 {
35 u32 vd = pci_read_long(t, PCI_VENDOR_ID);
36 struct pci_dev *d;
37
38 if (!vd || vd == 0xffffffff)
39 break;
40 ht = pci_read_byte(t, PCI_HEADER_TYPE);
41 if (!t->func)
42 multi = ht & 0x80;
43 ht &= 0x7f;
44 d = pci_alloc_dev(a);
45 d->bus = t->bus;
46 d->dev = t->dev;
47 d->func = t->func;
48 d->vendor_id = vd & 0xffff;
49 d->device_id = vd >> 16U;
50 d->known_fields = PCI_FILL_IDENT;
51 d->hdrtype = ht;
52 pci_link_dev(a, d);
53 switch (ht)
54 {
55 case PCI_HEADER_TYPE_NORMAL:
56 break;
57 case PCI_HEADER_TYPE_BRIDGE:
58 case PCI_HEADER_TYPE_CARDBUS:
59 pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS));
60 break;
61 default:
62 a->debug("Device %02x:%02x.%d has unknown header type %02x.\n", d->bus, d->dev, d->func);
63 }
64 if (!multi)
65 break;
66 }
67 }
68 }
69
70 void
71 pci_generic_scan(struct pci_access *a)
72 {
73 byte busmap[256];
74
75 bzero(busmap, sizeof(busmap));
76 pci_generic_scan_bus(a, busmap, 0);
77 }
78
79 void
80 pci_generic_fill_info(struct pci_dev *d, int flags)
81 {
82 struct pci_access *a = d->access;
83
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_IRQ)
90 d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE);
91 if (flags & PCI_FILL_BASES)
92 {
93 int cnt = 0, i;
94 bzero(d->base_addr, sizeof(d->base_addr));
95 switch (d->hdrtype)
96 {
97 case PCI_HEADER_TYPE_NORMAL:
98 cnt = 6;
99 break;
100 case PCI_HEADER_TYPE_BRIDGE:
101 cnt = 2;
102 break;
103 case PCI_HEADER_TYPE_CARDBUS:
104 cnt = 1;
105 break;
106 }
107 if (cnt)
108 {
109 u16 cmd = pci_read_word(d, PCI_COMMAND);
110 for(i=0; i<cnt; i++)
111 {
112 u32 x = pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4);
113 if (!x || x == (u32) ~0)
114 continue;
115 d->base_addr[i] = x;
116 if (x & PCI_BASE_ADDRESS_SPACE_IO)
117 {
118 if (!(cmd & PCI_COMMAND_IO))
119 d->base_addr[i] = 0;
120 }
121 else if (cmd & PCI_COMMAND_MEMORY)
122 {
123 if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
124 {
125 if (i >= cnt-1)
126 a->warning("%02x:%02x.%d: Invalid 64-bit address seen.", d->bus, d->dev, d->func);
127 else
128 {
129 u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4);
130 #ifdef HAVE_64BIT_LONG_INT
131 d->base_addr[i-1] |= ((unsigned long) y) << 32;
132 #else
133 if (y)
134 {
135 a->warning("%02x:%02x.%d 64-bit device address ignored.", d->bus, d->dev, d->func);
136 d->base_addr[i-1] = 0;
137 }
138 #endif
139 }
140 }
141 }
142 else
143 d->base_addr[i] = 0;
144 }
145 }
146 }
147 if (flags & PCI_FILL_ROM_BASE)
148 {
149 int reg = 0;
150 d->rom_base_addr = 0;
151 switch (d->hdrtype)
152 {
153 case PCI_HEADER_TYPE_NORMAL:
154 reg = PCI_ROM_ADDRESS;
155 break;
156 case PCI_HEADER_TYPE_BRIDGE:
157 reg = PCI_ROM_ADDRESS1;
158 break;
159 }
160 if (reg)
161 {
162 u32 a = pci_read_long(d, reg);
163 if (a & PCI_ROM_ADDRESS_ENABLE)
164 d->rom_base_addr = a;
165 }
166 }
167 }
168
169 static int
170 pci_generic_block_op(struct pci_dev *d, int pos, byte *buf, int len,
171 int (*r)(struct pci_dev *d, int pos, byte *buf, int len))
172 {
173 if ((pos & 1) && len >= 1)
174 {
175 if (!r(d, pos, buf, 1))
176 return 0;
177 pos++; buf++; len--;
178 }
179 if ((pos & 3) && len >= 2)
180 {
181 if (!r(d, pos, buf, 2))
182 return 0;
183 pos += 2; buf += 2; len -= 2;
184 }
185 while (len >= 4)
186 {
187 if (!r(d, pos, buf, 4))
188 return 0;
189 pos += 4; buf += 4; len -= 4;
190 }
191 if (len >= 2)
192 {
193 if (!r(d, pos, buf, 2))
194 return 0;
195 pos += 2; buf += 2; len -= 2;
196 }
197 if (len && !r(d, pos, buf, 1))
198 return 0;
199 return 1;
200 }
201
202 int
203 pci_generic_block_read(struct pci_dev *d, int pos, byte *buf, int len)
204 {
205 return pci_generic_block_op(d, pos, buf, len, d->access->methods->read);
206 }
207
208 int
209 pci_generic_block_write(struct pci_dev *d, int pos, byte *buf, int len)
210 {
211 return pci_generic_block_op(d, pos, buf, len, d->access->methods->write);
212 }