Main Page | Directories | File List | Globals

pcibus_irq.c File Reference

#include <agnix/agnix.h>
#include <agnix/adi/adi.h>
#include <agnix/list.h>
#include <agnix/spinlock.h>
#include <agnix/console.h>
#include <asm/pgtable.h>
#include "pcibus_define_names.h"

Include dependency graph for pcibus_irq.c:

Go to the source code of this file.

Defines

#define MOD_NAME   "PCI: \t\t"
#define PCIBUS_ROUTING_TABLE_START   phys_to_virt(0xf0000)
#define PCIBUS_ROUTING_TABLE_END   phys_to_virt(0x100000)
#define pcibus_irq_router_get(pirq, irq_ptr)   pcidev_irq_router_ops->pirq_get(pirq, irq_ptr)
#define pcibus_irq_router_set(pirq, irq)   pcidev_irq_router_ops->pirq_set(pirq, irq)
#define PCI_DEBUG   0

Functions

int pcibus_irq_piix_get (int pirq, u8 *irq)
int pcibus_irq_piix_set (int pirq, u8 irq)
u8 pcibus_irq_checksum (struct pcibus_irq_table *pirq_table)
pcibus_irq_table * pcibus_irq_find_routing_table (void)
pcidev_s * pcibus_irq_find_router (struct pcibus_irq_table *pirq_table)
pcibus_irq_router_ops * pcibus_irq_find_router_ops (struct pcidev_s *pcidev)
pcibus_irq_table_slot * pcibus_irq_find_slot (struct pcidev_s *pcidev)
int pcibus_irq_dev_set (struct pcidev_s *pcidev)
int pcibus_irq_all_set (void)
int pcibus_irq_init (void)

Variables

list_head pcidev_list
spinlock_t pcidev_list_lock
pcibus_irq_table * pirq_table
pcidev_s * pcidev_irq_router
pcibus_irq_router_ops * pcidev_irq_router_ops
pcibus_irq_router irq_routers []


Define Documentation

#define MOD_NAME   "PCI: \t\t"
 

Definition at line 22 of file pcibus_irq.c.

#define PCI_DEBUG   0
 

Definition at line 29 of file pcibus_irq.c.

#define pcibus_irq_router_get pirq,
irq_ptr   )     pcidev_irq_router_ops->pirq_get(pirq, irq_ptr)
 

Definition at line 26 of file pcibus_irq.c.

Referenced by pcibus_irq_dev_set().

#define pcibus_irq_router_set pirq,
irq   )     pcidev_irq_router_ops->pirq_set(pirq, irq)
 

Definition at line 27 of file pcibus_irq.c.

Referenced by pcibus_irq_dev_set().

#define PCIBUS_ROUTING_TABLE_END   phys_to_virt(0x100000)
 

Definition at line 24 of file pcibus_irq.c.

Referenced by pcibus_irq_find_routing_table().

#define PCIBUS_ROUTING_TABLE_START   phys_to_virt(0xf0000)
 

Definition at line 23 of file pcibus_irq.c.

Referenced by pcibus_irq_find_routing_table().


Function Documentation

int pcibus_irq_all_set void   ) 
 

Definition at line 252 of file pcibus_irq.c.

References flags, pcibus_irq_dev_set(), pcidev_list, and pcidev_list_lock.

Referenced by pcibus_irq_init().

00253 {
00254     struct list_head *tmp;
00255     struct pcidev_s *pcidev;
00256     int ret = 0;
00257     u32 flags;
00258 
00259     spin_lock_irqsave(&pcidev_list_lock, flags);
00260     
00261     list_for_each(tmp, &pcidev_list) {
00262         pcidev = list_entry(tmp, struct pcidev_s, dev_list);
00263         pcibus_irq_dev_set(pcidev);
00264     }    
00265     
00266     spin_unlock_irqrestore(&pcidev_list_lock, flags);
00267     
00268     return ret;
00269 }

Here is the call graph for this function:

u8 pcibus_irq_checksum struct pcibus_irq_table *  pirq_table  ) 
 

Definition at line 61 of file pcibus_irq.c.

Referenced by pcibus_irq_find_routing_table().

