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

unix.superglobalmegacorp.com

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