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

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

unix.superglobalmegacorp.com

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