00062 {
00063     u8  *pirq_table_ptr;
00064     u16 i;
00065     u8  checksum = 0;
00066     
00067     pirq_table_ptr = (u8 *)pirq_table;
00068     for (i = 0; i < pirq_table->size; i++)
00069         checksum += pirq_table_ptr[i];
00070     
00071     return checksum;
00072 }

int pcibus_irq_dev_set struct pcidev_s *  pcidev  ) 
 

Definition at line 152 of file pcibus_irq.c.

References MOD_NAME, pcibus_irq_find_slot(), pcibus_irq_router_get, pcibus_irq_router_set, pcidev_list, and printk().

Referenced by pcibus_irq_all_set().

00153 {
00154     struct pcibus_irq_table_slot *slot;
00155     struct pcibus_irq_table_slot_irq *slot_irq;    
00156     struct pcidev_s *pcidev_tmp;
00157     struct list_head *tmp;
00158     u8 dev_pin;
00159     u8 dev_irq;
00160     u8  router_irq_ptr;
00161     u16 router_irq_bitmap;
00162     int sharing_with = 0;
00163             
00164     pci_read_config_byte(pcidev, PCIDEV_INTERRUPT_PIN, &dev_pin);
00165 
00166     dev_irq = pcidev->dev_irq;
00167 
00168     /* some devices has irq = 255 */
00169     if (dev_irq >= 16) {
00170 #if PCI_DEBUG
00171         printk(MOD_NAME "%02x.%02x has irq >= 16, setting to 0\n", PCIDEV_SLOT(pcidev), PCIDEV_FN(pcidev));
00172 #endif
00173         dev_irq = 0;
00174     }
00175 
00176     /* device has not irq pin */
00177     if (dev_pin == 0) {
00178         pcidev->dev_irq = dev_irq;
00179         return 0;
00180     }
00181     
00182     dev_pin--;
00183 
00184     if (dev_pin > PCIDEV_MAX_IRQS) {
00185 #if PCI_DEBUG
00186         printk("dev_pin > MAX\n");
00187 #endif
00188         return 0;
00189     }
00190 
00191     if ((slot = pcibus_irq_find_slot(pcidev)) == NULL) {
00192 #if PCI_DEBUG
00193         printk("slot not found\n");
00194 #endif
00195         return 0;
00196     }
00197 
00198     slot_irq = slot->dev_irq;
00199 
00200     router_irq_ptr    = slot_irq[dev_pin].link;
00201     router_irq_bitmap = slot_irq[dev_pin].bitmap;
00202     
00203     if (dev_irq == 0)
00204         pcibus_irq_router_get(router_irq_ptr, &dev_irq);
00205     else
00206         pcibus_irq_router_set(router_irq_ptr, dev_irq);
00207 
00208     pcidev->dev_irq = dev_irq;
00209 
00210     printk(MOD_NAME "found irq %d for %02x.%02x", dev_irq, PCIDEV_SLOT(pcidev), PCIDEV_FN(pcidev));
00211     
00212     list_for_each(tmp, &pcidev_list) {
00213         pcidev_tmp = list_entry(tmp, struct pcidev_s, dev_list);
00214         
00215         if (pcidev_tmp == pcidev)
00216             continue;
00217         
00218         pci_read_config_byte(pcidev_tmp, PCIDEV_INTERRUPT_PIN, &dev_pin);
00219         
00220         if (!dev_pin)
00221             continue;
00222         
00223         dev_pin--;
00224         
00225         if ((slot = pcibus_irq_find_slot(pcidev_tmp)) == NULL)
00226             continue;
00227         
00228         if (slot->dev_irq[dev_pin].link == router_irq_ptr) {
00229         
00230             if (pcidev_tmp->dev_irq >= 16)
00231                 pcidev_tmp->dev_irq = 0;
00232         
00233             if (pcidev_tmp->dev_irq && (pcidev_tmp->dev_irq != pcidev->dev_irq)) {
00234                 printk(", conflict with %02x.%02x", PCIDEV_SLOT(pcidev_tmp), PCIDEV_FN(pcidev_tmp));
00235                 return -1;
00236             }
00237         
00238             pcidev_tmp->dev_irq = dev_irq;
00239             if (!sharing_with) {
00240                 sharing_with = 1;
00241                 printk(", sharing with");
00242             }
00243             printk(" %02x.%02x", PCIDEV_SLOT(pcidev_tmp), PCIDEV_FN(pcidev_tmp));
00244         }
00245     }
00246     
00247     printk("\n");
00248     
00249     return 0;
00250 }

