Annotation of 43BSD/sys/vaxif/if_hy.c, revision 1.1

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

unix.superglobalmegacorp.com

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