Main Page | Directories | File List | Globals

pcibus_scan.c File Reference

#include <agnix/agnix.h>
#include <agnix/adi/adi.h>
#include <agnix/memory.h>
#include <agnix/spinlock.h>
#include <agnix/console.h>

Include dependency graph for pcibus_scan.c:

Go to the source code of this file.

Defines

#define MOD_NAME   "PCI: \t\t"
#define PCI_DEBUG   1

Functions

void pcibus_add_device (struct pcidev_s *pcidev)
void pcibus_add_bus (struct pcibus_s *pcibus)
pcidev_s * pcibus_find_device_by_id (u16 vendor_id, u16 device_id)
pcidev_s * pcibus_find_device_by_fn (u8 bus_nr, int function)
int pcibus_find_capability_pos (struct pcidev_s *pcidev, int cap_req_id)
int pcibus_power_change_delay (struct pcidev_s *pcidev, int power_1, int power_2)
int pcibus_set_power_state (struct pcidev_s *pcidev, int power_state)
int pcibus_enable_device (struct pcidev_s *pcidev)
pcibus_s * pcibus_allocate_primary_bus (int bus_nr, struct pcibus_ops_s *bus_ops)
pcibus_s * pcibus_allocate_child_bus (struct pcibus_s *parent, int child_bus_nr)
int pcibus_scan_card_memory (struct pcidev_s *pcidev, unsigned int res_nr)
int pcibus_scan_card_function (struct pcidev_s *pcidev)
int pcibus_scan_card (struct pcidev_s *pcidev)
int pcibus_scan (int bus_nr)
int pcibus_scan_all (void)
void pcibus_print_all (void)

Variables

list_head pcibus_list
list_head pcidev_list
spinlock_t pcibus_list_lock
spinlock_t pcidev_list_lock
pcibus_s * pcibus_primary
pcibus_ops_s pcibus_primary_ops
int pcibus_disable


Define Documentation

#define MOD_NAME   "PCI: \t\t"
 

Definition at line 24 of file pcibus_scan.c.

#define PCI_DEBUG   1
 

Definition at line 25 of file pcibus_scan.c.


Function Documentation

void pcibus_add_bus struct pcibus_s *  pcibus  ) 
 

Definition at line 45 of file pcibus_scan.c.

References flags, pcibus_list, and pcibus_list_lock.

Referenced by pcibus_allocate_primary_bus().

00046 {
00047     u32 flags;
00048 
00049     spin_lock_irqsave(&pcibus_list_lock, flags);
00050     list_add_tail(&(pcibus->bus_list), &pcibus_list);
00051     spin_unlock_irqrestore(&pcibus_list_lock, flags);
00052 }

void pcibus_add_device struct pcidev_s *  pcidev  ) 
 

Definition at line 36 of file pcibus_scan.c.

References flags, pcidev_list, and pcidev_list_lock.

Referenced by pcibus_scan_card().

00037 {
00038     u32 flags;
00039 
00040     spin_lock_irqsave(&pcidev_list_lock, flags);
00041     list_add_tail(&(pcidev->dev_list), &pcidev_list);
00042     spin_unlock_irqrestore(&pcidev_list_lock, flags);
00043 }

struct pcibus_s* pcibus_allocate_child_bus struct pcibus_s *  parent,
int  child_bus_nr
 

Definition at line 220 of file pcibus_scan.c.

References get_free_pages().

00221 {
00222     struct pcibus_s *child;
00223 
00224     child = (struct pcibus_s *)get_free_pages(0);
00225 
00226     child->bus_nr  = child_bus_nr;
00227     child->bus_ops = parent->bus_ops;
00228 
00229     return child;
00230 }

Here is the call graph for this function:

struct pcibus_s* pcibus_allocate_primary_bus int  bus_nr,
struct pcibus_ops_s *  bus_ops
 

Definition at line 201 of file pcibus_scan.c.

