Annotation of kernel/machdep/i386/intr.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*
                     26:  * Copyright (c) 1992,1993 NeXT Computer, Inc.
                     27:  *
                     28:  * Interrupt handling routines.
                     29:  *
                     30:  * HISTORY
                     31:  *
                     32:  * 5 July 1993 ? at NeXT
                     33:  *     Removed software interrupt support.
                     34:  *     Changed lower_ipl() to never raise masked_ipl.
                     35:  * 20 May 1993  Curtis Galloway at NeXT
                     36:  *     Added checking for phantom interrupts.
                     37:  * 26 August 1992 ? at NeXT
                     38:  *     Major rev for driverkit support.
                     39:  * 22 August 1992 ? at NeXT
                     40:  *     Added software interrupts.  Made all data structures static.
                     41:  * 20 Aug 1992 Joe Pasqua
                     42:  *     Added intr_enable_irq/disable_irq routines based on the enableMask.
                     43:  * 24 June 1992 ? at NeXT
                     44:  *     Rewritten to implement 'soft spls'.
                     45:  * 1 June 1992 ? at NeXT
                     46:  *     Created.
                     47:  */
                     48:  
                     49: #import <mach/mach_types.h>
                     50: 
                     51: #import <machdep/i386/intr_exported.h>
                     52: #import <machdep/i386/intr_internal.h>
                     53: #import <machdep/i386/intr_inline.h>
                     54: #import <machdep/i386/cpu_inline.h>
                     55: 
                     56: static intr_dispatch_t dispatch_table[INTR_NIRQ];
                     57: static intr_irq_mask_t ipl_mask[INTR_NIPL];
                     58: static intr_dispatch_t *defer_table[INTR_NIPL];
                     59: 
                     60: static int             current_ipl, masked_ipl;
                     61: static intr_irq_mask_t current_irq_mask, disabled_irq_mask;
                     62: static intr_irq_mask_t current_elcr;
                     63: 
                     64: /*
                     65:  * Send an EOI (end of interrupt) to both PICs.
                     66:  */
                     67: static inline
                     68: void
                     69: send_eoi(
                     70:     void
                     71: )
                     72: {
                     73:     send_eoi_command((intr_ocw2_t) {
                     74:                        0,              /* no level     */
                     75:                        0,              /* must be      */
                     76:                        TRUE,           /* EOI          */
                     77:                        FALSE,          /* non-specific */
                     78:                        FALSE           /* no rotation  */
                     79:                    });
                     80: }
                     81: 
                     82: static inline
                     83: void
                     84: set_elcr(
                     85:     intr_irq_mask_t            mask
                     86: )
                     87: {
                     88:     union {
                     89:        intr_irq_mask_t         full;
                     90:        struct {
                     91:            unsigned short
                     92:                                half    :8,
                     93:                                        :8;
                     94:        } master;
                     95:        struct {
                     96:            unsigned short
                     97:                                        :8,
                     98:                                half    :8;
                     99:        } slave;
                    100:     } new_mask;
                    101: 
                    102:     new_mask.full.mask = mask.mask;
                    103:     
                    104:     if (new_mask.full.mask != current_elcr.mask) {
                    105:        current_elcr = new_mask.full;
                    106: 
                    107:        set_master_elcr((intr_elcr_t) {
                    108:                                            new_mask.master.half });
                    109:     
                    110:        set_slave_elcr((intr_elcr_t) {
                    111:                                            new_mask.slave.half });
                    112:     }
                    113: }
                    114: 
                    115: /*
                    116:  * Set the interrupt masks of both PICs
                    117:  * according to the irq mask.
                    118:  */
                    119: static inline
                    120: void
                    121: set_irq_mask(
                    122:     intr_irq_mask_t            mask
                    123: )
                    124: {
                    125:     union {
                    126:        intr_irq_mask_t         full;
                    127:        struct {
                    128:            unsigned short
                    129:                                half    :8,
                    130:                                        :8;
                    131:        } master;
                    132:        struct {
                    133:            unsigned short
                    134:                                        :8,
                    135:                                half    :8;
                    136:        } slave;
                    137:     } new_mask;
                    138:     
                    139:     new_mask.full.mask = mask.mask | disabled_irq_mask.mask;
                    140: 
                    141:     if (new_mask.full.mask != current_irq_mask.mask) {
                    142:        current_irq_mask = new_mask.full;
                    143:     
                    144:        set_master_mask((intr_ocw1_t) {
                    145:                                            new_mask.master.half });
                    146:        
                    147:        set_slave_mask((intr_ocw1_t) {
                    148:                                            new_mask.slave.half });
                    149:     }
                    150: }
                    151: 
                    152: /*
                    153:  * Set the irq mask according to
                    154:  * the ipl.
                    155:  */
                    156: static inline
                    157: int
                    158: set_masked_ipl(
                    159:     int                ipl
                    160: )
                    161: {
                    162:     int                old_ipl = masked_ipl;
                    163: 
                    164:     if (ipl != masked_ipl) {
                    165:        set_irq_mask(ipl_mask[ipl]);
                    166:        masked_ipl = ipl;
                    167:     }
                    168:     
                    169:     return (old_ipl);
                    170: }
                    171: 
                    172: /*
                    173:  * Set the 'soft' ipl.
                    174:  */
                    175: static inline
                    176: int
                    177: set_ipl(
                    178:     int                ipl
                    179: )
                    180: {
                    181:     int                old_ipl = current_ipl;
                    182:        
                    183:     current_ipl = ipl;
                    184:     
                    185:     return (old_ipl);
                    186: }
                    187: 
                    188: /*
                    189:  * Clear the interrupt flag, and
                    190:  * return the original state of
                    191:  * the flag.
                    192:  */
                    193: boolean_t
                    194: intr_disbl(
                    195:     void
                    196: )
                    197: {
                    198:     unsigned int       efl;
                    199: 
                    200:     efl = eflags();
                    201:            
                    202:     cli();
                    203:            
                    204:     return ((efl & EFL_IF) != 0);
                    205: }
                    206: 
                    207: /*
                    208:  * Set or clear the interrupt
                    209:  * flag, and return the original
                    210:  * state of the flag.
                    211:  */
                    212: boolean_t
                    213: intr_enbl(
                    214:     boolean_t  enable
                    215: )
                    216: {
                    217:     unsigned int       efl;
                    218: 
                    219:     efl = eflags();
                    220:            
                    221:     if (enable) sti(); else cli();
                    222:        
                    223:     return ((efl & EFL_IF) != 0);
                    224: }
                    225: 
                    226: static inline
                    227: void
                    228: lower_masked_ipl(
                    229:     int                        ipl
                    230: )
                    231: {
                    232:     if (ipl < masked_ipl)
                    233:        (void) set_masked_ipl(ipl);
                    234: }
                    235: 
                    236: static
                    237: void
                    238: lower_ipl(
                    239:     int                        ipl,
                    240:     int                        old_ipl
                    241: )
                    242: {
                    243:     intr_dispatch_t    **d, *i;
                    244:     
                    245:     for (d = &defer_table[old_ipl]; d > &defer_table[ipl]; d--)
                    246:        if (i = *d) {
                    247:            *d = 0;
                    248: 
                    249:            (void) set_ipl(i->ipl);
                    250:            
                    251:            sti();
                    252:                (*i->routine)(i->which, 0, ipl); 
                    253:            cli();
                    254:        }
                    255:            
                    256:     (void) set_ipl(ipl);
                    257:     
                    258:     lower_masked_ipl(ipl);
                    259: }
                    260: 
                    261: /*
                    262:  * External 'well known' routines.
                    263:  */
                    264: 
                    265: inline
                    266: int
                    267: splx(
                    268:     int                ipl
                    269: )
                    270: {
                    271:     int                old_ipl;
                    272: 
                    273:     cli();
                    274: 
                    275:     old_ipl = set_ipl(ipl);
                    276:     if (ipl < old_ipl)
                    277:        lower_ipl(ipl, old_ipl);
                    278: 
                    279:     sti();
                    280:     
                    281:     return (old_ipl);
                    282: }
                    283: 
                    284: #define        DEFINE_SPL(name, ipl)   \
                    285: int spl##name(                 \
                    286:     void                       \
                    287: )                              \
                    288: {                              \
                    289:     return (splx(ipl));                \
                    290: }
                    291: 
                    292: #define DEFINE_SPLNOP(name)    \
                    293: int spl##name(                 \
                    294:     void                       \
                    295: )                              \
                    296: {                              \
                    297:     return (current_ipl);      \
                    298: }
                    299: 
                    300: DEFINE_SPL(0,          INTR_IPL0)
                    301: 
                    302: DEFINE_SPL(1,          INTR_IPL1)
                    303: DEFINE_SPLNOP(tty)
                    304: 
                    305: DEFINE_SPL(2,          INTR_IPL2)
                    306: 
                    307: DEFINE_SPL(3,          INTR_IPL3)
                    308: DEFINE_SPLNOP(net)
                    309: DEFINE_SPLNOP(vm)
                    310: DEFINE_SPLNOP(imp)
                    311: DEFINE_SPLNOP(bio)
                    312: DEFINE_SPL(device,     INTR_IPL3)
                    313: 
                    314: DEFINE_SPL(4,          INTR_IPL4)
                    315: 
                    316: DEFINE_SPL(5,          INTR_IPL5)
                    317: 
                    318: DEFINE_SPL(6,          INTR_IPL6)
                    319: DEFINE_SPL(dma,                INTR_IPL6)
                    320: DEFINE_SPL(usclock,    INTR_IPL6)
                    321: DEFINE_SPL(sched,      INTR_IPL6)
                    322: DEFINE_SPL(clock,      INTR_IPL6)
                    323: 
                    324: DEFINE_SPL(7,          INTR_IPL7)
                    325: DEFINE_SPL(high,       INTR_IPL7)
                    326: 
                    327: int
                    328: spln(
                    329:     int                ipl
                    330: )
                    331: {
                    332:     return (splx(ipl));
                    333: }
                    334: 
                    335: int
                    336: ipltospl(
                    337:     int                ipl
                    338: )
                    339: {
                    340:     return (ipl);
                    341: }
                    342: 
                    343: /*
                    344:  * Return the current ipl.
                    345:  */
                    346: int
                    347: curipl(
                    348:     void
                    349: )
                    350: {
                    351:     return (current_ipl);
                    352: }
                    353: 
                    354: /*
                    355:  * Initialization templates.
                    356:  */
                    357: 
                    358: #define MASTER_ICW1    ((intr_icw1_t) {                                \
                    359:                            TRUE,               /* IC4 needed   */      \
                    360:                            FALSE,              /* cascaded     */      \
                    361:                            0,                  /* not used     */      \
                    362:                            INTR_ICW1_EDGE_TRIG,                        \
                    363:                            1                   /* must be      */      \
                    364:                        })
                    365: #define MASTER_ICW2    ((intr_icw2_t) {                                \
                    366:                            INTR_VECT_OFF       /* index in IDT */      \
                    367:                        })
                    368: #define MASTER_ICW3    ((intr_icw3m_t) {                               \
                    369:                            INTR_MASK_SLAVE     /* slave inputs */      \
                    370:                        })
                    371: #define MASTER_ICW4    ((intr_icw4_t) {                                \
                    372:                            INTR_ICW4_8086_MODE,                        \
                    373:                            FALSE,              /* no auto EOI */       \
                    374:                            INTR_ICW4_NONBUF,                           \
                    375:                            FALSE               /* no SFN mode */       \
                    376:                        })
                    377: 
                    378: #define SLAVE_ICW1     ((intr_icw1_t) {                                \
                    379:                            TRUE,               /* IC4 needed   */      \
                    380:                            FALSE,              /* cascaded     */      \
                    381:                            0,                  /* not used     */      \
                    382:                            INTR_ICW1_EDGE_TRIG,                        \
                    383:                            1                   /* must be      */      \
                    384:                        })
                    385: #define SLAVE_ICW2     ((intr_icw2_t) {                                \
                    386:                            INTR_VECT_OFF + 8   /* index in IDT */      \
                    387:                        })
                    388: #define SLAVE_ICW3     ((intr_icw3s_t) {                               \
                    389:                            INTR_SLAVE_IRQ      /* slave id     */      \
                    390:                        })
                    391: #define SLAVE_ICW4     ((intr_icw4_t) {                                \
                    392:                            INTR_ICW4_8086_MODE,                        \
                    393:                            FALSE,              /* no auto EOI */       \
                    394:                            INTR_ICW4_NONBUF,                           \
                    395:                            FALSE               /* no SFN mode */       \
                    396:                        })
                    397: 
                    398: /*
                    399:  * Called early during system
                    400:  * initialization.  Sets up the
                    401:  * PICs, sets the ipl to IPLHI,
                    402:  * and masks all irqs.
                    403:  */
                    404: void
                    405: intr_initialize(
                    406:     void
                    407: )
                    408: {
                    409:     intr_irq_mask_t    *m;
                    410:     int                        i, mask;
                    411: 
                    412:     cli();
                    413: 
                    414:     initialize_master( MASTER_ICW1,
                    415:                        MASTER_ICW2,
                    416:                        MASTER_ICW3,
                    417:                        MASTER_ICW4);
                    418: 
                    419:     initialize_slave(  SLAVE_ICW1,
                    420:                        SLAVE_ICW2,
                    421:                        SLAVE_ICW3,
                    422:                        SLAVE_ICW4);
                    423: 
                    424:     mask = INTR_MASK_ALL;
                    425:     for (i = 0, m = ipl_mask; i++ < INTR_NIPL; m++)
                    426:        m->mask = mask;
                    427:        
                    428:     disabled_irq_mask.mask = INTR_MASK_NONE;
                    429: 
                    430:     set_masked_ipl(INTR_IPLHI);
                    431: 
                    432:     set_ipl(INTR_IPLHI);
                    433:     
                    434:     sti();
                    435: }
                    436: 
                    437: /*
                    438:  * Register an ISR for an irq at
                    439:  * the ipl.  Returns TRUE on success,
                    440:  * FALSE on failure.  Failure includes
                    441:  * trying to overwrite an existing ISR.
                    442:  */
                    443: boolean_t
                    444: intr_register_irq(
                    445:     int                        irq,
                    446:     intr_handler_t     routine,
                    447:     unsigned int       which,
                    448:     int                        ipl
                    449: )
                    450: {
                    451:     intr_irq_mask_t    *m;
                    452:     int                        i, mask;
                    453:     boolean_t          e;
                    454: 
                    455:     if (irq < 0 || irq >= INTR_NIRQ || irq == INTR_SLAVE_IRQ)
                    456:        return (FALSE);
                    457: 
                    458:     if (ipl < 0 || ipl >= INTR_NIPL)
                    459:        return (FALSE);
                    460: 
                    461:     if (dispatch_table[irq].routine)
                    462:        return (FALSE);
                    463: 
                    464:     e = intr_disbl();
                    465: 
                    466:     dispatch_table[irq].which  = which;
                    467:     dispatch_table[irq].routine        = routine;
                    468:     dispatch_table[irq].ipl    = ipl;
                    469: 
                    470:     mask = INTR_MASK_IRQ(irq);
                    471:     for (i = 0, m = ipl_mask; i < INTR_NIPL; i++, m++) {
                    472:        if (i < ipl)
                    473:            m->mask &= ~mask;
                    474:        else
                    475:            m->mask |= mask;
                    476:     }
                    477:     
                    478:     disabled_irq_mask.mask |= mask;
                    479: 
                    480:     set_irq_mask(ipl_mask[masked_ipl]);
                    481:     
                    482:     (void) intr_enbl(e);
                    483:     
                    484:     return (TRUE);
                    485: }
                    486: 
                    487: boolean_t
                    488: intr_unregister_irq(
                    489:     int                        irq
                    490: )
                    491: {
                    492:     intr_irq_mask_t    *m;
                    493:     int                        i, mask;
                    494:     boolean_t          e;
                    495: 
                    496:     if (irq < 0 || irq >= INTR_NIRQ || irq == INTR_SLAVE_IRQ)
                    497:        return (FALSE);
                    498: 
                    499:     if (!dispatch_table[irq].routine)
                    500:        return (FALSE);
                    501: 
                    502:     e = intr_disbl();
                    503: 
                    504:     dispatch_table[irq].which  = 0;
                    505:     dispatch_table[irq].routine        = 0;
                    506:     dispatch_table[irq].ipl    = 0;
                    507: 
                    508:     mask = INTR_MASK_IRQ(irq);
                    509:     for (i = 0, m = ipl_mask; i < INTR_NIPL; i++, m++) {
                    510:        m->mask |= mask;
                    511:     }
                    512: 
                    513:     set_irq_mask(ipl_mask[masked_ipl]);
                    514:     
                    515:     (void) intr_enbl(e);
                    516:     
                    517:     (void) intr_change_mode(irq, FALSE);
                    518:     
                    519:     return (TRUE);
                    520: }
                    521: 
                    522: boolean_t
                    523: intr_enable_irq(
                    524:     int                irq
                    525: )
                    526: {
                    527:     boolean_t  e;
                    528: 
                    529:     if (irq < 0 || irq >= INTR_NIRQ || irq == INTR_SLAVE_IRQ)
                    530:        return (FALSE);
                    531: 
                    532:     e = intr_disbl();
                    533: 
                    534:     disabled_irq_mask.mask &= ~INTR_MASK_IRQ(irq);
                    535:     set_irq_mask(ipl_mask[masked_ipl]);
                    536: 
                    537:     (void) intr_enbl(e);
                    538:     
                    539:     return (TRUE);
                    540: }
                    541: 
                    542: boolean_t
                    543: intr_disable_irq(
                    544:     int                irq
                    545: )
                    546: {
                    547:     boolean_t  e;
                    548: 
                    549:     if (irq < 0 || irq >= INTR_NIRQ || irq == INTR_SLAVE_IRQ)
                    550:        return (FALSE);
                    551: 
                    552:     e = intr_disbl();
                    553: 
                    554:     disabled_irq_mask.mask |= INTR_MASK_IRQ(irq);
                    555:     set_irq_mask(ipl_mask[masked_ipl]);
                    556:  
                    557:     (void) intr_enbl(e);
                    558:     
                    559:     return (TRUE);
                    560: }
                    561: 
                    562: boolean_t
                    563: intr_change_ipl(
                    564:     int                irq,
                    565:     int                ipl
                    566: )
                    567: {
                    568:     intr_irq_mask_t    *m;
                    569:     int                        i, mask;
                    570:     boolean_t          e;
                    571: 
                    572:     if (irq < 0 || irq >= INTR_NIRQ || irq == INTR_SLAVE_IRQ)
                    573:        return (FALSE);
                    574: 
                    575:     if (ipl < 0 || ipl >= INTR_NIPL)
                    576:        return (FALSE);
                    577: 
                    578:     if (dispatch_table[irq].routine == 0)
                    579:        return (FALSE);
                    580: 
                    581:     e = intr_disbl();
                    582: 
                    583:     dispatch_table[irq].ipl    = ipl;
                    584: 
                    585:     mask = INTR_MASK_IRQ(irq);
                    586:     for (i = 0, m = ipl_mask; i < INTR_NIPL; i++, m++) {
                    587:        if (i < ipl)
                    588:            m->mask &= ~mask;
                    589:        else
                    590:            m->mask |= mask;
                    591:     }
                    592: 
                    593:     set_irq_mask(ipl_mask[masked_ipl]);
                    594:     
                    595:     (void) intr_enbl(e);
                    596:     
                    597:     return (TRUE);
                    598: }
                    599: 
                    600: boolean_t
                    601: intr_change_mode(
                    602:     int                irq,
                    603:     boolean_t  level_trig
                    604: )
                    605: {
                    606:     intr_irq_mask_t    reg;
                    607:     boolean_t          e;
                    608: #define _T_    TRUE
                    609: #define _F_    FALSE
                    610:     static boolean_t   valid_irq[INTR_NIRQ] = {
                    611:                            _F_, _F_, _F_, _T_, _T_, _T_, _T_, _T_,
                    612:                            _F_, _T_, _T_, _T_, _T_, _F_, _T_, _T_
                    613:                        };
                    614: #undef _T_
                    615: #undef _F_
                    616:     
                    617:     if (!eisa_present())
                    618:        return (FALSE);
                    619: 
                    620:     if (irq < 0 || irq >= INTR_NIRQ || !valid_irq[irq])
                    621:        return (FALSE);
                    622:        
                    623:     e = intr_disbl();
                    624:     
                    625:     reg = current_elcr;
                    626:     
                    627:     if (level_trig)
                    628:        reg.mask |= INTR_MASK_IRQ(irq);
                    629:     else
                    630:        reg.mask &= ~INTR_MASK_IRQ(irq);
                    631:        
                    632:     set_elcr(reg);
                    633:     
                    634:     (void) intr_enbl(e);
                    635:     
                    636:     return (TRUE);
                    637: }
                    638: 
                    639: struct {
                    640:     unsigned int       intr;
                    641:     unsigned int       defer;
                    642:     unsigned int       phantom;
                    643: } intr_cnt;
                    644: 
                    645: /*
                    646:  * The system interrupt handler.
                    647:  */
                    648: void
                    649: intr_handler(
                    650:     void                       *_state
                    651: )
                    652: {
                    653:     thread_saved_state_t       *state = (thread_saved_state_t *)_state;
                    654:     int                                irq = state->trapno - INTR_VECT_OFF;
                    655:     intr_dispatch_t            *i = &dispatch_table[irq];
                    656:     int                                old_masked_ipl;
                    657: 
                    658:     intr_cnt.intr++;
                    659: 
                    660:     /*
                    661:      * Check for phantom interrupt.
                    662:      */
                    663:     if (((irq == INTR_MASTER_PHANTOM_IRQ && 
                    664:                (get_master_isr() & INTR_PHANTOM_IRQ_MASK) == 0)) ||
                    665:        ((irq == INTR_SLAVE_PHANTOM_IRQ &&
                    666:                (get_slave_isr() & INTR_PHANTOM_IRQ_MASK) == 0)) ) {
                    667:         intr_cnt.phantom++;
                    668:         return;
                    669:     }
                    670: 
                    671:     /*
                    672:      * Mask this interrupt before
                    673:      * acknowledging so that level
                    674:      * triggered inputs work.
                    675:      */
                    676:     old_masked_ipl = set_masked_ipl(i->ipl);
                    677: 
                    678:     /*
                    679:      * Acknowledge by sending
                    680:      * an EOI command to the PICs.
                    681:      */
                    682:     send_eoi();  
                    683: 
                    684:     /*
                    685:      * Leave this interrupt
                    686:      * disabled if it isn't
                    687:      * currently registered.
                    688:      * N.B.: This should never
                    689:      * happen.
                    690:      */
                    691:     if (i->routine == 0)       
                    692:        printf("intr: dropped IRQ %d\n", irq);
                    693:     else
                    694:     /*
                    695:      * If this interrupt isn't
                    696:      * disallowed via spl(),
                    697:      * handle it now.
                    698:      */
                    699:     if (current_ipl < i->ipl) {
                    700:        int     old_ipl         = set_ipl(i->ipl);
                    701:                
                    702:        sti(); (*i->routine)(i->which, state, old_ipl); cli();
                    703:        
                    704:        (void) set_ipl(old_ipl);
                    705:        (void) set_masked_ipl(old_masked_ipl);
                    706:     }
                    707:     /*
                    708:      * Otherwise, leave it masked
                    709:      * and defer it until later.
                    710:      */
                    711:     else {
                    712:        intr_cnt.defer++;
                    713:                
                    714:        defer_table[i->ipl] = i;
                    715:     }
                    716: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.