1 /* 2 * @(#)if_hy.c 6.9 (Berkeley) 02/23/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 = ®fmt[2]; 1236 while (--len >= 0) { 1237 printL(fmt, *cp++ & 0xff); 1238 fmt = ®fmt[2]; 1239 if (--count <= 0) { 1240 fmt = ®fmt[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 1486