References get_free_pages(), MOD_NAME, pcibus_add_bus(), and printk().

Referenced by pcibus_scan_all().

00202 {
00203     struct pcibus_s *pcibus;
00204 
00205     if (bus_ops == NULL || bus_ops->pcibus_read_config == NULL 
00206                         || bus_ops->pcibus_write_config == NULL) {
00207         printk(MOD_NAME "invalid bus_ops\n");
00208         return NULL;
00209     }
00210 
00211     pcibus = (struct pcibus_s *)get_free_pages(0);
00212     pcibus->bus_nr  = bus_nr;
00213     pcibus->bus_ops = bus_ops;
00214 
00215     pcibus_add_bus(pcibus);
00216 
00217     return pcibus;
00218 }

Here is the call graph for this function:

int pcibus_enable_device struct pcidev_s *  pcidev  ) 
 

Definition at line 176 of file pcibus_scan.c.

References pcibus_set_power_state().

Referenced by rtl_8029_probe().

00177 {
00178     u16 pcidev_cmd_tmp;
00179     u16 pcidev_cmd;
00180     int i;
00181 
00182     pcibus_set_power_state(pcidev, 0);
00183     
00184     pci_read_config_word(pcidev, PCI_COMMAND, &pcidev_cmd);
00185     pcidev_cmd_tmp = pcidev_cmd;
00186     
00187     for (i = 0; i < pcidev->dev_max_resources; i++) {
00188         if (pcidev->dev_resources[i].res_flags & ADI_RES_FLAG_IO)
00189             pcidev_cmd |= PCI_COMMAND_IO;
00190         else
00191         if (pcidev->dev_resources[i].res_flags & ADI_RES_FLAG_MEM)
00192             pcidev_cmd |= PCI_COMMAND_MEMORY;
00193     }
00194     
00195     if (pcidev_cmd != pcidev_cmd_tmp) 
00196         pci_write_config_word(pcidev, PCI_COMMAND, pcidev_cmd);
00197 
00198     return 0;
00199 }

Here is the call graph for this function:

int pcibus_find_capability_pos struct pcidev_s *  pcidev,
int  cap_req_id
 

Definition at line 101 of file pcibus_scan.c.

Referenced by pcibus_set_power_state().

00102 {
00103     u16 dev_status;
00104     u8  cap_next;
00105     u8  cap_pos;
00106     u8  cap_id;
00107     int cap_max_entries = 48;
00108     
00109     pci_read_config_word(pcidev, PCI_STATUS, &dev_status);
00110     
00111     if (!(dev_status & PCI_STATUS_CAP_LIST))
00112         return -1;
00113 
00114     switch(pcidev->dev_header_type) {
00115         case PCIDEV_HDR_TYPE_NORMAL:
00116         case PCIDEV_HDR_TYPE_BRIDGE:
00117             cap_pos = PCI_CAPABILITY_LIST;
00118         case PCIDEV_HDR_TYPE_CB:
00119             cap_pos = PCI_CB_CAPABILITY_LIST;
00120         default:
00121             return -1;
00122     }
00123     
00124     for(cap_max_entries = 48; cap_max_entries > 0; cap_max_entries--) {
00125         pci_read_config_byte(pcidev, cap_pos + PCI_CAP_LIST_ID, &cap_id);
00126         
00127         if (cap_id == cap_req_id)
00128             return cap_pos;
00129         
00130         if (cap_id == 0xff)
00131             break;
00132             
00133         pci_read_config_byte(pcidev, cap_pos + PCI_CAP_LIST_NEXT, &cap_next);
00134         
00135         if (cap_pos <= 0x40)
00136             return -1;
00137         
00138         cap_pos = cap_next;
00139     }
00140 
00141     return -1;    
00142 }

struct pcidev_s* pcibus_find_device_by_fn u8  bus_nr,
int  function
 

Definition at line 78 of file pcibus_scan.c.

References flags, pcidev_list, and pcidev_list_lock.

