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

1.1     ! root        1: /*     if_hy.c 6.1     83/07/29        */
        !             2: 
        !             3: #include "hy.h"
        !             4: #if NHY > 0
        !             5: 
        !             6: /*
        !             7:  * Network Systems Copropration Hyperchanel interface
        !             8:  *
        !             9:  * UNTESTED WITH 4.2
        !            10:  */
        !            11: #include "../machine/pte.h"
        !            12: 
        !            13: #include "../h/param.h"
        !            14: #include "../h/systm.h"
        !            15: #include "../h/mbuf.h"
        !            16: #include "../h/buf.h"
        !            17: #include "../h/protosw.h"
        !            18: #include "../h/socket.h"
        !            19: #include "../h/vmmac.h"
        !            20: #include "../h/errno.h"
        !            21: #include "../h/time.h"
        !            22: #include "../h/kernel.h"
        !            23: #include "../h/ioctl.h"
        !            24: 
        !            25: #include "../net/if.h"
        !            26: #include "../net/netisr.h"
        !            27: #include "../net/route.h"
        !            28: #include "../netinet/in.h"
        !            29: #include "../netinet/in_systm.h"
        !            30: #include "../netinet/ip.h"
        !            31: #include "../netinet/ip_var.h"
        !            32: 
        !            33: #include "../vax/cpu.h"
        !            34: #include "../vax/mtpr.h"
        !            35: #include "../vaxuba/ubareg.h"
        !            36: #include "../vaxuba/ubavar.h"
        !            37: #include "../vaxif/if_hy.h"
        !            38: #include "../vaxif/if_hyreg.h"
        !            39: #include "../vaxif/if_uba.h"
        !            40: 
        !            41: #define HYROUTE
        !            42: #define HYELOG
        !            43: #define        HYMTU   576
        !            44: 
        !            45: int    hyprobe(), hyattach(), hyinit(), hyioctl();
        !            46: int    hyoutput(), hyreset(), hywatch();
        !            47: struct uba_device *hyinfo[NHY];
        !            48: u_short hystd[] = { 0772410, 0 };
        !            49: struct uba_driver hydriver =
        !            50:        { hyprobe, 0, hyattach, 0, hystd, "hy", hyinfo };
        !            51: 
        !            52: /*
        !            53:  * Hyperchannel software status per interface.
        !            54:  *
        !            55:  * Each interface is referenced by a network interface structure,
        !            56:  * hy_if, which the routing code uses to locate the interface.
        !            57:  * This structure contains the output queue for the interface, its address, ...
        !            58:  * We also have, for each interface, a UBA interface structure, which
        !            59:  * contains information about the UNIBUS resources held by the interface:
        !            60:  * map registers, buffered data paths, etc.  Information is cached in this
        !            61:  * structure for use by the if_uba.c routines in running the interface
        !            62:  * efficiently.
        !            63:  */
        !            64: struct hy_softc {
        !            65:        struct  ifnet hy_if;            /* network-visible interface */
        !            66:        struct  ifuba hy_ifuba;         /* UNIBUS resources */
        !            67:        short   hy_flags;               /* flags */
        !            68:        short   hy_state;               /* driver state */
        !            69:        int     hy_ilen;                /* mp length on input */
        !            70:        int     hy_olen;                /* packet length on output */
        !            71:        int     hy_lastwcr;             /* last command's word count */
        !            72:        short   hy_savedstate;          /* saved for reissue after status */
        !            73:        short   hy_savedcmd;            /* saved command for reissue */
        !            74:        int     hy_savedcount;          /* saved byte count for reissue */
        !            75:        int     hy_savedaddr;           /* saved unibus address for reissue */
        !            76:        int     hy_ntime;               /* number of timeouts since last cmd */
        !            77:        int     hy_retry;               /* retry counter */
        !            78:        struct  hy_stat hy_stat;        /* statistics */
        !            79:        struct  hy_status hy_status;    /* status */
        !            80: } hy_softc[NHY];
        !            81: 
        !            82: #ifdef HYELOG
        !            83: #define HYE_MAX        0x18
        !            84: u_long hy_elog[(HYE_MAX+1)*4];
        !            85: #endif
        !            86: 
        !            87: #ifdef DEBUG
        !            88: #define printL lprintf
        !            89: #define printD if (hy_debug_flag) lprintf
        !            90: int    hy_debug_flag = 0;
        !            91: /*
        !            92:  * hy_nodebug bit 0x01 set hy_debug_flag on hycancel
        !            93:  * hy_nodebug bit 0x02 set hy_debug_flag on command reissue
        !            94:  * hy_nodebug bit 0x04 set hy_debug_flag on abnormal interrupt
        !            95:  * hy_nodebug bit 0x08 set hy_debug_flag on hyouput
        !            96:  * hy_nodebug bit 0x10 set hy_debug_flag on hyouput with associated data
        !            97:  */
        !            98: int    hy_nodebug = 0x0;
        !            99: #else
        !           100: #define printD hyvoid
        !           101: #endif
        !           102: 
        !           103: /*
        !           104:  * Requests for service (in order by descending priority).
        !           105:  */
        !           106: #define RQ_ENDOP       001     /* end the last adapter function */
        !           107: #define RQ_REISSUE     002     /* reissue previous cmd after status */
        !           108: #define RQ_STATUS      004     /* get the status of the adapter */
        !           109: #define RQ_STATISTICS  010     /* get the statistics of the adapter */
        !           110: #define RQ_MARKDOWN    020     /* mark this adapter port down */
        !           111: #define RQ_MARKUP      040     /* mark this interface up */
        !           112: 
        !           113: #define RQ_XASSOC      0100    /* associated data to transmit */
        !           114: 
        !           115: /* 
        !           116:  * Driver states.
        !           117:  */
        !           118: #define        STARTUP         0       /* initial state (before fully there) */
        !           119: #define        IDLE            1       /* idle state */
        !           120: #define        STATSENT        2       /* status cmd sent to adapter */
        !           121: #define        ENDOPSENT       3       /* end operation cmd sent */
        !           122: #define        RECVSENT        4       /* input message cmd sent */
        !           123: #define        RECVDATASENT    5       /* input data cmd sent */
        !           124: #define        XMITSENT        6       /* transmit message cmd sent */
        !           125: #define        XMITDATASENT    7       /* transmit data cmd sent */
        !           126: #define        WAITING         8       /* waiting for messages */
        !           127: #define        CLEARSENT       9       /* clear wait for message cmd sent */
        !           128: #define MARKPORT       10      /* mark this host's adapter port down issued */
        !           129: #define RSTATSENT      11      /* read statistics cmd sent to adapter */
        !           130: 
        !           131: #ifdef DEBUG
        !           132: char *hy_state_names[] = {
        !           133:        "Startup",
        !           134:        "Idle",
        !           135:        "Status Sent",
        !           136:        "End op Sent",
        !           137:        "Recieve Message Proper Sent",
        !           138:        "Recieve Data Sent",
        !           139:        "Transmit Message Proper Sent",
        !           140:        "Transmit Data Sent",
        !           141:        "Wait for Message Sent",
        !           142:        "Clear Wait for Message Sent",
        !           143:        "Mark Port Down Sent",
        !           144:        "Read Statistics Sent"
        !           145: };
        !           146: #endif
        !           147: 
        !           148: #define SCANINTERVAL   10      /* seconds */
        !           149: #define MAXINTERVAL    20      /* seconds (max action) */
        !           150: 
        !           151: /*
        !           152:  * Cause a device interrupt.  This code uses a buffer starting at
        !           153:  * location zero on the unibus (which is already mapped by the
        !           154:  * autoconfigure code in the kernel).
        !           155:  */
        !           156: hyprobe(reg)
        !           157:        caddr_t reg;
        !           158: {
        !           159:        register int br, cvec;          /* r11, r10 value-result */
        !           160:        register struct hydevice *addr = (struct hydevice *) reg;
        !           161: 
        !           162: #ifdef lint
        !           163:        br = 0; cvec = br; br = cvec;
        !           164:        hyint(0);
        !           165: #endif
        !           166:        /*
        !           167:         * request adapter status to a buffer starting at unibus location 0
        !           168:         */
        !           169:        addr->hyd_bar = 0;
        !           170:        addr->hyd_wcr = -((sizeof(struct hy_status) + 1) >> 1);
        !           171:        addr->hyd_dbuf = HYF_STATUS;
        !           172: #ifdef PI13
        !           173:        addr->hyd_csr |= S_GO | S_IE | S_IATTN;
        !           174: #else
        !           175:        addr->hyd_csr |= S_GO | S_IE;
        !           176: #endif
        !           177:        DELAY(10000);
        !           178: #ifdef PI13
        !           179:        addr->hyd_csr |= S_CLRINT;      /* clear any stacked interrupts */
        !           180: #endif
        !           181:        addr->hyd_csr &= ~(S_IE | S_CLRINT);    /* disable further interrupts */
        !           182:        return(1);
        !           183: }
        !           184: 
        !           185: /*
        !           186:  * Interface exists: make available by filling in network interface
        !           187:  * record.  System will initialize the interface when it is ready
        !           188:  * to accept packets.
        !           189:  */
        !           190: hyattach(ui)
        !           191:        struct uba_device *ui;
        !           192: {
        !           193:        register struct hy_softc *is = &hy_softc[ui->ui_unit];
        !           194:        register struct ifnet *ifp = &is->hy_if;
        !           195: 
        !           196:        ifp->if_unit = ui->ui_unit;
        !           197:        ifp->if_name = "hy";
        !           198:        ifp->if_mtu = HYMTU;
        !           199:        is->hy_state = STARTUP;         /* don't allow state transitions yet */
        !           200:        ifp->if_init = hyinit;
        !           201:        ifp->if_ioctl = hyioctl;
        !           202:        ifp->if_output = hyoutput;
        !           203:        ifp->if_reset = hyreset;
        !           204:        ifp->if_watchdog = hywatch;
        !           205:        ifp->if_timer = SCANINTERVAL;
        !           206:        is->hy_ifuba.ifu_flags = UBA_CANTWAIT;
        !           207: #ifdef notdef
        !           208:        is->hy_ifuba.ifu_flags |= UBA_NEEDBDP;
        !           209: #endif
        !           210:        if_attach(ifp);
        !           211: }
        !           212: 
        !           213: /*
        !           214:  * Reset of interface after UNIBUS reset.
        !           215:  * If interface is on specified uba, reset its state.
        !           216:  */
        !           217: hyreset(unit, uban)
        !           218:        int unit, uban;
        !           219: {
        !           220:        register struct uba_device *ui = hyinfo[unit];
        !           221: 
        !           222:        if (unit >= NHY || ui == 0 || ui->ui_alive == 0 ||
        !           223:          ui->ui_ubanum != uban)
        !           224:                return;
        !           225:        printf(" hy%d", unit);
        !           226:        hyinit(unit);
        !           227: }
        !           228: 
        !           229: /*
        !           230:  * Initialization of interface; clear recorded pending
        !           231:  * operations, and reinitialize UNIBUS usage.
        !           232:  */
        !           233: hyinit(unit)
        !           234:        int unit;
        !           235: {
        !           236:        register struct hy_softc *is = &hy_softc[unit];
        !           237:        register struct uba_device *ui = hyinfo[unit];
        !           238:        struct sockaddr_in *sin;
        !           239:        int s;
        !           240: 
        !           241:        sin = (struct sockaddr_in *)&is->hy_if.if_addr;
        !           242:        if (in_netof(sin->sin_addr) == 0)
        !           243:                return;
        !           244:        if (if_ubainit(&is->hy_ifuba, ui->ui_ubanum,
        !           245:            sizeof (struct hy_hdr), (int)btoc(HYMTU)) == 0) { 
        !           246: #ifdef DEBUG
        !           247:                if (hy_nodebug & 4)
        !           248:                        hy_debug_flag = 1;
        !           249: #endif
        !           250:                printf("hy%d: can't initialize\n", unit);
        !           251:                is->hy_if.if_flags &= ~IFF_UP;
        !           252:                return;
        !           253:        }
        !           254:        is->hy_if.if_flags |= IFF_RUNNING;
        !           255:        /*
        !           256:         * Issue wait for message and start the state machine
        !           257:         */
        !           258:        s = splimp();
        !           259:        is->hy_state = IDLE;
        !           260:        is->hy_flags = RQ_STATUS | RQ_STATISTICS | RQ_MARKUP;
        !           261:        is->hy_retry = 0;
        !           262:        hyact(ui);
        !           263:        splx(s);
        !           264: }
        !           265: 
        !           266: /*
        !           267:  * Issue a command to the adapter
        !           268:  */
        !           269: hystart(ui, cmd, count, ubaddr)
        !           270:        struct uba_device *ui;
        !           271:        int cmd, count, ubaddr;
        !           272: {
        !           273:        register struct hy_softc *is = &hy_softc[ui->ui_unit];
        !           274:        register struct hydevice *addr = (struct hydevice *)ui->ui_addr;
        !           275: 
        !           276: #ifdef DEBUG
        !           277:        printD("hy%d: hystart cmd = 0x%x count=%d ubaddr=0x%x\n",
        !           278:                ui->ui_unit, cmd, count, ubaddr);
        !           279:        printD("hy%d: - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n",
        !           280:                ui->ui_unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar,
        !           281:                addr->hyd_wcr);
        !           282: #endif
        !           283:        if (((is->hy_flags & RQ_REISSUE) == 0) &&
        !           284:          (cmd != HYF_STATUS) && (cmd != HYF_END_OP) && (cmd != HYF_RSTATS)) {
        !           285:                is->hy_savedstate = is->hy_state;
        !           286:                is->hy_savedcmd = cmd;
        !           287:                is->hy_savedcount = count;
        !           288:                is->hy_savedaddr = ubaddr;
        !           289:        }
        !           290:        addr->hyd_bar = ubaddr & 0xffff;
        !           291:        addr->hyd_wcr = is->hy_lastwcr = -((count+1) >> 1);
        !           292:        addr->hyd_dbuf = cmd;
        !           293: #ifdef PI13
        !           294:        addr->hyd_csr = ((ubaddr >> XBASHIFT) & S_XBA) | S_GO | S_IE | S_IATTN;
        !           295: #else
        !           296:        addr->hyd_csr = ((ubaddr >> XBASHIFT) & S_XBA) | S_GO | S_IE;
        !           297: #endif
        !           298: #ifdef DEBUG
        !           299:        printD("hy%d: exit hystart - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n",
        !           300:                ui->ui_unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar,
        !           301:                addr->hyd_wcr);
        !           302: #endif
        !           303: #ifdef HYLOG
        !           304:        {
        !           305:                struct {
        !           306:                        u_char  hcmd;
        !           307:                        u_char  hstate;
        !           308:                        short   hcount;
        !           309:                } hcl;
        !           310: 
        !           311:                hcl.hcmd = cmd;
        !           312:                hcl.hstate = is->hy_state;
        !           313:                hcl.hcount = count;
        !           314:                hylog(HYL_CMD, sizeof(hcl), (char *)&hcl);
        !           315:        }
        !           316: #endif
        !           317:        is->hy_ntime = 0;
        !           318: }
        !           319: 
        !           320: int hyint_active = 0;          /* set during hy interrupt */
        !           321: /*
        !           322:  * Hyperchannel interface interrupt.
        !           323:  *
        !           324:  * An interrupt can occur for many reasons.  Examine the status of
        !           325:  * the hyperchannel status bits to determine what to do next.
        !           326:  *
        !           327:  * If input error just drop packet.
        !           328:  * Otherwise purge input buffered data path and examine 
        !           329:  * packet to determine type.  Othewise decapsulate
        !           330:  * packet based on type and pass to type specific higher-level
        !           331:  * input routine.
        !           332:  */
        !           333: hyint(unit)
        !           334:        int unit;
        !           335: {
        !           336:        register struct hy_softc *is = &hy_softc[unit];
        !           337:        register struct uba_device *ui = hyinfo[unit];
        !           338:        register struct hydevice *addr = (struct hydevice *)ui->ui_addr;
        !           339: 
        !           340:        if (hyint_active)
        !           341:                panic("RECURSIVE HYPERCHANNEL INTERRUPT");
        !           342:        hyint_active++;
        !           343: #ifdef DEBUG
        !           344:        printD("hy%d: hyint enter - csr = 0x%b, bar = 0x%x, wcr = 0x%x\n",
        !           345:                unit, addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar, addr->hyd_wcr);
        !           346: #endif
        !           347: #ifdef HYLOG
        !           348: logit:
        !           349:        {
        !           350:                struct {
        !           351:                        u_char  hstate;
        !           352:                        u_char  hflags;
        !           353:                        short   hcsr;
        !           354:                        short   hwcr;
        !           355:                } hil;
        !           356:                hil.hstate = is->hy_state;
        !           357:                hil.hflags = is->hy_flags;
        !           358:                hil.hcsr = addr->hyd_csr;
        !           359:                hil.hwcr = addr->hyd_wcr;
        !           360:                hylog(HYL_INT, sizeof(hil), (char *)&hil);
        !           361:        }
        !           362: #endif
        !           363:        if (HYS_ERROR(addr) && ((addr->hyd_csr & S_ATTN) == 0)) {
        !           364:                /*
        !           365:                 * Error bit set, some sort of error in the interface.
        !           366:                 *
        !           367:                 * The adapter sets attn on command completion so that's not
        !           368:                 * a real error even though the interface considers it one.
        !           369:                 */
        !           370: #ifdef DEBUG
        !           371:                if (hy_nodebug & 4)
        !           372:                        hy_debug_flag = 1;
        !           373: #endif
        !           374:                printf("csr = 0x%b\nbar = 0x%x\nwcr = 0x%x\n",
        !           375:                        addr->hyd_csr, HY_CSR_BITS, addr->hyd_bar,
        !           376:                        addr->hyd_wcr);
        !           377:                if (addr->hyd_csr & S_NEX) {
        !           378:                        printf("hy%d: NEX - Non Existant Memory\n", unit);
        !           379: #ifdef PI13
        !           380:                        addr->hyd_csr |= S_NEX;  /* as per PI13 manual */
        !           381: #else
        !           382:                        addr->hyd_csr &= ~S_NEX;
        !           383: #endif
        !           384:                        hycancel(ui);
        !           385: #ifdef PI13
        !           386:                } else if (addr->hyd_csr & S_POWEROFF) {
        !           387:                        printf("hy%d: Power Off bit set, trying to reset\n",
        !           388:                                unit);
        !           389:                        addr->hyd_csr |= S_POWEROFF;
        !           390:                        DELAY(100);
        !           391:                        if (addr->hyd_csr & S_POWEROFF) {
        !           392:                                if_down(&is->hy_if);
        !           393:                                is->hy_state = STARTUP;
        !           394:                                printf(
        !           395:                                  "hy%d: Power Off Error, network shutdown\n",
        !           396:                                  unit);
        !           397:                        }
        !           398: #endif
        !           399:                } else {
        !           400:                        printf("hy%d:  BAR overflow\n", unit);
        !           401:                        hycancel(ui);
        !           402:                }
        !           403:        } else if (HYS_NORMAL(addr)) {
        !           404:                /*
        !           405:                 * Normal interrupt, bump state machine unless in state
        !           406:                 * waiting and no data present (assumed to be word count
        !           407:                 * zero interrupt or other hardware botch).
        !           408:                 */
        !           409:                if (is->hy_state != WAITING || HYS_RECVDATA(addr))
        !           410:                        hyact(ui);
        !           411:        } else if (HYS_ABNORMAL(addr)) {
        !           412:                /*
        !           413:                 * Abnormal termination.
        !           414:                 * bump error counts, retry the last function
        !           415:                 * 'MAXRETRY' times before kicking the bucket.
        !           416:                 *
        !           417:                 * Don't reissue the cmd if in certain states, abnormal
        !           418:                 * on a reissued cmd or max retry exceeded.
        !           419:                 */
        !           420: #ifdef HYLOG
        !           421:                if (hy_log.hyl_enable != hy_log.hyl_onerr) {
        !           422:                        hy_log.hyl_enable = hy_log.hyl_onerr;
        !           423:                        goto logit;
        !           424:                }
        !           425: #endif
        !           426: #ifdef DEBUG
        !           427:                if (hy_nodebug & 4)
        !           428:                        hy_debug_flag = 1;
        !           429:                printD("hy%d: abnormal interrupt, driver state \"%s\" (%d)\n",
        !           430:                        unit, hy_state_names[is->hy_state], is->hy_state);
        !           431:                printD("\tflags 0x%x ilen %d olen %d lastwcr %d retry %d\n",
        !           432:                        is->hy_flags, is->hy_ilen, is->hy_olen,
        !           433:                        is->hy_lastwcr, is->hy_retry);
        !           434:                printD("\tsaved: state %d count %d cmd 0x%x ptr 0x%x\n",
        !           435:                        is->hy_savedstate, is->hy_savedcount,
        !           436:                        is->hy_savedaddr, is->hy_savedcmd);
        !           437: #endif
        !           438: #ifdef PI13
        !           439:                addr->hyd_csr &= ~S_C;  /* clear the damned PI-13 */
        !           440: #endif
        !           441:                if (is->hy_state == XMITSENT || is->hy_state == XMITDATASENT)
        !           442:                        is->hy_if.if_oerrors++;
        !           443:                if (is->hy_state == RECVSENT || is->hy_state == RECVDATASENT)
        !           444:                        is->hy_if.if_ierrors++;
        !           445:                if (is->hy_state == XMITDATASENT ||
        !           446:                    is->hy_state == RECVSENT ||
        !           447:                    is->hy_state == RECVDATASENT ||
        !           448:                    (is->hy_flags & RQ_REISSUE) != 0 || is->hy_retry > MAXRETRY)
        !           449:                        hycancel(ui);
        !           450:                else {
        !           451: #ifdef DEBUG
        !           452:                        if (hy_nodebug & 2)
        !           453:                                hy_debug_flag = 1;
        !           454: #endif
        !           455:                        is->hy_retry++;
        !           456:                        is->hy_flags |= RQ_ENDOP | RQ_STATUS | RQ_REISSUE;
        !           457:                        is->hy_state = IDLE;
        !           458:                        hyact(ui);
        !           459:                }
        !           460:        } else {
        !           461:                /*
        !           462:                 * Interrupt is neither normal, abnormal, or interface error.
        !           463:                 * Ignore it. It's either stacked or a word count 0.
        !           464:                 */
        !           465: #ifdef HYLOG
        !           466:                if (hy_log.hyl_enable != hy_log.hyl_onerr) {
        !           467:                        hy_log.hyl_enable = hy_log.hyl_onerr;
        !           468:                        goto logit;
        !           469:                }
        !           470: #endif
        !           471: #ifdef DEBUG
        !           472:                printD("hy%d: possible stacked interrupt ignored\n", unit);
        !           473: #endif
        !           474:        }
        !           475: #ifdef DEBUG
        !           476:        printD("hy%d: hyint exit\n\n", unit);
        !           477: #endif
        !           478:        hyint_active = 0;
        !           479: 
        !           480: }
        !           481: 
        !           482: /*
        !           483:  * Encapsulate a packet of type family for the local net.
        !           484:  */
        !           485: hyoutput(ifp, m0, dst)
        !           486:        struct ifnet *ifp;
        !           487:        struct mbuf *m0;
        !           488:        struct sockaddr *dst;
        !           489: {
        !           490:        register struct hym_hdr *hym;
        !           491:        register struct mbuf *m;
        !           492: #ifdef HYROUTE
        !           493:        register struct hyroute *r = &hy_route[ifp->if_unit];
        !           494: #endif
        !           495:        short dtype;            /* packet type */
        !           496:        int dhost;              /* destination adapter address */
        !           497:        int dlen;
        !           498:        int mplen = 0;          /* message proper length */
        !           499:        short loopback = 0;     /* hardware loopback requested */
        !           500:        int error = 0;
        !           501:        int s;
        !           502: 
        !           503: #ifdef DEBUG
        !           504:        if (hy_nodebug & 8)
        !           505:                hy_debug_flag = 1;
        !           506: #endif
        !           507:        dlen = 0;
        !           508:        for (m = m0; m; m = m->m_next)
        !           509:                dlen += m->m_len;
        !           510:        m = m0;
        !           511:        switch(dst->sa_family) {
        !           512: 
        !           513: #ifdef INET
        !           514:        case AF_INET: {
        !           515:                register struct ip *ip = mtod(m, struct ip *);
        !           516:                register struct sockaddr_in *sin = (struct sockaddr_in *)dst;
        !           517:                register long hostaddr = in_lnaof(sin->sin_addr);
        !           518: 
        !           519:                dhost = hostaddr & 0xffff;
        !           520:                dtype = HYLINK_IP;
        !           521: #ifdef DEBUG
        !           522:                printD("hy%d: output to host %x, dhost %x\n",
        !           523:                        ifp->if_unit, sin->sin_addr.s_addr, dhost);
        !           524: #endif
        !           525:                /*
        !           526:                 * Debugging loopback support:
        !           527:                 * upper byte of 24 bit host number interpreted as follows
        !           528:                 *      0x00 --> no loopback
        !           529:                 *      0x01 --> hardware loop through remote adapter
        !           530:                 *      other --> software loop through remote ip layer
        !           531:                 */
        !           532:                if (hostaddr & 0xff0000) {
        !           533:                        struct in_addr temp;
        !           534: 
        !           535:                        temp = ip->ip_dst;
        !           536:                        ip->ip_dst = ip->ip_src;
        !           537:                        ip->ip_src = temp;
        !           538:                        if ((hostaddr & 0xff0000) == 0x10000)
        !           539:                                loopback = H_LOOPBK;
        !           540:                }
        !           541:                /*
        !           542:                 * If entire packet won't fit in message proper, just
        !           543:                 * send hyperchannel hardware header and ip header in
        !           544:                 * message proper.  If that won't fit either, just send
        !           545:                 * the maximum message proper.
        !           546:                 *
        !           547:                 * This insures that the associated data is at least a
        !           548:                 * TCP/UDP header in length and thus prevents potential
        !           549:                 * problems with very short word counts.
        !           550:                 */
        !           551:                if (dlen > MPSIZE - sizeof (struct hy_hdr)) {
        !           552:                        mplen = sizeof(struct hy_hdr) + (ip->ip_hl << 2);
        !           553:                        if (mplen > MPSIZE)
        !           554:                                mplen = MPSIZE;
        !           555:                }
        !           556:                break;
        !           557:        }
        !           558: #endif
        !           559: 
        !           560:        default:
        !           561:                printf("hy%d: can't handle af%d\n", ifp->if_unit,
        !           562:                        dst->sa_family);
        !           563: #ifdef DEBUG
        !           564:                if (hy_nodebug & 4)
        !           565:                        hy_debug_flag = 1;
        !           566: #endif
        !           567:                error = EAFNOSUPPORT;
        !           568:                goto drop;
        !           569:        }
        !           570: 
        !           571:        /*
        !           572:         * Add the software and hardware hyperchannel headers.
        !           573:         * If there's not enough space in the first mbuf, allocate another.
        !           574:         * If that should fail, drop this sucker.
        !           575:         * No extra space for headers is allocated.
        !           576:         */
        !           577:        if (m->m_off > MMAXOFF ||
        !           578:            MMINOFF + sizeof(struct hym_hdr) > m->m_off) {
        !           579:                m = m_get(M_DONTWAIT, MT_HEADER);
        !           580:                if (m == 0) {
        !           581:                        m = m0;
        !           582:                        error = ENOBUFS;
        !           583:                        goto drop;
        !           584:                }
        !           585:                m->m_next = m0;
        !           586:                m->m_off = MMINOFF;
        !           587:                m->m_len = sizeof(struct hym_hdr);
        !           588:        } else {
        !           589:                m->m_off -= sizeof(struct hym_hdr);
        !           590:                m->m_len += sizeof(struct hym_hdr);
        !           591:        }
        !           592:        hym = mtod(m, struct hym_hdr *);
        !           593:        hym->hym_mplen = mplen;
        !           594:        hym->hym_hdr.hyh_type = dtype;
        !           595:        hym->hym_hdr.hyh_off = 0;
        !           596:        hym->hym_hdr.hyh_from = htons((u_short)ifp->if_host[0]);
        !           597:        hym->hym_hdr.hyh_param = loopback;
        !           598: #ifdef HYROUTE
        !           599:        if (r->hyr_lasttime.tv_sec != 0) {
        !           600:                register struct hy_hash *rh;
        !           601:                register int i;
        !           602: 
        !           603:                i = HYRHASH(dhost);
        !           604:                rh = &r->hyr_hash[i];
        !           605:                i = 0;
        !           606:                while (rh->hyr_key != dhost) {
        !           607:                        rh++; i++;
        !           608:                        if (rh > &r->hyr_hash[HYRSIZE])
        !           609:                                rh = &r->hyr_hash[0];
        !           610:                        if (rh->hyr_flags == 0 || i > HYRSIZE)
        !           611:                                goto notfound;
        !           612:                }
        !           613:                if (rh->hyr_flags & HYR_GATE) {
        !           614:                        loopback = 0;   /* no hardware loopback on gateways */
        !           615:                        i = rh->hyr_nextgate;
        !           616:                        if (i >= rh->hyr_egate)
        !           617:                                rh->hyr_nextgate = rh->hyr_pgate;
        !           618:                        else
        !           619:                                rh->hyr_nextgate++;
        !           620:                        rh = &r->hyr_hash[r->hyr_gateway[i]];
        !           621:                        if ((rh->hyr_flags & HYR_DIR) == 0)
        !           622:                                goto notfound;
        !           623:                }
        !           624:                hym->hym_hdr.hyh_ctl = rh->hyr_ctl;
        !           625:                hym->hym_hdr.hyh_access = rh->hyr_access;
        !           626:                hym->hym_hdr.hyh_to = rh->hyr_dst;
        !           627:        } else {
        !           628:                hym->hym_hdr.hyh_ctl = H_XTRUNKS | H_RTRUNKS;
        !           629:                hym->hym_hdr.hyh_access = 0;
        !           630:                hym->hym_hdr.hyh_to = htons((u_short)dhost);
        !           631:        }
        !           632: #else
        !           633:        hym->hym_hdr.hyh_ctl = H_XTRUNKS | H_RTRUNKS;
        !           634:        hym->hym_hdr.hyh_access = 0;
        !           635:        hym->hym_hdr.hyh_to = htons(dhost);
        !           636: #endif
        !           637: 
        !           638:        if (hym->hym_mplen) {
        !           639:                hym->hym_hdr.hyh_ctl |= H_ASSOC;
        !           640: #ifdef DEBUG
        !           641:                if (hy_nodebug & 16)
        !           642:                        hy_debug_flag = 1;
        !           643: #endif
        !           644:        } else
        !           645:                hym->hym_hdr.hyh_ctl &= ~H_ASSOC;
        !           646: #ifdef DEBUG
        !           647:        printD("hy%d: output mplen=%x ctl=%x access=%x to=%x",
        !           648:                ifp->if_unit, hym->hym_mplen, hym->hym_hdr.hyh_ctl,
        !           649:                hym->hym_hdr.hyh_access, hym->hym_hdr.hyh_to);
        !           650:        printD(" (adapter %x) from=%x param=%x type=%x off=%x\n",
        !           651:                hym->hym_hdr.hyh_to_adapter,
        !           652:                hym->hym_hdr.hyh_from, hym->hym_hdr.hyh_param,
        !           653:                hym->hym_hdr.hyh_type, hym->hym_hdr.hyh_off);
        !           654: #endif
        !           655:        s = splimp();
        !           656:        if (IF_QFULL(&ifp->if_snd)) {
        !           657:                IF_DROP(&ifp->if_snd);
        !           658:                error = ENOBUFS;
        !           659:                splx(s);
        !           660:                goto drop;
        !           661:        }
        !           662:        IF_ENQUEUE(&ifp->if_snd, m);
        !           663:        if (hy_softc[ifp->if_unit].hy_state == WAITING)
        !           664:                hyact(hyinfo[ifp->if_unit]);
        !           665:        splx(s);
        !           666:        return (0);
        !           667: notfound:
        !           668:        error = ENETUNREACH;                    /* XXX */
        !           669: drop:
        !           670:        m_freem(m);
        !           671:        return (error);
        !           672: }
        !           673: 
        !           674: hyact(ui)
        !           675:        register struct uba_device *ui;
        !           676: {
        !           677:        register struct hy_softc *is = &hy_softc[ui->ui_unit];
        !           678:        register struct hydevice *addr = (struct hydevice *)ui->ui_addr;
        !           679: 
        !           680: actloop:
        !           681: #ifdef DEBUG
        !           682:        printD("hy%d: hyact, enter state \"%s\"\n", ui->ui_unit,
        !           683:                hy_state_names[is->hy_state]);
        !           684: #endif
        !           685:        switch (is->hy_state) {
        !           686: 
        !           687:        case STARTUP:
        !           688:                goto endintr;
        !           689: 
        !           690:        case IDLE: {
        !           691:                register rq = is->hy_flags;
        !           692: 
        !           693:                if (rq & RQ_STATUS) {
        !           694:                        is->hy_flags &= ~RQ_STATUS;
        !           695:                        is->hy_state = STATSENT;
        !           696:                        hystart(ui, HYF_STATUS, sizeof (is->hy_status),
        !           697:                            is->hy_ifuba.ifu_r.ifrw_info);
        !           698:                } else if (rq & RQ_ENDOP) {
        !           699:                        is->hy_flags &= ~RQ_ENDOP;
        !           700:                        is->hy_state = ENDOPSENT;
        !           701:                        hystart(ui, HYF_END_OP, 0, 0);
        !           702:                } else if (rq & RQ_STATISTICS) {
        !           703:                        is->hy_flags &= ~RQ_STATISTICS;
        !           704:                        is->hy_state = RSTATSENT;
        !           705:                        hystart(ui, HYF_RSTATS, sizeof (is->hy_stat),
        !           706:                            is->hy_ifuba.ifu_r.ifrw_info);
        !           707:                } else if (HYS_RECVDATA(addr)) {
        !           708:                        is->hy_state = RECVSENT;
        !           709:                        is->hy_retry = 0;
        !           710:                        hystart(ui, HYF_INPUTMSG, MPSIZE,
        !           711:                            is->hy_ifuba.ifu_r.ifrw_info);
        !           712:                } else if (rq & RQ_REISSUE) {
        !           713:                        is->hy_flags &= ~RQ_REISSUE;
        !           714:                        is->hy_state = is->hy_savedstate;
        !           715: #ifdef DEBUG
        !           716:                        printD("hy%d: reissue cmd=0x%x count=%d",
        !           717:                          ui->ui_unit, is->hy_savedcmd, is->hy_savedcount);
        !           718:                        printD(" ubaddr=0x%x retry=%d\n",
        !           719:                          is->hy_savedaddr, is->hy_retry);
        !           720: #endif
        !           721:                        hystart(ui, is->hy_savedcmd, is->hy_savedcount,
        !           722:                            is->hy_savedaddr);
        !           723:                } else {
        !           724:                        register struct mbuf *m;
        !           725: 
        !           726:                        IF_DEQUEUE(&is->hy_if.if_snd, m);
        !           727:                        if (m != NULL) {
        !           728:                                register struct hym_hdr *hym;
        !           729:                                register int mplen;
        !           730:                                register int cmd;
        !           731: 
        !           732:                                is->hy_state = XMITSENT;
        !           733:                                is->hy_retry = 0;
        !           734:                                hym = mtod(m, struct hym_hdr *);
        !           735: #ifdef HYLOG
        !           736:                                hylog(HYL_XMIT, sizeof(struct hym_hdr),
        !           737:                                    (char *)hym);
        !           738: #endif
        !           739:                                mplen = hym->hym_mplen;
        !           740:                                if (hym->hym_hdr.hyh_to_adapter ==
        !           741:                                    hym->hym_hdr.hyh_from_adapter)
        !           742:                                        cmd = HYF_XMITLOCMSG;
        !           743:                                else
        !           744:                                        cmd = HYF_XMITMSG;
        !           745: #ifdef DEBUG
        !           746:                                printD("hy%d: hym_hdr = ", ui->ui_unit);
        !           747:                                if (hy_debug_flag)
        !           748:                                        hyprintdata((char *)hym,
        !           749:                                            sizeof (struct hym_hdr));
        !           750: #endif
        !           751:                                /*
        !           752:                                 * Strip off the software part of
        !           753:                                 * the hyperchannel header
        !           754:                                 */
        !           755:                                m->m_off += sizeof(struct hym_data);
        !           756:                                m->m_len -= sizeof(struct hym_data);
        !           757:                                is->hy_olen = if_wubaput(&is->hy_ifuba, m);
        !           758:                                if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP)
        !           759:                                        UBAPURGE(is->hy_ifuba.ifu_uba,
        !           760:                                                is->hy_ifuba.ifu_w.ifrw_bdp);
        !           761: #ifdef DEBUG
        !           762:                                printD(
        !           763:                "hy%d: sending packet (mplen = %d, hy_olen = %d) data = ",
        !           764:                                        ui->ui_unit, mplen, is->hy_olen);
        !           765:                                if (hy_debug_flag)
        !           766:                                        hyprintdata(
        !           767:                                            is->hy_ifuba.ifu_w.ifrw_addr,
        !           768:                                            is->hy_olen);
        !           769: #endif
        !           770:                                hystart(ui, cmd,
        !           771:                                    (mplen == 0) ? is->hy_olen : mplen,
        !           772:                                    is->hy_ifuba.ifu_w.ifrw_info);
        !           773:                                if (mplen != 0)
        !           774:                                        is->hy_flags |= RQ_XASSOC;
        !           775:                        } else if (rq & RQ_MARKDOWN) {
        !           776:                                is->hy_flags &= ~(RQ_MARKUP | RQ_MARKDOWN);
        !           777:                                is->hy_state = MARKPORT;
        !           778:                                is->hy_retry = 0;
        !           779:                                /*
        !           780:                                 * Port number is taken from status data
        !           781:                                 */
        !           782:                                hystart(ui,
        !           783:                                 (int)(HYF_MARKP0|(PORTNUM(&is->hy_status)<<2)),
        !           784:                                 0, 0);
        !           785:                        } else if (rq & RQ_MARKUP) {
        !           786:                                register struct ifnet *ifp = &is->hy_if;
        !           787:                                register struct sockaddr_in *sin =
        !           788:                                   (struct sockaddr_in *)&ifp->if_addr;
        !           789: 
        !           790:                                is->hy_flags &= ~RQ_MARKUP;
        !           791:                                is->hy_retry = 0;
        !           792:                                /*
        !           793:                                 * Fill in the host number
        !           794:                                 * from the status buffer
        !           795:                                 */
        !           796:                                printf(
        !           797:        "hy%d: unit number 0x%x port %d type %x microcode level 0x%x\n",
        !           798:                                        ui->ui_unit,
        !           799:                                        is->hy_stat.hyc_uaddr,
        !           800:                                        PORTNUM(&is->hy_status),
        !           801:                                        (is->hy_stat.hyc_atype[0]<<8) |
        !           802:                                                is->hy_stat.hyc_atype[1],
        !           803:                                        is->hy_stat.hyc_atype[2]);
        !           804: 
        !           805:                                ifp->if_host[0] =
        !           806:                                  (is->hy_stat.hyc_uaddr << 8) |
        !           807:                                        PORTNUM(&is->hy_status);
        !           808:                                sin->sin_addr =
        !           809:                                   if_makeaddr(ifp->if_net, ifp->if_host[0]);
        !           810:                                ifp->if_flags |= IFF_UP;
        !           811:                                if_rtinit(ifp, RTF_UP);
        !           812: #ifdef HYLOG
        !           813:                                hylog(HYL_UP, 0, (char *)0);
        !           814: #endif
        !           815:                        } else {
        !           816:                                is->hy_state = WAITING;
        !           817:                                is->hy_retry = 0;
        !           818:                                hystart(ui, HYF_WAITFORMSG, 0, 0);
        !           819:                        }
        !           820:                }
        !           821:                break;
        !           822:        }
        !           823: 
        !           824:        case STATSENT:
        !           825:                bcopy(is->hy_ifuba.ifu_r.ifrw_addr, (caddr_t)&is->hy_status,
        !           826:                  sizeof (struct hy_status));
        !           827: #ifdef DEBUG
        !           828:                printD("hy%d: status - %x %x %x %x %x %x %x %x\n",
        !           829:                        ui->ui_unit, is->hy_status.hys_gen_status,
        !           830:                        is->hy_status.hys_last_fcn,
        !           831:                        is->hy_status.hys_resp_trunk,
        !           832:                        is->hy_status.hys_status_trunk,
        !           833:                        is->hy_status.hys_recd_resp,
        !           834:                        is->hy_status.hys_error,
        !           835:                        is->hy_status.hys_caddr,
        !           836:                        is->hy_status.hys_pad);
        !           837: #endif
        !           838:                is->hy_state = IDLE;
        !           839: #ifdef HYLOG
        !           840:                hylog(HYL_STATUS, sizeof (struct hy_status),
        !           841:                        (char *)&is->hy_status);
        !           842: #endif
        !           843: #ifdef HYELOG
        !           844:                {
        !           845:                        register int i;
        !           846:                        
        !           847:                        i = is->hy_status.hys_error;
        !           848:                        if (i < HYE_MAX)
        !           849:                                i = HYE_MAX;
        !           850:                        switch (is->hy_status.hys_last_fcn) {
        !           851:                                case HYF_XMITLOCMSG:
        !           852:                                        i += HYE_MAX+1; /* fall through */
        !           853:                                case HYF_XMITLSTDATA:
        !           854:                                        i += HYE_MAX+1; /* fall through */
        !           855:                                case HYF_XMITMSG:
        !           856:                                        i += HYE_MAX+1;
        !           857:                        }
        !           858:                        hy_elog[i]++;
        !           859:                }
        !           860: #endif
        !           861:                break;
        !           862: 
        !           863:        case RSTATSENT: {
        !           864:                register struct hy_stat *p =
        !           865:                        (struct hy_stat *)is->hy_ifuba.ifu_r.ifrw_addr;
        !           866: 
        !           867:                is->hy_stat.hyc_msgcnt = ntohl(p->hyc_msgcnt);
        !           868:                is->hy_stat.hyc_dbcnt = ntohl(p->hyc_dbcnt);
        !           869:                is->hy_stat.hyc_tbusy = ntohl(p->hyc_tbusy);
        !           870:                is->hy_stat.hyc_hwret = ntohl(p->hyc_hwret);
        !           871:                is->hy_stat.hyc_crcbad = ntohl(p->hyc_crcbad);
        !           872:                is->hy_stat.hyc_mcret = ntohl(p->hyc_mcret);
        !           873:                is->hy_stat.hyc_tdabort = ntohl(p->hyc_tdabort);
        !           874:                is->hy_stat.hyc_atype[0] = p->hyc_atype[0];
        !           875:                is->hy_stat.hyc_atype[1] = p->hyc_atype[1];
        !           876:                is->hy_stat.hyc_atype[2] = p->hyc_atype[2];
        !           877:                is->hy_stat.hyc_uaddr = p->hyc_uaddr;
        !           878: #ifdef DEBUG
        !           879:                printD(
        !           880:        "hy%d: statistics - msgcnt %d dbcnt %d hwret %d tbusy %d crcbad %d\n",
        !           881:                        ui->ui_unit,
        !           882:                        is->hy_stat.hyc_msgcnt, is->hy_stat.hyc_dbcnt,
        !           883:                        is->hy_stat.hyc_tbusy, is->hy_stat.hyc_hwret,
        !           884:                        is->hy_stat.hyc_crcbad);
        !           885:                printD("        mcret %d tdabort %d atype %x %x %x uaddr %x\n",
        !           886:                        is->hy_stat.hyc_mcret, is->hy_stat.hyc_tdabort,
        !           887:                        is->hy_stat.hyc_atype[0], is->hy_stat.hyc_atype[1],
        !           888:                        is->hy_stat.hyc_atype[2], is->hy_stat.hyc_uaddr);
        !           889: #endif
        !           890:                is->hy_state = IDLE;
        !           891: #ifdef HYLOG
        !           892:                hylog(HYL_STATISTICS, sizeof (struct hy_stat),
        !           893:                        (char *)&is->hy_stat);
        !           894: #endif
        !           895:                break;
        !           896:        }
        !           897: 
        !           898:        case CLEARSENT:
        !           899:                is->hy_state = IDLE;
        !           900:                break;
        !           901: 
        !           902:        case ENDOPSENT:
        !           903:                is->hy_state = IDLE;
        !           904:                break;
        !           905: 
        !           906:        case RECVSENT: {
        !           907:                register struct hy_hdr *hyh;
        !           908:                register unsigned len;
        !           909: 
        !           910:                if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP)
        !           911:                        UBAPURGE(is->hy_ifuba.ifu_uba,
        !           912:                            is->hy_ifuba.ifu_r.ifrw_bdp);
        !           913:                hyh = (struct hy_hdr *) (is->hy_ifuba.ifu_r.ifrw_addr);
        !           914:                len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1;
        !           915:                if (len > MPSIZE) {
        !           916:                        printf("hy%d: RECVD MP > MPSIZE (%d)\n",
        !           917:                            ui->ui_unit, len);
        !           918: #ifdef DEBUG
        !           919:                        hy_debug_flag = 1;
        !           920:                        printD("hy%d: csr = 0x%b, bar = 0x%x, wcr = 0x%x\n",
        !           921:                                ui->ui_unit, addr->hyd_csr, HY_CSR_BITS,
        !           922:                                addr->hyd_bar, addr->hyd_wcr);
        !           923: #endif
        !           924:                }
        !           925: #ifdef DEBUG
        !           926:                printD("hy%d: recvd mp, len = %d, data = ", ui->ui_unit, len);
        !           927:                if (hy_debug_flag)
        !           928:                        hyprintdata((char *)hyh, len);
        !           929: #endif
        !           930:                if (hyh->hyh_ctl & H_ASSOC) {
        !           931:                        is->hy_state = RECVDATASENT;
        !           932:                        is->hy_ilen = len;
        !           933:                        is->hy_retry = 0;
        !           934:                        hystart(ui, HYF_INPUTDATA,
        !           935:                            (int)(HYMTU-len+sizeof (struct hy_hdr)),
        !           936:                            (int)(is->hy_ifuba.ifu_r.ifrw_info + len));
        !           937:                } else {
        !           938:                        hyrecvdata(ui, hyh, (int)len);
        !           939:                        is->hy_state = IDLE;
        !           940:                }
        !           941:                break;
        !           942:        }
        !           943: 
        !           944:        case RECVDATASENT: {
        !           945:                register struct hy_hdr *hyh;
        !           946:                register unsigned len;
        !           947: 
        !           948:                if (is->hy_ifuba.ifu_flags & UBA_NEEDBDP)
        !           949:                        UBAPURGE(is->hy_ifuba.ifu_uba,
        !           950:                            is->hy_ifuba.ifu_r.ifrw_bdp);
        !           951:                hyh = (struct hy_hdr *) (is->hy_ifuba.ifu_r.ifrw_addr);
        !           952:                len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1;
        !           953: #ifdef DEBUG
        !           954:                printD("hy%d: recvd assoc data, len = %d, data = ",
        !           955:                        ui->ui_unit, len);
        !           956:                if (hy_debug_flag)
        !           957:                        hyprintdata((char *)hyh + is->hy_ilen, len);
        !           958: #endif
        !           959:                hyrecvdata(ui, hyh, (int)(len + is->hy_ilen));
        !           960:                is->hy_state = IDLE;
        !           961:                break;
        !           962:        }
        !           963: 
        !           964:        case XMITSENT:
        !           965:                if (is->hy_flags & RQ_XASSOC) {
        !           966:                        register int len;
        !           967: 
        !           968:                        is->hy_flags &= ~RQ_XASSOC;
        !           969:                        is->hy_state = XMITDATASENT;
        !           970:                        is->hy_retry = 0;
        !           971:                        len = (0xffff & (addr->hyd_wcr - is->hy_lastwcr)) << 1;
        !           972:                        if (len > is->hy_olen) {
        !           973:                                printf(
        !           974:                                "hy%d: xmit error - len > hy_olen [%d > %d]\n",
        !           975:                                ui->ui_unit, len, is->hy_olen);
        !           976: #ifdef DEBUG
        !           977:                                hy_debug_flag = 1;
        !           978: #endif
        !           979:                        }
        !           980:                        hystart(ui, HYF_XMITLSTDATA, is->hy_olen - len,
        !           981:                            is->hy_ifuba.ifu_w.ifrw_info + len);
        !           982:                        break;
        !           983:                }
        !           984:                /* fall through to ... */
        !           985:                
        !           986:        case XMITDATASENT:
        !           987:                hyxmitdata(ui);
        !           988:                is->hy_state = IDLE;
        !           989:                break;
        !           990: 
        !           991:        case WAITING:   /* wait for message complete or output requested */
        !           992:                if (HYS_RECVDATA(addr))
        !           993:                        is->hy_state = IDLE;
        !           994:                else {
        !           995:                        is->hy_state = CLEARSENT;
        !           996:                        is->hy_retry = 0;
        !           997:                        hystart(ui, HYF_CLRWFMSG, 0, 0);
        !           998:                }
        !           999:                break;
        !          1000: 
        !          1001:        case MARKPORT:
        !          1002:                is->hy_state = STARTUP;
        !          1003:                is->hy_if.if_flags &= ~IFF_UP;
        !          1004:                goto endintr;
        !          1005:        
        !          1006:        default:
        !          1007:                printf("hy%d: DRIVER BUG - INVALID STATE %d\n",
        !          1008:                        ui->ui_unit, is->hy_state);
        !          1009:                panic("HYPERCHANNEL IN INVALID STATE");
        !          1010:                /*NOTREACHED*/
        !          1011:        }
        !          1012:        if (is->hy_state == IDLE)
        !          1013:                goto actloop;
        !          1014: endintr:
        !          1015:        ;
        !          1016: #ifdef DEBUG
        !          1017:        printD("hy%d: hyact, exit at \"%s\"\n", ui->ui_unit,
        !          1018:                hy_state_names[is->hy_state]);
        !          1019: #endif
        !          1020: }
        !          1021: 
        !          1022: /*
        !          1023:  * Called from device interrupt when receiving data.
        !          1024:  * Examine packet to determine type.  Decapsulate packet
        !          1025:  * based on type and pass to type specific higher-level
        !          1026:  * input routine.
        !          1027:  */
        !          1028: hyrecvdata(ui, hyh, len)
        !          1029:        struct uba_device *ui;
        !          1030:        register struct hy_hdr *hyh;
        !          1031:        int len;
        !          1032: {
        !          1033:        register struct hy_softc *is = &hy_softc[ui->ui_unit];
        !          1034:        struct mbuf *m;
        !          1035:        register struct ifqueue *inq;
        !          1036: 
        !          1037:        is->hy_if.if_ipackets++;
        !          1038: #ifdef DEBUG
        !          1039:        printD("hy%d: recieved packet, len = %d (actual %d)\n",
        !          1040:                ui->ui_unit, len,
        !          1041:                len - (hyh->hyh_off + sizeof (struct hy_hdr)));
        !          1042: #endif
        !          1043: #ifdef HYLOG
        !          1044:        {
        !          1045:                struct {
        !          1046:                        short hlen;
        !          1047:                        struct hy_hdr hhdr;
        !          1048:                } hh;
        !          1049:                hh.hlen = len;
        !          1050:                hh.hhdr = *hyh;
        !          1051:                hylog(HYL_RECV, sizeof(hh), (char *)&hh);
        !          1052:        }
        !          1053: #endif
        !          1054:        if (len > HYMTU + MPSIZE || len == 0)
        !          1055:                return;                 /* sanity */
        !          1056:        /*
        !          1057:         * Pull packet off interface.
        !          1058:         */
        !          1059:        m = if_rubaget(&is->hy_ifuba, len, 0);
        !          1060:        if (m == NULL)
        !          1061:                return;
        !          1062:        switch (hyh->hyh_type) {
        !          1063: 
        !          1064: #ifdef INET
        !          1065:        case HYLINK_IP:
        !          1066:                /*
        !          1067:                 * Strip the variable portion of the hyperchannel header
        !          1068:                 * (fixed portion stripped in if_rubaget).
        !          1069:                 */
        !          1070:                m->m_len -= hyh->hyh_off;
        !          1071:                m->m_off += hyh->hyh_off;
        !          1072:                schednetisr(NETISR_IP);
        !          1073:                inq = &ipintrq;
        !          1074:                break;
        !          1075: #endif
        !          1076:        default:
        !          1077:                m_freem(m);
        !          1078:                return;
        !          1079:        }
        !          1080:        if (IF_QFULL(inq)) {
        !          1081:                IF_DROP(inq);
        !          1082:                m_freem(m);
        !          1083:        } else
        !          1084:                IF_ENQUEUE(inq, m);
        !          1085: }
        !          1086: 
        !          1087: /*
        !          1088:  * Transmit done, release resources, bump counters.
        !          1089:  */
        !          1090: hyxmitdata(ui)
        !          1091:        struct uba_device *ui;
        !          1092: {
        !          1093:        register struct hy_softc *is = &hy_softc[ui->ui_unit];
        !          1094: 
        !          1095:        is->hy_if.if_opackets++;
        !          1096:        if (is->hy_ifuba.ifu_xtofree) {
        !          1097:                m_freem(is->hy_ifuba.ifu_xtofree);
        !          1098:                is->hy_ifuba.ifu_xtofree = 0;
        !          1099:        }
        !          1100: }
        !          1101: 
        !          1102: hycancel(ui)
        !          1103:        register struct uba_device *ui;
        !          1104: {
        !          1105:        register struct hy_softc *is = &hy_softc[ui->ui_unit];
        !          1106: 
        !          1107:        if (is->hy_ifuba.ifu_xtofree) {
        !          1108:                m_freem(is->hy_ifuba.ifu_xtofree);
        !          1109:                is->hy_ifuba.ifu_xtofree = 0;
        !          1110:        }
        !          1111: #ifdef DEBUG
        !          1112:        if (hy_nodebug & 1)
        !          1113:                hy_debug_flag = 1;
        !          1114: #endif
        !          1115: #ifdef DEBUG
        !          1116:        printD("hy%d: cancel from state \"%s\" cmd=0x%x count=%d ptr=0x%x\n",
        !          1117:                ui->ui_unit, hy_state_names[is->hy_state], is->hy_savedcmd,
        !          1118:                is->hy_savedcount, is->hy_savedaddr);
        !          1119:        printD("\tflags 0x%x ilen %d olen %d lastwcr %d retry %d\n",
        !          1120:                is->hy_flags, is->hy_ilen, is->hy_olen, is->hy_lastwcr,
        !          1121:                is->hy_retry);
        !          1122:        printD("\tsaved: state %d count %d ptr 0x%x cmd 0x%x\n",
        !          1123:                is->hy_savedstate, is->hy_savedcount, is->hy_savedaddr,
        !          1124:                is->hy_savedcmd);
        !          1125: #endif
        !          1126:        is->hy_state = IDLE;
        !          1127:        is->hy_flags |= (RQ_ENDOP | RQ_STATUS);
        !          1128:        hyact(ui);
        !          1129: }
        !          1130: 
        !          1131: #ifdef DEBUG
        !          1132: hyprintdata(cp, len)
        !          1133:        register char *cp;
        !          1134:        register int len;
        !          1135: {
        !          1136:        register int count = 16;
        !          1137:        register char *fmt;
        !          1138:        static char regfmt[] = "\n\t %x";
        !          1139: 
        !          1140:        fmt = &regfmt[2];
        !          1141:        while (--len >= 0) {
        !          1142:                printL(fmt, *cp++ & 0xff);
        !          1143:                fmt = &regfmt[2];
        !          1144:                if (--count <= 0) {
        !          1145:                        fmt = &regfmt[0];
        !          1146:                        count = 16;
        !          1147:                }
        !          1148:        }
        !          1149:        printL("\n");
        !          1150: }
        !          1151: #endif
        !          1152: 
        !          1153: hywatch(unit)
        !          1154:        int unit;
        !          1155: {
        !          1156:        register struct hy_softc *is = &hy_softc[unit];
        !          1157:        register struct uba_device *ui = hyinfo[unit];
        !          1158:        register struct hydevice *addr = (struct hydevice *)ui->ui_addr;
        !          1159:        int s;
        !          1160: 
        !          1161:        s = splimp();
        !          1162:        is->hy_if.if_timer = SCANINTERVAL;
        !          1163:        if (is->hy_ntime > 2 && is->hy_state != WAITING &&
        !          1164:          is->hy_state != STARTUP && is->hy_state != IDLE) {
        !          1165:                printf("hy%d: watchdog timer expired\n", unit);
        !          1166:                hycancel(ui);
        !          1167:        }
        !          1168: #ifdef PI13
        !          1169:        if ((addr->hyd_csr & S_POWEROFF) != 0) {
        !          1170:                addr->hyd_csr |= S_POWEROFF;
        !          1171:                DELAY(100);
        !          1172:                if ((addr->hyd_csr & S_POWEROFF) == 0) {
        !          1173:                        printf("hy%d: adapter power restored\n", unit);
        !          1174:                        is->hy_state = IDLE;
        !          1175:                        is->hy_flags |=
        !          1176:                          (RQ_MARKUP | RQ_STATISTICS | RQ_ENDOP | RQ_STATUS);
        !          1177:                        hyact(ui);
        !          1178:                }
        !          1179:        }
        !          1180: #endif
        !          1181:        splx(s);
        !          1182: }
        !          1183: 
        !          1184: #ifdef HYLOG
        !          1185: hylog(code, len, ptr)
        !          1186:        int code, len;
        !          1187:        char *ptr;
        !          1188: {
        !          1189:        register unsigned char *p;
        !          1190:        int s;
        !          1191: 
        !          1192:        s = splimp();
        !          1193:        if (hy_log.hyl_self != &hy_log) {
        !          1194:                hy_log.hyl_eptr = &hy_log.hyl_buf[HYL_SIZE];
        !          1195:                hy_log.hyl_ptr = &hy_log.hyl_buf[0];
        !          1196:                hy_log.hyl_self = &hy_log;
        !          1197:                hy_log.hyl_enable = HYL_DISABLED;
        !          1198:                hy_log.hyl_onerr = HYL_CATCH1;
        !          1199:        }
        !          1200:        if (hy_log.hyl_enable == HYL_DISABLED ||
        !          1201:          hy_log.hyl_enable == HYL_CAUGHT1 ||
        !          1202:          hy_log.hyl_enable == HYL_CAUGHTSTATUS ||
        !          1203:          (hy_log.hyl_enable == HYL_CATCHSTATUS && code != HYL_STATUS))
        !          1204:                goto out;
        !          1205:        p = hy_log.hyl_ptr;
        !          1206:        if (p + len + 2 >= hy_log.hyl_eptr) {
        !          1207:                bzero((caddr_t)p, (unsigned)(hy_log.hyl_eptr - p));
        !          1208:                p = &hy_log.hyl_buf[0];
        !          1209:                if (hy_log.hyl_enable == HYL_CATCH1) {
        !          1210:                        hy_log.hyl_enable = hy_log.hyl_onerr = HYL_CAUGHT1;
        !          1211:                        goto out;
        !          1212:                }
        !          1213:                if (hy_log.hyl_enable == HYL_CATCHSTATUS) {
        !          1214:                        hy_log.hyl_enable = hy_log.hyl_onerr = HYL_CAUGHTSTATUS;
        !          1215:                        goto out;
        !          1216:                }
        !          1217:        }
        !          1218:        *p++ = code;
        !          1219:        *p++ = len;
        !          1220:        bcopy((caddr_t)ptr, (caddr_t)p, (unsigned)len);
        !          1221:        hy_log.hyl_ptr = p + len;
        !          1222: out:
        !          1223:        splx(s);
        !          1224: }
        !          1225: #endif
        !          1226: 
        !          1227: /*ARGSUSED*/
        !          1228: hyioctl(ifp, cmd, data)
        !          1229:        register struct ifnet *ifp;
        !          1230:        int cmd;
        !          1231:        caddr_t data;
        !          1232: {
        !          1233:        struct sockaddr_in *sin;
        !          1234:        struct ifreq *ifr = (struct ifreq *)data;
        !          1235:        int s = splimp(), error = 0;
        !          1236: 
        !          1237:        switch(cmd) {
        !          1238: 
        !          1239:        case SIOCSIFADDR:
        !          1240:                if (ifp->if_flags & IFF_RUNNING)
        !          1241:                        if_rtinit(ifp, -1);
        !          1242:                sin = (struct sockaddr_in *)&ifr->ifr_addr;
        !          1243:                ifp->if_net = in_netof(sin->sin_addr);
        !          1244:                sin = (struct sockaddr_in *)&ifp->if_addr;
        !          1245:                sin->sin_family = AF_INET;
        !          1246:                sin->sin_addr = if_makeaddr(ifp->if_net, ifp->if_host[0]);
        !          1247:                if (ifp->if_flags & IFF_RUNNING)
        !          1248:                        if_rtinit(ifp, RTF_UP);
        !          1249:                else
        !          1250:                        hyinit(ifp->if_unit);
        !          1251:                break;
        !          1252: 
        !          1253:        case HYSETROUTE:
        !          1254:                if (!suser()) {
        !          1255:                        error = EPERM;
        !          1256:                        goto bad;
        !          1257:                }
        !          1258:                hy_route[ifp->if_unit] = *(struct hyroute *)ifr->ifr_data;
        !          1259:                hy_route[ifp->if_unit].hyr_lasttime = time;
        !          1260:                break;
        !          1261: 
        !          1262:        case HYGETROUTE:
        !          1263:                *(struct hyroute *)ifr->ifr_data = hy_route[ifp->if_unit];
        !          1264:                break;
        !          1265: 
        !          1266:        default:
        !          1267:                error = EINVAL;
        !          1268:                break;
        !          1269:        }
        !          1270: bad:
        !          1271:        splx(s);
        !          1272:        return (error);
        !          1273: }
        !          1274: #endif

unix.superglobalmegacorp.com

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