arch/i386/kernel/irq.h
1666 #ifndef __irq_h
1667 #define __irq_h
1668
1669 #include <asm/irq.h>
1670
1671 /* Interrupt controller descriptor. This is all we need
1672 * to describe about the low-level hardware. */
1673 struct hw_interrupt_type {
1674 const char * typename;
1675 void (*startup)(unsigned int irq);
1676 void (*shutdown)(unsigned int irq);
1677 void (*handle)(unsigned int irq,struct pt_regs * regs);
1678 void (*enable)(unsigned int irq);
1679 void (*disable)(unsigned int irq);
1680 };
1681
1682 extern struct hw_interrupt_type no_irq_type;
1683
1684 /* IRQ line status. */
1685 #define IRQ_INPROGRESS 1 /* active - do not enter! */
1686 #define IRQ_DISABLED 2 /* disabled - do not enter! */
1687 #define IRQ_PENDING 4 /* pending, replay on enable*/
1688 #define IRQ_REPLAY 8 /* replayed but not acked */
1689 #define IRQ_AUTODETECT 16 /* IRQ being autodetected */
1690
1691 /* This is the "IRQ descriptor", which contains various
1692 * information about the irq, including what kind of
1693 * hardware handling it has, whether it is disabled etc
1694 * etc.
1695 *
1696 * Pad this out to 32 bytes for cache and indexing
1697 * reasons. */
1698 typedef struct {
1699 /* IRQ status - IRQ_INPROGRESS, IRQ_DISABLED */
1700 unsigned int status;
1701 /* handle/enable/disable functions */
1702 struct hw_interrupt_type *handler;
1703 /* IRQ action list */
1704 struct irqaction *action;
1705 /* Disable depth for nested irq disables */
1706 unsigned int depth;
1707 } irq_desc_t;
1708
1709 /* IDT vectors usable for external interrupt sources
1710 * start at 0x20: */
1711 #define FIRST_EXTERNAL_VECTOR 0x20
1712
1713 #define SYSCALL_VECTOR 0x80
1714
1715 /* Vectors 0x20-0x2f are used for ISA interrupts. */
1716
1717 /* Special IRQ vectors used by the SMP architecture:
1718 *
1719 * (some of the following vectors are 'rare', they might
1720 * be merged into a single vector to save vector
1721 * space. TLB, reschedule and local APIC vectors are
1722 * performance-critical.) */
1723 #define RESCHEDULE_VECTOR 0x30
1724 #define INVALIDATE_TLB_VECTOR 0x31
1725 #define STOP_CPU_VECTOR 0x40
1726 #define LOCAL_TIMER_VECTOR 0x41
1727 #define MTRR_CHANGE_VECTOR 0x50
1728
1729 /* First APIC vector available to drivers: (vectors
1730 * 0x51-0xfe) */
1731 #define IRQ0_TRAP_VECTOR 0x51
1732
1733 /* This IRQ should never happen, but we print a message
1734 nevertheless. */
1735 #define SPURIOUS_APIC_VECTOR 0xff
1736
1737 extern irq_desc_t irq_desc[NR_IRQS];
1738 extern int irq_vector[NR_IRQS];
1739 #define IO_APIC_VECTOR(irq) irq_vector[irq]
1740
1741 extern void init_IRQ_SMP(void);
1742 extern int handle_IRQ_event(unsigned int,
1743 struct pt_regs *, struct irqaction *);
1744 extern int setup_x86_irq(unsigned int,
1745 struct irqaction *);
1746
1747 /* Various low-level irq details needed by irq.c,
1748 * process.c, time.c, io_apic.c and smp.c
1749 *
1750 * Interrupt entry/exit code at both C and assembly level
1751 */
1752
1753 extern void no_action(int cpl, void *dev_id,
1754 struct pt_regs *regs);
1755 extern void mask_irq(unsigned int irq);
1756 extern void unmask_irq(unsigned int irq);
1757 extern void disable_8259A_irq(unsigned int irq);
1758 extern int i8259A_irq_pending(unsigned int irq);
1759 extern void ack_APIC_irq(void);
1760 extern void FASTCALL(send_IPI_self(int vector));
1761 extern void smp_send_mtrr(void);
1762 extern void init_VISWS_APIC_irqs(void);
1763 extern void setup_IO_APIC(void);
1764 extern int IO_APIC_get_PCI_irq_vector(int bus, int slot,
1765 int fn);
1766 extern void make_8259A_irq(unsigned int irq);
1767 extern void send_IPI(int dest, int vector);
1768 extern void init_pic_mode(void);
1769 extern void print_IO_APIC(void);
1770
1771 extern unsigned long io_apic_irqs;
1772
1773 extern char _stext, _etext;
1774
1775 #define MAX_IRQ_SOURCES 128
1776 #define MAX_MP_BUSSES 32
1777 enum mp_bustype {
1778 MP_BUS_ISA,
1779 MP_BUS_PCI
1780 };
1781 extern int mp_bus_id_to_type [MAX_MP_BUSSES];
1782 extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
1783 extern char ioapic_OEM_ID [16];
1784 extern char ioapic_Product_ID [16];
1785
1786 extern spinlock_t irq_controller_lock;
1787
1788 #ifdef __SMP__
1789
1790 #include <asm/atomic.h>
1791
1792 static inline void irq_enter(int cpu, unsigned int irq)
1793 {
1794 hardirq_enter(cpu);
1795 while (test_bit(0,&global_irq_lock)) {
1796 /* nothing */;
1797 }
1798 }
1799
1800 static inline void irq_exit(int cpu, unsigned int irq)
1801 {
1802 hardirq_exit(cpu);
1803 }
1804
1805 #define IO_APIC_IRQ(x) (((x) >= 16) || \
1806 ((1<<(x)) & io_apic_irqs))
1807
1808 #else
1809
1810 #define irq_enter(cpu, irq) (++local_irq_count[cpu])
1811 #define irq_exit(cpu, irq) (--local_irq_count[cpu])
1812
1813 #define IO_APIC_IRQ(x) (0)
1814
1815 #endif
1816
1817 #define __STR(x) #x
1818 #define STR(x) __STR(x)
1819
1820 #define SAVE_ALL \
1821 "cld\n\t" \
1822 "pushl %es\n\t" \
1823 "pushl %ds\n\t" \
1824 "pushl %eax\n\t" \
1825 "pushl %ebp\n\t" \
1826 "pushl %edi\n\t" \
1827 "pushl %esi\n\t" \
1828 "pushl %edx\n\t" \
1829 "pushl %ecx\n\t" \
1830 "pushl %ebx\n\t" \
1831 "movl $" STR(__KERNEL_DS) ",%edx\n\t" \
1832 "movl %dx,%ds\n\t" \
1833 "movl %dx,%es\n\t"
1834
1835 #define IRQ_NAME2(nr) nr##_interrupt(void)
1836 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
1837
1838 #define GET_CURRENT \
1839 "movl %esp, %ebx\n\t" \
1840 "andl $-8192, %ebx\n\t"
1841
1842 #ifdef __SMP__
1843
1844 /* SMP has a few special interrupts for IPI messages */
1845
1846 #define BUILD_SMP_INTERRUPT(x) \
1847 asmlinkage void x(void); \
1848 __asm__( \
1849 "\n"__ALIGN_STR"\n" \
1850 SYMBOL_NAME_STR(x) ":\n\t" \
1851 "pushl $-1\n\t" \
1852 SAVE_ALL \
1853 "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
1854 "jmp ret_from_intr\n");
1855
1856 #define BUILD_SMP_TIMER_INTERRUPT(x) \
1857 asmlinkage void x(struct pt_regs * regs); \
1858 __asm__( \
1859 "\n"__ALIGN_STR"\n" \
1860 SYMBOL_NAME_STR(x) ":\n\t" \
1861 "pushl $-1\n\t" \
1862 SAVE_ALL \
1863 "movl %esp,%eax\n\t" \
1864 "pushl %eax\n\t" \
1865 "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
1866 "addl $4,%esp\n\t" \
1867 "jmp ret_from_intr\n");
1868
1869 #endif /* __SMP__ */
1870
1871 #define BUILD_COMMON_IRQ() \
1872 __asm__( \
1873 "\n" __ALIGN_STR"\n" \
1874 "common_interrupt:\n\t" \
1875 SAVE_ALL \
1876 "pushl $ret_from_intr\n\t" \
1877 "jmp "SYMBOL_NAME_STR(do_IRQ));
1878
1879 /* subtle. orig_eax is used by the signal code to
1880 * distinct between system calls and interrupted 'random
1881 * user-space'. Thus we have to put a negative value into
1882 * orig_eax here. (the problem is that both system calls
1883 * and IRQs want to have small integer numbers in
1884 * orig_eax, and the syscall code has won the
1885 * optimization conflict ;) */
1886 #define BUILD_IRQ(nr) \
1887 asmlinkage void IRQ_NAME(nr); \
1888 __asm__( \
1889 "\n"__ALIGN_STR"\n" \
1890 SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
1891 "pushl $"#nr"-256\n\t" \
1892 "jmp common_interrupt");
1893
1894 /* x86 profiling function, SMP safe. We might want to do
1895 * this in assembly totally? */
1896 static inline void x86_do_profile (unsigned long eip)
1897 {
1898 if (prof_buffer && current->pid) {
1899 eip -= (unsigned long) &_stext;
1900 eip >>= prof_shift;
1901 /* Don't ignore out-of-bounds EIP values silently,
1902 * put them into the last histogram slot, so if
1903 * present, they will show up as a sharp peak. */
1904 if (eip > prof_len-1)
1905 eip = prof_len-1;
1906 atomic_inc((atomic_t *)&prof_buffer[eip]);
1907 }
1908 }
1909
1910 #endif
Сайт управляется системой
uCoz