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

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

unix.superglobalmegacorp.com

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