Ядро Linux в комментариях

       

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


Содержание раздела