Here is the call graph for this function:

struct pcidev_s* pcibus_irq_find_router struct pcibus_irq_table *  pirq_table  ) 
 

Definition at line 103 of file pcibus_irq.c.

References pcibus_find_device_by_fn(), and pcibus_find_device_by_id().

Referenced by pcibus_irq_init().

00104 {
00105     struct pcidev_s *pcidev_1 = NULL;
00106     struct pcidev_s *pcidev_2 = NULL;
00107 
00108     if (pirq_table->router_vendor != 0x0000 && pirq_table->router_vendor != 0xffff &&
00109         pirq_table->router_device != 0x0000 && pirq_table->router_device != 0xffff)
00110             pcidev_1 = pcibus_find_device_by_id(pirq_table->router_vendor, pirq_table->router_device);
00111 
00112     pcidev_2 = pcibus_find_device_by_fn(pirq_table->router_bus, pirq_table->router_function);
00113     
00114     if (pcidev_1 != NULL && pcidev_2 != NULL && pcidev_1 == pcidev_2)
00115         return pcidev_1;
00116 
00117     if (pcidev_1 == NULL)
00118         return pcidev_2;
00119     
00120     return pcidev_1;
00121 }

Here is the call graph for this function:

struct pcibus_irq_router_ops* pcibus_irq_find_router_ops struct pcidev_s *  pcidev  ) 
 

Definition at line 123 of file pcibus_irq.c.

References irq_routers.

Referenced by pcibus_irq_init().

00124 {
00125     int i = 0;
00126 
00127     for (i = 0; irq_routers[i].router_vendor_id; i++) {
00128         if (pcidev->dev_vendor_id == irq_routers[i].router_vendor_id &&
00129             pcidev->dev_device_id == irq_routers[i].router_device_id)
00130                 return &(irq_routers[i].router_ops);
00131     }
00132     
00133     return NULL;
00134 }

struct pcibus_irq_table* pcibus_irq_find_routing_table void   ) 
 

Definition at line 74 of file pcibus_irq.c.

References MOD_NAME, pcibus_irq_checksum(), PCIBUS_ROUTING_TABLE_END, PCIBUS_ROUTING_TABLE_START, pirq_table, and printk().

Referenced by pcibus_irq_init().

00075 {
00076     u32 table_start = PCIBUS_ROUTING_TABLE_START;
00077     u32 table_end   = PCIBUS_ROUTING_TABLE_END;
00078     u32 table_ptr;
00079     struct pcibus_irq_table *pirq_table;
00080     
00081     for (table_ptr = table_start; table_ptr < table_end; table_ptr += 16) {
00082         pirq_table = (struct pcibus_irq_table *)table_ptr;
00083         
00084         if (pirq_table->signature == PCIBUS_PIRQ_SIGNATURE &&
00085             pirq_table->version   == PCIBUS_PIRQ_VERSION   && 
00086             pirq_table->size       > sizeof(struct pcibus_irq_table)) {
00087             
00088             if (pcibus_irq_checksum(pirq_table) == 0) {
00089                 printk(MOD_NAME "irq routing table found (at address 0x%08x)\n", virt_to_phys(table_ptr));
00090                 return pirq_table;
00091             } else {
00092                 printk(MOD_NAME "irq routing table checksum failed! (at address 0x%08x)\n", virt_to_phys(table_ptr));
00093                 return NULL;
00094             }
00095         }
00096     }
00097     
00098     printk(MOD_NAME "irq routing table not found\n");
00099     
00100     return NULL;
00101 }

Here is the call graph for this function:

struct pcibus_irq_table_slot* pcibus_irq_find_slot struct pcidev_s *  pcidev  ) 
 

Definition at line 136 of file pcibus_irq.c.

References pirq_table.

