The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/icu_vector.s

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *      from: vector.s, 386BSD 0.1 unknown origin
    3  * $FreeBSD: releng/5.1/sys/i386/isa/icu_vector.s 93945 2002-04-06 08:25:05Z nyan $
    4  */
    5 
    6 #define IRQ_BIT(irq_num)        (1 << ((irq_num) % 8))
    7 #define IRQ_LBIT(irq_num)       (1 << (irq_num))
    8 #define IRQ_BYTE(irq_num)       ((irq_num) >> 3)
    9 
   10 #ifdef AUTO_EOI_1
   11 
   12 #define ENABLE_ICU1             /* use auto-EOI to reduce i/o */
   13 #define OUTB_ICU1
   14 
   15 #else
   16 
   17 #define ENABLE_ICU1                                                     \
   18         movb    $ICU_EOI,%al ;  /* as soon as possible send EOI ... */  \
   19         OUTB_ICU1               /* ... to clear in service bit */
   20 
   21 #define OUTB_ICU1                                                       \
   22         outb    %al,$IO_ICU1
   23 
   24 #endif
   25 
   26 #ifdef AUTO_EOI_2
   27 /*
   28  * The data sheet says no auto-EOI on slave, but it sometimes works.
   29  */
   30 #define ENABLE_ICU1_AND_2       ENABLE_ICU1
   31 
   32 #else
   33 
   34 #define ENABLE_ICU1_AND_2                                               \
   35         movb    $ICU_EOI,%al ;  /* as above */                          \
   36         outb    %al,$IO_ICU2 ;  /* but do second icu first ... */       \
   37         OUTB_ICU1               /* ... then first icu (if !AUTO_EOI_1) */
   38 
   39 #endif
   40 
   41 #define PUSH_FRAME                                                      \
   42         pushl   $0 ;            /* dummy error code */                  \
   43         pushl   $0 ;            /* dummy trap type */                   \
   44         pushal ;                /* 8 ints */                            \
   45         pushl   %ds ;           /* save data and extra segments ... */  \
   46         pushl   %es ;                                                   \
   47         pushl   %fs
   48 
   49 #define PUSH_DUMMY                                                      \
   50         pushfl ;                /* eflags */                            \
   51         pushl   %cs ;           /* cs */                                \
   52         pushl   12(%esp) ;      /* original caller eip */               \
   53         pushl   $0 ;            /* dummy error code */                  \
   54         pushl   $0 ;            /* dummy trap type */                   \
   55         subl    $11*4,%esp
   56 
   57 #define POP_FRAME                                                       \
   58         popl    %fs ;                                                   \
   59         popl    %es ;                                                   \
   60         popl    %ds ;                                                   \
   61         popal ;                                                         \
   62         addl    $4+4,%esp
   63 
   64 #define POP_DUMMY                                                       \
   65         addl    $16*4,%esp
   66 
   67 #define MASK_IRQ(icu, irq_num)                                          \
   68         movb    imen + IRQ_BYTE(irq_num),%al ;                          \
   69         orb     $IRQ_BIT(irq_num),%al ;                                 \
   70         movb    %al,imen + IRQ_BYTE(irq_num) ;                          \
   71         outb    %al,$icu+ICU_IMR_OFFSET
   72 
   73 #define UNMASK_IRQ(icu, irq_num)                                        \
   74         movb    imen + IRQ_BYTE(irq_num),%al ;                          \
   75         andb    $~IRQ_BIT(irq_num),%al ;                                \
   76         movb    %al,imen + IRQ_BYTE(irq_num) ;                          \
   77         outb    %al,$icu+ICU_IMR_OFFSET
   78 /*
   79  * Macros for interrupt interrupt entry, call to handler, and exit.
   80  */
   81 
   82 #define FAST_INTR(irq_num, vec_name, icu, enable_icus)                  \
   83         .text ;                                                         \
   84         SUPERALIGN_TEXT ;                                               \
   85 IDTVEC(vec_name) ;                                                      \
   86         PUSH_FRAME ;                                                    \
   87         mov     $KDSEL,%ax ;                                            \
   88         mov     %ax,%ds ;                                               \
   89         mov     %ax,%es ;                                               \
   90         mov     $KPSEL,%ax ;                                            \
   91         mov     %ax,%fs ;                                               \
   92         FAKE_MCOUNT((12+ACTUALLY_PUSHED)*4(%esp)) ;                     \
   93         movl    PCPU(CURTHREAD),%ebx ;                                  \
   94         cmpl    $0,TD_CRITNEST(%ebx) ;                                  \
   95         je      1f ;                                                    \
   96 ;                                                                       \
   97         movl    $1,PCPU(INT_PENDING) ;                                  \
   98         orl     $IRQ_LBIT(irq_num),PCPU(FPENDING) ;                     \
   99         MASK_IRQ(icu, irq_num) ;                                        \
  100         enable_icus ;                                                   \
  101         jmp     10f ;                                                   \
  102 1: ;                                                                    \
  103         incl    TD_CRITNEST(%ebx) ;                                     \
  104         incl    TD_INTR_NESTING_LEVEL(%ebx) ;                           \
  105         pushl   intr_unit + (irq_num) * 4 ;                             \
  106         call    *intr_handler + (irq_num) * 4 ;                         \
  107         addl    $4,%esp ;                                               \
  108         enable_icus ;                                                   \
  109         incl    cnt+V_INTR ;    /* book-keeping can wait */             \
  110         movl    intr_countp + (irq_num) * 4,%eax ;                      \
  111         incl    (%eax) ;                                                \
  112         decl    TD_CRITNEST(%ebx) ;                                     \
  113         cmpl    $0,PCPU(INT_PENDING) ;                                  \
  114         je      2f ;                                                    \
  115 ;                                                                       \
  116         call    i386_unpend ;                                           \
  117 2: ;                                                                    \
  118         decl    TD_INTR_NESTING_LEVEL(%ebx) ;                           \
  119 10: ;                                                                   \
  120         MEXITCOUNT ;                                                    \
  121         jmp     doreti
  122 
  123 /*
  124  * Restart a fast interrupt that was held up by a critical section.
  125  * This routine is called from unpend().  unpend() ensures we are
  126  * in a critical section and deals with the interrupt nesting level
  127  * for us.  If we previously masked the irq, we have to unmask it.
  128  *
  129  * We have a choice.  We can regenerate the irq using the 'int'
  130  * instruction or we can create a dummy frame and call the interrupt
  131  * handler directly.  I've chosen to use the dummy-frame method.
  132  */
  133 #define FAST_UNPEND(irq_num, vec_name, icu)                             \
  134         .text ;                                                         \
  135         SUPERALIGN_TEXT ;                                               \
  136 IDTVEC(vec_name) ;                                                      \
  137 ;                                                                       \
  138         pushl %ebp ;                                                    \
  139         movl %esp, %ebp ;                                               \
  140         PUSH_DUMMY ;                                                    \
  141         pushl   intr_unit + (irq_num) * 4 ;                             \
  142         call    *intr_handler + (irq_num) * 4 ; /* do the work ASAP */  \
  143         addl    $4, %esp ;                                              \
  144         incl    cnt+V_INTR ;    /* book-keeping can wait */             \
  145         movl    intr_countp + (irq_num) * 4,%eax ;                      \
  146         incl    (%eax) ;                                                \
  147         UNMASK_IRQ(icu, irq_num) ;                                      \
  148         POP_DUMMY ;                                                     \
  149         popl %ebp ;                                                     \
  150         ret
  151 
  152 /* 
  153  * Slow, threaded interrupts.
  154  *
  155  * XXX Most of the parameters here are obsolete.  Fix this when we're
  156  * done.
  157  * XXX we really shouldn't return via doreti if we just schedule the
  158  * interrupt handler and don't run anything.  We could just do an
  159  * iret.  FIXME.
  160  */
  161 #define INTR(irq_num, vec_name, icu, enable_icus, maybe_extra_ipending) \
  162         .text ;                                                         \
  163         SUPERALIGN_TEXT ;                                               \
  164 IDTVEC(vec_name) ;                                                      \
  165         PUSH_FRAME ;                                                    \
  166         mov     $KDSEL,%ax ;    /* load kernel ds, es and fs */         \
  167         mov     %ax,%ds ;                                               \
  168         mov     %ax,%es ;                                               \
  169         mov     $KPSEL,%ax ;                                            \
  170         mov     %ax,%fs ;                                               \
  171 ;                                                                       \
  172         maybe_extra_ipending ;                                          \
  173         MASK_IRQ(icu, irq_num) ;                                        \
  174         enable_icus ;                                                   \
  175 ;                                                                       \
  176         movl    PCPU(CURTHREAD),%ebx ;                                  \
  177         cmpl    $0,TD_CRITNEST(%ebx) ;                                  \
  178         je      1f ;                                                    \
  179         movl    $1,PCPU(INT_PENDING);                                   \
  180         orl     $IRQ_LBIT(irq_num),PCPU(IPENDING) ;                     \
  181         jmp     10f ;                                                   \
  182 1: ;                                                                    \
  183         incl    TD_INTR_NESTING_LEVEL(%ebx) ;                           \
  184 ;                                                                       \
  185         FAKE_MCOUNT(13*4(%esp)) ;       /* XXX late to avoid double count */ \
  186         cmpl    $0,PCPU(INT_PENDING) ;                                  \
  187         je      9f ;                                                    \
  188         call    i386_unpend ;                                           \
  189 9: ;                                                                    \
  190         pushl   $irq_num;       /* pass the IRQ */                      \
  191         call    sched_ithd ;                                            \
  192         addl    $4, %esp ;      /* discard the parameter */             \
  193 ;                                                                       \
  194         decl    TD_INTR_NESTING_LEVEL(%ebx) ;                           \
  195 10: ;                                                                   \
  196         MEXITCOUNT ;                                                    \
  197         jmp     doreti
  198 
  199 MCOUNT_LABEL(bintr)
  200         FAST_INTR(0,fastintr0, IO_ICU1, ENABLE_ICU1)
  201         FAST_INTR(1,fastintr1, IO_ICU1, ENABLE_ICU1)
  202         FAST_INTR(2,fastintr2, IO_ICU1, ENABLE_ICU1)
  203         FAST_INTR(3,fastintr3, IO_ICU1, ENABLE_ICU1)
  204         FAST_INTR(4,fastintr4, IO_ICU1, ENABLE_ICU1)
  205         FAST_INTR(5,fastintr5, IO_ICU1, ENABLE_ICU1)
  206         FAST_INTR(6,fastintr6, IO_ICU1, ENABLE_ICU1)
  207         FAST_INTR(7,fastintr7, IO_ICU1, ENABLE_ICU1)
  208         FAST_INTR(8,fastintr8, IO_ICU2, ENABLE_ICU1_AND_2)
  209         FAST_INTR(9,fastintr9, IO_ICU2, ENABLE_ICU1_AND_2)
  210         FAST_INTR(10,fastintr10, IO_ICU2, ENABLE_ICU1_AND_2)
  211         FAST_INTR(11,fastintr11, IO_ICU2, ENABLE_ICU1_AND_2)
  212         FAST_INTR(12,fastintr12, IO_ICU2, ENABLE_ICU1_AND_2)
  213         FAST_INTR(13,fastintr13, IO_ICU2, ENABLE_ICU1_AND_2)
  214         FAST_INTR(14,fastintr14, IO_ICU2, ENABLE_ICU1_AND_2)
  215         FAST_INTR(15,fastintr15, IO_ICU2, ENABLE_ICU1_AND_2)
  216 
  217 #define CLKINTR_PENDING movl $1,CNAME(clkintr_pending)
  218 /* Threaded interrupts */
  219         INTR(0,intr0, IO_ICU1, ENABLE_ICU1, CLKINTR_PENDING)
  220         INTR(1,intr1, IO_ICU1, ENABLE_ICU1,)
  221         INTR(2,intr2, IO_ICU1, ENABLE_ICU1,)
  222         INTR(3,intr3, IO_ICU1, ENABLE_ICU1,)
  223         INTR(4,intr4, IO_ICU1, ENABLE_ICU1,)
  224         INTR(5,intr5, IO_ICU1, ENABLE_ICU1,)
  225         INTR(6,intr6, IO_ICU1, ENABLE_ICU1,)
  226         INTR(7,intr7, IO_ICU1, ENABLE_ICU1,)
  227         INTR(8,intr8, IO_ICU2, ENABLE_ICU1_AND_2,)
  228         INTR(9,intr9, IO_ICU2, ENABLE_ICU1_AND_2,)
  229         INTR(10,intr10, IO_ICU2, ENABLE_ICU1_AND_2,)
  230         INTR(11,intr11, IO_ICU2, ENABLE_ICU1_AND_2,)
  231         INTR(12,intr12, IO_ICU2, ENABLE_ICU1_AND_2,)
  232         INTR(13,intr13, IO_ICU2, ENABLE_ICU1_AND_2,)
  233         INTR(14,intr14, IO_ICU2, ENABLE_ICU1_AND_2,)
  234         INTR(15,intr15, IO_ICU2, ENABLE_ICU1_AND_2,)
  235 
  236         FAST_UNPEND(0,fastunpend0, IO_ICU1)
  237         FAST_UNPEND(1,fastunpend1, IO_ICU1)
  238         FAST_UNPEND(2,fastunpend2, IO_ICU1)
  239         FAST_UNPEND(3,fastunpend3, IO_ICU1)
  240         FAST_UNPEND(4,fastunpend4, IO_ICU1)
  241         FAST_UNPEND(5,fastunpend5, IO_ICU1)
  242         FAST_UNPEND(6,fastunpend6, IO_ICU1)
  243         FAST_UNPEND(7,fastunpend7, IO_ICU1)
  244         FAST_UNPEND(8,fastunpend8, IO_ICU2)
  245         FAST_UNPEND(9,fastunpend9, IO_ICU2)
  246         FAST_UNPEND(10,fastunpend10, IO_ICU2)
  247         FAST_UNPEND(11,fastunpend11, IO_ICU2)
  248         FAST_UNPEND(12,fastunpend12, IO_ICU2)
  249         FAST_UNPEND(13,fastunpend13, IO_ICU2)
  250         FAST_UNPEND(14,fastunpend14, IO_ICU2)
  251         FAST_UNPEND(15,fastunpend15, IO_ICU2)
  252 MCOUNT_LABEL(eintr)
  253 

Cache object: abd67ae3fe905619861402a2f3e96086


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.