# 2.11BSD#431 - /usr/src/sys/vaxif/if_hy.c

##### Functions

    hyact             X
    hyattach          X
    hycancel          X
    hyinit            X
    hyint             X
    hyioctl           X
    hylog             X
    hyoutput          X
    hyprintdata       X
    hyprobe           X
    hyrecvdata        X
    hyreset           X
    hyroute           X
    hystart           X
    hywatch           X
    hyxmitdata        X

##### Variables

    hy_debug_flag     X
    hy_elog           X
    hy_log            X
    hy_nodebug        X
    hy_route          X
    hy_softc          X
    hydriver          X
    hyinfo            X
    hyint_active      X
    hyoutprint        X
    hypdst            X
    hypproto          X
    hypsrc            X
    hystd             X

##### Macros

    HYELOG            X
    HYLOG             X
    HYMTU             X
    HYROUTE           X
    MAXINTERVAL       X
    PI13              X
    SCANINTERVAL      X
    printD            X
    printL            X

##### struct's

    hy_softc          X

       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

#### Defined functions

hyact defined in line 755; used 5 times

- in line 476, 525, 684, 1223, 1266

hyattach defined in line 223; used 2 times

- in line 119-124(2)

hycancel defined in line 1195; used 5 times

- in line 312, 450, 467, 516, 1281

hyinit defined in line 269; used 4 times

- in line 119, 233, 262, 1376

hyint defined in line 399; used 1 times

- in line 197

hyioctl defined in line 1340; used 2 times

- in line 119, 234

hylog defined in line 1288; used 11 times

- in line 300, 380, 426, 816, 883, 910, 959, 1122, 1205, 1442, 1480

hyoutput defined in line 554; used 2 times

- in line 120, 235

hyprintdata defined in line 1227; used 4 times

- in line 827, 839, 997, 1025

hyprobe defined in line 189; used 2 times

- in line 119-124(2)

hyrecvdata defined in line 1101; used 2 times

- in line 1006, 1027

hyreset defined in line 250; used 2 times

- in line 120, 236

hyroute defined in line 694; used 1 times

- in line 618

hystart defined in line 319; used 11 times

- in line 777-791(4), 801, 849, 857, 888, 1002, 1048, 1065

hywatch defined in line 1248; used 2 times

- in line 120, 237

hyxmitdata defined in line 1183; used 1 times

- in line 1055

#### Defined variables

hy_debug_flag defined in line 172; used 12 times

- in line 171, 285, 438, 494, 520, 826, 838, 987, 996, 1024, 1045, 1209

hy_elog defined in line 158; used 6 times

- in line 928, 1417-1421(3), 1430(2)

hy_log defined in line 162; used 55 times

- in line 487-488(4), 533-534(4), 1296-1313(21), 1320-1333(13), 1441-1464(13)

hy_nodebug defined in line 178; used 5 times

- in line 284, 437, 493, 519, 1208

hy_route defined in line 166; used 2 times

- in line 701, 1350

hy_softc defined in line 155; used 14 times

- in line 226, 260, 272, 323, 402, 660, 683, 758, 1106, 1186, 1198, 1251, 1353, 1377

hydriver defined in line 123; never used
hyinfo defined in line 121; used 6 times

- in line 124, 256, 273, 403, 684, 1252

hyint_active defined in line 386; used 3 times

- in line 406-408(2), 545

hyoutprint defined in line 549; used 1 times

- in line 665

hypdst defined in line 1092; used 2 times

- in line 1166-1169(2)

hypproto defined in line 1091; used 2 times

- in line 1165-1168(2)

hypsrc defined in line 1093; used 2 times

- in line 1167-1168(2)

hystd defined in line 122; used 1 times

- in line 124

#### Defined struct's

hy_softc defined in line 138; used 22 times

- in line 226(2), 254(2), 272(2), 323(2), 402(2), 758(2), 1106(2), 1186(2), 1198(2), 1251(2), 1353(2)

#### Defined macros

HYELOG defined in line 106; used 4 times

- in line 157, 913, 1347, 1415

HYLOG defined in line 112; used 20 times

- in line 161, 299, 369, 413, 486, 532, 815, 882, 909, 958, 1114, 1204, 1272, 1287, 1347-1352(2), 1378, 1399, 1435, 1476

HYMTU defined in line 108; used 4 times

- in line 231, 282, 1003, 1125

HYROUTE defined in line 105; used 4 times

- in line 165, 700, 707, 745

MAXINTERVAL defined in line 182; never used
PI13 defined in line 109; used 8 times

- in line 205, 211, 340, 359, 445, 451, 503, 1257

SCANINTERVAL defined in line 181; used 2 times

- in line 238, 1284

printD defined in line 171; used 27 times

- in line 327-329(2), 365, 410, 495-499(3), 539-543(2), 670, 763, 796-798(2), 825, 835, 898, 940, 946-951(2), 988, 995, 1022, 1086, 1112, 1212-1217(3)

printL defined in line 170; used 2 times

- in line 1237, 1244

Last modified: 1986-06-06 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 295 |