Referenced by pcibus_irq_find_router().

00079 {
00080     u32 flags;
00081     struct list_head *tmp;
00082     struct pcidev_s *pcidev;
00083 
00084     spin_lock_irqsave(&pcidev_list_lock, flags);
00085     
00086     list_for_each(tmp, &pcidev_list) {
00087         pcidev = list_entry(tmp, struct pcidev_s, dev_list);
00088         
00089         if (pcidev->dev_fn == function && pcidev->dev_bus->bus_nr == bus_nr)
00090                 goto pcidev_found;
00091     }
00092     
00093     pcidev = NULL;
00094     
00095 pcidev_found:
00096     spin_unlock_irqrestore(&pcidev_list_lock, flags);
00097 
00098     return pcidev;
00099 }

struct pcidev_s* pcibus_find_device_by_id u16  vendor_id,
u16  device_id
 

Definition at line 54 of file pcibus_scan.c.

References flags, pcidev_list, and pcidev_list_lock.

Referenced by adi_pcibus_device_init(), and pcibus_irq_find_router().

00055 {
00056     u32 flags;
00057     struct list_head *tmp;
00058     struct pcidev_s *pcidev;
00059 
00060     spin_lock_irqsave(&pcidev_list_lock, flags);
00061     
00062     list_for_each(tmp, &pcidev_list) {
00063         pcidev = list_entry(tmp, struct pcidev_s, dev_list);
00064         
00065         if (pcidev->dev_vendor_id == vendor_id &&
00066             pcidev->dev_device_id == device_id)
00067                 goto pcidev_found;
00068     }
00069     
00070     pcidev = NULL;
00071     
00072 pcidev_found:
00073     spin_unlock_irqrestore(&pcidev_list_lock, flags);
00074 
00075     return pcidev;
00076 }

int pcibus_power_change_delay struct pcidev_s *  pcidev,
int  power_1,
int  power_2
 

Definition at line 144 of file pcibus_scan.c.

Referenced by pcibus_set_power_state().

00145 {       
00146     return 0;
00147 }

void pcibus_print_all void   ) 
 

Definition at line 428 of file pcibus_scan.c.

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

Referenced by agnix_console_pci_list().

00429 {
00430     struct list_head *tmp;
00431     struct pcidev_s *dev;
00432     u32 flags;
00433 
00434     printf("\n");
00435 
00436     spin_lock_irqsave(&pcidev_list_lock, flags);
00437 
00438     list_for_each(tmp, &pcidev_list) {
00439         dev = list_entry(tmp, struct pcidev_s, dev_list);
00440         if (dev->dev_irq == 0)
00441             printf("%02x:%02x.%x [no irq] %s\n", PCIDEV_BUS(dev), PCIDEV_SLOT(dev), PCIDEV_FN(dev), dev->dev_name);
00442         else
00443             printf("%02x:%02x.%x [irq %d] %s\n", PCIDEV_BUS(dev), PCIDEV_SLOT(dev), PCIDEV_FN(dev), dev->dev_irq, dev->dev_name);
00444     };
00445     
00446     spin_unlock_irqrestore(&pcidev_list_lock, flags);
00447 }

Here is the call graph for this function:

int pcibus_scan int  bus_nr  ) 
 

Definition at line 391 of file pcibus_scan.c.

References MOD_NAME, and printk().

00392 {
00393     printk(MOD_NAME "scanning PCI bus %d\n", bus_nr);
00394 
00395     return 0;
00396 }

Here is the call graph for this function:

int pcibus_scan_all void   ) 
 

Definition at line 398 of file pcibus_scan.c.

References MOD_NAME, pcibus_allocate_primary_bus(), pcibus_disable, pcibus_primary, pcibus_primary_ops, pcibus_scan_card(), and printk().

Referenced by adi_pcibus_init().