Referenced by pcibus_irq_dev_set().

00137 {
00138     int i;
00139     int slots_nr = (pirq_table->size - sizeof(struct pcibus_irq_table)) / sizeof(struct pcibus_irq_table_slot);
00140     struct pcibus_irq_table_slot *table_slot = 
00141                   (struct pcibus_irq_table_slot *)(((void *)pirq_table) + sizeof(struct pcibus_irq_table));
00142 
00143     for (i = 0; i <= slots_nr + 2; i++) {
00144         if ((table_slot[i].dev_bus                         == pcidev->dev_bus->bus_nr) &&
00145             (PCIDEV_FN_TO_SLOT(table_slot[i].dev_function) == PCIDEV_SLOT(pcidev)))
00146                 return &table_slot[i];
00147     }
00148         
00149     return NULL;
00150 }

int pcibus_irq_init void   ) 
 

Definition at line 271 of file pcibus_irq.c.

References MOD_NAME, pcibus_irq_all_set(), pcibus_irq_find_router(), pcibus_irq_find_router_ops(), pcibus_irq_find_routing_table(), pcidev_irq_router, pcidev_irq_router_ops, pirq_table, and printk().

Referenced by adi_pcibus_init().

00272 {
00273     pirq_table            = pcibus_irq_find_routing_table();
00274     pcidev_irq_router     = pcibus_irq_find_router(pirq_table);
00275     pcidev_irq_router_ops = pcibus_irq_find_router_ops(pcidev_irq_router);
00276 
00277     if (pcidev_irq_router != NULL)
00278         printk(MOD_NAME "found %s irq router\n", pcidev_irq_router->dev_name);
00279     else
00280         printk(MOD_NAME "irq router not found\n");
00281 
00282     if (pcidev_irq_router_ops == NULL)
00283         printk(MOD_NAME "irq router ops not found\n");
00284     else {
00285         printk(MOD_NAME "setting pirqs.... \n");
00286 
00287         if (!pcibus_irq_all_set())
00288             return -1;
00289     }
00290 
00291     return 0;
00292 }

Here is the call graph for this function:

int pcibus_irq_piix_get int  pirq,
u8 *  irq
 

Definition at line 47 of file pcibus_irq.c.

References pcidev_irq_router.

00048 {
00049     pci_read_config_byte(pcidev_irq_router, pirq, irq);
00050     
00051     return 0;
00052 }

int pcibus_irq_piix_set int  pirq,
u8  irq
 

Definition at line 54 of file pcibus_irq.c.

References pcidev_irq_router.

00055 {
00056     pci_write_config_byte(pcidev_irq_router, pirq, irq);
00057     
00058     return 0;
00059 }


Variable Documentation

struct pcibus_irq_router irq_routers[]
 

Initial value:

 {
    { PCIBUS_VENDOR_INTEL_ID, PCIBUS_DEVICE_82371AB_ID, { pcibus_irq_piix_get, pcibus_irq_piix_set } },
    { PCIBUS_VENDOR_INTEL_ID, PCIBUS_DEVICE_82371SB_ID, { pcibus_irq_piix_get, pcibus_irq_piix_set } },
    { 0 ,}
}

Definition at line 41 of file pcibus_irq.c.

Referenced by pcibus_irq_find_router_ops().

struct pcidev_s* pcidev_irq_router
 

Definition at line 35 of file pcibus_irq.c.

Referenced by pcibus_irq_init(), pcibus_irq_piix_get(), and pcibus_irq_piix_set().

struct pcibus_irq_router_ops* pcidev_irq_router_ops
 

Definition at line 36 of file pcibus_irq.c.

Referenced by pcibus_irq_init().

struct list_head pcidev_list
 

Definition at line 23 of file pcibus_core.c.

spinlock_t pcidev_list_lock
 

Definition at line 25 of file pcibus_core.c.

struct pcibus_irq_table* pirq_table
 

Definition at line 34 of file pcibus_irq.c.

Referenced by pcibus_irq_find_routing_table(), pcibus_irq_find_slot(), and pcibus_irq_init().

Dokumentacje wygenerowano programem Doxygen 1.4.2 dla projektu Agnix