⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 io_apic.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
     * Determine IRQ line polarity (high active or low active):     */    switch (mp_irqs[idx].mpc_irqflag & 3)    {    case 0: /* conforms, ie. bus-type dependent polarity */    {        switch (mp_bus_id_to_type[bus])        {        case MP_BUS_ISA: /* ISA pin */        {            polarity = default_ISA_polarity(idx);            break;        }        case MP_BUS_EISA: /* EISA pin */        {            polarity = default_EISA_polarity(idx);            break;        }        case MP_BUS_PCI: /* PCI pin */        {            polarity = default_PCI_polarity(idx);            break;        }        case MP_BUS_MCA: /* MCA pin */        {            polarity = default_MCA_polarity(idx);            break;        }        case MP_BUS_NEC98: /* NEC 98 pin */        {            polarity = default_NEC98_polarity(idx);            break;        }        default:        {            printk(KERN_WARNING "broken BIOS!!\n");            polarity = 1;            break;        }        }        break;    }    case 1: /* high active */    {        polarity = 0;        break;    }    case 2: /* reserved */    {        printk(KERN_WARNING "broken BIOS!!\n");        polarity = 1;        break;    }    case 3: /* low active */    {        polarity = 1;        break;    }    default: /* invalid */    {        printk(KERN_WARNING "broken BIOS!!\n");        polarity = 1;        break;    }    }    return polarity;}static int MPBIOS_trigger(int idx){    int bus = mp_irqs[idx].mpc_srcbus;    int trigger;    /*     * Determine IRQ trigger mode (edge or level sensitive):     */    switch ((mp_irqs[idx].mpc_irqflag>>2) & 3)    {    case 0: /* conforms, ie. bus-type dependent */    {        switch (mp_bus_id_to_type[bus])        {        case MP_BUS_ISA: /* ISA pin */        {            trigger = default_ISA_trigger(idx);            break;        }        case MP_BUS_EISA: /* EISA pin */        {            trigger = default_EISA_trigger(idx);            break;        }        case MP_BUS_PCI: /* PCI pin */        {            trigger = default_PCI_trigger(idx);            break;        }        case MP_BUS_MCA: /* MCA pin */        {            trigger = default_MCA_trigger(idx);            break;        }        case MP_BUS_NEC98: /* NEC 98 pin */        {            trigger = default_NEC98_trigger(idx);            break;        }        default:        {            printk(KERN_WARNING "broken BIOS!!\n");            trigger = 1;            break;        }        }        break;    }    case 1: /* edge */    {        trigger = 0;        break;    }    case 2: /* reserved */    {        printk(KERN_WARNING "broken BIOS!!\n");        trigger = 1;        break;    }    case 3: /* level */    {        trigger = 1;        break;    }    default: /* invalid */    {        printk(KERN_WARNING "broken BIOS!!\n");        trigger = 0;        break;    }    }    return trigger;}static inline int irq_polarity(int idx){    return MPBIOS_polarity(idx);}static inline int irq_trigger(int idx){    return MPBIOS_trigger(idx);}static int pin_2_irq(int idx, int apic, int pin){    int irq, i;    int bus = mp_irqs[idx].mpc_srcbus;    /*     * Debugging check, we are in big trouble if this message pops up!     */    if (mp_irqs[idx].mpc_dstirq != pin)        printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");    switch (mp_bus_id_to_type[bus])    {    case MP_BUS_ISA: /* ISA pin */    case MP_BUS_EISA:    case MP_BUS_MCA:    case MP_BUS_NEC98:    {        irq = mp_irqs[idx].mpc_srcbusirq;        break;    }    case MP_BUS_PCI: /* PCI pin */    {        /*         * PCI IRQs are mapped in order         */        i = irq = 0;        while (i < apic)            irq += nr_ioapic_registers[i++];        irq += pin;        /*         * For MPS mode, so far only needed by ES7000 platform         */        if (ioapic_renumber_irq)            irq = ioapic_renumber_irq(apic, irq);        break;    }    default:    {        printk(KERN_ERR "unknown bus type %d.\n",bus);        irq = 0;        break;    }    }    return irq;}static inline int IO_APIC_irq_trigger(int irq){    int apic, idx, pin;    for (apic = 0; apic < nr_ioapics; apic++) {        for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {            idx = find_irq_entry(apic,pin,mp_INT);            if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin)))                return irq_trigger(idx);        }    }    /*     * nonexistent IRQs are edge default     */    return 0;}/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */u8 irq_vector[NR_IRQ_VECTORS] __read_mostly;int assign_irq_vector(int irq){    static unsigned current_vector = FIRST_DYNAMIC_VECTOR, offset = 0;    unsigned vector;    BUG_ON(irq >= NR_IRQ_VECTORS);    spin_lock(&vector_lock);    if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {        spin_unlock(&vector_lock);        return IO_APIC_VECTOR(irq);    }next:    current_vector += 8;    /* Skip the hypercall vector. */    if (current_vector == HYPERCALL_VECTOR)        goto next;    /* Skip the Linux/BSD fast-trap vector. */    if (current_vector == 0x80)        goto next;    if (current_vector > LAST_DYNAMIC_VECTOR) {        offset++;        if (!(offset%8)) {            spin_unlock(&vector_lock);            return -ENOSPC;        }        current_vector = FIRST_DYNAMIC_VECTOR + offset;    }    vector = current_vector;    vector_irq[vector] = irq;    if (irq != AUTO_ASSIGN)        IO_APIC_VECTOR(irq) = vector;    spin_unlock(&vector_lock);    return vector;}static struct hw_interrupt_type ioapic_level_type;static struct hw_interrupt_type ioapic_edge_type;#define IOAPIC_AUTO	-1#define IOAPIC_EDGE	0#define IOAPIC_LEVEL	1static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger){    if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||        trigger == IOAPIC_LEVEL)        irq_desc[vector].handler = &ioapic_level_type;    else        irq_desc[vector].handler = &ioapic_edge_type;}static void __init setup_IO_APIC_irqs(void){    struct IO_APIC_route_entry entry;    int apic, pin, idx, irq, first_notcon = 1, vector;    unsigned long flags;    apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");    for (apic = 0; apic < nr_ioapics; apic++) {	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {            /*             * add it to the IO-APIC irq-routing table:             */            memset(&entry,0,sizeof(entry));            entry.delivery_mode = INT_DELIVERY_MODE;            entry.dest_mode = INT_DEST_MODE;            entry.mask = 0;				/* enable IRQ */            entry.dest.logical.logical_dest =                 cpu_mask_to_apicid(TARGET_CPUS);            idx = find_irq_entry(apic,pin,mp_INT);            if (idx == -1) {                if (first_notcon) {                    apic_printk(APIC_VERBOSE, KERN_DEBUG                                " IO-APIC (apicid-pin) %d-%d",                                mp_ioapics[apic].mpc_apicid,                                pin);                    first_notcon = 0;                } else                    apic_printk(APIC_VERBOSE, ", %d-%d",                                mp_ioapics[apic].mpc_apicid, pin);                continue;            }            entry.trigger = irq_trigger(idx);            entry.polarity = irq_polarity(idx);            if (irq_trigger(idx)) {                entry.trigger = 1;                entry.mask = 1;            }            irq = pin_2_irq(idx, apic, pin);            /*             * skip adding the timer int on secondary nodes, which causes             * a small but painful rift in the time-space continuum             */            if (multi_timer_check(apic, irq))                continue;            else                add_pin_to_irq(irq, apic, pin);            if (!apic && !IO_APIC_IRQ(irq))                continue;            if (IO_APIC_IRQ(irq)) {                vector = assign_irq_vector(irq);                entry.vector = vector;                ioapic_register_intr(irq, vector, IOAPIC_AUTO);		                if (!apic && (irq < 16))                    disable_8259A_irq(irq);            }            spin_lock_irqsave(&ioapic_lock, flags);            io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));            io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));            set_native_irq_info(entry.vector, TARGET_CPUS);            spin_unlock_irqrestore(&ioapic_lock, flags);	}    }    if (!first_notcon)        apic_printk(APIC_VERBOSE, " not connected.\n");}/* * Set up the 8259A-master output pin: */static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector){    struct IO_APIC_route_entry entry;    unsigned long flags;    memset(&entry,0,sizeof(entry));    disable_8259A_irq(0);    /* mask LVT0 */    apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);    /*     * We use logical delivery to get the timer IRQ     * to the first CPU.     */    entry.dest_mode = INT_DEST_MODE;    entry.mask = 0;					/* unmask IRQ now */    entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);    entry.delivery_mode = INT_DELIVERY_MODE;    entry.polarity = 0;    entry.trigger = 0;    entry.vector = vector;    /*     * The timer IRQ doesn't have to know that behind the     * scene we have a 8259A-master in AEOI mode ...     */    irq_desc[IO_APIC_VECTOR(0)].handler = &ioapic_edge_type;    /*     * Add it to the IO-APIC irq-routing table:     */    spin_lock_irqsave(&ioapic_lock, flags);    io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));    io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));    spin_unlock_irqrestore(&ioapic_lock, flags);    enable_8259A_irq(0);}static inline void UNEXPECTED_IO_APIC(void){}void /*__init*/ __print_IO_APIC(void){    int apic, i;    union IO_APIC_reg_00 reg_00;    union IO_APIC_reg_01 reg_01;    union IO_APIC_reg_02 reg_02;    union IO_APIC_reg_03 reg_03;    unsigned long flags;    printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);    for (i = 0; i < nr_ioapics; i++)        printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",               mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]);    /*     * We are a bit conservative about what we expect.  We have to     * know about every hardware change ASAP.     */    printk(KERN_INFO "testing the IO APIC.......................\n");    for (apic = 0; apic < nr_ioapics; apic++) {	spin_lock_irqsave(&ioapic_lock, flags);	reg_00.raw = io_apic_read(apic, 0);	reg_01.raw = io_apic_read(apic, 1);	if (reg_01.bits.version >= 0x10)            reg_02.raw = io_apic_read(apic, 2);	if (reg_01.bits.version >= 0x20)            reg_03.raw = io_apic_read(apic, 3);	spin_unlock_irqrestore(&ioapic_lock, flags);	printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid);	printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);	printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);	printk(KERN_DEBUG ".......    : Delivery Type: %X\n", reg_00.bits.delivery_type);	printk(KERN_DEBUG ".......    : LTS          : %X\n", reg_00.bits.LTS);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -