Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * numa.c - Low-level PCI access for NUMA-Q machines
  3  */
  4 
  5 #include <linux/pci.h>
  6 #include <linux/init.h>
  7 #include <linux/nodemask.h>
  8 #include "pci.h"
  9 
 10 #define BUS2QUAD(global) (mp_bus_id_to_node[global])
 11 #define BUS2LOCAL(global) (mp_bus_id_to_local[global])
 12 #define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local])
 13 
 14 #define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \
 15         (0x80000000 | (BUS2LOCAL(bus) << 16) | (devfn << 8) | (reg & ~3))
 16 
 17 static int pci_conf1_mq_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
 18 {
 19         unsigned long flags;
 20 
 21         if (!value || (bus > MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
 22                 return -EINVAL;
 23 
 24         spin_lock_irqsave(&pci_config_lock, flags);
 25 
 26         outl_quad(PCI_CONF1_MQ_ADDRESS(bus, devfn, reg), 0xCF8, BUS2QUAD(bus));
 27 
 28         switch (len) {
 29         case 1:
 30                 *value = inb_quad(0xCFC + (reg & 3), BUS2QUAD(bus));
 31                 break;
 32         case 2:
 33                 *value = inw_quad(0xCFC + (reg & 2), BUS2QUAD(bus));
 34                 break;
 35         case 4:
 36                 *value = inl_quad(0xCFC, BUS2QUAD(bus));
 37                 break;
 38         }
 39 
 40         spin_unlock_irqrestore(&pci_config_lock, flags);
 41 
 42         return 0;
 43 }
 44 
 45 static int pci_conf1_mq_write (int seg, int bus, int devfn, int reg, int len, u32 value)
 46 {
 47         unsigned long flags;
 48 
 49         if ((bus > MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) 
 50                 return -EINVAL;
 51 
 52         spin_lock_irqsave(&pci_config_lock, flags);
 53 
 54         outl_quad(PCI_CONF1_MQ_ADDRESS(bus, devfn, reg), 0xCF8, BUS2QUAD(bus));
 55 
 56         switch (len) {
 57         case 1:
 58                 outb_quad((u8)value, 0xCFC + (reg & 3), BUS2QUAD(bus));
 59                 break;
 60         case 2:
 61                 outw_quad((u16)value, 0xCFC + (reg & 2), BUS2QUAD(bus));
 62                 break;
 63         case 4:
 64                 outl_quad((u32)value, 0xCFC, BUS2QUAD(bus));
 65                 break;
 66         }
 67 
 68         spin_unlock_irqrestore(&pci_config_lock, flags);
 69 
 70         return 0;
 71 }
 72 
 73 #undef PCI_CONF1_MQ_ADDRESS
 74 
 75 static struct pci_raw_ops pci_direct_conf1_mq = {
 76         .read   = pci_conf1_mq_read,
 77         .write  = pci_conf1_mq_write
 78 };
 79 
 80 
 81 static void __devinit pci_fixup_i450nx(struct pci_dev *d)
 82 {
 83         /*
 84          * i450NX -- Find and scan all secondary buses on all PXB's.
 85          */
 86         int pxb, reg;
 87         u8 busno, suba, subb;
 88         int quad = BUS2QUAD(d->bus->number);
 89 
 90         printk("PCI: Searching for i450NX host bridges on %s\n", pci_name(d));
 91         reg = 0xd0;
 92         for(pxb=0; pxb<2; pxb++) {
 93                 pci_read_config_byte(d, reg++, &busno);
 94                 pci_read_config_byte(d, reg++, &suba);
 95                 pci_read_config_byte(d, reg++, &subb);
 96                 DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
 97                 if (busno)
 98                         pci_scan_bus(QUADLOCAL2BUS(quad,busno), &pci_root_ops, NULL);   /* Bus A */
 99                 if (suba < subb)
100                         pci_scan_bus(QUADLOCAL2BUS(quad,suba+1), &pci_root_ops, NULL);  /* Bus B */
101         }
102         pcibios_last_bus = -1;
103 }
104 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
105 
106 static int __init pci_numa_init(void)
107 {
108         int quad;
109 
110         raw_pci_ops = &pci_direct_conf1_mq;
111 
112         if (pcibios_scanned++)
113                 return 0;
114 
115         pci_root_bus = pcibios_scan_root(0);
116         if (num_online_nodes() > 1)
117                 for_each_online_node(quad) {
118                         if (quad == 0)
119                                 continue;
120                         printk("Scanning PCI bus %d for quad %d\n", 
121                                 QUADLOCAL2BUS(quad,0), quad);
122                         pci_scan_bus(QUADLOCAL2BUS(quad,0), 
123                                 &pci_root_ops, NULL);
124                 }
125         return 0;
126 }
127 
128 subsys_initcall(pci_numa_init);
129 
  This page was automatically generated by the LXR engine.