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
hyattach defined in line 223; used 2 times
hycancel defined in line 1195; used 5 times
hyinit defined in line 269; used 4 times
hyint defined in line 399; used 1 times
hyioctl defined in line 1340; used 2 times
hylog defined in line 1288; used 11 times
hyoutput defined in line 554; used 3 times
hyprintdata defined in line 1227; used 4 times
hyprobe defined in line 189; used 2 times
hyrecvdata defined in line 1101; used 2 times
hyreset defined in line 250; used 2 times
hyroute defined in line 694; used 1 times
hystart defined in line 319; used 11 times
hywatch defined in line 1248; used 2 times
hyxmitdata defined in line 1183; used 1 times

Defined variables

hy_debug_flag defined in line 172; used 12 times
hy_elog defined in line 158; used 6 times
hy_log defined in line 162; used 55 times
hy_nodebug defined in line 178; used 5 times
hy_route defined in line 166; used 2 times
hy_softc defined in line 155; used 14 times
hydriver defined in line 123; never used
hyinfo defined in line 121; used 6 times
hyint_active defined in line 386; used 3 times
hyoutprint defined in line 549; used 1 times
hypdst defined in line 1092; used 2 times
hypproto defined in line 1091; used 2 times
hypsrc defined in line 1093; used 2 times
hystd defined in line 122; used 1 times

Defined struct's

hy_softc defined in line 138; used 22 times

Defined macros

HYELOG defined in line 106; used 4 times
HYLOG defined in line 112; used 20 times
HYMTU defined in line 108; used 4 times
HYROUTE defined in line 105; used 4 times
MAXINTERVAL defined in line 182; never used
PI13 defined in line 109; used 8 times
SCANINTERVAL defined in line 181; used 2 times
printD defined in line 171; used 27 times
printL defined in line 170; used 2 times
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4986
Valid CSS Valid XHTML 1.0 Strict