blob: fcf9730981519870b8f8cc300d5c08aead58202f [file] [log] [blame]
Eric Biederman8ca8d762003-04-22 19:02:15 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Uwe Hermannb80dbf02007-04-22 19:08:13 +00003 *
4 * It was originally based on the Linux kernel (drivers/pci/pci.c).
5 *
6 * Modifications are:
7 * Copyright (C) 2003-2004 Linux Networx
8 * (Written by Eric Biederman <ebiederman@lnxi.com> for Linux Networx)
9 * Copyright (C) 2003-2006 Ronald G. Minnich <rminnich@gmail.com>
10 * Copyright (C) 2004-2005 Li-Ta Lo <ollie@lanl.gov>
11 * Copyright (C) 2005-2006 Tyan
12 * (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
13 * Copyright (C) 2005-2007 Stefan Reinauer <stepan@openbios.org>
14 */
15
16/*
Eric Biederman8ca8d762003-04-22 19:02:15 +000017 * PCI Bus Services, see include/linux/pci.h for further explanation.
18 *
19 * Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter,
20 * David Mosberger-Tang
21 *
22 * Copyright 1997 -- 1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
Eric Biederman8ca8d762003-04-22 19:02:15 +000023 */
24
25#include <console/console.h>
26#include <stdlib.h>
27#include <stdint.h>
28#include <bitops.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +000029#include <string.h>
Ronald G. Minnich6dd6c6852003-10-02 00:08:42 +000030#include <arch/io.h>
Eric Biederman5899fd82003-04-24 06:25:08 +000031#include <device/device.h>
32#include <device/pci.h>
33#include <device/pci_ids.h>
Eric Biedermane9a271e32003-09-02 03:36:25 +000034#include <part/hard_reset.h>
Eric Biederman30e143a2003-09-01 23:45:32 +000035#include <part/fallback_boot.h>
Eric Biederman03acab62004-10-14 21:25:53 +000036#include <delay.h>
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000037#if CONFIG_HYPERTRANSPORT_PLUGIN_SUPPORT == 1
38#include <device/hypertransport.h>
39#endif
40#if CONFIG_PCIX_PLUGIN_SUPPORT == 1
41#include <device/pcix.h>
42#endif
43#if CONFIG_PCIEXP_PLUGIN_SUPPORT == 1
44#include <device/pciexp.h>
45#endif
46#if CONFGI_AGP_PLUGIN_SUPPORT == 1
47#include <device/agp.h>
48#endif
49#if CONFIG_CARDBUS_PLUGIN_SUPPORT == 1
50#include <device/cardbus.h>
51#endif
Eric Biederman03acab62004-10-14 21:25:53 +000052
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000053uint8_t pci_moving_config8(struct device *dev, unsigned reg)
Eric Biederman03acab62004-10-14 21:25:53 +000054{
55 uint8_t value, ones, zeroes;
56 value = pci_read_config8(dev, reg);
57
58 pci_write_config8(dev, reg, 0xff);
59 ones = pci_read_config8(dev, reg);
60
61 pci_write_config8(dev, reg, 0x00);
62 zeroes = pci_read_config8(dev, reg);
63
64 pci_write_config8(dev, reg, value);
65
66 return ones ^ zeroes;
67}
Li-Ta Lo9a5b4962004-12-23 21:48:01 +000068
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000069uint16_t pci_moving_config16(struct device *dev, unsigned reg)
Eric Biederman03acab62004-10-14 21:25:53 +000070{
71 uint16_t value, ones, zeroes;
72 value = pci_read_config16(dev, reg);
73
74 pci_write_config16(dev, reg, 0xffff);
75 ones = pci_read_config16(dev, reg);
76
77 pci_write_config16(dev, reg, 0x0000);
78 zeroes = pci_read_config16(dev, reg);
79
80 pci_write_config16(dev, reg, value);
81
82 return ones ^ zeroes;
83}
Li-Ta Loe8b1c9d2004-12-27 04:25:41 +000084
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000085uint32_t pci_moving_config32(struct device *dev, unsigned reg)
Eric Biederman03acab62004-10-14 21:25:53 +000086{
87 uint32_t value, ones, zeroes;
88 value = pci_read_config32(dev, reg);
89
90 pci_write_config32(dev, reg, 0xffffffff);
91 ones = pci_read_config32(dev, reg);
92
93 pci_write_config32(dev, reg, 0x00000000);
94 zeroes = pci_read_config32(dev, reg);
95
96 pci_write_config32(dev, reg, value);
97
98 return ones ^ zeroes;
99}
100
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000101unsigned pci_find_next_capability(device_t dev, unsigned cap, unsigned last)
Eric Biederman03acab62004-10-14 21:25:53 +0000102{
103 unsigned pos;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000104 unsigned status;
105 unsigned reps = 48;
Eric Biederman03acab62004-10-14 21:25:53 +0000106 pos = 0;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000107 status = pci_read_config16(dev, PCI_STATUS);
108 if (!(status & PCI_STATUS_CAP_LIST)) {
109 return 0;
110 }
Eric Biederman03acab62004-10-14 21:25:53 +0000111 switch(dev->hdr_type & 0x7f) {
112 case PCI_HEADER_TYPE_NORMAL:
113 case PCI_HEADER_TYPE_BRIDGE:
114 pos = PCI_CAPABILITY_LIST;
115 break;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000116 case PCI_HEADER_TYPE_CARDBUS:
117 pos = PCI_CB_CAPABILITY_LIST;
118 break;
119 default:
120 return 0;
Eric Biederman03acab62004-10-14 21:25:53 +0000121 }
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000122 pos = pci_read_config8(dev, pos);
123 while(reps-- && (pos >= 0x40)) { /* loop through the linked list */
Eric Biederman03acab62004-10-14 21:25:53 +0000124 int this_cap;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000125 pos &= ~3;
Eric Biederman03acab62004-10-14 21:25:53 +0000126 this_cap = pci_read_config8(dev, pos + PCI_CAP_LIST_ID);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000127 printk_spew("Capability: 0x%02x @ 0x%02x\n", cap, pos);
128 if (this_cap == 0xff) {
129 break;
130 }
131 if (!last && (this_cap == cap)) {
Eric Biederman03acab62004-10-14 21:25:53 +0000132 return pos;
133 }
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000134 if (last == pos) {
135 last = 0;
136 }
137 pos = pci_read_config8(dev, pos + PCI_CAP_LIST_NEXT);
Eric Biederman03acab62004-10-14 21:25:53 +0000138 }
139 return 0;
140}
141
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000142unsigned pci_find_capability(device_t dev, unsigned cap)
143{
144 return pci_find_next_capability(dev, cap, 0);
145
146}
147
Eric Biederman8ca8d762003-04-22 19:02:15 +0000148/** Given a device and register, read the size of the BAR for that register.
149 * @param dev Pointer to the device structure
150 * @param resource Pointer to the resource structure
151 * @param index Address of the pci configuration register
152 */
Eric Biederman03acab62004-10-14 21:25:53 +0000153struct resource *pci_get_resource(struct device *dev, unsigned long index)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000154{
Eric Biederman5cd81732004-03-11 15:01:31 +0000155 struct resource *resource;
Eric Biederman03acab62004-10-14 21:25:53 +0000156 unsigned long value, attr;
157 resource_t moving, limit;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000158
159 /* Initialize the resources to nothing */
Eric Biederman03acab62004-10-14 21:25:53 +0000160 resource = new_resource(dev, index);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000161
Eric Biederman03acab62004-10-14 21:25:53 +0000162 /* Get the initial value */
163 value = pci_read_config32(dev, index);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000164
Eric Biederman03acab62004-10-14 21:25:53 +0000165 /* See which bits move */
166 moving = pci_moving_config32(dev, index);
Li-Ta Lo9a5b4962004-12-23 21:48:01 +0000167
Eric Biederman03acab62004-10-14 21:25:53 +0000168 /* Initialize attr to the bits that do not move */
169 attr = value & ~moving;
170
171 /* If it is a 64bit resource look at the high half as well */
172 if (((attr & PCI_BASE_ADDRESS_SPACE_IO) == 0) &&
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000173 ((attr & PCI_BASE_ADDRESS_MEM_LIMIT_MASK) == PCI_BASE_ADDRESS_MEM_LIMIT_64))
Eric Biederman03acab62004-10-14 21:25:53 +0000174 {
175 /* Find the high bits that move */
176 moving |= ((resource_t)pci_moving_config32(dev, index + 4)) << 32;
177 }
178 /* Find the resource constraints.
179 *
180 * Start by finding the bits that move. From there:
181 * - Size is the least significant bit of the bits that move.
182 * - Limit is all of the bits that move plus all of the lower bits.
183 * See PCI Spec 6.2.5.1 ...
Eric Biederman8ca8d762003-04-22 19:02:15 +0000184 */
Eric Biederman03acab62004-10-14 21:25:53 +0000185 limit = 0;
186 if (moving) {
187 resource->size = 1;
188 resource->align = resource->gran = 0;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000189 while(!(moving & resource->size)) {
Eric Biederman03acab62004-10-14 21:25:53 +0000190 resource->size <<= 1;
191 resource->align += 1;
192 resource->gran += 1;
193 }
194 resource->limit = limit = moving | (resource->size - 1);
195 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000196 /*
197 * some broken hardware has read-only registers that do not
Eric Biederman03acab62004-10-14 21:25:53 +0000198 * really size correctly.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000199 * Example: the acer m7229 has BARs 1-4 normally read-only.
200 * so BAR1 at offset 0x10 reads 0x1f1. If you size that register
201 * by writing 0xffffffff to it, it will read back as 0x1f1 -- a
202 * violation of the spec.
Eric Biederman03acab62004-10-14 21:25:53 +0000203 * We catch this case and ignore it by observing which bits move,
204 * This also catches the common case unimplemented registers
205 * that always read back as 0.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000206 */
Eric Biederman03acab62004-10-14 21:25:53 +0000207 if (moving == 0) {
208 if (value != 0) {
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000209 printk_debug(
210 "%s register %02x(%08x), read-only ignoring it\n",
211 dev_path(dev), index, value);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000212 }
213 resource->flags = 0;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000214 }
215 else if (attr & PCI_BASE_ADDRESS_SPACE_IO) {
Eric Biederman03acab62004-10-14 21:25:53 +0000216 /* An I/O mapped base address */
217 attr &= PCI_BASE_ADDRESS_IO_ATTR_MASK;
Eric Biederman5cd81732004-03-11 15:01:31 +0000218 resource->flags |= IORESOURCE_IO;
Eric Biederman03acab62004-10-14 21:25:53 +0000219 /* I don't want to deal with 32bit I/O resources */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000220 resource->limit = 0xffff;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000221 }
222 else {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000223 /* A Memory mapped base address */
Eric Biederman03acab62004-10-14 21:25:53 +0000224 attr &= PCI_BASE_ADDRESS_MEM_ATTR_MASK;
Eric Biederman5cd81732004-03-11 15:01:31 +0000225 resource->flags |= IORESOURCE_MEM;
Eric Biederman03acab62004-10-14 21:25:53 +0000226 if (attr & PCI_BASE_ADDRESS_MEM_PREFETCH) {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000227 resource->flags |= IORESOURCE_PREFETCH;
228 }
Eric Biederman03acab62004-10-14 21:25:53 +0000229 attr &= PCI_BASE_ADDRESS_MEM_LIMIT_MASK;
230 if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_32) {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000231 /* 32bit limit */
232 resource->limit = 0xffffffffUL;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000233 }
234 else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_1M) {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000235 /* 1MB limit */
236 resource->limit = 0x000fffffUL;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000237 }
238 else if (attr == PCI_BASE_ADDRESS_MEM_LIMIT_64) {
Eric Biederman03acab62004-10-14 21:25:53 +0000239 /* 64bit limit */
240 resource->limit = 0xffffffffffffffffULL;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000241 resource->flags |= IORESOURCE_PCI64;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000242 }
243 else {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000244 /* Invalid value */
245 resource->flags = 0;
246 }
247 }
Eric Biederman03acab62004-10-14 21:25:53 +0000248 /* Don't let the limit exceed which bits can move */
249 if (resource->limit > limit) {
250 resource->limit = limit;
251 }
252#if 0
253 if (resource->flags) {
254 printk_debug("%s %02x ->",
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000255 dev_path(dev), resource->index);
Eric Biederman03acab62004-10-14 21:25:53 +0000256 printk_debug(" value: 0x%08Lx zeroes: 0x%08Lx ones: 0x%08Lx attr: %08lx\n",
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000257 value, zeroes, ones, attr);
Eric Biederman03acab62004-10-14 21:25:53 +0000258 printk_debug(
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000259 "%s %02x -> size: 0x%08Lx max: 0x%08Lx %s\n ",
Eric Biederman03acab62004-10-14 21:25:53 +0000260 dev_path(dev),
261 resource->index,
262 resource->size, resource->limit,
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000263 resource_type(resource));
Eric Biederman03acab62004-10-14 21:25:53 +0000264 }
265#endif
266
Eric Biederman5cd81732004-03-11 15:01:31 +0000267 return resource;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000268}
269
Li-Ta Loe8b1c9d2004-12-27 04:25:41 +0000270static void pci_get_rom_resource(struct device *dev, unsigned long index)
Li-Ta Lo9a5b4962004-12-23 21:48:01 +0000271{
272 struct resource *resource;
Li-Ta Loe8b1c9d2004-12-27 04:25:41 +0000273 unsigned long value;
Li-Ta Lo9a5b4962004-12-23 21:48:01 +0000274 resource_t moving, limit;
275
Li-Ta Lobec039c2005-01-19 23:19:26 +0000276 if ((dev->on_mainboard) && (dev->rom_address == 0)) {
277 //skip it if rom_address is not set in MB Config.lb
Yinghai Lubcde1612005-01-14 05:34:09 +0000278 return;
279 }
280
Li-Ta Lo9a5b4962004-12-23 21:48:01 +0000281 /* Initialize the resources to nothing */
282 resource = new_resource(dev, index);
283
284 /* Get the initial value */
285 value = pci_read_config32(dev, index);
286
287 /* See which bits move */
288 moving = pci_moving_config32(dev, index);
289 /* clear the Enable bit */
Li-Ta Loe8b1c9d2004-12-27 04:25:41 +0000290 moving = moving & ~PCI_ROM_ADDRESS_ENABLE;
Li-Ta Lo9a5b4962004-12-23 21:48:01 +0000291
292 /* Find the resource constraints.
293 *
294 * Start by finding the bits that move. From there:
295 * - Size is the least significant bit of the bits that move.
296 * - Limit is all of the bits that move plus all of the lower bits.
297 * See PCI Spec 6.2.5.1 ...
298 */
299 limit = 0;
300
301 if (moving) {
302 resource->size = 1;
303 resource->align = resource->gran = 0;
Li-Ta Loe8b1c9d2004-12-27 04:25:41 +0000304 while (!(moving & resource->size)) {
Li-Ta Lo9a5b4962004-12-23 21:48:01 +0000305 resource->size <<= 1;
306 resource->align += 1;
307 resource->gran += 1;
308 }
309 resource->limit = limit = moving | (resource->size - 1);
Li-Ta Lo9a5b4962004-12-23 21:48:01 +0000310 }
311
312 if (moving == 0) {
313 if (value != 0) {
314 printk_debug("%s register %02x(%08x), read-only ignoring it\n",
315 dev_path(dev), index, value);
316 }
317 resource->flags = 0;
318 } else {
319 resource->flags |= IORESOURCE_MEM | IORESOURCE_READONLY;
320 }
Yinghai Luc7870ac2005-01-13 19:14:52 +0000321
322 /* for on board device with embedded ROM image, the ROM image is at
323 * fixed address specified in the Config.lb, the dev->rom_address is
324 * inited by driver_pci_onboard_ops::enable_dev() */
Yinghai Lubcde1612005-01-14 05:34:09 +0000325 if ((dev->on_mainboard) && (dev->rom_address != 0)) {
Yinghai Luc7870ac2005-01-13 19:14:52 +0000326 resource->base = dev->rom_address;
327 resource->flags |= IORESOURCE_MEM | IORESOURCE_READONLY |
328 IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
329 }
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000330
331 compact_resources(dev);
Li-Ta Loe8b1c9d2004-12-27 04:25:41 +0000332}
Li-Ta Lo9a5b4962004-12-23 21:48:01 +0000333
Li-Ta Loe8b1c9d2004-12-27 04:25:41 +0000334/** Read the base address registers for a given device.
335 * @param dev Pointer to the dev structure
336 * @param howmany How many registers to read (6 for device, 2 for bridge)
337 */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000338static void pci_read_bases(struct device *dev, unsigned int howmany)
Li-Ta Loe8b1c9d2004-12-27 04:25:41 +0000339{
340 unsigned long index;
341
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000342 for(index = PCI_BASE_ADDRESS_0; (index < PCI_BASE_ADDRESS_0 + (howmany << 2)); ) {
Li-Ta Loe8b1c9d2004-12-27 04:25:41 +0000343 struct resource *resource;
344 resource = pci_get_resource(dev, index);
345 index += (resource->flags & IORESOURCE_PCI64)?8:4;
346 }
Li-Ta Loe8b1c9d2004-12-27 04:25:41 +0000347
348 compact_resources(dev);
Li-Ta Lo9a5b4962004-12-23 21:48:01 +0000349}
350
Eric Biederman03acab62004-10-14 21:25:53 +0000351static void pci_set_resource(struct device *dev, struct resource *resource);
352
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000353static void pci_record_bridge_resource(
354 struct device *dev, resource_t moving,
355 unsigned index, unsigned long mask, unsigned long type)
Eric Biederman03acab62004-10-14 21:25:53 +0000356{
357 /* Initiliaze the constraints on the current bus */
358 struct resource *resource;
359 resource = 0;
360 if (moving) {
361 unsigned long gran;
362 resource_t step;
363 resource = new_resource(dev, index);
364 resource->size = 0;
365 gran = 0;
366 step = 1;
367 while((moving & step) == 0) {
368 gran += 1;
369 step <<= 1;
370 }
371 resource->gran = gran;
372 resource->align = gran;
373 resource->limit = moving | (step - 1);
374 resource->flags = type | IORESOURCE_PCI_BRIDGE;
375 compute_allocate_resource(&dev->link[0], resource, mask, type);
376 /* If there is nothing behind the resource,
377 * clear it and forget it.
378 */
379 if (resource->size == 0) {
Stefan Reinauer532fd2d2008-10-29 03:15:42 +0000380#if CONFIG_PCI_64BIT_PREF_MEM == 1
Eric Biederman03acab62004-10-14 21:25:53 +0000381 resource->base = moving;
Stefan Reinauer532fd2d2008-10-29 03:15:42 +0000382#else
383 resource->base = moving & 0xffffffff;
384#endif
Eric Biederman03acab62004-10-14 21:25:53 +0000385 resource->flags |= IORESOURCE_ASSIGNED;
386 resource->flags &= ~IORESOURCE_STORED;
387 pci_set_resource(dev, resource);
388 resource->flags = 0;
389 }
390 }
391 return;
392}
393
Eric Biederman8ca8d762003-04-22 19:02:15 +0000394static void pci_bridge_read_bases(struct device *dev)
395{
Eric Biederman03acab62004-10-14 21:25:53 +0000396 resource_t moving_base, moving_limit, moving;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000397
Eric Biederman03acab62004-10-14 21:25:53 +0000398 /* See if the bridge I/O resources are implemented */
399 moving_base = ((uint32_t)pci_moving_config8(dev, PCI_IO_BASE)) << 8;
400 moving_base |= ((uint32_t)pci_moving_config16(dev, PCI_IO_BASE_UPPER16)) << 16;
401
402 moving_limit = ((uint32_t)pci_moving_config8(dev, PCI_IO_LIMIT)) << 8;
403 moving_limit |= ((uint32_t)pci_moving_config16(dev, PCI_IO_LIMIT_UPPER16)) << 16;
404
405 moving = moving_base & moving_limit;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000406
407 /* Initialize the io space constraints on the current bus */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000408 pci_record_bridge_resource(
409 dev, moving, PCI_IO_BASE,
410 IORESOURCE_IO, IORESOURCE_IO);
411
Eric Biederman03acab62004-10-14 21:25:53 +0000412
413 /* See if the bridge prefmem resources are implemented */
414 moving_base = ((resource_t)pci_moving_config16(dev, PCI_PREF_MEMORY_BASE)) << 16;
415 moving_base |= ((resource_t)pci_moving_config32(dev, PCI_PREF_BASE_UPPER32)) << 32;
416
417 moving_limit = ((resource_t)pci_moving_config16(dev, PCI_PREF_MEMORY_LIMIT)) << 16;
418 moving_limit |= ((resource_t)pci_moving_config32(dev, PCI_PREF_LIMIT_UPPER32)) << 32;
419
420 moving = moving_base & moving_limit;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000421 /* Initiliaze the prefetchable memory constraints on the current bus */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000422 pci_record_bridge_resource(
423 dev, moving, PCI_PREF_MEMORY_BASE,
424 IORESOURCE_MEM | IORESOURCE_PREFETCH,
425 IORESOURCE_MEM | IORESOURCE_PREFETCH);
426
Eric Biederman03acab62004-10-14 21:25:53 +0000427
428 /* See if the bridge mem resources are implemented */
429 moving_base = ((uint32_t)pci_moving_config16(dev, PCI_MEMORY_BASE)) << 16;
430 moving_limit = ((uint32_t)pci_moving_config16(dev, PCI_MEMORY_LIMIT)) << 16;
431
432 moving = moving_base & moving_limit;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000433
434 /* Initialize the memory resources on the current bus */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000435 pci_record_bridge_resource(
436 dev, moving, PCI_MEMORY_BASE,
437 IORESOURCE_MEM | IORESOURCE_PREFETCH,
438 IORESOURCE_MEM);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000439
Eric Biederman5cd81732004-03-11 15:01:31 +0000440 compact_resources(dev);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000441}
442
Eric Biederman5899fd82003-04-24 06:25:08 +0000443void pci_dev_read_resources(struct device *dev)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000444{
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000445 pci_read_bases(dev, 6);
446 pci_get_rom_resource(dev, PCI_ROM_ADDRESS);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000447}
448
Eric Biederman5899fd82003-04-24 06:25:08 +0000449void pci_bus_read_resources(struct device *dev)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000450{
Eric Biederman8ca8d762003-04-22 19:02:15 +0000451 pci_bridge_read_bases(dev);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000452 pci_read_bases(dev, 2);
453 pci_get_rom_resource(dev, PCI_ROM_ADDRESS1);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000454}
455
Eric Biederman8ca8d762003-04-22 19:02:15 +0000456static void pci_set_resource(struct device *dev, struct resource *resource)
457{
Eric Biederman03acab62004-10-14 21:25:53 +0000458 resource_t base, end;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000459
Eric Biederman8ca8d762003-04-22 19:02:15 +0000460 /* Make certain the resource has actually been set */
Eric Biederman5cd81732004-03-11 15:01:31 +0000461 if (!(resource->flags & IORESOURCE_ASSIGNED)) {
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000462 printk_err("ERROR: %s %02x %s size: 0x%010Lx not assigned\n",
463 dev_path(dev), resource->index,
464 resource_type(resource),
465 resource->size);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000466 return;
467 }
468
Eric Biederman5cd81732004-03-11 15:01:31 +0000469 /* If I have already stored this resource don't worry about it */
470 if (resource->flags & IORESOURCE_STORED) {
471 return;
472 }
473
Eric Biederman03acab62004-10-14 21:25:53 +0000474 /* If the resources is substractive don't worry about it */
475 if (resource->flags & IORESOURCE_SUBTRACTIVE) {
476 return;
477 }
478
Eric Biederman8ca8d762003-04-22 19:02:15 +0000479 /* Only handle PCI memory and IO resources for now */
480 if (!(resource->flags & (IORESOURCE_MEM |IORESOURCE_IO)))
481 return;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000482
Eric Biederman03acab62004-10-14 21:25:53 +0000483 /* Enable the resources in the command register */
484 if (resource->size) {
485 if (resource->flags & IORESOURCE_MEM) {
486 dev->command |= PCI_COMMAND_MEMORY;
487 }
488 if (resource->flags & IORESOURCE_IO) {
489 dev->command |= PCI_COMMAND_IO;
490 }
491 if (resource->flags & IORESOURCE_PCI_BRIDGE) {
492 dev->command |= PCI_COMMAND_MASTER;
493 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000494 }
495 /* Get the base address */
496 base = resource->base;
Eric Biederman5cd81732004-03-11 15:01:31 +0000497
Eric Biederman03acab62004-10-14 21:25:53 +0000498 /* Get the end */
499 end = resource_end(resource);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000500
Eric Biederman5cd81732004-03-11 15:01:31 +0000501 /* Now store the resource */
502 resource->flags |= IORESOURCE_STORED;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000503 if (!(resource->flags & IORESOURCE_PCI_BRIDGE)) {
Eric Biederman03acab62004-10-14 21:25:53 +0000504 unsigned long base_lo, base_hi;
Eric Biedermanb78c1972004-10-14 20:54:17 +0000505 /*
506 * some chipsets allow us to set/clear the IO bit.
507 * (e.g. VIA 82c686a.) So set it to be safe)
508 */
Eric Biederman03acab62004-10-14 21:25:53 +0000509 base_lo = base & 0xffffffff;
510 base_hi = (base >> 32) & 0xffffffff;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000511 if (resource->flags & IORESOURCE_IO) {
Eric Biederman03acab62004-10-14 21:25:53 +0000512 base_lo |= PCI_BASE_ADDRESS_SPACE_IO;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000513 }
Eric Biederman03acab62004-10-14 21:25:53 +0000514 pci_write_config32(dev, resource->index, base_lo);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000515 if (resource->flags & IORESOURCE_PCI64) {
Eric Biederman03acab62004-10-14 21:25:53 +0000516 pci_write_config32(dev, resource->index + 4, base_hi);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000517 }
Eric Biedermanb78c1972004-10-14 20:54:17 +0000518 }
519 else if (resource->index == PCI_IO_BASE) {
Eric Biederman03acab62004-10-14 21:25:53 +0000520 /* set the IO ranges */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000521 compute_allocate_resource(&dev->link[0], resource,
Eric Biedermanb78c1972004-10-14 20:54:17 +0000522 IORESOURCE_IO, IORESOURCE_IO);
Eric Biederman03acab62004-10-14 21:25:53 +0000523 pci_write_config8(dev, PCI_IO_BASE, base >> 8);
524 pci_write_config16(dev, PCI_IO_BASE_UPPER16, base >> 16);
525 pci_write_config8(dev, PCI_IO_LIMIT, end >> 8);
526 pci_write_config16(dev, PCI_IO_LIMIT_UPPER16, end >> 16);
Eric Biedermanb78c1972004-10-14 20:54:17 +0000527 }
528 else if (resource->index == PCI_MEMORY_BASE) {
Eric Biederman03acab62004-10-14 21:25:53 +0000529 /* set the memory range */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000530 compute_allocate_resource(&dev->link[0], resource,
Eric Biedermanb78c1972004-10-14 20:54:17 +0000531 IORESOURCE_MEM | IORESOURCE_PREFETCH,
532 IORESOURCE_MEM);
Eric Biederman7a5416a2003-06-12 19:23:51 +0000533 pci_write_config16(dev, PCI_MEMORY_BASE, base >> 16);
Eric Biederman03acab62004-10-14 21:25:53 +0000534 pci_write_config16(dev, PCI_MEMORY_LIMIT, end >> 16);
Eric Biedermanb78c1972004-10-14 20:54:17 +0000535 }
536 else if (resource->index == PCI_PREF_MEMORY_BASE) {
Eric Biederman03acab62004-10-14 21:25:53 +0000537 /* set the prefetchable memory range */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000538 compute_allocate_resource(&dev->link[0], resource,
Eric Biedermanb78c1972004-10-14 20:54:17 +0000539 IORESOURCE_MEM | IORESOURCE_PREFETCH,
540 IORESOURCE_MEM | IORESOURCE_PREFETCH);
Eric Biederman03acab62004-10-14 21:25:53 +0000541 pci_write_config16(dev, PCI_PREF_MEMORY_BASE, base >> 16);
542 pci_write_config32(dev, PCI_PREF_BASE_UPPER32, base >> 32);
543 pci_write_config16(dev, PCI_PREF_MEMORY_LIMIT, end >> 16);
544 pci_write_config32(dev, PCI_PREF_LIMIT_UPPER32, end >> 32);
Eric Biedermanb78c1972004-10-14 20:54:17 +0000545 }
546 else {
Eric Biederman5cd81732004-03-11 15:01:31 +0000547 /* Don't let me think I stored the resource */
548 resource->flags &= ~IORESOURCE_STORED;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000549 printk_err("ERROR: invalid resource->index %x\n",
Eric Biedermanb78c1972004-10-14 20:54:17 +0000550 resource->index);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000551 }
Eric Biederman03acab62004-10-14 21:25:53 +0000552 report_resource_stored(dev, resource, "");
Eric Biederman8ca8d762003-04-22 19:02:15 +0000553 return;
554}
555
Eric Biederman5899fd82003-04-24 06:25:08 +0000556void pci_dev_set_resources(struct device *dev)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000557{
558 struct resource *resource, *last;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000559 unsigned link;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000560 uint8_t line;
561
562 last = &dev->resource[dev->resources];
Eric Biedermanb78c1972004-10-14 20:54:17 +0000563
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000564 for(resource = &dev->resource[0]; resource < last; resource++) {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000565 pci_set_resource(dev, resource);
566 }
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000567 for(link = 0; link < dev->links; link++) {
Eric Biedermane9a271e32003-09-02 03:36:25 +0000568 struct bus *bus;
569 bus = &dev->link[link];
570 if (bus->children) {
571 assign_resources(bus);
572 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000573 }
574
575 /* set a default latency timer */
Eric Biederman7a5416a2003-06-12 19:23:51 +0000576 pci_write_config8(dev, PCI_LATENCY_TIMER, 0x40);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000577
578 /* set a default secondary latency timer */
579 if ((dev->hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) {
Eric Biederman7a5416a2003-06-12 19:23:51 +0000580 pci_write_config8(dev, PCI_SEC_LATENCY_TIMER, 0x40);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000581 }
582
583 /* zero the irq settings */
Eric Biederman7a5416a2003-06-12 19:23:51 +0000584 line = pci_read_config8(dev, PCI_INTERRUPT_PIN);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000585 if (line) {
Eric Biederman7a5416a2003-06-12 19:23:51 +0000586 pci_write_config8(dev, PCI_INTERRUPT_LINE, 0);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000587 }
588 /* set the cache line size, so far 64 bytes is good for everyone */
Eric Biederman7a5416a2003-06-12 19:23:51 +0000589 pci_write_config8(dev, PCI_CACHE_LINE_SIZE, 64 >> 2);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000590}
591
Eric Biedermane9a271e32003-09-02 03:36:25 +0000592void pci_dev_enable_resources(struct device *dev)
593{
Eric Biedermana9e632c2004-11-18 22:38:08 +0000594 const struct pci_operations *ops;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000595 uint16_t command;
Eric Biederman03acab62004-10-14 21:25:53 +0000596
597 /* Set the subsystem vendor and device id for mainboard devices */
598 ops = ops_pci(dev);
Eric Biedermandbec2d42004-10-21 10:44:08 +0000599 if (dev->on_mainboard && ops && ops->set_subsystem) {
Eric Biederman03acab62004-10-14 21:25:53 +0000600 printk_debug("%s subsystem <- %02x/%02x\n",
601 dev_path(dev),
602 MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID,
603 MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID);
604 ops->set_subsystem(dev,
605 MAINBOARD_PCI_SUBSYSTEM_VENDOR_ID,
606 MAINBOARD_PCI_SUBSYSTEM_DEVICE_ID);
607 }
Eric Biedermane9a271e32003-09-02 03:36:25 +0000608 command = pci_read_config16(dev, PCI_COMMAND);
609 command |= dev->command;
610 printk_debug("%s cmd <- %02x\n", dev_path(dev), command);
611 pci_write_config16(dev, PCI_COMMAND, command);
Eric Biedermane9a271e32003-09-02 03:36:25 +0000612}
613
614void pci_bus_enable_resources(struct device *dev)
615{
616 uint16_t ctrl;
Li-Ta Lo515f6c72005-01-11 22:48:54 +0000617 /* enable IO in command register if there is VGA card
618 * connected with (even it does not claim IO resource) */
619 if (dev->link[0].bridge_ctrl & PCI_BRIDGE_CTL_VGA)
620 dev->command |= PCI_COMMAND_IO;
Eric Biedermane9a271e32003-09-02 03:36:25 +0000621 ctrl = pci_read_config16(dev, PCI_BRIDGE_CONTROL);
622 ctrl |= dev->link[0].bridge_ctrl;
Eric Biederman5cd81732004-03-11 15:01:31 +0000623 ctrl |= (PCI_BRIDGE_CTL_PARITY + PCI_BRIDGE_CTL_SERR); /* error check */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000624 printk_debug("%s bridge ctrl <- %04x\n", dev_path(dev), ctrl);
625 pci_write_config16(dev, PCI_BRIDGE_CONTROL, ctrl);
626
627 pci_dev_enable_resources(dev);
Eric Biedermandbec2d42004-10-21 10:44:08 +0000628
629 enable_childrens_resources(dev);
Eric Biedermane9a271e32003-09-02 03:36:25 +0000630}
631
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000632void pci_bus_reset(struct bus *bus)
633{
634 unsigned ctl;
635 ctl = pci_read_config16(bus->dev, PCI_BRIDGE_CONTROL);
636 ctl |= PCI_BRIDGE_CTL_BUS_RESET;
637 pci_write_config16(bus->dev, PCI_BRIDGE_CONTROL, ctl);
638 mdelay(10);
639 ctl &= ~PCI_BRIDGE_CTL_BUS_RESET;
640 pci_write_config16(bus->dev, PCI_BRIDGE_CONTROL, ctl);
641 delay(1);
642}
643
Eric Biedermandbec2d42004-10-21 10:44:08 +0000644void pci_dev_set_subsystem(device_t dev, unsigned vendor, unsigned device)
Eric Biederman03acab62004-10-14 21:25:53 +0000645{
646 pci_write_config32(dev, PCI_SUBSYSTEM_VENDOR_ID,
647 ((device & 0xffff) << 16) | (vendor & 0xffff));
648}
649
Torsten Duwe1f2f8002008-01-06 01:10:54 +0000650/** default handler: only runs the relevant pci bios. */
Li-Ta Lo883b8792005-01-10 23:16:22 +0000651void pci_dev_init(struct device *dev)
652{
Torsten Duwe1f2f8002008-01-06 01:10:54 +0000653#if CONFIG_PCI_ROM_RUN == 1 || CONFIG_VGA_ROM_RUN == 1
Stefan Reinauerd98cf5b2008-08-01 11:25:41 +0000654 void run_bios(struct device * dev, unsigned long addr);
Li-Ta Lo883b8792005-01-10 23:16:22 +0000655 struct rom_header *rom, *ram;
656
Roman Kononov778a42b2007-04-06 18:34:39 +0000657#if CONFIG_PCI_ROM_RUN != 1
Torsten Duwe1f2f8002008-01-06 01:10:54 +0000658 /* We want to execute VGA option ROMs when CONFIG_VGA_ROM_RUN
Roman Kononov778a42b2007-04-06 18:34:39 +0000659 * is set but CONFIG_PCI_ROM_RUN is not. In this case we skip
660 * all other option ROM types.
661 */
Ronald Hoogenboom9b6b63e2008-02-28 23:10:38 +0000662 if ((dev->class>>8)!=PCI_CLASS_DISPLAY_VGA)
Roman Kononov778a42b2007-04-06 18:34:39 +0000663 return;
664#endif
665
Li-Ta Lo883b8792005-01-10 23:16:22 +0000666 rom = pci_rom_probe(dev);
667 if (rom == NULL)
668 return;
Roman Kononov778a42b2007-04-06 18:34:39 +0000669
Li-Ta Lo883b8792005-01-10 23:16:22 +0000670 ram = pci_rom_load(dev, rom);
Yinghai Lu9e4faef2005-01-14 22:04:49 +0000671 if (ram == NULL)
672 return;
Li-Ta Lo883b8792005-01-10 23:16:22 +0000673
Stefan Reinauerd98cf5b2008-08-01 11:25:41 +0000674 run_bios(dev, (unsigned long)ram);
Roman Kononov778a42b2007-04-06 18:34:39 +0000675
676#if CONFIG_CONSOLE_VGA == 1
Torsten Duwe1f2f8002008-01-06 01:10:54 +0000677 /* vga_inited is a trigger of the VGA console code. */
Ronald Hoogenboom9b6b63e2008-02-28 23:10:38 +0000678 if ((dev->class>>8) == PCI_CLASS_DISPLAY_VGA) {
Torsten Duwe1f2f8002008-01-06 01:10:54 +0000679 extern int vga_inited;
680 vga_inited = 1;
681 }
682#endif /* CONFIG_CONSOLE_VGA */
683#endif /* CONFIG_PCI_ROM_RUN || CONFIG_VGA_ROM_RUN */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000684}
Li-Ta Lo883b8792005-01-10 23:16:22 +0000685
Li-Ta Loe5266692004-03-23 21:28:05 +0000686/** Default device operation for PCI devices */
Eric Biedermana9e632c2004-11-18 22:38:08 +0000687static struct pci_operations pci_dev_ops_pci = {
Eric Biederman03acab62004-10-14 21:25:53 +0000688 .set_subsystem = pci_dev_set_subsystem,
689};
690
Eric Biederman8ca8d762003-04-22 19:02:15 +0000691struct device_operations default_pci_ops_dev = {
Eric Biedermane9a271e32003-09-02 03:36:25 +0000692 .read_resources = pci_dev_read_resources,
693 .set_resources = pci_dev_set_resources,
694 .enable_resources = pci_dev_enable_resources,
Li-Ta Lo883b8792005-01-10 23:16:22 +0000695 .init = pci_dev_init,
Li-Ta Loe5266692004-03-23 21:28:05 +0000696 .scan_bus = 0,
Eric Biederman03acab62004-10-14 21:25:53 +0000697 .enable = 0,
Eric Biedermana9e632c2004-11-18 22:38:08 +0000698 .ops_pci = &pci_dev_ops_pci,
Eric Biederman8ca8d762003-04-22 19:02:15 +0000699};
Li-Ta Loe5266692004-03-23 21:28:05 +0000700
701/** Default device operations for PCI bridges */
Eric Biedermana9e632c2004-11-18 22:38:08 +0000702static struct pci_operations pci_bus_ops_pci = {
Eric Biederman03acab62004-10-14 21:25:53 +0000703 .set_subsystem = 0,
704};
Li-Ta Lo883b8792005-01-10 23:16:22 +0000705
Eric Biederman8ca8d762003-04-22 19:02:15 +0000706struct device_operations default_pci_ops_bus = {
Eric Biedermane9a271e32003-09-02 03:36:25 +0000707 .read_resources = pci_bus_read_resources,
708 .set_resources = pci_dev_set_resources,
709 .enable_resources = pci_bus_enable_resources,
Li-Ta Loe5266692004-03-23 21:28:05 +0000710 .init = 0,
711 .scan_bus = pci_scan_bridge,
Eric Biederman03acab62004-10-14 21:25:53 +0000712 .enable = 0,
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000713 .reset_bus = pci_bus_reset,
Eric Biedermana9e632c2004-11-18 22:38:08 +0000714 .ops_pci = &pci_bus_ops_pci,
Eric Biederman8ca8d762003-04-22 19:02:15 +0000715};
Li-Ta Loe5266692004-03-23 21:28:05 +0000716
717/**
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000718 * @brief Detect the type of downstream bridge
719 *
720 * This function is a heuristic to detect which type
721 * of bus is downstream of a pci to pci bridge. This
722 * functions by looking for various capability blocks
723 * to figure out the type of downstream bridge. PCI-X
724 * PCI-E, and Hypertransport all seem to have appropriate
725 * capabilities.
726 *
727 * When only a PCI-Express capability is found the type
728 * is examined to see which type of bridge we have.
729 *
730 * @param dev
731 *
732 * @return appropriate bridge operations
733 */
734static struct device_operations *get_pci_bridge_ops(device_t dev)
735{
736 unsigned pos;
737
738#if CONFIG_PCIX_PLUGIN_SUPPORT == 1
739 pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
740 if (pos) {
741 printk_debug("%s subbordinate bus PCI-X\n", dev_path(dev));
742 return &default_pcix_ops_bus;
743 }
744#endif
745#if CONFIG_AGP_PLUGIN_SUPPORT == 1
746 /* How do I detect an PCI to AGP bridge? */
747#endif
748#if CONFIG_HYPERTRANSPORT_PLUGIN_SUPPORT == 1
749 pos = 0;
750 while((pos = pci_find_next_capability(dev, PCI_CAP_ID_HT, pos))) {
751 unsigned flags;
752 flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
753 if ((flags >> 13) == 1) {
754 /* Host or Secondary Interface */
755 printk_debug("%s subbordinate bus Hypertransport\n",
756 dev_path(dev));
757 return &default_ht_ops_bus;
758 }
759 }
760#endif
761#if CONFIG_PCIEXP_PLUGIN_SUPPORT == 1
762 pos = pci_find_capability(dev, PCI_CAP_ID_PCIE);
763 if (pos) {
764 unsigned flags;
765 flags = pci_read_config16(dev, pos + PCI_EXP_FLAGS);
766 switch((flags & PCI_EXP_FLAGS_TYPE) >> 4) {
767 case PCI_EXP_TYPE_ROOT_PORT:
768 case PCI_EXP_TYPE_UPSTREAM:
769 case PCI_EXP_TYPE_DOWNSTREAM:
770 printk_debug("%s subbordinate bus PCI Express\n",
771 dev_path(dev));
772 return &default_pciexp_ops_bus;
773 case PCI_EXP_TYPE_PCI_BRIDGE:
774 printk_debug("%s subbordinate PCI\n",
775 dev_path(dev));
776 return &default_pci_ops_bus;
777 default:
778 break;
779 }
780 }
781#endif
782 return &default_pci_ops_bus;
783}
784
785/**
Li-Ta Loe5266692004-03-23 21:28:05 +0000786 * @brief Set up PCI device operation
787 *
788 *
789 * @param dev
790 *
791 * @see pci_drivers
792 */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000793static void set_pci_ops(struct device *dev)
794{
795 struct pci_driver *driver;
796 if (dev->ops) {
797 return;
798 }
Li-Ta Loe5266692004-03-23 21:28:05 +0000799
Yinghai Lu5f9624d2006-10-04 22:56:21 +0000800 /* Look through the list of setup drivers and find one for
Eric Biedermanb78c1972004-10-14 20:54:17 +0000801 * this pci device
802 */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000803 for(driver = &pci_drivers[0]; driver != &epci_drivers[0]; driver++) {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000804 if ((driver->vendor == dev->vendor) &&
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000805 (driver->device == dev->device))
Eric Biedermanb78c1972004-10-14 20:54:17 +0000806 {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000807 dev->ops = driver->ops;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000808 printk_spew("%s [%04x/%04x] %sops\n",
Eric Biedermanb78c1972004-10-14 20:54:17 +0000809 dev_path(dev),
810 driver->vendor, driver->device,
811 (driver->ops->scan_bus?"bus ":""));
Eric Biederman5899fd82003-04-24 06:25:08 +0000812 return;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000813 }
814 }
Li-Ta Loe5266692004-03-23 21:28:05 +0000815
Eric Biederman8ca8d762003-04-22 19:02:15 +0000816 /* If I don't have a specific driver use the default operations */
817 switch(dev->hdr_type & 0x7f) { /* header type */
818 case PCI_HEADER_TYPE_NORMAL: /* standard header */
819 if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
820 goto bad;
821 dev->ops = &default_pci_ops_dev;
822 break;
823 case PCI_HEADER_TYPE_BRIDGE:
824 if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
825 goto bad;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000826 dev->ops = get_pci_bridge_ops(dev);
Eric Biederman8ca8d762003-04-22 19:02:15 +0000827 break;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000828#if CONFIG_CARDBUS_PLUGIN_SUPPORT == 1
829 case PCI_HEADER_TYPE_CARDBUS:
830 dev->ops = &default_cardbus_ops_bus;
831 break;
832#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000833 default:
834 bad:
Li-Ta Lo69c5a902004-04-29 20:08:54 +0000835 if (dev->enabled) {
Eric Biederman83b991a2003-10-11 06:20:25 +0000836 printk_err("%s [%04x/%04x/%06x] has unknown header "
Eric Biedermanb78c1972004-10-14 20:54:17 +0000837 "type %02x, ignoring.\n",
838 dev_path(dev),
839 dev->vendor, dev->device,
840 dev->class >> 8, dev->hdr_type);
Eric Biederman83b991a2003-10-11 06:20:25 +0000841 }
Eric Biederman8ca8d762003-04-22 19:02:15 +0000842 }
843 return;
844}
845
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000846
847
Eric Biederman8ca8d762003-04-22 19:02:15 +0000848/**
Eric Biederman03acab62004-10-14 21:25:53 +0000849 * @brief See if we have already allocated a device structure for a given devfn.
Li-Ta Loe5266692004-03-23 21:28:05 +0000850 *
851 * Given a linked list of PCI device structures and a devfn number, find the
Li-Ta Lo3a812852004-12-03 22:39:34 +0000852 * device structure correspond to the devfn, if present. This function also
853 * removes the device structure from the linked list.
Li-Ta Loe5266692004-03-23 21:28:05 +0000854 *
855 * @param list the device structure list
Eric Biederman8ca8d762003-04-22 19:02:15 +0000856 * @param devfn a device/function number
Li-Ta Loe5266692004-03-23 21:28:05 +0000857 *
Li-Ta Lo3a812852004-12-03 22:39:34 +0000858 * @return pointer to the device structure found or null of we have not
859 * allocated a device for this devfn yet.
Eric Biederman8ca8d762003-04-22 19:02:15 +0000860 */
Eric Biedermanb78c1972004-10-14 20:54:17 +0000861static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000862{
Eric Biedermanb78c1972004-10-14 20:54:17 +0000863 struct device *dev;
Eric Biedermanb78c1972004-10-14 20:54:17 +0000864 dev = 0;
865 for(; *list; list = &(*list)->sibling) {
Eric Biedermanad1b35a2003-10-14 02:36:51 +0000866 if ((*list)->path.type != DEVICE_PATH_PCI) {
Li-Ta Loe5266692004-03-23 21:28:05 +0000867 printk_err("child %s not a pci device\n",
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000868 dev_path(*list));
Eric Biedermanad1b35a2003-10-14 02:36:51 +0000869 continue;
870 }
Eric Biedermane9a271e32003-09-02 03:36:25 +0000871 if ((*list)->path.u.pci.devfn == devfn) {
Eric Biederman8ca8d762003-04-22 19:02:15 +0000872 /* Unlink from the list */
873 dev = *list;
874 *list = (*list)->sibling;
875 dev->sibling = 0;
876 break;
877 }
878 }
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000879 /* Just like alloc_dev add the device to the list of device on the bus.
880 * When the list of devices was formed we removed all of the parents
881 * children, and now we are interleaving static and dynamic devices in
Li-Ta Lo3a812852004-12-03 22:39:34 +0000882 * order on the bus.
Eric Biedermanb78c1972004-10-14 20:54:17 +0000883 */
Eric Biedermane9a271e32003-09-02 03:36:25 +0000884 if (dev) {
885 device_t child;
886 /* Find the last child of our parent */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000887 for(child = dev->bus->children; child && child->sibling; ) {
Eric Biedermane9a271e32003-09-02 03:36:25 +0000888 child = child->sibling;
889 }
890 /* Place the device on the list of children of it's parent. */
891 if (child) {
892 child->sibling = dev;
893 } else {
894 dev->bus->children = dev;
895 }
896 }
897
Eric Biederman8ca8d762003-04-22 19:02:15 +0000898 return dev;
899}
900
Eric Biedermanb78c1972004-10-14 20:54:17 +0000901/**
902 * @brief Scan a PCI bus.
Li-Ta Loe5266692004-03-23 21:28:05 +0000903 *
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000904 * Determine the existence of a given PCI device.
905 *
906 * @param bus pointer to the bus structure
907 * @param devfn to look at
908 *
909 * @return The device structure for hte device (if found)
910 * or the NULL if no device is found.
911 */
912device_t pci_probe_dev(device_t dev, struct bus *bus, unsigned devfn)
913{
914 uint32_t id, class;
915 uint8_t hdr_type;
916
917 /* Detect if a device is present */
918 if (!dev) {
919 struct device dummy;
920 dummy.bus = bus;
921 dummy.path.type = DEVICE_PATH_PCI;
922 dummy.path.u.pci.devfn = devfn;
923 id = pci_read_config32(&dummy, PCI_VENDOR_ID);
924 /* Have we found somthing?
925 * Some broken boards return 0 if a slot is empty.
926 */
927 if ( (id == 0xffffffff) || (id == 0x00000000) ||
928 (id == 0x0000ffff) || (id == 0xffff0000))
929 {
Stefan Reinauerf657d752008-09-11 06:52:22 +0000930 printk_spew("%s, bad id 0x%x\n", dev_path(&dummy), id);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000931 return NULL;
932 }
933 dev = alloc_dev(bus, &dummy.path);
934 }
935 else {
936 /* Enable/disable the device. Once we have
937 * found the device specific operations this
938 * operations we will disable the device with
939 * those as well.
940 *
941 * This is geared toward devices that have subfunctions
942 * that do not show up by default.
943 *
944 * If a device is a stuff option on the motherboard
945 * it may be absent and enable_dev must cope.
946 *
947 */
948 /* Run the magice enable sequence for the device */
949 if (dev->chip_ops && dev->chip_ops->enable_dev) {
950 dev->chip_ops->enable_dev(dev);
951 }
952 /* Now read the vendor and device id */
953 id = pci_read_config32(dev, PCI_VENDOR_ID);
954
955
956 /* If the device does not have a pci id disable it.
957 * Possibly this is because we have already disabled
958 * the device. But this also handles optional devices
959 * that may not always show up.
960 */
961 /* If the chain is fully enumerated quit */
962 if ( (id == 0xffffffff) || (id == 0x00000000) ||
963 (id == 0x0000ffff) || (id == 0xffff0000))
964 {
965 if (dev->enabled) {
966 printk_info("Disabling static device: %s\n",
967 dev_path(dev));
968 dev->enabled = 0;
969 }
970 return dev;
971 }
972 }
973 /* Read the rest of the pci configuration information */
974 hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
975 class = pci_read_config32(dev, PCI_CLASS_REVISION);
976
977 /* Store the interesting information in the device structure */
978 dev->vendor = id & 0xffff;
979 dev->device = (id >> 16) & 0xffff;
980 dev->hdr_type = hdr_type;
981 /* class code, the upper 3 bytes of PCI_CLASS_REVISION */
982 dev->class = class >> 8;
983
984
985 /* Architectural/System devices always need to
986 * be bus masters.
987 */
988 if ((dev->class >> 16) == PCI_BASE_CLASS_SYSTEM) {
989 dev->command |= PCI_COMMAND_MASTER;
990 }
991 /* Look at the vendor and device id, or at least the
992 * header type and class and figure out which set of
993 * configuration methods to use. Unless we already
994 * have some pci ops.
995 */
996 set_pci_ops(dev);
997
998 /* Now run the magic enable/disable sequence for the device */
999 if (dev->ops && dev->ops->enable) {
1000 dev->ops->enable(dev);
1001 }
1002
1003
1004 /* Display the device and error if we don't have some pci operations
1005 * for it.
1006 */
1007 printk_debug("%s [%04x/%04x] %s%s\n",
1008 dev_path(dev),
1009 dev->vendor, dev->device,
1010 dev->enabled?"enabled": "disabled",
1011 dev->ops?"" : " No operations"
1012 );
1013
1014 return dev;
1015}
1016
1017/**
1018 * @brief Scan a PCI bus.
1019 *
Li-Ta Loe5266692004-03-23 21:28:05 +00001020 * Determine the existence of devices and bridges on a PCI bus. If there are
1021 * bridges on the bus, recursively scan the buses behind the bridges.
1022 *
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001023 * This function is the default scan_bus() method for the root device
1024 * 'dev_root'.
1025 *
Eric Biedermane9a271e32003-09-02 03:36:25 +00001026 * @param bus pointer to the bus structure
1027 * @param min_devfn minimum devfn to look at in the scan usually 0x00
1028 * @param max_devfn maximum devfn to look at in the scan usually 0xff
Eric Biederman8ca8d762003-04-22 19:02:15 +00001029 * @param max current bus number
Li-Ta Loe5266692004-03-23 21:28:05 +00001030 *
Eric Biederman8ca8d762003-04-22 19:02:15 +00001031 * @return The maximum bus number found, after scanning all subordinate busses
1032 */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001033unsigned int pci_scan_bus(struct bus *bus,
1034 unsigned min_devfn, unsigned max_devfn,
1035 unsigned int max)
Eric Biederman8ca8d762003-04-22 19:02:15 +00001036{
1037 unsigned int devfn;
Eric Biedermane9a271e32003-09-02 03:36:25 +00001038 device_t old_devices;
1039 device_t child;
Eric Biederman8ca8d762003-04-22 19:02:15 +00001040
Yinghai Lu5f9624d2006-10-04 22:56:21 +00001041#if PCI_BUS_SEGN_BITS
1042 printk_debug("PCI: pci_scan_bus for bus %04x:%02x\n", bus->secondary >> 8, bus->secondary & 0xff);
1043#else
1044 printk_debug("PCI: pci_scan_bus for bus %02x\n", bus->secondary);
1045#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +00001046
1047 old_devices = bus->children;
1048 bus->children = 0;
Eric Biederman8ca8d762003-04-22 19:02:15 +00001049
1050 post_code(0x24);
Li-Ta Lo9782f752004-05-05 21:15:42 +00001051 /* probe all devices/functions on this bus with some optimization for
Eric Biedermanb78c1972004-10-14 20:54:17 +00001052 * non-existence and single funcion devices
1053 */
Eric Biedermane9a271e32003-09-02 03:36:25 +00001054 for (devfn = min_devfn; devfn <= max_devfn; devfn++) {
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001055 device_t dev;
Eric Biederman8ca8d762003-04-22 19:02:15 +00001056
Eric Biederman03acab62004-10-14 21:25:53 +00001057 /* First thing setup the device structure */
Eric Biederman8ca8d762003-04-22 19:02:15 +00001058 dev = pci_scan_get_dev(&old_devices, devfn);
Li-Ta Lo9782f752004-05-05 21:15:42 +00001059
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001060 /* See if a device is present and setup the device
1061 * structure.
Eric Biederman03acab62004-10-14 21:25:53 +00001062 */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001063 dev = pci_probe_dev(dev, bus, devfn);
Eric Biederman03acab62004-10-14 21:25:53 +00001064
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001065 /* if this is not a multi function device,
1066 * or the device is not present don't waste
1067 * time probing another function.
1068 * Skip to next device.
Eric Biederman8ca8d762003-04-22 19:02:15 +00001069 */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001070 if ((PCI_FUNC(devfn) == 0x00) &&
1071 (!dev || (dev->enabled && ((dev->hdr_type & 0x80) != 0x80))))
1072 {
Eric Biederman8ca8d762003-04-22 19:02:15 +00001073 devfn += 0x07;
1074 }
1075 }
1076 post_code(0x25);
1077
Stefan Reinauerd98cf5b2008-08-01 11:25:41 +00001078 /* Die if any left over static devices are are found.
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001079 * There's probably a problem in the Config.lb.
1080 */
1081 if(old_devices) {
1082 device_t left;
1083 for(left = old_devices; left; left = left->sibling) {
Ronald G. Minniche800b912006-01-17 21:12:03 +00001084 printk_err("%s\n", dev_path(left));
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001085 }
Stefan Reinauerd98cf5b2008-08-01 11:25:41 +00001086 printk_warning("PCI: Left over static devices. Check your mainboard Config.lb\n");
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001087 }
1088
Eric Biedermanb78c1972004-10-14 20:54:17 +00001089 /* For all children that implement scan_bus (i.e. bridges)
1090 * scan the bus behind that child.
1091 */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001092 for(child = bus->children; child; child = child->sibling) {
1093 max = scan_bus(child, max);
Eric Biederman8ca8d762003-04-22 19:02:15 +00001094 }
Li-Ta Loe5266692004-03-23 21:28:05 +00001095
Eric Biederman8ca8d762003-04-22 19:02:15 +00001096 /*
1097 * We've scanned the bus and so we know all about what's on
1098 * the other side of any bridges that may be on this bus plus
1099 * any devices.
1100 *
1101 * Return how far we've got finding sub-buses.
1102 */
Yinghai Lu5f9624d2006-10-04 22:56:21 +00001103 printk_debug("PCI: pci_scan_bus returning with max=%03x\n", max);
Eric Biederman8ca8d762003-04-22 19:02:15 +00001104 post_code(0x55);
1105 return max;
1106}
1107
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001108
Li-Ta Loe5266692004-03-23 21:28:05 +00001109/**
1110 * @brief Scan a PCI bridge and the buses behind the bridge.
1111 *
1112 * Determine the existence of buses behind the bridge. Set up the bridge
1113 * according to the result of the scan.
1114 *
1115 * This function is the default scan_bus() method for PCI bridge devices.
1116 *
1117 * @param dev pointer to the bridge device
1118 * @param max the highest bus number assgined up to now
1119 *
Eric Biederman8ca8d762003-04-22 19:02:15 +00001120 * @return The maximum bus number found, after scanning all subordinate busses
1121 */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001122unsigned int do_pci_scan_bridge(struct device *dev, unsigned int max,
1123 unsigned int (*do_scan_bus)(struct bus *bus,
1124 unsigned min_devfn, unsigned max_devfn, unsigned int max))
Eric Biederman8ca8d762003-04-22 19:02:15 +00001125{
Eric Biedermane9a271e32003-09-02 03:36:25 +00001126 struct bus *bus;
Eric Biederman8ca8d762003-04-22 19:02:15 +00001127 uint32_t buses;
1128 uint16_t cr;
Eric Biederman83b991a2003-10-11 06:20:25 +00001129
Li-Ta Lo3a812852004-12-03 22:39:34 +00001130 printk_spew("%s for %s\n", __func__, dev_path(dev));
1131
Eric Biedermane9a271e32003-09-02 03:36:25 +00001132 bus = &dev->link[0];
Eric Biedermana9e632c2004-11-18 22:38:08 +00001133 bus->dev = dev;
Eric Biedermane9a271e32003-09-02 03:36:25 +00001134 dev->links = 1;
1135
Eric Biederman8ca8d762003-04-22 19:02:15 +00001136 /* Set up the primary, secondary and subordinate bus numbers. We have
1137 * no idea how many buses are behind this bridge yet, so we set the
Eric Biedermanb78c1972004-10-14 20:54:17 +00001138 * subordinate bus number to 0xff for the moment.
1139 */
Eric Biederman8ca8d762003-04-22 19:02:15 +00001140 bus->secondary = ++max;
1141 bus->subordinate = 0xff;
Li-Ta Loe5266692004-03-23 21:28:05 +00001142
Eric Biederman8ca8d762003-04-22 19:02:15 +00001143 /* Clear all status bits and turn off memory, I/O and master enables. */
Eric Biedermane9a271e32003-09-02 03:36:25 +00001144 cr = pci_read_config16(dev, PCI_COMMAND);
1145 pci_write_config16(dev, PCI_COMMAND, 0x0000);
1146 pci_write_config16(dev, PCI_STATUS, 0xffff);
Eric Biederman8ca8d762003-04-22 19:02:15 +00001147
Eric Biedermanb78c1972004-10-14 20:54:17 +00001148 /*
1149 * Read the existing primary/secondary/subordinate bus
1150 * number configuration.
1151 */
Eric Biedermane9a271e32003-09-02 03:36:25 +00001152 buses = pci_read_config32(dev, PCI_PRIMARY_BUS);
Eric Biederman8ca8d762003-04-22 19:02:15 +00001153
1154 /* Configure the bus numbers for this bridge: the configuration
1155 * transactions will not be propagated by the bridge if it is not
Eric Biedermanb78c1972004-10-14 20:54:17 +00001156 * correctly configured.
1157 */
Eric Biederman8ca8d762003-04-22 19:02:15 +00001158 buses &= 0xff000000;
Eric Biedermane9a271e32003-09-02 03:36:25 +00001159 buses |= (((unsigned int) (dev->bus->secondary) << 0) |
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001160 ((unsigned int) (bus->secondary) << 8) |
1161 ((unsigned int) (bus->subordinate) << 16));
Eric Biedermane9a271e32003-09-02 03:36:25 +00001162 pci_write_config32(dev, PCI_PRIMARY_BUS, buses);
Li-Ta Lo3a812852004-12-03 22:39:34 +00001163
Eric Biedermanb78c1972004-10-14 20:54:17 +00001164 /* Now we can scan all subordinate buses
1165 * i.e. the bus behind the bridge.
1166 */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001167 max = do_scan_bus(bus, 0x00, 0xff, max);
Li-Ta Lo3a812852004-12-03 22:39:34 +00001168
Eric Biederman8ca8d762003-04-22 19:02:15 +00001169 /* We know the number of buses behind this bridge. Set the subordinate
Eric Biedermanb78c1972004-10-14 20:54:17 +00001170 * bus number to its real value.
1171 */
Eric Biederman8ca8d762003-04-22 19:02:15 +00001172 bus->subordinate = max;
1173 buses = (buses & 0xff00ffff) |
1174 ((unsigned int) (bus->subordinate) << 16);
Eric Biedermane9a271e32003-09-02 03:36:25 +00001175 pci_write_config32(dev, PCI_PRIMARY_BUS, buses);
1176 pci_write_config16(dev, PCI_COMMAND, cr);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001177
Eric Biedermanb78c1972004-10-14 20:54:17 +00001178 printk_spew("%s returns max %d\n", __func__, max);
Eric Biederman8ca8d762003-04-22 19:02:15 +00001179 return max;
1180}
Li-Ta Loe5266692004-03-23 21:28:05 +00001181
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001182/**
1183 * @brief Scan a PCI bridge and the buses behind the bridge.
1184 *
1185 * Determine the existence of buses behind the bridge. Set up the bridge
1186 * according to the result of the scan.
1187 *
1188 * This function is the default scan_bus() method for PCI bridge devices.
1189 *
1190 * @param dev pointer to the bridge device
1191 * @param max the highest bus number assgined up to now
1192 *
1193 * @return The maximum bus number found, after scanning all subordinate busses
1194 */
1195unsigned int pci_scan_bridge(struct device *dev, unsigned int max)
1196{
1197 return do_pci_scan_bridge(dev, max, pci_scan_bus);
1198}
1199
Ronald G. Minnich6dd6c6852003-10-02 00:08:42 +00001200/*
1201 Tell the EISA int controller this int must be level triggered
1202 THIS IS A KLUDGE -- sorry, this needs to get cleaned up.
1203*/
Ronald G. Minnich88fb1a62006-06-22 04:37:27 +00001204void pci_level_irq(unsigned char intNum)
Ronald G. Minnich6dd6c6852003-10-02 00:08:42 +00001205{
Ronald G. Minnichcb3f4982003-10-02 18:16:07 +00001206 unsigned short intBits = inb(0x4d0) | (((unsigned) inb(0x4d1)) << 8);
Ronald G. Minnich6dd6c6852003-10-02 00:08:42 +00001207
Eric Biedermanb78c1972004-10-14 20:54:17 +00001208 printk_spew("%s: current ints are 0x%x\n", __func__, intBits);
Ronald G. Minnich6dd6c6852003-10-02 00:08:42 +00001209 intBits |= (1 << intNum);
1210
Eric Biedermanb78c1972004-10-14 20:54:17 +00001211 printk_spew("%s: try to set ints 0x%x\n", __func__, intBits);
Ronald G. Minnichcb3f4982003-10-02 18:16:07 +00001212
Ronald G. Minnich6dd6c6852003-10-02 00:08:42 +00001213 // Write new values
1214 outb((unsigned char) intBits, 0x4d0);
1215 outb((unsigned char) (intBits >> 8), 0x4d1);
Ronald G. Minnichcb3f4982003-10-02 18:16:07 +00001216
Ronald G. Minnichb56ef072003-10-15 20:05:11 +00001217 /* this seems like an error but is not ... */
Ronald G. Minnich02fa3b22004-10-06 17:33:54 +00001218#if 1
Ronald G. Minnich2cf779d2006-09-18 22:50:51 +00001219 if (inb(0x4d0) != (intBits & 0xff)) {
Ronald G. Minnichcb3f4982003-10-02 18:16:07 +00001220 printk_err("%s: lower order bits are wrong: want 0x%x, got 0x%x\n",
Ronald G. Minnich2cf779d2006-09-18 22:50:51 +00001221 __func__, intBits &0xff, inb(0x4d0));
Ronald G. Minnichcb3f4982003-10-02 18:16:07 +00001222 }
Ronald G. Minnich2cf779d2006-09-18 22:50:51 +00001223 if (inb(0x4d1) != ((intBits >> 8) & 0xff)) {
Ronald G. Minnichcb3f4982003-10-02 18:16:07 +00001224 printk_err("%s: lower order bits are wrong: want 0x%x, got 0x%x\n",
Ronald G. Minnich2cf779d2006-09-18 22:50:51 +00001225 __func__, (intBits>>8) &0xff, inb(0x4d1));
Ronald G. Minnichcb3f4982003-10-02 18:16:07 +00001226 }
Ronald G. Minnichb56ef072003-10-15 20:05:11 +00001227#endif
Ronald G. Minnich6dd6c6852003-10-02 00:08:42 +00001228}
1229
Ronald G. Minnich6dd6c6852003-10-02 00:08:42 +00001230/*
1231 This function assigns IRQs for all functions contained within
1232 the indicated device address. If the device does not exist or does
1233 not require interrupts then this function has no effect.
1234
1235 This function should be called for each PCI slot in your system.
1236
1237 pIntAtoD is an array of IRQ #s that are assigned to PINTA through PINTD of
1238 this slot.
1239 The particular irq #s that are passed in depend on the routing inside
1240 your southbridge and on your motherboard.
1241
1242 -kevinh@ispiri.com
1243*/
Yinghai Lu13f1c2a2005-07-08 02:49:49 +00001244void pci_assign_irqs(unsigned bus, unsigned slot,
1245 const unsigned char pIntAtoD[4])
Ronald G. Minnich6dd6c6852003-10-02 00:08:42 +00001246{
1247 unsigned functNum;
1248 device_t pdev;
1249 unsigned char line;
1250 unsigned char irq;
1251 unsigned char readback;
1252
1253 /* Each slot may contain up to eight functions */
1254 for (functNum = 0; functNum < 8; functNum++) {
1255 pdev = dev_find_slot(bus, (slot << 3) + functNum);
1256
1257 if (pdev) {
1258 line = pci_read_config8(pdev, PCI_INTERRUPT_PIN);
1259
1260 // PCI spec says all other values are reserved
1261 if ((line >= 1) && (line <= 4)) {
1262 irq = pIntAtoD[line - 1];
1263
1264 printk_debug("Assigning IRQ %d to %d:%x.%d\n", \
1265 irq, bus, slot, functNum);
1266
1267 pci_write_config8(pdev, PCI_INTERRUPT_LINE,\
1268 pIntAtoD[line - 1]);
1269
1270 readback = pci_read_config8(pdev, PCI_INTERRUPT_LINE);
1271 printk_debug(" Readback = %d\n", readback);
1272
1273 // Change to level triggered
1274 pci_level_irq(pIntAtoD[line - 1]);
1275 }
1276 }
1277 }
1278}