pci 구동 프레임 워 크
13939 단어 링크 ux 구동
struct pci_bus {
// , ,
struct list_head node; /* node in list of buses */
//pci
struct pci_bus *parent; /* parent bus this bridge is on */
// pci
struct list_head children; /* list of child buses */
// pci pci
struct list_head devices; /* list of devices on this bus */
// pci
struct pci_dev *self; /* bridge device as seen by parent */
// pci
struct list_head slots; /* list of slots on this bus */
struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
struct list_head resources; /* address space routed to this bus */
// pci
struct pci_ops *ops; /* configuration access functions */
void *sysdata; /* hook for sys-specific extension */
struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */
unsigned char number; /* bus number */ //
unsigned char primary; /* number of primary bridge */ // pci pci_dev
unsigned char secondary; /* number of secondary bridge */ // pci pci_dev
unsigned char subordinate; /* max number of subordinate buses */ // pci subordinate
unsigned char max_bus_speed; /* enum pci_bus_speed */
unsigned char cur_bus_speed; /* enum pci_bus_speed */
char name[48];
unsigned short bridge_ctl; /* manage NO_ISA/FBB/et al behaviors */
pci_bus_flags_t bus_flags; /* Inherited by child busses */
struct device *bridge; // pci pci_dev device
struct device dev; //
struct bin_attribute *legacy_io; /* legacy I/O for this bus */
struct bin_attribute *legacy_mem; /* legacy mem */
unsigned int is_added:1;
};
struct pci_dev {
// pci
struct list_head bus_list; /* node in per-bus list */
// pci
struct pci_bus *bus; /* bus this device is on */
// pci_dev ,
struct pci_bus *subordinate; /* bus this device bridges to */
void *sysdata; /* hook for sys-specific extension */
struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */
//
struct pci_slot *slot; /* Physical slot this device is in */
unsigned int devfn; /* encoded device & function index */ //pci
unsigned short vendor; // ID
unsigned short device; // ID
unsigned short subsystem_vendor; // ID
unsigned short subsystem_device; // ID
unsigned int class; /* 3 bytes: (base,sub,prog-if) */
u8 revision; /* PCI revision, low byte of class word */
u8 hdr_type; /* PCI header type (`multi' flag masked out) */
u8 pcie_cap; /* PCI-E capability offset */
u8 pcie_type:4; /* PCI-E device/port type */
u8 pcie_mpss:3; /* PCI-E Max Payload Size Supported */
//ROM pci
u8 rom_base_reg; /* which config register controls the ROM */
u8 pin; /* which interrupt pin this device uses */
// pci_dev pci_driver
struct pci_driver *driver; /* which driver has allocated this device */
u64 dma_mask; /* Mask of the bits of bus address this
device implements. Normally this is
0xffffffff. You only need to change
this if your device has broken DMA
or supports 64-bit transfers. */
struct device_dma_parameters dma_parms;
pci_power_t current_state; /* Current operating state. In ACPI-speak,
this is D0-D3, D0 being fully functional,
and D3 being off. */
int pm_cap; /* PM capability offset in the
configuration space */
unsigned int pme_support:5; /* Bitmask of states from which PME#
can be generated */
unsigned int pme_interrupt:1;
unsigned int d1_support:1; /* Low power state D1 is supported */
unsigned int d2_support:1; /* Low power state D2 is supported */
unsigned int no_d1d2:1; /* Only allow D0 and D3 */
unsigned int mmio_always_on:1; /* disallow turning off io/mem
decoding during bar sizing */
unsigned int wakeup_prepared:1;
unsigned int d3_delay; /* D3->D0 transition time in ms */
#ifdef CONFIG_PCIEASPM
struct pcie_link_state *link_state; /* ASPM link state. */
#endif
pci_channel_state_t error_state; /* current connectivity state */
//
struct device dev; /* Generic device interface */
int cfg_size; /* Size of configuration space */
/*
* Instead of touching interrupt line and base address registers
* directly, use the values stored here. They might be different!
*/
unsigned int irq;
struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
resource_size_t fw_addr[DEVICE_COUNT_RESOURCE]; /* FW-assigned addr */
/* These fields are used by common fixups */
unsigned int transparent:1; /* Transparent PCI bridge */
unsigned int multifunction:1;/* Part of multi-function device */
/* keep track of device state */
unsigned int is_added:1;
unsigned int is_busmaster:1; /* device is busmaster */
unsigned int no_msi:1; /* device may not use msi */
unsigned int block_ucfg_access:1; /* userspace config space access is blocked */
unsigned int broken_parity_status:1; /* Device generates false positive parity */
unsigned int irq_reroute_variant:2; /* device needs IRQ rerouting variant */
unsigned int msi_enabled:1;
unsigned int msix_enabled:1;
unsigned int ari_enabled:1; /* ARI forwarding */
unsigned int is_managed:1;
unsigned int is_pcie:1; /* Obsolete. Will be removed.
Use pci_is_pcie() instead */
unsigned int needs_freset:1; /* Dev requires fundamental reset */
unsigned int state_saved:1;
unsigned int is_physfn:1;
unsigned int is_virtfn:1;
unsigned int reset_fn:1;
unsigned int is_hotplug_bridge:1;
unsigned int __aer_firmware_first_valid:1;
unsigned int __aer_firmware_first:1;
pci_dev_flags_t dev_flags;
atomic_t enable_cnt; /* pci_enable_device has been called */
u32 saved_config_space[16]; /* config space saved at suspend time */
struct hlist_head saved_cap_space;
struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
int rom_attr_enabled; /* has display of the rom attribute been enabled? */
struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */
struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */
#ifdef CONFIG_PCI_MSI
struct list_head msi_list;
#endif
struct pci_vpd *vpd;
#ifdef CONFIG_PCI_IOV
union {
struct pci_sriov *sriov; /* SR-IOV capability related */
struct pci_dev *physfn; /* the PF this VF is associated with */
};
struct pci_ats *ats; /* Address Translation Service */
#endif
};
pci_dev 는 논리 장 치 를 묘사 하 는데 usb 시스템 의 (usb devie 와 usb interface) 개념 과 약간 유사 하 다.설정 이 든 스 캔 이 든 모두 Pci 논리 장치 에 기반 합 니 다.그러나 핫 플러그 는 반드시 Pci 물리 장 치 를 대상 으로 Pci 물리 장 치 를 묘사 하 는 구조 체 는 Pci 입 니 다.slot。 struct pci_slot {
struct pci_bus *bus; /* The bus this slot is on */ // slot pci
struct list_head list; /* node in list of slots on this bus */ // pci slot
struct hotplug_slot *hotplug; /* Hotplug info (migrate over time) */
unsigned char number; /* PCI_SLOT(pci_dev->devfn) */
struct kobject kobj;
};
2. x86 구조의 Pci 시스템 초기 화(1)pci_bus 클래스 초기 화 (initcall 2)
static int __init pcibus_class_init(void)
{
return class_register(&pcibus_class);
}
postcore_initcall(pcibus_class_init);
(2) Pci 버스 초기 화 (initcall 2)static int __init pci_driver_init(void)
{
return bus_register(&pci_bus_type);
}
postcore_initcall(pci_driver_init);
(3) pci 설정 접근 방법의 초기 화 (initcall 3)pci_arch_init 의 주요 목적 은 rawpci_ops 또는 rawpci_ext_ops 할당 은 Pci 설정 공간 에 접근 하 는 작업 표를 가리 키 기 때문에 Pci 스 캔 전에 완료 해 야 합 니 다.
이 함수 의 논 리 는: pci 를 먼저 호출 하 는 것 입 니 다.direct_probe 함수 검사 메커니즘 \ # 1 (또는 메커니즘 \ # 2), pci 호출pcibios_init 함수 검사 pci bios 방식, 마지막 으로 pci 호출direct_init 함 수 는 메커니즘 을 사용 해 야 하 는 지 돌아 보 았 습 니 다. \ # 1 (또는 메커니즘 \ # 2), 이러한 호출 순 서 는 우선 사용 메커니즘 \ # 1 (또는 메커니즘 \ # 2) 을 확보 합 니 다.
static __init int pci_arch_init(void)
{
#ifdef CONFIG_PCI_DIRECT
int type = 0;
type = pci_direct_probe();
#endif
if (!(pci_probe & PCI_PROBE_NOEARLY))
pci_mmcfg_early_init();
if (x86_init.pci.arch_init && !x86_init.pci.arch_init())
return 0;
#ifdef CONFIG_PCI_BIOS
pci_pcbios_init();
#endif
/*
* don't check for raw_pci_ops here because we want pcbios as last
* fallback, yet it's needed to run first to set pcibios_last_bus
* in case legacy PCI probing is used. otherwise detecting peer busses
* fails.
*/
#ifdef CONFIG_PCI_DIRECT
pci_direct_init(type);
#endif
if (!raw_pci_ops && !raw_pci_ext_ops)
printk(KERN_ERR
"PCI: Fatal: No config space access function found
");
dmi_check_pciprobe();
dmi_check_skip_isa_align();
return 0;
}
arch_initcall(pci_arch_init);
(4) Pci 버스 스 캔 (initcall 4)pci 버스 스캐닝 프로 세 스 pcisubsys_init 함수 시작, 주로 세 가지 문 제 를 해결 합 니 다:
Pci 버스 스 캔 을 통 해 시스템 의 각급 버스 에 있 는 Pci 장 치 를 발견 하고 모든 Pci 장 치 를 설정 합 니 다.
메모리 에 각 Pci 장치 에 대응 하 는 데이터 구 조 를 구축 하여 후속 적 으로 조작 할 수 있 도록 합 니 다.
sysfs 파일 시스템 에 Pci 디 렉 터 리 트 리 를 구축 하여 사용자 공간 에 정 보 를 내 보 내 고 제어 인 터 페 이 스 를 제공 합 니 다.
int __init pci_subsys_init(void)
{
/*
* The init function returns an non zero value when
* pci_legacy_init should be invoked.
*/
if (x86_init.pci.init())
pci_legacy_init(); // pci ,
pcibios_fixup_peer_bridges();
x86_init.pci.init_irq(); //pci
pcibios_init(); //pci
return 0;
}
subsys_initcall(pci_subsys_init);
int __init pci_legacy_init(void)
{
if (!raw_pci_ops) {
printk("PCI: System does not support PCI
");
return 0;
}
printk("PCI: Probing PCI hardware
");
pci_root_bus = pcibios_scan_root(0); // pci
if (pci_root_bus)
pci_bus_add_devices(pci_root_bus); // pci pci sysfs
return 0;
}
pci_legacy_init pci_scan_bus_parented
pci_create_bus
pci_scan_child_bus
pci_scan_slot
pci_scan_single_device
pci_scan_device
alloc_pci_dev
pci_setup_device
pci_device_add
pci_scan_bridge
pci_add_new_bus
pci_alloc_child_bus
pci_scan_child_bus
pci 인 터 럽 트 루트 초기 화
void __init pcibios_irq_init(void)
{
DBG(KERN_DEBUG "PCI: IRQ init
");
if (raw_pci_ops == NULL)
return;
dmi_check_system(pciirq_dmi_table);
pirq_table = pirq_find_routing_table(); //
#ifdef CONFIG_PCI_BIOS
if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN))
pirq_table = pcibios_get_irq_routing_table(); //
#endif
if (pirq_table) { //
pirq_peer_trick(); // pci pci ,
pirq_find_router(&pirq_router); // , pirq_router
if (pirq_table->exclusive_irqs) {
int i;
for (i = 0; i < 16; i++)
if (!(pirq_table->exclusive_irqs & (1 << i)))
pirq_penalty[i] += 100;
}
/*
* If we're using the I/O APIC, avoid using the PCI IRQ
* routing table
*/
if (io_apic_assign_pci_irqs)
pirq_table = NULL;
}
x86_init.pci.fixup_irqs(); // ISA IRQ
if (io_apic_assign_pci_irqs && pci_routeirq) {
struct pci_dev *dev = NULL;
/*
* PCI IRQ routing is set up by pci_enable_device(), but we
* also do it here in case there are still broken drivers that
* don't use pci_enable_device().
*/
printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified
");
for_each_pci_dev(dev)
pirq_enable_irq(dev);
}
}
Pci 자원 배분 절차 초기 화int __init pcibios_init(void)
{
if (!raw_pci_ops) {
printk(KERN_WARNING "PCI: System does not support PCI
");
return 0;
}
pcibios_set_cache_line_size();
pcibios_resource_survey();
if (pci_bf_sort >= pci_force_bf)
pci_sort_breadthfirst();
return 0;
}
void __init pcibios_resource_survey(void)
{
DBG("PCI: Allocating resources
");
pcibios_allocate_bus_resources(&pci_root_buses);
pcibios_allocate_resources(0);
pcibios_allocate_resources(1);
e820_reserve_resources_late();
/*
* Insert the IO APIC resources after PCI initialization has
* occurred to handle IO APICS that are mapped in on a BAR in
* PCI space, but before trying to assign unassigned pci res.
*/
ioapic_insert_resources();
}
pcibios_allocate_bus_resources 함 수 는 모든 하위 버스 에 자원 창 을 저장 하고 유지 할 수 있다 면 자원 을 부모 자원 의 링크 에 걸 어 줍 니 다.pcibios_allocate_resources (0) 시 작 된 Pci 장치 처리
pcibios_allocate_resources (1) 사용 하지 않 는 Pci 장치 처리
3. pci 장치 구동 에 대한 소개
struct pci_driver {
struct list_head node;
const char *name;
const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */
int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */
void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */
int (*suspend) (struct pci_dev *dev, pm_message_t state); /* Device suspended */
int (*suspend_late) (struct pci_dev *dev, pm_message_t state);
int (*resume_early) (struct pci_dev *dev);
int (*resume) (struct pci_dev *dev); /* Device woken up */
void (*shutdown) (struct pci_dev *dev);
struct pci_error_handlers *err_handler;
struct device_driver driver;
struct pci_dynids dynids;
};
pci_register_driver 등록 pci 드라이버pci_register_driver
driver_register
bus_add_driver
driver_attach
bus_for_each_dev(drv->bus, NULL, drv, __driver_attach)
__driver_attach
driver_match_device
pci_bus_match
pci_match_device / / 현재 동적 Id 체인 테이블 에서 일치 하고 정적 ID 테이블 에서 일치 합 니 다
driver_probe_device
really_probe
dev->bus->probe(dev)
pci_device_probe
__pci_device_probe
pci_match_device
pci_call_probe
local_pci_probe
ddi->drv->probe(ddi->dev, ddi->id)
여기까지 Pci 프레임 워 크 는 대체적으로 소개 되 었 고 구체 적 인 스 캔 과정 은 을 참조 할 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
u - boot 2 단계 빗질 시작\ #define DECLARE_GLOBAL_DATA_PTR register volatile gd_t * gd asm ("r8") 설명: register 를 통 해 레지스터 변 수 를 표시 하고, asm ("r8")...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.