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