|
|
1.1 root 1: /*
2: * Copyright (C) 2006 Michael Brown <[email protected]>.
3: *
4: * Based in part on pci.c from Etherboot 5.4, by Ken Yap and David
5: * Munro, in turn based on the Linux kernel's PCI implementation.
6: *
7: * This program is free software; you can redistribute it and/or
8: * modify it under the terms of the GNU General Public License as
9: * published by the Free Software Foundation; either version 2 of the
10: * License, or any later version.
11: *
12: * This program is distributed in the hope that it will be useful, but
13: * WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15: * General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public License
18: * along with this program; if not, write to the Free Software
19: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20: */
21:
22: FILE_LICENCE ( GPL2_OR_LATER );
23:
24: #include <stdint.h>
25: #include <stdlib.h>
26: #include <stdio.h>
27: #include <string.h>
28: #include <errno.h>
29: #include <ipxe/tables.h>
30: #include <ipxe/device.h>
31: #include <ipxe/pci.h>
32:
33: /** @file
34: *
35: * PCI bus
36: *
37: */
38:
39: static void pcibus_remove ( struct root_device *rootdev );
40:
41: /**
42: * Read PCI BAR
43: *
44: * @v pci PCI device
45: * @v reg PCI register number
46: * @ret bar Base address register
47: *
48: * Reads the specified PCI base address register, including the flags
49: * portion. 64-bit BARs will be handled automatically. If the value
50: * of the 64-bit BAR exceeds the size of an unsigned long (i.e. if the
51: * high dword is non-zero on a 32-bit platform), then the value
52: * returned will be zero plus the flags for a 64-bit BAR. Unreachable
53: * 64-bit BARs are therefore returned as uninitialised 64-bit BARs.
54: */
55: static unsigned long pci_bar ( struct pci_device *pci, unsigned int reg ) {
56: uint32_t low;
57: uint32_t high;
58:
59: pci_read_config_dword ( pci, reg, &low );
60: if ( ( low & (PCI_BASE_ADDRESS_SPACE|PCI_BASE_ADDRESS_MEM_TYPE_MASK) )
61: == (PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64) ){
62: pci_read_config_dword ( pci, reg + 4, &high );
63: if ( high ) {
64: if ( sizeof ( unsigned long ) > sizeof ( uint32_t ) ) {
65: return ( ( ( uint64_t ) high << 32 ) | low );
66: } else {
67: DBGC ( pci, PCI_FMT " unhandled 64-bit BAR "
68: "%08x%08x\n",
69: PCI_ARGS ( pci ), high, low );
70: return PCI_BASE_ADDRESS_MEM_TYPE_64;
71: }
72: }
73: }
74: return low;
75: }
76:
77: /**
78: * Find the start of a PCI BAR
79: *
80: * @v pci PCI device
81: * @v reg PCI register number
82: * @ret start BAR start address
83: *
84: * Reads the specified PCI base address register, and returns the
85: * address portion of the BAR (i.e. without the flags).
86: *
87: * If the address exceeds the size of an unsigned long (i.e. if a
88: * 64-bit BAR has a non-zero high dword on a 32-bit machine), the
89: * return value will be zero.
90: */
91: unsigned long pci_bar_start ( struct pci_device *pci, unsigned int reg ) {
92: unsigned long bar;
93:
94: bar = pci_bar ( pci, reg );
95: if ( (bar & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY ){
96: return ( bar & PCI_BASE_ADDRESS_MEM_MASK );
97: } else {
98: return ( bar & PCI_BASE_ADDRESS_IO_MASK );
99: }
100: }
101:
102: /**
103: * Read membase and ioaddr for a PCI device
104: *
105: * @v pci PCI device
106: *
107: * This scans through all PCI BARs on the specified device. The first
108: * valid memory BAR is recorded as pci_device::membase, and the first
109: * valid IO BAR is recorded as pci_device::ioaddr.
110: *
111: * 64-bit BARs are handled automatically. On a 32-bit platform, if a
112: * 64-bit BAR has a non-zero high dword, it will be regarded as
113: * invalid.
114: */
115: static void pci_read_bases ( struct pci_device *pci ) {
116: unsigned long bar;
117: int reg;
118:
119: for ( reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4 ) {
120: bar = pci_bar ( pci, reg );
121: if ( bar & PCI_BASE_ADDRESS_SPACE_IO ) {
122: if ( ! pci->ioaddr )
123: pci->ioaddr =
124: ( bar & PCI_BASE_ADDRESS_IO_MASK );
125: } else {
126: if ( ! pci->membase )
127: pci->membase =
128: ( bar & PCI_BASE_ADDRESS_MEM_MASK );
129: /* Skip next BAR if 64-bit */
130: if ( bar & PCI_BASE_ADDRESS_MEM_TYPE_64 )
131: reg += 4;
132: }
133: }
134: }
135:
136: /**
137: * Enable PCI device
138: *
139: * @v pci PCI device
140: *
141: * Set device to be a busmaster in case BIOS neglected to do so. Also
142: * adjust PCI latency timer to a reasonable value, 32.
143: */
144: void adjust_pci_device ( struct pci_device *pci ) {
145: unsigned short new_command, pci_command;
146: unsigned char pci_latency;
147:
148: pci_read_config_word ( pci, PCI_COMMAND, &pci_command );
149: new_command = ( pci_command | PCI_COMMAND_MASTER |
150: PCI_COMMAND_MEM | PCI_COMMAND_IO );
151: if ( pci_command != new_command ) {
152: DBGC ( pci, PCI_FMT " device not enabled by BIOS! Updating "
153: "PCI command %04x->%04x\n",
154: PCI_ARGS ( pci ), pci_command, new_command );
155: pci_write_config_word ( pci, PCI_COMMAND, new_command );
156: }
157:
158: pci_read_config_byte ( pci, PCI_LATENCY_TIMER, &pci_latency);
159: if ( pci_latency < 32 ) {
160: DBGC ( pci, PCI_FMT " latency timer is unreasonably low at "
161: "%d. Setting to 32.\n", PCI_ARGS ( pci ), pci_latency );
162: pci_write_config_byte ( pci, PCI_LATENCY_TIMER, 32);
163: }
164: }
165:
166: /**
167: * Read PCI device configuration
168: *
169: * @v pci PCI device
170: * @ret rc Return status code
171: */
172: int pci_read_config ( struct pci_device *pci ) {
173: uint32_t tmp;
174:
175: /* Check for physical device presence */
176: pci_read_config_dword ( pci, PCI_VENDOR_ID, &tmp );
177: if ( ( tmp == 0xffffffff ) || ( tmp == 0 ) )
178: return -ENODEV;
179:
180: /* Populate struct pci_device */
181: pci->vendor = ( tmp & 0xffff );
182: pci->device = ( tmp >> 16 );
183: pci_read_config_dword ( pci, PCI_REVISION, &tmp );
184: pci->class = ( tmp >> 8 );
185: pci_read_config_byte ( pci, PCI_INTERRUPT_LINE, &pci->irq );
186: pci_read_bases ( pci );
187:
188: /* Initialise generic device component */
189: snprintf ( pci->dev.name, sizeof ( pci->dev.name ),
190: "PCI%02x:%02x.%x", PCI_BUS ( pci->busdevfn ),
191: PCI_SLOT ( pci->busdevfn ), PCI_FUNC ( pci->busdevfn ) );
192: pci->dev.desc.bus_type = BUS_TYPE_PCI;
193: pci->dev.desc.location = pci->busdevfn;
194: pci->dev.desc.vendor = pci->vendor;
195: pci->dev.desc.device = pci->device;
196: pci->dev.desc.class = pci->class;
197: pci->dev.desc.ioaddr = pci->ioaddr;
198: pci->dev.desc.irq = pci->irq;
199: INIT_LIST_HEAD ( &pci->dev.siblings );
200: INIT_LIST_HEAD ( &pci->dev.children );
201:
202: return 0;
203: }
204:
205: /**
206: * Find driver for PCI device
207: *
208: * @v pci PCI device
209: * @ret rc Return status code
210: */
211: int pci_find_driver ( struct pci_device *pci ) {
212: struct pci_driver *driver;
213: struct pci_device_id *id;
214: unsigned int i;
215:
216: for_each_table_entry ( driver, PCI_DRIVERS ) {
217: for ( i = 0 ; i < driver->id_count ; i++ ) {
218: id = &driver->ids[i];
219: if ( ( id->vendor != PCI_ANY_ID ) &&
220: ( id->vendor != pci->vendor ) )
221: continue;
222: if ( ( id->device != PCI_ANY_ID ) &&
223: ( id->device != pci->device ) )
224: continue;
225: pci_set_driver ( pci, driver, id );
226: return 0;
227: }
228: }
229: return -ENOENT;
230: }
231:
232: /**
233: * Probe a PCI device
234: *
235: * @v pci PCI device
236: * @ret rc Return status code
237: *
238: * Searches for a driver for the PCI device. If a driver is found,
239: * its probe() routine is called.
240: */
241: int pci_probe ( struct pci_device *pci ) {
242: int rc;
243:
244: DBGC ( pci, PCI_FMT " (%04x:%04x) has driver \"%s\"\n",
245: PCI_ARGS ( pci ), pci->vendor, pci->device, pci->id->name );
246: DBGC ( pci, PCI_FMT " has mem %lx io %lx irq %d\n",
247: PCI_ARGS ( pci ), pci->membase, pci->ioaddr, pci->irq );
248:
249: if ( ( rc = pci->driver->probe ( pci ) ) != 0 ) {
250: DBGC ( pci, PCI_FMT " probe failed: %s\n",
251: PCI_ARGS ( pci ), strerror ( rc ) );
252: return rc;
253: }
254:
255: return 0;
256: }
257:
258: /**
259: * Remove a PCI device
260: *
261: * @v pci PCI device
262: */
263: void pci_remove ( struct pci_device *pci ) {
264: pci->driver->remove ( pci );
265: DBGC ( pci, PCI_FMT " removed\n", PCI_ARGS ( pci ) );
266: }
267:
268: /**
269: * Probe PCI root bus
270: *
271: * @v rootdev PCI bus root device
272: *
273: * Scans the PCI bus for devices and registers all devices it can
274: * find.
275: */
276: static int pcibus_probe ( struct root_device *rootdev ) {
277: struct pci_device *pci = NULL;
278: unsigned int num_bus;
279: unsigned int busdevfn;
280: uint8_t hdrtype = 0;
281: int rc;
282:
283: num_bus = pci_num_bus();
284: for ( busdevfn = 0 ; busdevfn < PCI_BUSDEVFN ( num_bus, 0, 0 ) ;
285: busdevfn++ ) {
286:
287: /* Allocate struct pci_device */
288: if ( ! pci )
289: pci = malloc ( sizeof ( *pci ) );
290: if ( ! pci ) {
291: rc = -ENOMEM;
292: goto err;
293: }
294: memset ( pci, 0, sizeof ( *pci ) );
295: pci_init ( pci, busdevfn );
296:
297: /* Skip all but the first function on
298: * non-multifunction cards
299: */
300: if ( PCI_FUNC ( busdevfn ) == 0 ) {
301: pci_read_config_byte ( pci, PCI_HEADER_TYPE,
302: &hdrtype );
303: } else if ( ! ( hdrtype & 0x80 ) ) {
304: continue;
305: }
306:
307: /* Read device configuration */
308: if ( ( rc = pci_read_config ( pci ) ) != 0 )
309: continue;
310:
311: /* Look for a driver */
312: if ( ( rc = pci_find_driver ( pci ) ) != 0 ) {
313: DBGC ( pci, PCI_FMT " (%04x:%04x) has no driver\n",
314: PCI_ARGS ( pci ), pci->vendor, pci->device );
315: continue;
316: }
317:
318: /* Add to device hierarchy */
319: pci->dev.parent = &rootdev->dev;
320: list_add ( &pci->dev.siblings, &rootdev->dev.children);
321:
322: /* Look for a driver */
323: if ( ( rc = pci_probe ( pci ) ) == 0 ) {
324: /* pcidev registered, we can drop our ref */
325: pci = NULL;
326: } else {
327: /* Not registered; re-use struct pci_device */
328: list_del ( &pci->dev.siblings );
329: }
330: }
331:
332: free ( pci );
333: return 0;
334:
335: err:
336: free ( pci );
337: pcibus_remove ( rootdev );
338: return rc;
339: }
340:
341: /**
342: * Remove PCI root bus
343: *
344: * @v rootdev PCI bus root device
345: */
346: static void pcibus_remove ( struct root_device *rootdev ) {
347: struct pci_device *pci;
348: struct pci_device *tmp;
349:
350: list_for_each_entry_safe ( pci, tmp, &rootdev->dev.children,
351: dev.siblings ) {
352: pci_remove ( pci );
353: list_del ( &pci->dev.siblings );
354: free ( pci );
355: }
356: }
357:
358: /** PCI bus root device driver */
359: static struct root_driver pci_root_driver = {
360: .probe = pcibus_probe,
361: .remove = pcibus_remove,
362: };
363:
364: /** PCI bus root device */
365: struct root_device pci_root_device __root_device = {
366: .dev = { .name = "PCI" },
367: .driver = &pci_root_driver,
368: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.