00399 {
00400     struct pcidev_s pcidev;
00401     u8 dev_fn;
00402     int i;
00403 
00404     printk(MOD_NAME "scanning all PCI buses\n");
00405 
00406     pcibus_primary = pcibus_allocate_primary_bus(0, &pcibus_primary_ops);
00407 
00408     if (pcibus_primary == NULL) {
00409         printk(MOD_NAME "can not allocate memory for primary PCI bus, disabling PCI subsystem\n");
00410         pcibus_disable = 1;
00411         return 0;
00412     }
00413 
00414     pcidev.dev_bus = pcibus_primary;
00415     
00416     for (i = 0, dev_fn = 0; i < 32; dev_fn += 8, i++) {
00417         pcidev.dev_fn = dev_fn;
00418         
00419         pcibus_scan_card(&pcidev);
00420     }
00421 
00422 //    adi_print_io_resources();
00423 //    adi_print_mem_resources();
00424 
00425     return 0;
00426 }

Here is the call graph for this function:

int pcibus_scan_card struct pcidev_s *  pcidev  ) 
 

Definition at line 335 of file pcibus_scan.c.

References get_free_pages(), memcpy(), MOD_NAME, pcibus_add_device(), pcibus_device_name(), pcibus_scan_card_function(), and printk().

Referenced by pcibus_scan_all().

00336 {
00337     u8  dev_fn;
00338     u8  dev_fn_cur = 0;
00339     int dev_multi  = 0;
00340     struct pcidev_s *detected_dev;
00341     u16 dev_vendor_id;
00342     u16 dev_device_id;
00343     u8  dev_header_type;
00344 
00345     for (dev_fn = pcidev->dev_fn; dev_fn_cur < 8; dev_fn++, dev_fn_cur++) {
00346         if ((!dev_multi) && dev_fn_cur)
00347             break;
00348             
00349         pcidev->dev_fn = dev_fn;
00350 
00351         pci_read_config_byte(pcidev, PCIDEV_HEADER_TYPE, &dev_header_type);
00352         pci_read_config_word(pcidev, PCIDEV_VENDOR_ID, &dev_vendor_id);
00353         pci_read_config_word(pcidev, PCIDEV_DEVICE_ID, &dev_device_id);
00354 
00355         if ((dev_vendor_id == 0x0000 && ((dev_device_id == 0xFFFF) || (dev_device_id == 0x0000))) || 
00356             (dev_vendor_id == 0xffff))
00357             return -1;
00358             
00359         detected_dev = (struct pcidev_s *)get_free_pages(0);
00360 
00361         if (detected_dev == NULL) {
00362 #if PCI_DEBUG   
00363             printk(MOD_NAME "can not allocate memory for PCI dev\n");
00364 #endif
00365             return -1;
00366         }
00367         
00368         memcpy(detected_dev, pcidev, sizeof(struct pcidev_s));
00369 
00370         if ((dev_header_type & 0x80) && (!dev_fn_cur))
00371             dev_multi = 1;
00372 
00373         detected_dev->dev_header_type  = dev_header_type & 0x7F;
00374         detected_dev->dev_vendor_id    = dev_vendor_id;
00375         detected_dev->dev_device_id    = dev_device_id;
00376         detected_dev->dev_name         = pcibus_device_name(dev_vendor_id, dev_device_id);
00377         detected_dev->dev_multi        = dev_multi;
00378 
00379         pcibus_scan_card_function(detected_dev);
00380 
00381 #if PCI_DEBUG   
00382         printk(MOD_NAME "detected %s (%04x, %04x)\n", detected_dev->dev_name, dev_vendor_id, dev_device_id);
00383 #endif
00384 
00385         pcibus_add_device(detected_dev);
00386     }
00387 
00388     return 0;
00389 }

Here is the call graph for this function:

int pcibus_scan_card_function struct pcidev_s *  pcidev  ) 
 

Definition at line 287 of file pcibus_scan.c.

References MOD_NAME, pcibus_scan_card_memory(), and printk().

Referenced by pcibus_scan_card().

