linux/arch/sh/drivers/pci/common.c
<<
>>
Prefs
   1#include <linux/pci.h>
   2#include <linux/interrupt.h>
   3#include <linux/timer.h>
   4#include <linux/kernel.h>
   5
   6/*
   7 * These functions are used early on before PCI scanning is done
   8 * and all of the pci_dev and pci_bus structures have been created.
   9 */
  10static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
  11        int top_bus, int busnr, int devfn)
  12{
  13        static struct pci_dev dev;
  14        static struct pci_bus bus;
  15
  16        dev.bus = &bus;
  17        dev.sysdata = hose;
  18        dev.devfn = devfn;
  19        bus.number = busnr;
  20        bus.sysdata = hose;
  21        bus.ops = hose->pci_ops;
  22
  23        if(busnr != top_bus)
  24                /* Fake a parent bus structure. */
  25                bus.parent = &bus;
  26        else
  27                bus.parent = NULL;
  28
  29        return &dev;
  30}
  31
  32#define EARLY_PCI_OP(rw, size, type)                                    \
  33int __init early_##rw##_config_##size(struct pci_channel *hose,         \
  34        int top_bus, int bus, int devfn, int offset, type value)        \
  35{                                                                       \
  36        return pci_##rw##_config_##size(                                \
  37                fake_pci_dev(hose, top_bus, bus, devfn),                \
  38                offset, value);                                         \
  39}
  40
  41EARLY_PCI_OP(read, byte, u8 *)
  42EARLY_PCI_OP(read, word, u16 *)
  43EARLY_PCI_OP(read, dword, u32 *)
  44EARLY_PCI_OP(write, byte, u8)
  45EARLY_PCI_OP(write, word, u16)
  46EARLY_PCI_OP(write, dword, u32)
  47
  48int __init pci_is_66mhz_capable(struct pci_channel *hose,
  49                                int top_bus, int current_bus)
  50{
  51        u32 pci_devfn;
  52        unsigned short vid;
  53        int cap66 = -1;
  54        u16 stat;
  55
  56        printk(KERN_INFO "PCI: Checking 66MHz capabilities...\n");
  57
  58        for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
  59                if (PCI_FUNC(pci_devfn))
  60                        continue;
  61                if (early_read_config_word(hose, top_bus, current_bus,
  62                                           pci_devfn, PCI_VENDOR_ID, &vid) !=
  63                    PCIBIOS_SUCCESSFUL)
  64                        continue;
  65                if (vid == 0xffff)
  66                        continue;
  67
  68                /* check 66MHz capability */
  69                if (cap66 < 0)
  70                        cap66 = 1;
  71                if (cap66) {
  72                        early_read_config_word(hose, top_bus, current_bus,
  73                                               pci_devfn, PCI_STATUS, &stat);
  74                        if (!(stat & PCI_STATUS_66MHZ)) {
  75                                printk(KERN_DEBUG
  76                                       "PCI: %02x:%02x not 66MHz capable.\n",
  77                                       current_bus, pci_devfn);
  78                                cap66 = 0;
  79                                break;
  80                        }
  81                }
  82        }
  83
  84        return cap66 > 0;
  85}
  86
  87static void pcibios_enable_err(unsigned long __data)
  88{
  89        struct pci_channel *hose = (struct pci_channel *)__data;
  90
  91        del_timer(&hose->err_timer);
  92        printk(KERN_DEBUG "PCI: re-enabling error IRQ.\n");
  93        enable_irq(hose->err_irq);
  94}
  95
  96static void pcibios_enable_serr(unsigned long __data)
  97{
  98        struct pci_channel *hose = (struct pci_channel *)__data;
  99
 100        del_timer(&hose->serr_timer);
 101        printk(KERN_DEBUG "PCI: re-enabling system error IRQ.\n");
 102        enable_irq(hose->serr_irq);
 103}
 104
 105void pcibios_enable_timers(struct pci_channel *hose)
 106{
 107        if (hose->err_irq) {
 108                init_timer(&hose->err_timer);
 109                hose->err_timer.data = (unsigned long)hose;
 110                hose->err_timer.function = pcibios_enable_err;
 111        }
 112
 113        if (hose->serr_irq) {
 114                init_timer(&hose->serr_timer);
 115                hose->serr_timer.data = (unsigned long)hose;
 116                hose->serr_timer.function = pcibios_enable_serr;
 117        }
 118}
 119
 120/*
 121 * A simple handler for the regular PCI status errors, called from IRQ
 122 * context.
 123 */
 124unsigned int pcibios_handle_status_errors(unsigned long addr,
 125                                          unsigned int status,
 126                                          struct pci_channel *hose)
 127{
 128        unsigned int cmd = 0;
 129
 130        if (status & PCI_STATUS_REC_MASTER_ABORT) {
 131                printk(KERN_DEBUG "PCI: master abort, pc=0x%08lx\n", addr);
 132                cmd |= PCI_STATUS_REC_MASTER_ABORT;
 133        }
 134
 135        if (status & PCI_STATUS_REC_TARGET_ABORT) {
 136                printk(KERN_DEBUG "PCI: target abort: ");
 137                pcibios_report_status(PCI_STATUS_REC_TARGET_ABORT |
 138                                      PCI_STATUS_SIG_TARGET_ABORT |
 139                                      PCI_STATUS_REC_MASTER_ABORT, 1);
 140                printk("\n");
 141
 142                cmd |= PCI_STATUS_REC_TARGET_ABORT;
 143        }
 144
 145        if (status & (PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY)) {
 146                printk(KERN_DEBUG "PCI: parity error detected: ");
 147                pcibios_report_status(PCI_STATUS_PARITY |
 148                                      PCI_STATUS_DETECTED_PARITY, 1);
 149                printk("\n");
 150
 151                cmd |= PCI_STATUS_PARITY | PCI_STATUS_DETECTED_PARITY;
 152
 153                /* Now back off of the IRQ for awhile */
 154                if (hose->err_irq) {
 155                        disable_irq_nosync(hose->err_irq);
 156                        hose->err_timer.expires = jiffies + HZ;
 157                        add_timer(&hose->err_timer);
 158                }
 159        }
 160
 161        return cmd;
 162}
 163