Annotation of Net2/arch/vax/if/if_hy.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1988 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * Tektronix Inc.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
                     36:  *     @(#)if_hy.c     7.7 (Berkeley) 12/16/90
                     37:  */
                     38: 
                     39: /*
                     40:  * 4.2 BSD Unix Kernel - Vax Network Interface Support
                     41:  *
                     42:  * $Header: if_hy.c,v 10.1 84/07/22 21:02:56 steveg Exp $
                     43:  * $Locker:  $
                     44:  *
                     45:  * Modifications from Berkeley 4.2 BSD
                     46:  * Copyright (c) 1983, Tektronix Inc.
                     47:  * All Rights Reserved
                     48:  *
                     49:  * $Log:       if_hy.c,v $
                     50:  *     Revision 10.1  84/07/22  21:02:56  steveg
                     51:  *     define PI13 (moved from if_hyreg.h, somehow got dropped in the process)
                     52:  *     rework hywatch to check for power fails first
                     53:  *     
                     54:  *     Revision 10.0  84/06/30  19:54:27  steveg
                     55:  *     Big Build
                     56:  *     
                     57:  *     Revision 3.17  84/06/20  19:20:28  steveg
                     58:  *     increment hy_ntime in hywatch
                     59:  *     print out state name, csr, last command, and hy_flags when watchdog timer
                     60:  *     expires
                     61:  *     
                     62:  *     Revision 3.16  84/06/20  19:09:34  steveg
                     63:  *     turn on continuous logging by default
                     64:  *     
                     65:  *     Revision 3.15  84/05/30  22:19:09  steveg
                     66:  *     changes to reflect new layout ot statistics data
                     67:  *     
                     68:  *     Revision 3.14  84/05/30  19:25:15  steveg
                     69:  *     move driver states to if_hy.h so log printing programs can use them
                     70:  *     
                     71:  *     Revision 3.13  84/05/30  17:13:26  steveg
                     72:  *     make it compile
                     73:  *     
                     74:  *     Revision 3.12  84/05/30  13:46:16  steveg
                     75:  *     rework logging
                     76:  *     
                     77:  *     Revision 3.11  84/05/18  19:35:02  steveg
                     78:  *     clear IFF_RUNNING and IFF_UP on unibus reset to force resource allocation
                     79:  *     by the init routine
                     80:  *     
                     81:  *     Revision 3.10  84/05/04  12:14:44  steveg
                     82:  *     more rework to make it actually work under 4.2
                     83:  *     
                     84:  *     Revision 3.9  84/05/01  23:34:52  steveg
                     85:  *     fix typo so it compiles (unit -> ui->ui_unit)
                     86:  *     
                     87:  *     Revision 3.8  84/05/01  23:18:30  steveg
                     88:  *     changes after talking with rickk
                     89:  *     - check power off more closely
                     90:  *     - support remote loopback through A710 adapters
                     91:  *     - IMPLINK -> HYLINK
                     92:  *     - return EHOSTUNREACH on hyroute failure
                     93:  *     - bump if_collisions on abnormal interrupts that aren't input or output
                     94:  *     
                     95:  *
                     96:  */
                     97: 
                     98: 
                     99: #include "hy.h"
                    100: #if NHY > 0
                    101: 
                    102: /*
                    103:  * Network Systems Copropration Hyperchanel interface
                    104:  */
                    105: #include "../include/pte.h"
                    106: 
                    107: #include "sys/param.h"
                    108: #include "sys/systm.h"
                    109: #include "sys/mbuf.h"
                    110: #include "sys/buf.h"
                    111: #include "sys/protosw.h"
                    112: #include "sys/socket.h"
                    113: #include "sys/vmmac.h"
                    114: #include "sys/errno.h"
                    115: #include "sys/time.h"
                    116: #include "sys/kernel.h"
                    117: #include "sys/ioctl.h"
                    118: 
                    119: #include "net/if.h"
                    120: #include "net/netisr.h"
                    121: #include "net/route.h"
                    122: 
                    123: #ifdef INET
                    124: #include "netinet/in.h"
                    125: #include "netinet/in_systm.h"
                    126: #include "netinet/in_var.h"
                    127: #include "netinet/ip.h"
                    128: #endif
                    129: 
                    130: #include "../include/cpu.h"
                    131: #include "../include/mtpr.h"
                    132: #include "../uba/ubareg.h"
                    133: #include "../uba/ubavar.h"
                    134: 
                    135: /*
                    136:  * configuration specific paramters
                    137:  *     - change as appropriate for particular installaions
                    138:  */
                    139: #define        HYROUTE
                    140: #define        HYELOG
                    141: #define        HYLOG
                    142: #define        HYMTU   1100
                    143: #define PI13
                    144: 
                    145: #ifdef DEBUG
                    146: #define        HYLOG
                    147: #endif
                    148: 
                    149: #include "if_hy.h"
                    150: #include "if_hyreg.h"
                    151: #include "if_uba.h"
                    152: 
                    153: int    hyprobe(), hyattach(), hyinit(), hyioctl();
                    154: int    hyoutput(), hyreset(), hywatch();
                    155: struct uba_device *hyinfo[NHY];
                    156: u_short hystd[] = { 0772410, 0 };
                    157: struct uba_driver hydriver =
                    158:        { hyprobe, 0, hyattach, 0, hystd, "hy", hyinfo };
                    159: 
                    160: /*
                    161:  * Hyperchannel software status per interface.
                    162:  *
                    163:  * Each interface is referenced by a network interface structure,
                    164:  * hy_if, which the routing code uses to locate the interface.
                    165:  * This structure contains the output queue for the interface, its address, ...
                    166:  * We also have, for each interface, a UBA interface structure, which
                    167:  * contains information about the UNIBUS resources held by the interface:
                    168:  * map registers, buffered data paths, etc.  Information is cached in this
                    169:  * structure for use by the if_uba.c routines in running the interface
                    170:  * efficiently.
                    171:  */
                    172: struct hy_softc {
                    173:        struct  ifnet hy_if;            /* network-visible interface */
                    174:        struct  ifuba hy_ifuba;         /* UNIBUS resources */
                    175:        short   hy_flags;               /* flags */
                    176:        short   hy_state;               /* driver state */
                    177:        u_short hy_host;                /* local host number */
                    178:        struct  in_addr hy_addr;        /* internet address */
                    179:        int     hy_olen;                /* packet length on output */
                    180:        int     hy_lastwcr;             /* last command's word count */
                    181:        short   hy_savedstate;          /* saved for reissue after status */
                    182:        short   hy_savedcmd;            /* saved command for reissue */
                    183:        int     hy_savedcount;          /* saved byte count for reissue */
                    184:        int     hy_savedaddr;           /* saved unibus address for reissue */
                    185:        int     hy_ntime;               /* number of timeouts since last cmd */
                    186:        int     hy_retry;               /* retry counter */
                    187:        struct  hy_stat hy_stat;        /* statistics */
                    188:        struct  hy_status hy_status;    /* status */
                    189: } hy_softc[NHY];
                    190: 
                    191: #ifdef HYELOG
                    192: u_long hy_elog[HYE_SIZE];
                    193: #endif
                    194: 
                    195: #ifdef HYLOG
                    196: struct hy_log hy_log;
                    197: #endif
                    198: 
                    199: #ifdef HYROUTE
                    200: struct hy_route hy_route[NHY];
                    201: #endif
                    202: 
                    203: #ifdef DEBUG
                    204: #define printL printf
                    205: #define printD if (hy_debug_flag) printf
                    206: int    hy_debug_flag = 0;
                    207: /*
                    208:  * hy_nodebug bit 0x01 set hy_debug_flag on hycancel
                    209:  * hy_nodebug bit 0x02 set hy_debug_flag on command reissue
                    210:  * hy_nodebug bit 0x04 set hy_debug_flag on abnormal interrupt
                    211:  */
                    212: int    hy_nodebug = 0x0;
                    213: #endif
                    214: 
                    215: #define SCANINTERVAL   10      /* seconds */
                    216: #define MAXINTERVAL    20      /* seconds (max action) */
                    217: 
                    218: /*
                    219:  * Cause a device interrupt.  This code uses a buffer starting at
                    220:  * location zero on the unibus (which is already mapped by the
                    221:  * autoconfigure code in the kernel).
                    222:  */
                    223: hyprobe(reg)
                    224:        caddr_t reg;
                    225: {
                    226:        register int br, cvec;          /* r11, r10 value-result */
                    227:        register struct hydevice *addr = (struct hydevice *) reg;
                    228: 
                    229: #ifdef lint
                    230:        br = 0; cvec = br; br = cvec;
                    231:        hyint(0);
                    232: #endif
                    233:        /*
                    234:         * request adapter status to a buffer starting at unibus location 0
                    235:         */
                    236:        addr->hyd_bar = 0;
                    237:        addr->hyd_wcr = -((sizeof(struct hy_status) + 1) >> 1);
                    238:        addr->hyd_dbuf = HYF_STATUS;
                    239: #ifdef PI13
                    240:        addr->hyd_csr |= S_GO | S_IE | S_IATTN;
                    241: #else
                    242:        addr->hyd_csr |= S_GO | S_IE;
                    243: #endif
                    244:        DELAY(10000);
                    245: #ifdef PI13
                    246:        addr->hyd_csr |= S_CLRINT;      /* clear any stacked interrupts */
                    247: #endif
                    248:        addr->hyd_csr &= ~(S_IE | S_CLRINT);    /* disable further interrupts */
                    249:        return(sizeof(struct hydevice));
                    250: }
                    251: 
                    252: /*
                    253:  * Interface exists: make available by filling in network interface
                    254:  * record.  System will initialize the interface when it is ready
                    255:  * to accept packets.
                    256:  */
                    257: hyattach(ui)
                    258:        struct uba_device *ui;
                    259: {
                    260:        register struct hy_softc *is = &hy_softc[ui->ui_unit];
                    261:        register struct ifnet *ifp = &is->hy_if;
                    262: 
                    263:        ifp->if_unit = ui->ui_unit;
                    264:        ifp->if_name = "hy";
                    265:        ifp->if_mtu = HYMTU;
                    266:        is->hy_state = STARTUP;         /* don't allow state transitions yet */
                    267:        ifp->if_init = hyinit;
                    268:        ifp->if_ioctl = hyioctl;
                    269:        ifp->if_output = hyoutput;
                    270:        ifp->if_reset = hyreset;
                    271:        ifp->if_watchdog = hywatch;
                    272:        ifp->if_timer = SCANINTERVAL;
                    273:        is->hy_ifuba.ifu_flags = UBA_CANTWAIT;
                    274: #ifdef notdef
                    275:        is->hy_ifuba.ifu_flags |= UBA_NEEDBDP;
                    276: #endif
                    277:        if_attach(ifp);
                    278: }
                    279: 
                    280: /*
                    281:  * Reset of interface after UNIBUS reset.
                    282:  * If interface is on specified uba, reset its state.
                    283:  */
                    284: hyreset(unit, uban)
                    285:        int unit, uban;
                    286: {
                    287:        register struct uba_device *ui;
                    288:        register struct hy_softc *is;
                    289: 
                    290:        if (unit >= NHY || (ui = hyinfo[unit]) == 0 || ui->ui_alive == 0 ||
                    291:          ui->ui_ubanum != uban)
                    292:                return;
                    293:        printf(" hy%d", unit);
                    294:        is = &hy_softc[unit];           /* force unibus resource allocation */
                    295:        is->hy_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
                    296:        hyinit(unit);
                    297: }
                    298: 
                    299: /*
                    300:  * Initialization of interface; clear recorded pending
                    301:  * operations, and reinitialize UNIBUS usage.
                    302:  */
                    303: hyinit(unit)
                    304:        int unit;
                    305: {
                    306:        register struct hy_softc *is = &hy_softc[unit];
                    307:        register struct uba_device *ui = hyinfo[unit];
                    308:        register struct mbuf *m;
                    309:        int s;
                    310: 
                    311:        if (is->hy_if.if_addrlist == 0)         /* address still unknown */
                    312:                return;
                    313:        if (is->hy_if.if_flags & IFF_RUNNING)   /* just reset the device */
                    314:                goto justreset;
                    315:        if (if_ubainit(&is->hy_ifuba, ui->ui_ubanum,
                    316:            sizeof (struct hym_hdr), (int)btoc(HYMTU)) == 0) { 
                    317: #ifdef DEBUG
                    318:                if (hy_nodebug & 4)
                    319:                        hy_debug_flag = 1;
                    320: #endif
                    321:                printf("hy%d: can't initialize\n", unit);
                    322:                is->hy_if.if_flags &= ~IFF_UP;
                    323:                return;
                    324:        }
                    325:        is->hy_if.if_flags |= IFF_RUNNING;
                    326: 
                    327: justreset:
                    328:        /*
                    329:         * remove any left over outgoing messages, reset the hardware and
                    330:         * start the state machine
                    331:         */
                    332:        s = splimp();
                    333: #ifdef HYLOG
                    334:        hylog(HYL_RESET, 0, (char *)0);
                    335: #endif
                    336:        is->hy_state = IDLE;
                    337:        is->hy_flags = RQ_STATUS | RQ_STATISTICS | RQ_MARKUP;
                    338:        is->hy_retry = 0;
                    339:        for(;;) {
                    340:                IF_DEQUEUE(&is->hy_if.if_snd, m);
                    341:                if (m != NULL)
                    342:                        m_freem(m);
                    343:                else
                    344:                        break;
                    345:        }
                    346:        hycancel(ui);           /* also bumps the state machine */
                    347:        splx(s);
                    348: }
                    349: 
                    350: /*
                    351:  * Issue a command to the adapter
                    352:  */
                    353: hystart(ui, cmd, count, ubaddr)
                    354:        struct uba_device *ui;
                    355:        int cmd, count, ubaddr;
                    356: {
                    357:        register struct hy_softc *is = &hy_softc[ui->ui_unit];
                    358:        register struct hydevice *addr = (struct hydevice *)ui->ui_addr;
                    359: 
                    360: #ifdef DEBUG
                    361:        printD("hy%d: hystart cmd = 0x%x count=%d ubaddr=0x%x\n",
                    362:                ui->ui_unit, cmd, count, ubaddr);
                    363:        printD("hy%d: - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n",
                    364:                ui->ui_unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar,
                    365:                addr->hyd_wcr);
                    366: #endif
                    367:        if (((is->hy_flags & RQ_REISSUE) == 0) &&
                    368:          (cmd != HYF_STATUS) && (cmd != HYF_END_OP) && (cmd != HYF_RSTATS)) {
                    369:                is->hy_savedstate = is->hy_state;
                    370:                is->hy_savedcmd = cmd;
                    371:                is->hy_savedcount = count;
                    372:                is->hy_savedaddr = ubaddr;
                    373:        }
                    374: #ifdef PI13
                    375:        if (addr->hyd_csr & S_POWEROFF) {
                    376:                printf("hy%d: \"Soft\" Adapter Power Failure (hystart)\n", ui->ui_unit);
                    377:                addr->hyd_csr |= S_POWEROFF;
                    378:                DELAY(100);
                    379:                if (addr->hyd_csr & S_POWEROFF) {
                    380:                        printf( "hy%d: \"Hard\" Adapter Power Failure, Network Shutdown (hystart)\n", ui->ui_unit);
                    381:                        if_down(&is->hy_if);
                    382:                        is->hy_if.if_flags &= ~IFF_UP;
                    383:                        is->hy_state = STARTUP;
                    384:                } else {
                    385:                        printf("hy%d: Adapter Power Restored (hystart)\n", ui->ui_unit);
                    386:                }
                    387:                return;
                    388:        }
                    389: #endif
                    390:        addr->hyd_bar = ubaddr & 0xffff;
                    391:        addr->hyd_wcr = is->hy_lastwcr = -((count+1) >> 1);
                    392:        addr->hyd_dbuf = cmd;
                    393: #ifdef PI13
                    394:        addr->hyd_csr = ((ubaddr >> XBASHIFT) & S_XBA) | S_GO | S_IE | S_IATTN;
                    395: #else
                    396:        addr->hyd_csr = ((ubaddr >> XBASHIFT) & S_XBA) | S_GO | S_IE;
                    397: #endif
                    398: #ifdef DEBUG
                    399:        printD("hy%d: exit hystart - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n",
                    400:                ui->ui_unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar,
                    401:                addr->hyd_wcr);
                    402: #endif
                    403: #ifdef HYLOG
                    404:        {
                    405:                struct {
                    406:                        u_char  hcmd;
                    407:                        u_char  hstate;
                    408:                        short   hcount;
                    409:                } hcl;
                    410: 
                    411:                hcl.hcmd = cmd;
                    412:                hcl.hstate = is->hy_state;
                    413:                hcl.hcount = count;
                    414:                hylog(HYL_CMD, sizeof(hcl), (char *)&hcl);
                    415:        }
                    416: #endif
                    417:        is->hy_ntime = 0;
                    418: }
                    419: 
                    420: int hyint_active = 0;          /* set during hy interrupt */
                    421: /*
                    422:  * Hyperchannel interface interrupt.
                    423:  *
                    424:  * An interrupt can occur for many reasons.  Examine the status of
                    425:  * the hyperchannel status bits to determine what to do next.
                    426:  *
                    427:  * If input error just drop packet.
                    428:  * Otherwise purge input buffered data path and examine 
                    429:  * packet to determine type.  Othewise decapsulate
                    430:  * packet based on type and pass to type specific higher-level
                    431:  * input routine.
                    432:  */
                    433: hyint(unit)
                    434:        int unit;
                    435: {
                    436:        register struct hy_softc *is = &hy_softc[unit];
                    437:        register struct uba_device *ui = hyinfo[unit];
                    438:        register struct hydevice *addr = (struct hydevice *)ui->ui_addr;
                    439: 
                    440:        if (hyint_active)
                    441:                panic("RECURSIVE HYPERCHANNEL INTERRUPT");
                    442:        hyint_active++;
                    443: #ifdef DEBUG
                    444:        printD("hy%d: hyint enter - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n",
                    445:                unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, addr->hyd_wcr);
                    446: #endif
                    447: #ifdef HYLOG
                    448: logit:
                    449:        {
                    450:                struct {
                    451:                        u_char  hstate;
                    452:                        u_char  hflags;
                    453:                        short   hcsr;
                    454:                        short   hwcr;
                    455:                } hil;
                    456:                hil.hstate = is->hy_state;
                    457:                hil.hflags = is->hy_flags;
                    458:                hil.hcsr = addr->hyd_csr;
                    459:                hil.hwcr = addr->hyd_wcr;
                    460:                hylog(HYL_INT, sizeof(hil), (char *)&hil);
                    461:        }
                    462: #endif
                    463:        if (HYS_ERROR(addr) && ((addr->hyd_csr & S_ATTN) == 0)) {
                    464:                /*
                    465:                 * Error bit set, some sort of error in the interface.
                    466:                 *
                    467:                 * The adapter sets attn on command completion so that's not
                    468:                 * a real error even though the interface considers it one.
                    469:                 */
                    470: #ifdef DEBUG
                    471:                if (hy_nodebug & 4)
                    472:                        hy_debug_flag = 1;
                    473: #endif
                    474:                printf("csr = 0x%b\nbar = 0x%x\nwcr = 0x%x\n",
                    475:                        addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar,
                    476:                        addr->hyd_wcr);
                    477:                if (addr->hyd_csr & S_NEX) {
                    478:                        printf("hy%d: NEX - Non Existant Memory\n", unit);
                    479: #ifdef PI13
                    480:                        addr->hyd_csr |= S_NEX;  /* as per PI13 manual */
                    481: #else
                    482:                        addr->hyd_csr &= ~S_NEX;
                    483: #endif
                    484:                        hycancel(ui);
                    485: #ifdef PI13
                    486:                } else if (addr->hyd_csr & S_POWEROFF) {
                    487:                        printf("hy%d: \"Soft\" Adapter Power Failure (hyint)\n", unit);
                    488:                        addr->hyd_csr |= S_POWEROFF;
                    489:                        DELAY(100);
                    490:                        if (addr->hyd_csr & S_POWEROFF) {
                    491:                                printf( "hy%d: \"Hard\" Adapter Power Failure, Network Shutdown (hyint)\n", unit);
                    492:                                if_down(&is->hy_if);
                    493:                                is->hy_if.if_flags &= ~IFF_UP;
                    494:                                is->hy_state = STARTUP;
                    495:                        } else {
                    496:                                printf("hy%d: Adapter Power Restored (hyint)\n", unit);
                    497:                        }
                    498: #endif
                    499:                } else {
                    500:                        printf("hy%d:  BAR overflow\n", unit);
                    501:                        hycancel(ui);
                    502:                }
                    503:        } else if (HYS_NORMAL(addr)) {
                    504:                /*
                    505:                 * Normal interrupt, bump state machine unless in state
                    506:                 * waiting and no data present (assumed to be word count
                    507:                 * zero interrupt or other hardware botch).
                    508:                 */
                    509:                if (is->hy_state != WAITING || HYS_RECVDATA(addr))
                    510:                        hyact(ui);
                    511:        } else if (HYS_ABNORMAL(addr)) {
                    512:                /*
                    513:                 * Abnormal termination.
                    514:                 * bump error counts, retry the last function
                    515:                 * 'MAXRETRY' times before kicking the bucket.
                    516:                 *
                    517:                 * Don't reissue the cmd if in certain states, abnormal
                    518:                 * on a reissued cmd or max retry exceeded.
                    519:                 */
                    520: #ifdef HYLOG
                    521:                if (hy_log.hyl_enable != hy_log.hyl_onerr) {
                    522:                        hy_log.hyl_enable = hy_log.hyl_onerr;
                    523:                        goto logit;
                    524:                }
                    525: #endif
                    526: #ifdef DEBUG
                    527:                if (hy_nodebug & 4)
                    528:                        hy_debug_flag = 1;
                    529:                printD("hy%d: abnormal interrupt, driver state \"%s\" (%d)\n",
                    530:                        unit, hy_state_names[is->hy_state], is->hy_state);
                    531:                printD("\tflags 0x%x olen %d lastwcr %d retry %d\n",
                    532:                        is->hy_flags, is->hy_olen, is->hy_lastwcr, is->hy_retry);
                    533:                printD("\tsaved: state %d count %d cmd 0x%x ptr 0x%x\n",
                    534:                        is->hy_savedstate, is->hy_savedcount,
                    535:                        is->hy_savedaddr, is->hy_savedcmd);
                    536: #endif
                    537: #ifdef PI13
                    538:                addr->hyd_csr &= ~S_C;  /* clear the damned PI-13 */
                    539: #endif
                    540:                if (is->hy_state == XMITSENT || is->hy_state == XMITDATASENT)
                    541:                        is->hy_if.if_oerrors++;
                    542:                else if (is->hy_state == RECVSENT || is->hy_state == RECVDATASENT)
                    543:                        is->hy_if.if_ierrors++;
                    544:                else
                    545:                        is->hy_if.if_collisions++;      /* other errors */
                    546:                if (is->hy_state == XMITDATASENT ||
                    547:                    is->hy_state == RECVSENT ||
                    548:                    is->hy_state == RECVDATASENT ||
                    549:                    (is->hy_flags & RQ_REISSUE) != 0 || is->hy_retry > MAXRETRY)
                    550:                        hycancel(ui);
                    551:                else {
                    552: #ifdef DEBUG
                    553:                        if (hy_nodebug & 2)
                    554:                                hy_debug_flag = 1;
                    555: #endif
                    556:                        is->hy_retry++;
                    557:                        is->hy_flags |= RQ_ENDOP | RQ_STATUS | RQ_REISSUE;
                    558:                        is->hy_state = IDLE;
                    559:                        hyact(ui);
                    560:                }
                    561:        } else {
                    562:                /*
                    563:                 * Interrupt is neither normal, abnormal, or interface error.
                    564:                 * Ignore it. It's either stacked or a word count 0.
                    565:                 */
                    566: #ifdef HYLOG
                    567:                if (hy_log.hyl_enable != hy_log.hyl_onerr) {
                    568:                        hy_log.hyl_enable = hy_log.hyl_onerr;
                    569:                        goto logit;
                    570:                }
                    571: #endif
                    572: #ifdef DEBUG
                    573:                printD("hy%d: possible stacked interrupt ignored\n", unit);
                    574: #endif
                    575:        }
                    576: #ifdef DEBUG
                    577:        printD("hy%d: hyint exit\n\n", unit);
                    578: #endif
                    579:        hyint_active = 0;
                    580: 
                    581: }
                    582: 
                    583: int hyoutprint = 0;
                    584: 
                    585: /*
                    586:  * Encapsulate a packet of type family for the local net.
                    587:  */
                    588: hyoutput(ifp, m0, dst)
                    589:        struct ifnet *ifp;
                    590:        struct mbuf *m0;
                    591:        struct sockaddr *dst;
                    592: {
                    593:        register struct hym_hdr *hym;
                    594:        register struct mbuf *m;
                    595:        register char *mp;
                    596:        int dlen;       /* packet size, incl hardware header, but not sw header */
                    597:        int error = 0;
                    598:        int s;
                    599: 
                    600:        /*
                    601:         * Calculate packet length for later deciding whether it will fit
                    602:         * in a message proper or we also need associated data.
                    603:         */
                    604:        dlen = 0;
                    605:        for (m = m0; m; m = m->m_next)
                    606:                dlen += m->m_len;
                    607:        m = m0;
                    608:        if (dst->sa_family == AF_HYLINK) {      /* don't add header */
                    609:                dlen -= HYM_SWLEN;
                    610:                goto headerexists;
                    611:        }
                    612: 
                    613:        /*
                    614:         * Add the software and hardware hyperchannel headers.
                    615:         * If there's not enough space in the first mbuf, allocate another.
                    616:         * If that should fail, drop this sucker.
                    617:         * No extra space for headers is allocated.
                    618:         */
                    619:        mp = mtod(m, char *);   /* save pointer to real message */
                    620:        M_PREPEND(m, sizeof(struct hym_hdr), M_DONTWAIT);
                    621:        if (m == 0) {
                    622:                error = ENOBUFS;
                    623:                goto bad;
                    624:        }
                    625:        dlen += sizeof(struct hym_hdr) - HYM_SWLEN;
                    626: 
                    627:        hym = mtod(m, struct hym_hdr *);
                    628: 
                    629:        bzero((caddr_t)hym, sizeof(struct hym_hdr));
                    630: 
                    631:        switch(dst->sa_family) {
                    632: 
                    633: #ifdef INET
                    634:        case AF_INET: {
                    635:                int i;
                    636: 
                    637:                /*
                    638:                 * if loopback address, swizzle ip header so when
                    639:                 * it comes back it looks like it was addressed to us
                    640:                 */
                    641:                i = hyroute(ifp, (u_long)in_lnaof(((struct sockaddr_in *)dst)->sin_addr), hym);
                    642:                if (i < 0)
                    643:                        goto notfound;
                    644:                if (i > 0) {
                    645:                        struct in_addr temp;
                    646: 
                    647:                        temp.s_addr = ((struct ip *)mp)->ip_dst.s_addr;
                    648:                        ((struct ip *)mp)->ip_dst.s_addr = ((struct ip *)mp)->ip_src.s_addr;
                    649:                        ((struct ip *)mp)->ip_src.s_addr = temp.s_addr;
                    650:                }
                    651:                /*
                    652:                 * If entire packet won't fit in message proper, just
                    653:                 * send hyperchannel hardware header and ip header in
                    654:                 * message proper.
                    655:                 *
                    656:                 * This insures that the associated data is at least a
                    657:                 * TCP/UDP header in length and thus prevents potential
                    658:                 * problems with very short word counts.
                    659:                 */
                    660:                if (dlen > MPSIZE)
                    661:                        hym->hym_mplen = sizeof(struct hy_hdr) + (((struct ip *)mp)->ip_hl << 2);
                    662:                hym->hym_type = HYLINK_IP;
                    663:                break;
                    664:        }
                    665: #endif
                    666: 
                    667:        default:
                    668:                printf("hy%d: can't handle af%d\n", ifp->if_unit,
                    669:                        dst->sa_family);
                    670:                error = EAFNOSUPPORT;
                    671:                goto drop;
                    672:        }
                    673: 
                    674: 
                    675: headerexists:
                    676: 
                    677:        /*
                    678:         * insure message proper is below the maximum
                    679:         */
                    680:        if (hym->hym_mplen > MPSIZE || (dlen > MPSIZE && hym->hym_mplen == 0))
                    681:                hym->hym_mplen = MPSIZE;
                    682: 
                    683:        hym->hym_from = htons(hy_softc[ifp->if_unit].hy_host);
                    684:        if (hym->hym_mplen)
                    685:                hym->hym_ctl |= H_ASSOC;
                    686:        else
                    687:                hym->hym_ctl &= ~H_ASSOC;
                    688:        if (hyoutprint) printf("hy%d: output mplen=%x ctl=%x access=%x to=%x from=%x param=%x type=%x\n",
                    689:                ifp->if_unit, hym->hym_mplen, hym->hym_ctl,
                    690:                hym->hym_access, hym->hym_to, hym->hym_from,
                    691:                hym->hym_param, hym->hym_type);
                    692: #ifdef DEBUG
                    693:        printD("hy%d: output mplen=%x ctl=%x access=%x to=%x from=%x param=%x type=%x\n",
                    694:                ifp->if_unit, hym->hym_mplen, hym->hym_ctl,
                    695:                hym->hym_access, hym->hym_to, hym->hym_from,
                    696:                hym->hym_param, hym->hym_type);
                    697: #endif
                    698:        s = splimp();
                    699:        if (IF_QFULL(&ifp->if_snd)) {
                    700:                IF_DROP(&ifp->if_snd);
                    701:                error = ENOBUFS;
                    702:                splx(s);
                    703:                goto drop;
                    704:        }
                    705:        IF_ENQUEUE(&ifp->if_snd, m);
                    706:        if (hy_softc[ifp->if_unit].hy_state == WAITING)
                    707:                hyact(hyinfo[ifp->if_unit]);
                    708:        splx(s);
                    709:        return (0);
                    710: notfound:
                    711:        error = EHOSTUNREACH;
                    712: drop:
                    713:        m_freem(m);
                    714:        return (error);
                    715: }
                    716: 
                    717: int
                    718: hyroute(ifp, dest, hym)
                    719:        register struct ifnet *ifp;
                    720:        u_long dest;
                    721:        register struct hym_hdr *hym;
                    722: {
                    723: #ifdef HYROUTE
                    724:        register struct hy_route *rt = &hy_route[ifp->if_unit];
                    725:        register struct hyr_hash *rhash;
                    726:        register int i;
                    727: #endif
                    728: 
                    729:        hym->hym_param = 0;
                    730: #ifdef HYROUTE
                    731:        if (rt->hyr_lasttime != 0) {
                    732:                i = HYRHASH(dest);
                    733:                rhash = &rt->hyr_hash[i];
                    734:                i = 0;
                    735:                while (rhash->hyr_key != dest) {
                    736:                        if (rhash->hyr_flags == 0 || i > HYRSIZE)
                    737:                                return(-1);
                    738:                        rhash++; i++;
                    739:                        if (rhash >= &rt->hyr_hash[HYRSIZE])
                    740:                                rhash = &rt->hyr_hash[0];
                    741:                }
                    742:                if (rhash->hyr_flags & HYR_GATE) {
                    743:                        i = rhash->hyr_nextgate;
                    744:                        if (i >= rhash->hyr_egate)
                    745:                                rhash->hyr_nextgate = rhash->hyr_pgate;
                    746:                        else
                    747:                                rhash->hyr_nextgate++;
                    748:                        rhash = &rt->hyr_hash[rt->hyr_gateway[i]];
                    749:                        if ((rhash->hyr_flags & HYR_DIR) == 0)
                    750:                                return(-1);
                    751:                } else if (rhash->hyr_flags & HYR_LOOP) {
                    752:                        hym->hym_param = H_LOOPBK;      /* adapter loopback */
                    753:                } else if (rhash->hyr_flags & HYR_RLOOP) {
                    754:                        hym->hym_param = H_RLOOPBK;     /* A710 remote loopback */
                    755:                }
                    756:                hym->hym_ctl = rhash->hyr_ctl;
                    757:                hym->hym_access = rhash->hyr_access;
                    758:                hym->hym_to = rhash->hyr_dst;
                    759:        } else {
                    760: #endif
                    761:                hym->hym_ctl = H_XTRUNKS | H_RTRUNKS;
                    762:                hym->hym_access = 0;
                    763:                hym->hym_to = htons((u_short)dest);
                    764:                if (dest & 0x010000)
                    765:                        hym->hym_param = H_LOOPBK;      /* adapter loopback */
                    766:                else if (dest & 0x020000)
                    767:                        hym->hym_param = H_RLOOPBK;     /* A710 remote loopback */
                    768: #ifdef HYROUTE
                    769:        }
                    770: #endif
                    771: 
                    772:        if (hym->hym_param == 0)
                    773:                return(0);
                    774:        else
                    775:                return(1);
                    776: }
                    777: 
                    778: hyact(ui)
                    779:        register struct uba_device *ui;
                    780: {
                    781:        register struct hy_softc *is = &hy_softc[ui->ui_unit];
                    782:        register struct hydevice *addr = (struct hydevice *)ui->ui_addr;
                    783: 
                    784: actloop:
                    785: #ifdef DEBUG
                    786:        printD("hy%d: hyact, enter state \"%s\"\n", ui->ui_unit,
                    787:                hy_state_names[is->hy_state]);
                    788: #endif
                    789:        switch (is->hy_state) {
                    790: 
                    791:        case STARTUP:
                    792:                goto endintr;
                    793: 
                    794:        case IDLE: {
                    795:                register rq = is->hy_flags;
                    796: 
                    797:                if (rq & RQ_STATUS) {
                    798:                        is->hy_flags &= ~RQ_STATUS;
                    799:                        is->hy_state = STATSENT;
                    800:                        hystart(ui, HYF_STATUS, sizeof (is->hy_status),
                    801:                            is->hy_ifuba.ifu_r.ifrw_info);
                    802:                } else if (rq & RQ_ENDOP) {
                    803:                        is->hy_flags &= ~RQ_ENDOP;
                    804:                        is->hy_state = ENDOPSENT;
                    805:                        hystart(ui, HYF_END_OP, 0, 0);
                    806:                } else if (rq & RQ_STATISTICS) {
                    807:                        is->hy_flags &= ~RQ_STATISTICS;
                    808:                        is->hy_state = RSTATSENT;
                    809:                        hystart(ui, HYF_RSTATS, sizeof (is->hy_stat),
                    810:                            is->hy_ifuba.ifu_r.ifrw_info);
                    811:                } else if (HYS_RECVDATA(addr)) {
                    812:                        is->hy_state = RECVSENT;
                    813:                        is->hy_retry = 0;
                    814:                        hystart(ui, HYF_INPUTMSG, MPSIZE, is->hy_ifuba.ifu_r.ifrw_info + HYM_SWLEN);
                    815:                } else if (rq & RQ_REISSUE) {
                    816:                        is->hy_flags &= ~RQ_REISSUE;
                    817:                        is->hy_state = is->hy_savedstate;
                    818: #ifdef DEBUG
                    819:                        printD("hy%d: reissue cmd=0x%x count=%d",
                    820:                          ui->ui_unit, is->hy_savedcmd, is->hy_savedcount);
                    821:                        printD(" ubaddr=0x%x retry=%d\n",
                    822:                          is->hy_savedaddr, is->hy_retry);
                    823: #endif
                    824:                        hystart(ui, is->hy_savedcmd, is->hy_savedcount,
                    825:                            is->hy_savedaddr);
                    826:                } else {
                    827:                        register struct mbuf *m;
                    828: 
                    829:                        IF_DEQUEUE(&is->hy_if.if_snd, m);
                    830:                        if (m != NULL) {
                    831:                                register struct hym_hdr *hym;
                    832:                                register int mplen;
                    833:                                register int cmd;
                    834: 
                    835:                                is->hy_state = XMITSENT;
                    836:                                is->hy_retry = 0;
                    837:                                hym = mtod(m, struct hym_hdr *);
                    838: #ifdef HYLOG
                    839:                                hylog(HYL_XMIT, sizeof(struct hym_hdr),
                    840:                                    (char *)hym);
                    841: #endif
                    842:                                mplen = hym->hym_mplen;
                    843:                                if (hym->hym_to_adapter == hym->hym_from_adapter)
                    844:                                        cmd = HYF_XMITLOCMSG;
                    845:                                else
                    846:                                        cmd = HYF_XMITMSG;
                    847: #ifdef DEBUG
                    848:                                printD("hy%d: hym_hdr = ", ui->ui_unit);
                    849:                                if (hy_debug_flag)
                    850:                                        hyprintdata((char *)hym,
                    851:                                            sizeof (struct hym_hdr));
                    852: #endif
                    853:                                is->hy_olen = if_wubaput(&is->hy_ifuba, m) - HYM_SWLEN;
                    854:                                if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP)
                    855:                                        UBAPURGE(is->hy_ifuba.ifu_uba,
                    856:                                                is->hy_ifuba.ifu_w.ifrw_bdp);
                    857: #ifdef DEBUG
                    858:                                printD(
                    859:                "hy%d: sending packet (mplen = %d, hy_olen = %d) data = ",
                    860:                                        ui->ui_unit, mplen, is->hy_olen);
                    861:                                if (hy_debug_flag)
                    862:                                        hyprintdata(
                    863:                                            is->hy_ifuba.ifu_w.ifrw_addr,
                    864:                                            is->hy_olen + HYM_SWLEN);
                    865: #endif
                    866:                                if (mplen == 0) {
                    867:                                        is->hy_flags &= ~RQ_XASSOC;
                    868:                                        mplen = is->hy_olen;
                    869:                                } else {
                    870:                                        is->hy_flags |= RQ_XASSOC;
                    871:                                }
                    872:                                hystart(ui, cmd, mplen, is->hy_ifuba.ifu_w.ifrw_info + HYM_SWLEN);
                    873:                        } else if (rq & RQ_MARKDOWN) {
                    874:                                is->hy_flags &= ~(RQ_MARKUP | RQ_MARKDOWN);
                    875:                                is->hy_state = MARKPORT;
                    876:                                is->hy_retry = 0;
                    877:                                /*
                    878:                                 * Port number is taken from status data
                    879:                                 */
                    880:                                hystart(ui,
                    881:                                 (int)(HYF_MARKP0|(PORTNUM(&is->hy_status)<<2)),
                    882:                                 0, 0);
                    883:                        } else if (rq & RQ_MARKUP) {
                    884:                                register struct ifnet *ifp = &is->hy_if;
                    885: 
                    886:                                is->hy_flags &= ~RQ_MARKUP;
                    887:                                is->hy_retry = 0;
                    888:                                /*
                    889:                                 * Fill in the host number
                    890:                                 * from the status buffer
                    891:                                 */
                    892:                                printf(
                    893:        "hy%d: unit number 0x%x port %d type %x microcode level 0x%x\n",
                    894:                                        ui->ui_unit,
                    895:                                        is->hy_stat.hyc_uaddr,
                    896:                                        PORTNUM(&is->hy_status),
                    897:                                        (is->hy_stat.hyc_atype[0]<<8) |
                    898:                                                is->hy_stat.hyc_atype[1],
                    899:                                        is->hy_stat.hyc_atype[2]);
                    900: 
                    901:                                is->hy_host =
                    902:                                  (is->hy_stat.hyc_uaddr << 8) |
                    903:                                        PORTNUM(&is->hy_status);
                    904:                                ifp->if_flags |= IFF_UP;
                    905: #ifdef HYLOG
                    906:                                hylog(HYL_UP, 0, (char *)0);
                    907: #endif
                    908:                        } else {
                    909:                                is->hy_state = WAITING;
                    910:                                is->hy_retry = 0;
                    911:                                hystart(ui, HYF_WAITFORMSG, 0, 0);
                    912:                        }
                    913:                }
                    914:                break;
                    915:        }
                    916: 
                    917:        case STATSENT:
                    918:                bcopy(is->hy_ifuba.ifu_r.ifrw_addr, (caddr_t)&is->hy_status,
                    919:                  sizeof (struct hy_status));
                    920: #ifdef DEBUG
                    921:                printD("hy%d: status - %x %x %x %x %x %x %x %x\n",
                    922:                        ui->ui_unit, is->hy_status.hys_gen_status,
                    923:                        is->hy_status.hys_last_fcn,
                    924:                        is->hy_status.hys_resp_trunk,
                    925:                        is->hy_status.hys_status_trunk,
                    926:                        is->hy_status.hys_recd_resp,
                    927:                        is->hy_status.hys_error,
                    928:                        is->hy_status.hys_caddr,
                    929:                        is->hy_status.hys_pad);
                    930: #endif
                    931:                is->hy_state = IDLE;
                    932: #ifdef HYLOG
                    933:                hylog(HYL_STATUS, sizeof (struct hy_status),
                    934:                        (char *)&is->hy_status);
                    935: #endif
                    936: #ifdef HYELOG
                    937:                {
                    938:                        register int i;
                    939:                        
                    940:                        i = is->hy_status.hys_error;
                    941:                        if (i > HYE_MAX)
                    942:                                i = HYE_MAX;
                    943:                        switch (is->hy_status.hys_last_fcn) {
                    944:                                case HYF_XMITLOCMSG:
                    945:                                        i += HYE_MAX+1; /* fall through */
                    946:                                case HYF_XMITLSTDATA:
                    947:                                        i += HYE_MAX+1; /* fall through */
                    948:                                case HYF_XMITMSG:
                    949:                                        i += HYE_MAX+1;
                    950:                        }
                    951:                        hy_elog[i]++;
                    952:                }
                    953: #endif
                    954:                break;
                    955: 
                    956:        case RSTATSENT: {
                    957:                register struct hy_stat *p =
                    958:                        (struct hy_stat *)is->hy_ifuba.ifu_r.ifrw_addr;
                    959: 
                    960:                bcopy((caddr_t)p, (caddr_t)&is->hy_stat, sizeof(struct hy_stat));
                    961: #ifdef DEBUG
                    962: 
                    963:                printD("hy%d: statistics - df0 %d df1 %d df2 %d df3 %d\n",
                    964:                        ui->ui_unit,
                    965:                        (is->hy_stat.hyc_df0[0]<<16) | (is->hy_stat.hyc_df0[1]<<8) | is->hy_stat.hyc_df0[2],
                    966:                        (is->hy_stat.hyc_df1[0]<<16) | (is->hy_stat.hyc_df1[1]<<8) | is->hy_stat.hyc_df1[2],
                    967:                        (is->hy_stat.hyc_df2[0]<<16) | (is->hy_stat.hyc_df2[1]<<8) | is->hy_stat.hyc_df2[2],
                    968:                        (is->hy_stat.hyc_df3[0]<<16) | (is->hy_stat.hyc_df3[1]<<8) | is->hy_stat.hyc_df3[2]);
                    969:                printD("        ret0 %d ret1 %d ret2 %d ret3 %d\n",
                    970:                        (is->hy_stat.hyc_ret0[0]<<16) | (is->hy_stat.hyc_ret0[1]<<8) | is->hy_stat.hyc_ret0[2],
                    971:                        (is->hy_stat.hyc_ret1[0]<<16) | (is->hy_stat.hyc_ret1[1]<<8) | is->hy_stat.hyc_ret1[2],
                    972:                        (is->hy_stat.hyc_ret2[0]<<16) | (is->hy_stat.hyc_ret2[1]<<8) | is->hy_stat.hyc_ret2[2],
                    973:                        (is->hy_stat.hyc_ret3[0]<<16) | (is->hy_stat.hyc_ret3[1]<<8) | is->hy_stat.hyc_ret3[2]);
                    974:                printD("        cancel %d abort %d atype %x %x %x uaddr %x\n",
                    975:                        (is->hy_stat.hyc_cancel[0]<<8) | is->hy_stat.hyc_cancel[1],
                    976:                        (is->hy_stat.hyc_abort[0]<<8) | is->hy_stat.hyc_abort[1],
                    977:                        is->hy_stat.hyc_atype[0], is->hy_stat.hyc_atype[1],
                    978:                        is->hy_stat.hyc_atype[2], is->hy_stat.hyc_uaddr);
                    979: #endif
                    980:                is->hy_state = IDLE;
                    981: #ifdef HYLOG
                    982:                hylog(HYL_STATISTICS, sizeof (struct hy_stat),
                    983:                        (char *)&is->hy_stat);
                    984: #endif
                    985:                break;
                    986:        }
                    987: 
                    988:        case CLEARSENT:
                    989:                is->hy_state = IDLE;
                    990:                break;
                    991: 
                    992:        case ENDOPSENT:
                    993:                is->hy_state = IDLE;
                    994:                break;
                    995: 
                    996:        case RECVSENT: {
                    997:                register struct hym_hdr *hym;
                    998:                register unsigned len;
                    999: 
                   1000:                if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP)
                   1001:                        UBAPURGE(is->hy_ifuba.ifu_uba,
                   1002:                            is->hy_ifuba.ifu_r.ifrw_bdp);
                   1003:                hym = (struct hym_hdr *) (is->hy_ifuba.ifu_r.ifrw_addr);
                   1004:                len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1;
                   1005:                if (len > MPSIZE) {
                   1006:                        printf("hy%d: RECVD MP > MPSIZE (%d)\n",
                   1007:                            ui->ui_unit, len);
                   1008:                        is->hy_state = IDLE;
                   1009: #ifdef DEBUG
                   1010:                        hy_debug_flag = 1;
                   1011:                        printD("hy%d: csr = 0x%b, bar = 0x%x, wcr = 0x%x\n",
                   1012:                                ui->ui_unit, addr->hyd_csr, HY_CSR_BITS,
                   1013:                                addr->hyd_bar, addr->hyd_wcr);
                   1014: #endif
                   1015:                }
                   1016:                hym->hym_mplen = len;
                   1017: #ifdef DEBUG
                   1018:                printD("hy%d: recvd mp, len = %d, data = ", ui->ui_unit, len);
                   1019:                if (hy_debug_flag)
                   1020:                        hyprintdata((char *)hym, len + HYM_SWLEN);
                   1021: #endif
                   1022:                if (hym->hym_ctl & H_ASSOC) {
                   1023:                        is->hy_state = RECVDATASENT;
                   1024:                        is->hy_retry = 0;
                   1025:                        hystart(ui, HYF_INPUTDATA,
                   1026:                            (int)(HYMTU + sizeof (struct hy_hdr) - len),
                   1027:                            (int)(HYM_SWLEN + is->hy_ifuba.ifu_r.ifrw_info + len));
                   1028:                } else {
                   1029:                        hyrecvdata(ui, hym, (int)len + HYM_SWLEN);
                   1030:                        is->hy_state = IDLE;
                   1031:                }
                   1032:                break;
                   1033:        }
                   1034: 
                   1035:        case RECVDATASENT: {
                   1036:                register struct hym_hdr *hym;
                   1037:                register unsigned len;
                   1038: 
                   1039:                if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP)
                   1040:                        UBAPURGE(is->hy_ifuba.ifu_uba,
                   1041:                            is->hy_ifuba.ifu_r.ifrw_bdp);
                   1042:                hym = (struct hym_hdr *) (is->hy_ifuba.ifu_r.ifrw_addr);
                   1043:                len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1;
                   1044: #ifdef DEBUG
                   1045:                printD("hy%d: recvd assoc data, len = %d, data = ",
                   1046:                        ui->ui_unit, len);
                   1047:                if (hy_debug_flag)
                   1048:                        hyprintdata((char *)hym + hym->hym_mplen, len);
                   1049: #endif
                   1050:                hyrecvdata(ui, hym, (int)(len + hym->hym_mplen + HYM_SWLEN));
                   1051:                is->hy_state = IDLE;
                   1052:                break;
                   1053:        }
                   1054: 
                   1055:        case XMITSENT:
                   1056:                if (is->hy_flags & RQ_XASSOC) {
                   1057:                        register int len;
                   1058: 
                   1059:                        is->hy_flags &= ~RQ_XASSOC;
                   1060:                        is->hy_state = XMITDATASENT;
                   1061:                        is->hy_retry = 0;
                   1062:                        len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1;
                   1063:                        if (len > is->hy_olen) {
                   1064:                                printf(
                   1065:                                "hy%d: xmit error - len > hy_olen [%d > %d]\n",
                   1066:                                ui->ui_unit, len, is->hy_olen);
                   1067: #ifdef DEBUG
                   1068:                                hy_debug_flag = 1;
                   1069: #endif
                   1070:                        }
                   1071:                        hystart(ui, HYF_XMITLSTDATA, is->hy_olen - len,
                   1072:                            is->hy_ifuba.ifu_w.ifrw_info + HYM_SWLEN + len);
                   1073:                        break;
                   1074:                }
                   1075:                /* fall through to ... */
                   1076:                
                   1077:        case XMITDATASENT:
                   1078:                hyxmitdata(ui);
                   1079:                is->hy_state = IDLE;
                   1080:                break;
                   1081: 
                   1082:        case WAITING:   /* wait for message complete or output requested */
                   1083:                if (HYS_RECVDATA(addr))
                   1084:                        is->hy_state = IDLE;
                   1085:                else {
                   1086:                        is->hy_state = CLEARSENT;
                   1087:                        is->hy_retry = 0;
                   1088:                        hystart(ui, HYF_CLRWFMSG, 0, 0);
                   1089:                }
                   1090:                break;
                   1091: 
                   1092:        case MARKPORT:
                   1093:                is->hy_state = STARTUP;
                   1094:                if_down(&is->hy_if);
                   1095:                is->hy_if.if_flags &= ~IFF_UP;
                   1096:                goto endintr;
                   1097:        
                   1098:        default:
                   1099:                printf("hy%d: DRIVER BUG - INVALID STATE %d\n",
                   1100:                        ui->ui_unit, is->hy_state);
                   1101:                panic("HYPERCHANNEL IN INVALID STATE");
                   1102:                /*NOTREACHED*/
                   1103:        }
                   1104:        if (is->hy_state == IDLE)
                   1105:                goto actloop;
                   1106: endintr:
                   1107:        ;
                   1108: #ifdef DEBUG
                   1109:        printD("hy%d: hyact, exit at \"%s\"\n", ui->ui_unit,
                   1110:                hy_state_names[is->hy_state]);
                   1111: #endif
                   1112: }
                   1113: 
                   1114: struct sockproto hypproto = { PF_HYLINK };
                   1115: struct sockaddr_in hypdst = { sizeof(hypdst), AF_HYLINK };
                   1116: struct sockaddr_in hypsrc = { sizeof(hypsrc), AF_HYLINK };
                   1117: 
                   1118: /*
                   1119:  * Called from device interrupt when receiving data.
                   1120:  * Examine packet to determine type.  Decapsulate packet
                   1121:  * based on type and pass to type specific higher-level
                   1122:  * input routine.
                   1123:  */
                   1124: hyrecvdata(ui, hym, len)
                   1125:        struct uba_device *ui;
                   1126:        register struct hym_hdr *hym;
                   1127:        int len;
                   1128: {
                   1129:        register struct hy_softc *is = &hy_softc[ui->ui_unit];
                   1130:        struct mbuf *m;
                   1131:        register struct ifqueue *inq;
                   1132: 
                   1133:        is->hy_if.if_ipackets++;
                   1134: #ifdef DEBUG
                   1135:        printD("hy%d: recieved packet, len = %d\n", ui->ui_unit, len);
                   1136: #endif
                   1137: #ifdef HYLOG
                   1138:        {
                   1139:                struct {
                   1140:                        short hlen;
                   1141:                        struct hym_hdr hhdr;
                   1142:                } hh;
                   1143:                hh.hlen = len;
                   1144:                hh.hhdr = *hym;
                   1145:                hylog(HYL_RECV, sizeof(hh), (char *)&hh);
                   1146:        }
                   1147: #endif
                   1148:        if (len > HYMTU + MPSIZE || len == 0)
                   1149:                return;                 /* sanity */
                   1150:        /*
                   1151:         * Pull packet off interface.
                   1152:         */
                   1153:        m = if_rubaget(&is->hy_ifuba, len, 0, &is->hy_if);
                   1154:        if (m == NULL)
                   1155:                return;
                   1156: 
                   1157:        /*
                   1158:         * if normal or adapter loopback response packet believe hym_type,
                   1159:         * otherwise, use the raw input queue cause it's a response from an
                   1160:         * adapter command.
                   1161:         */
                   1162:        if (hym->hym_param != 0 && (u_short)hym->hym_param != 0x80ff)
                   1163:                goto rawlinkin;
                   1164: 
                   1165:        switch (hym->hym_type) {
                   1166: 
                   1167: #ifdef INET
                   1168:        case HYLINK_IP:
                   1169:                schednetisr(NETISR_IP);
                   1170:                inq = &ipintrq;
                   1171:                break;
                   1172: #endif
                   1173:        default:
                   1174:        rawlinkin:
                   1175:                {
                   1176:                        M_PREPEND(m, sizeof(struct hym_hdr), M_DONTWAIT);
                   1177:                        if (m == 0) {
                   1178:                                m_freem(m);
                   1179:                                return;
                   1180:                        }
                   1181:                        bcopy((caddr_t)hym, mtod(m, caddr_t), sizeof(struct hym_hdr));
                   1182:                        hypproto.sp_protocol = 0;
                   1183:                        hypdst.sin_addr = is->hy_addr;
                   1184:                        hypsrc.sin_addr = is->hy_addr;
                   1185:                        raw_input(m, &hypproto, (struct sockaddr *)&hypsrc,
                   1186:                                (struct sockaddr *)&hypdst);
                   1187:                        return;
                   1188:                }
                   1189:        }
                   1190:        if (IF_QFULL(inq)) {
                   1191:                IF_DROP(inq);
                   1192:                m_freem(m);
                   1193:        } else
                   1194:                IF_ENQUEUE(inq, m);
                   1195: }
                   1196: 
                   1197: /*
                   1198:  * Transmit done, release resources, bump counters.
                   1199:  */
                   1200: hyxmitdata(ui)
                   1201:        struct uba_device *ui;
                   1202: {
                   1203:        register struct hy_softc *is = &hy_softc[ui->ui_unit];
                   1204: 
                   1205:        is->hy_if.if_opackets++;
                   1206:        if (is->hy_ifuba.ifu_xtofree) {
                   1207:                m_freem(is->hy_ifuba.ifu_xtofree);
                   1208:                is->hy_ifuba.ifu_xtofree = 0;
                   1209:        }
                   1210: }
                   1211: 
                   1212: hycancel(ui)
                   1213:        register struct uba_device *ui;
                   1214: {
                   1215:        register struct hy_softc *is = &hy_softc[ui->ui_unit];
                   1216: 
                   1217:        if (is->hy_ifuba.ifu_xtofree) {
                   1218:                m_freem(is->hy_ifuba.ifu_xtofree);
                   1219:                is->hy_ifuba.ifu_xtofree = 0;
                   1220:        }
                   1221: #ifdef HYLOG
                   1222:        hylog(HYL_CANCEL, 0, (char *)0);
                   1223: #endif
                   1224: #ifdef DEBUG
                   1225:        if (hy_nodebug & 1)
                   1226:                hy_debug_flag = 1;
                   1227: #endif
                   1228: #ifdef DEBUG
                   1229:        printD("hy%d: cancel from state \"%s\" cmd=0x%x count=%d ptr=0x%x\n",
                   1230:                ui->ui_unit, hy_state_names[is->hy_state], is->hy_savedcmd,
                   1231:                is->hy_savedcount, is->hy_savedaddr);
                   1232:        printD("\tflags 0x%x olen %d lastwcr %d retry %d\n",
                   1233:                is->hy_flags, is->hy_olen, is->hy_lastwcr, is->hy_retry);
                   1234:        printD("\tsaved: state %d count %d ptr 0x%x cmd 0x%x\n",
                   1235:                is->hy_savedstate, is->hy_savedcount, is->hy_savedaddr,
                   1236:                is->hy_savedcmd);
                   1237: #endif
                   1238:        is->hy_state = IDLE;
                   1239:        is->hy_flags |= (RQ_ENDOP | RQ_STATUS);
                   1240:        hyact(ui);
                   1241: }
                   1242: 
                   1243: #ifdef DEBUG
                   1244: hyprintdata(cp, len)
                   1245:        register char *cp;
                   1246:        register int len;
                   1247: {
                   1248:        register int count = 16;
                   1249:        register char *fmt;
                   1250:        static char regfmt[] = "\n\t %x";
                   1251: 
                   1252:        fmt = &regfmt[2];
                   1253:        while (--len >= 0) {
                   1254:                printL(fmt, *cp++ & 0xff);
                   1255:                fmt = &regfmt[2];
                   1256:                if (--count <= 0) {
                   1257:                        fmt = &regfmt[0];
                   1258:                        count = 16;
                   1259:                }
                   1260:        }
                   1261:        printL("\n");
                   1262: }
                   1263: #endif
                   1264: 
                   1265: hywatch(unit)
                   1266:        int unit;
                   1267: {
                   1268:        register struct hy_softc *is = &hy_softc[unit];
                   1269:        register struct uba_device *ui = hyinfo[unit];
                   1270:        register struct hydevice *addr = (struct hydevice *)ui->ui_addr;
                   1271:        int s;
                   1272: 
                   1273:        s = splimp();
                   1274: #ifdef PI13
                   1275:        if ((addr->hyd_csr & S_POWEROFF) != 0) {
                   1276:                addr->hyd_csr |= S_POWEROFF;
                   1277:                DELAY(100);
                   1278:                if ((addr->hyd_csr & S_POWEROFF) == 0) {
                   1279:                        printf("hy%d: Adapter Power Restored (hywatch)\n", unit);
                   1280:                        is->hy_state = IDLE;
                   1281:                        is->hy_flags |=
                   1282:                          (RQ_MARKUP | RQ_STATISTICS | RQ_ENDOP | RQ_STATUS);
                   1283:                        hyact(ui);
                   1284:                }
                   1285:        }
                   1286: #endif
                   1287:        if (++is->hy_ntime >= 2 && is->hy_state != WAITING &&
                   1288:          is->hy_state != STARTUP && is->hy_state != IDLE) {
                   1289: #ifdef HYLOG
                   1290:                printf("hy%d: watchdog timer expired in state \"%s\"\n", unit,
                   1291:                        hy_state_names[is->hy_state]);
                   1292: #else
                   1293:                printf("hy%d: watchdog timer expired in state %d\n", unit,
                   1294:                        is->hy_state);
                   1295: #endif
                   1296:                printf("hy%d: last command 0x%x, flags 0x%x, csr 0x%b\n", unit,
                   1297:                        is->hy_savedcmd, is->hy_flags, addr->hyd_csr, HY_CSR_BITS);
                   1298:                hycancel(ui);
                   1299:        }
                   1300:        splx(s);
                   1301:        is->hy_if.if_timer = SCANINTERVAL;
                   1302: }
                   1303: 
                   1304: #ifdef HYLOG
                   1305: hylog(code, len, ptr)
                   1306:        int code, len;
                   1307:        char *ptr;
                   1308: {
                   1309:        register unsigned char *p;
                   1310:        int s;
                   1311: 
                   1312:        s = splimp();
                   1313:        if (hy_log.hyl_self != &hy_log) {
                   1314:                hy_log.hyl_eptr = &hy_log.hyl_buf[HYL_SIZE];
                   1315:                hy_log.hyl_ptr = &hy_log.hyl_buf[0];
                   1316:                hy_log.hyl_self = &hy_log;
                   1317:                hy_log.hyl_enable = HYL_CONTINUOUS;
                   1318:                hy_log.hyl_onerr = HYL_CONTINUOUS;
                   1319:                hy_log.hyl_count = 0;
                   1320:                hy_log.hyl_icount = 16;
                   1321:                hy_log.hyl_filter = 0xffff;     /* enable all */
                   1322:        }
                   1323:        if (hy_log.hyl_enable == HYL_DISABLED || ((1 << code) & hy_log.hyl_filter) == 0)
                   1324:                goto out;
                   1325:        p = hy_log.hyl_ptr;
                   1326:        if (p + len + 3 >= hy_log.hyl_eptr) {
                   1327:                bzero((caddr_t)p, (unsigned)(hy_log.hyl_eptr - p));
                   1328:                p = &hy_log.hyl_buf[0];
                   1329:                if (hy_log.hyl_enable != HYL_CONTINUOUS) {
                   1330:                        hy_log.hyl_enable = HYL_DISABLED;
                   1331:                        goto out;
                   1332:                }
                   1333:        }
                   1334:        *p++ = code;
                   1335:        *p++ = len;
                   1336:        bcopy((caddr_t)ptr, (caddr_t)p, (unsigned)len);
                   1337:        if (hy_log.hyl_count != 0 && --hy_log.hyl_count == 0) {
                   1338:                *p++ = '\0';
                   1339:                hy_log.hyl_enable = HYL_DISABLED;
                   1340:                hy_log.hyl_count = hy_log.hyl_icount;
                   1341:        }
                   1342:        p += len;
                   1343:        if (hy_log.hyl_wait != 0) {             /* wakeup HYGETLOG if wanted */
                   1344:                if (hy_log.hyl_wait <= p - hy_log.hyl_ptr) {
                   1345:                        wakeup((caddr_t)&hy_log);
                   1346:                        hy_log.hyl_wait = 0;
                   1347:                } else
                   1348:                        hy_log.hyl_wait -= p - hy_log.hyl_ptr;
                   1349:        }
                   1350:        hy_log.hyl_ptr = p;
                   1351: out:
                   1352:        splx(s);
                   1353: }
                   1354: #endif
                   1355: 
                   1356: /*ARGSUSED*/
                   1357: hyioctl(ifp, cmd, data)
                   1358:        register struct ifnet *ifp;
                   1359:        int cmd;
                   1360:        caddr_t data;
                   1361: {
                   1362:        struct ifaddr *ifa = (struct ifaddr *) data;
                   1363:        struct hyrsetget *sg = (struct hyrsetget *)data;
                   1364: #if defined(HYLOG) || defined(HYELOG)
                   1365:        struct hylsetget *sgl = (struct hylsetget *)data;
                   1366: #endif
                   1367:        struct hy_route *r = (struct hy_route *)&hy_route[ifp->if_unit];
                   1368:        int s = splimp(), error = 0;
                   1369: #ifdef HYLOG
                   1370:        struct hy_softc *is = &hy_softc[ifp->if_unit];
                   1371:        struct {
                   1372:                u_char  hstate;
                   1373:                u_char  hflags;
                   1374:                u_short iflags;
                   1375:                int     hcmd;   
                   1376:                int     herror;
                   1377:                u_long  haddr;
                   1378:                u_long  hmisc;
                   1379:        } hil;
                   1380: 
                   1381:        hil.hmisc = -1;
                   1382:        hil.hstate = is->hy_state;
                   1383:        hil.hflags = is->hy_flags;
                   1384:        hil.hcmd = cmd;
                   1385: #endif
                   1386: 
                   1387:        switch(cmd) {
                   1388: 
                   1389:        case SIOCSIFADDR:
                   1390:                if (ifa->ifa_addr->sa_family != AF_INET)
                   1391:                        return(EINVAL);
                   1392:                if ((ifp->if_flags & IFF_RUNNING) == 0)
                   1393:                        hyinit(ifp->if_unit);
                   1394:                hy_softc[ifp->if_unit].hy_addr = IA_SIN(ifa)->sin_addr;
                   1395: #ifdef HYLOG
                   1396:                hil.haddr = is->hy_addr.s_addr;
                   1397: #endif
                   1398:                break;
                   1399: 
                   1400:        case HYSETROUTE:
                   1401:                if (error = suser(u.u_cred, &u.u_acflag))
                   1402:                        goto out;
                   1403: 
                   1404:                if (sg->hyrsg_len != sizeof(struct hy_route)) {
                   1405:                        error = EINVAL;
                   1406:                        goto out;
                   1407:                }
                   1408:                if (copyin((caddr_t)(sg->hyrsg_ptr), (caddr_t)r, sg->hyrsg_len)) {
                   1409:                        r->hyr_lasttime = 0;    /* disable further routing if trouble */
                   1410:                        error = EFAULT;
                   1411:                        goto out;
                   1412:                }
                   1413:                r->hyr_lasttime = time.tv_sec;
                   1414: #ifdef HYLOG
                   1415:                hil.hmisc = r->hyr_lasttime;
                   1416: #endif
                   1417:                break;
                   1418: 
                   1419:        case HYGETROUTE:
                   1420:                if (sg->hyrsg_len < sizeof(struct hy_route)) {
                   1421:                        error = EINVAL;
                   1422:                        goto out;
                   1423:                }
                   1424:                if (copyout((caddr_t)r, (caddr_t) (sg->hyrsg_ptr), sizeof(struct hy_route))) {
                   1425:                        error = EFAULT;
                   1426:                        goto out;
                   1427:                }
                   1428:                break;
                   1429: 
                   1430: #ifdef HYELOG
                   1431:        case HYGETELOG:
                   1432:                if (sgl->hylsg_len < sizeof(hy_elog)) {
                   1433:                        error = EINVAL;
                   1434:                        goto out;
                   1435:                }
                   1436:                if (copyout((caddr_t)hy_elog, sgl->hylsg_ptr, sizeof(hy_elog))) {
                   1437:                        error = EFAULT;
                   1438:                        goto out;
                   1439:                }
                   1440:                if (sgl->hylsg_cmd) {
                   1441:                        if (error = suser(u.u_cred, &u.u_acflag))
                   1442:                                goto out;
                   1443:                        bzero((caddr_t)hy_elog, sizeof(hy_elog));
                   1444:                }
                   1445:                break;
                   1446: #endif
                   1447: 
                   1448: #ifdef HYLOG
                   1449:        case HYSETLOG:
                   1450:                if (error = suser(u.u_cred, &u.u_acflag))
                   1451:                        goto out;
                   1452:                hy_log.hyl_enable = HYL_DISABLED;
                   1453:                hylog(HYL_NOP, 0, (char *)0);           /* force log init */
                   1454:                hy_log.hyl_enable = sgl->hylsg_cmd & 0x0f;
                   1455:                hy_log.hyl_onerr = (sgl->hylsg_cmd >> 4) & 0x0f;
                   1456:                hy_log.hyl_filter = (sgl->hylsg_cmd >> 8) & 0xffffff;
                   1457:                hy_log.hyl_count = hy_log.hyl_icount = sgl->hylsg_len;
                   1458:                wakeup((caddr_t)&hy_log);       /* wakeup sleeping HYGETLOG */
                   1459:                break;
                   1460: 
                   1461:        case HYGETLOG:
                   1462:                if (sgl->hylsg_len < sizeof(hy_log)) {
                   1463:                        error = EINVAL;
                   1464:                        goto out;
                   1465:                }
                   1466:                if (sgl->hylsg_cmd != 0) {
                   1467:                        if (hy_log.hyl_wait) {
                   1468:                                error = EBUSY;
                   1469:                                goto out;
                   1470:                        }
                   1471:                        hy_log.hyl_wait = sgl->hylsg_cmd;
                   1472:                        sleep((caddr_t)&hy_log, PZERO - 1);
                   1473:                }
                   1474: 
                   1475:                if (copyout((caddr_t)&hy_log, sgl->hylsg_ptr, sizeof(hy_log))) {
                   1476:                        error = EFAULT;
                   1477:                        goto out;
                   1478:                }
                   1479:                break;
                   1480: #endif
                   1481: 
                   1482:        default:
                   1483:                error = EINVAL;
                   1484:                break;
                   1485:        }
                   1486: out:
                   1487: #ifdef HYLOG
                   1488:        hil.herror = error;
                   1489:        hil.iflags = ifp->if_flags;
                   1490:        hil.haddr = is->hy_addr.s_addr;
                   1491:        hylog(HYL_IOCTL, sizeof(hil), (char *)&hil);
                   1492: #endif
                   1493:        splx(s);
                   1494:        return (error);
                   1495: }
                   1496: #endif

unix.superglobalmegacorp.com

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