Annotation of 42BSD/sys/vaxif/if_hy.c, revision 1.1.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.