00288 {
00289     u32 dev_class;
00290     u8  dev_irq_pin;
00291     u8  dev_irq;
00292     u16 dev_subvendor_id;
00293     u16 dev_subdevice_id;
00294 
00295     pci_read_config_dword(pcidev, PCIDEV_CLASS_REVISION,  &dev_class);
00296     pci_read_config_byte (pcidev, PCIDEV_INTERRUPT_PIN,   &dev_irq_pin);
00297     pci_read_config_byte (pcidev, PCIDEV_INTERRUPT_LINE,  &dev_irq);
00298     pci_read_config_word (pcidev, PCIDEV_SUBSYSTEM_ID,    &dev_subdevice_id);
00299     pci_read_config_word (pcidev, PCIDEV_SUBSYSTEM_VENDOR_ID, &dev_subvendor_id);
00300 
00301     pcidev->dev_class   = dev_class >> 8;
00302     pcidev->dev_irq_pin = dev_irq_pin;
00303     pcidev->dev_irq     = dev_irq;
00304     pcidev->dev_subvendor_id = dev_subvendor_id;
00305     pcidev->dev_subdevice_id = dev_subdevice_id;
00306 
00307     if ((u16)(pcidev->dev_class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) {
00308 #if PCI_DEBUG
00309         printk(MOD_NAME "%s cardbus legacy mode base\n", pcidev->dev_name);
00310 #endif
00311         pci_write_config_dword(pcidev, PCIDEV_CB_LEGACY_MODE_BASE, 0);
00312     }
00313 
00314     switch (pcidev->dev_header_type) {
00315         case PCIDEV_HDR_TYPE_NORMAL:
00316             pcibus_scan_card_memory(pcidev, PCIDEV_MAX_RESOURCES);
00317             break;
00318 
00319         case PCIDEV_HDR_TYPE_BRIDGE:
00320             pcibus_scan_card_memory(pcidev, PCIDEV_BRIDGE_RESOURCES);
00321             break;
00322 
00323         case PCIDEV_HDR_TYPE_CB:
00324             pcibus_scan_card_memory(pcidev, PCIDEV_CB_RESOURCES);
00325             break;
00326 
00327         default:
00328             printk(MOD_NAME "%s wrong header type\n", pcidev->dev_name);
00329             return -1;
00330     }
00331     
00332     return 0;
00333 }

Here is the call graph for this function:

int pcibus_scan_card_memory struct pcidev_s *  pcidev,
unsigned int  res_nr
 

Definition at line 232 of file pcibus_scan.c.

References adi_register_resource(), MOD_NAME, and printk().

Referenced by pcibus_scan_card_function().

00233 {
00234     u32 start;
00235     u32 size;
00236     u32 value;
00237     unsigned int i;
00238     unsigned int offset = 0;
00239     struct adi_resource_s *adi_resource;
00240 
00241     for (i = 0; i < res_nr; i++) {
00242         
00243         /* PCI Local Bus Specification 2.2 */
00244         offset = PCIDEV_BASE_ADDRESS_0 + (i << 2);
00245         pci_read_config_dword (pcidev, offset, &value);
00246         pci_write_config_dword(pcidev, offset, 0xFFFFFFFF);
00247         pci_read_config_dword (pcidev, offset, &size);
00248         pci_write_config_dword(pcidev, offset, value);
00249     
00250         if (size == 0x00000000 || size == 0xFFFFFFFF)
00251             continue;
00252 
00253         if (value == 0xFFFFFFFF) value = 0;
00254 
00255         adi_resource = &pcidev->dev_resources[i];
00256 
00257         if ((value & PCIDEV_BASE_ADDRESS_MASK) == PCIDEV_BASE_ADDRESS_MEMORY) {
00258             start = value & PCIDEV_BASE_ADDRESS_START_MASK_MEM;
00259             size &= PCIDEV_BASE_ADDRESS_START_MASK_MEM;
00260             size = size & (~(size - 1));
00261             size--;
00262             
00263             adi_resource->res_flags = ADI_RES_FLAG_MEM;
00264         } else
00265         if ((value & PCIDEV_BASE_ADDRESS_MASK) == PCIDEV_BASE_ADDRESS_IO) {
00266             start = value & PCIDEV_BASE_ADDRESS_START_MASK_IO;
00267             size &= PCIDEV_BASE_ADDRESS_START_MASK_IO;
00268             size = size & (~(size - 1));
00269             size--;
00270             
00271             adi_resource->res_flags = ADI_RES_FLAG_IO;
00272         }
00273         
00274         adi_resource->res_name = pcidev->dev_name;
00275         adi_resource->res_start = start;
00276         adi_resource->res_end = start + size;
00277 
00278         INIT_LIST_HEAD(&(adi_resource->res_list));
00279         if (adi_register_resource(adi_resource) < 0) {
00280             printk(MOD_NAME "Can not register resource\n");
00281         }
00282     }
00283     
00284     return 0;
00285 }

Here is the call graph for this function:

int pcibus_set_power_state struct pcidev_s *  pcidev,
int  power_state
 

Definition at line 149 of file pcibus_scan.c.

References pcibus_find_capability_pos(), and pcibus_power_change_delay().

Referenced by pcibus_enable_device().

00150 {
00151     int cap_pos;
00152     u16 pm_caps;
00153     u16 pm_ctrl;
00154 
00155     if (power_state < 0 || power_state > 3)
00156         return -1;
00157     
00158     if ((cap_pos = pcibus_find_capability_pos(pcidev, PCI_CAP_ID_PM)) < 0)
00159         return -1;
00160 
00161     if (power_state == 1 || power_state == 2) {
00162         pci_read_config_word(pcidev, cap_pos + PCI_PM_PMC, &pm_caps);
00163         if (!(pm_caps & (PCI_PM_CAP_D1 << (power_state - 1))))
00164             return -1;
00165     }
00166 
00167     pci_read_config_word(pcidev, cap_pos + PCI_PM_CTRL, &pm_ctrl);
00168     pm_ctrl = (pm_ctrl & (~PCI_PM_CTRL_STATE_MASK)) | power_state;
00169     pci_write_config_word(pcidev, cap_pos + PCI_PM_CTRL, pm_ctrl);
00170 
00171     pcibus_power_change_delay(pcidev, 0, 0);
00172 
00173     return 0;
00174 }

Here is the call graph for this function:


Variable Documentation

int pcibus_disable
 

Definition at line 27 of file pcibus_core.c.

Referenced by pcibus_scan_all().

struct list_head pcibus_list
 

Definition at line 22 of file pcibus_core.c.

Referenced by adi_pcibus_init(), and pcibus_add_bus().

spinlock_t pcibus_list_lock
 

Definition at line 24 of file pcibus_core.c.

Referenced by pcibus_add_bus().

struct pcibus_s* pcibus_primary
 

Definition at line 32 of file pcibus_scan.c.

Referenced by pcibus_scan_all().

struct pcibus_ops_s pcibus_primary_ops
 

Definition at line 30 of file pcibus_ops.c.

Referenced by pcibus_check_direct_access(), and pcibus_scan_all().

struct list_head pcidev_list
 

Definition at line 23 of file pcibus_core.c.

Referenced by adi_pcibus_init(), pcibus_add_device(), pcibus_find_device_by_fn(), pcibus_find_device_by_id(), pcibus_irq_all_set(), pcibus_irq_dev_set(), and pcibus_print_all().

spinlock_t pcidev_list_lock
 

Definition at line 25 of file pcibus_core.c.

Referenced by pcibus_add_device(), pcibus_find_device_by_fn(), pcibus_find_device_by_id(), pcibus_irq_all_set(), and pcibus_print_all().

Dokumentacje wygenerowano programem Doxygen 1.4.2 dla projektu Agnix