1 /* $NetBSD: if_el.c,v 1.91 2015/04/13 16:33:24 riastradh Exp $ */ 2 3 /* 4 * Copyright (c) 1994, Matthew E. Kimmel. Permission is hereby granted 5 * to use, copy, modify and distribute this software provided that both 6 * the copyright notice and this permission notice appear in all copies 7 * of the software, derivative works or modified versions, and any 8 * portions thereof. 9 */ 10 11 /* 12 * 3COM Etherlink 3C501 device driver 13 */ 14 15 /* 16 * Bugs/possible improvements: 17 * - Does not currently support DMA 18 * - Does not currently support multicasts 19 */ 20 21 #include <sys/cdefs.h> 22 __KERNEL_RCSID(0, "$NetBSD: if_el.c,v 1.91 2015/04/13 16:33:24 riastradh Exp $"); 23 24 #include "opt_inet.h" 25 26 #include <sys/param.h> 27 #include <sys/systm.h> 28 #include <sys/errno.h> 29 #include <sys/ioctl.h> 30 #include <sys/mbuf.h> 31 #include <sys/socket.h> 32 #include <sys/syslog.h> 33 #include <sys/device.h> 34 #include <sys/rndsource.h> 35 36 #include <net/if.h> 37 #include <net/if_dl.h> 38 #include <net/if_types.h> 39 40 #include <net/if_ether.h> 41 42 #ifdef INET 43 #include <netinet/in.h> 44 #include <netinet/in_systm.h> 45 #include <netinet/in_var.h> 46 #include <netinet/ip.h> 47 #include <netinet/if_inarp.h> 48 #endif 49 50 51 #include <net/bpf.h> 52 #include <net/bpfdesc.h> 53 54 #include <sys/cpu.h> 55 #include <sys/intr.h> 56 #include <sys/bus.h> 57 58 #include <dev/isa/isavar.h> 59 #include <dev/isa/if_elreg.h> 60 61 /* for debugging convenience */ 62 #ifdef EL_DEBUG 63 #define DPRINTF(x) printf x 64 #else 65 #define DPRINTF(x) 66 #endif 67 68 /* 69 * per-line info and status 70 */ 71 struct el_softc { 72 device_t sc_dev; 73 void *sc_ih; 74 75 struct ethercom sc_ethercom; /* ethernet common */ 76 bus_space_tag_t sc_iot; /* bus space identifier */ 77 bus_space_handle_t sc_ioh; /* i/o handle */ 78 79 krndsource_t rnd_source; 80 }; 81 82 /* 83 * prototypes 84 */ 85 int elintr(void *); 86 void elinit(struct el_softc *); 87 int elioctl(struct ifnet *, u_long, void *); 88 void elstart(struct ifnet *); 89 void elwatchdog(struct ifnet *); 90 void elreset(struct el_softc *); 91 void elstop(struct el_softc *); 92 static int el_xmit(struct el_softc *); 93 void elread(struct el_softc *, int); 94 struct mbuf *elget(struct el_softc *sc, int); 95 static inline void el_hardreset(struct el_softc *); 96 97 int elprobe(device_t, cfdata_t, void *); 98 void elattach(device_t, device_t, void *); 99 100 CFATTACH_DECL_NEW(el, sizeof(struct el_softc), 101 elprobe, elattach, NULL, NULL); 102 103 /* 104 * Probe routine. 105 * 106 * See if the card is there and at the right place. 107 * (XXX - cgd -- needs help) 108 */ 109 int 110 elprobe(device_t parent, cfdata_t match, void *aux) 111 { 112 struct isa_attach_args *ia = aux; 113 bus_space_tag_t iot = ia->ia_iot; 114 bus_space_handle_t ioh; 115 int iobase; 116 u_int8_t station_addr[ETHER_ADDR_LEN]; 117 u_int8_t i; 118 int rval; 119 120 rval = 0; 121 122 if (ia->ia_nio < 1) 123 return (0); 124 if (ia->ia_nirq < 1) 125 return (0); 126 127 if (ISA_DIRECT_CONFIG(ia)) 128 return (0); 129 130 iobase = ia->ia_io[0].ir_addr; 131 132 if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) 133 return (0); 134 if (ia->ia_irq[0].ir_irq == ISA_UNKNOWN_IRQ) 135 return (0); 136 137 /* First check the base. */ 138 if (iobase < 0x200 || iobase > 0x3f0) 139 return 0; 140 141 /* Map i/o space. */ 142 if (bus_space_map(iot, iobase, 16, 0, &ioh)) 143 return 0; 144 145 /* 146 * Now attempt to grab the station address from the PROM and see if it 147 * contains the 3com vendor code. 148 */ 149 DPRINTF(("Probing 3c501 at 0x%x...\n", iobase)); 150 151 /* Reset the board. */ 152 DPRINTF(("Resetting board...\n")); 153 bus_space_write_1(iot, ioh, EL_AC, EL_AC_RESET); 154 delay(5); 155 bus_space_write_1(iot, ioh, EL_AC, 0); 156 157 /* Now read the address. */ 158 DPRINTF(("Reading station address...\n")); 159 for (i = 0; i < ETHER_ADDR_LEN; i++) { 160 bus_space_write_1(iot, ioh, EL_GPBL, i); 161 station_addr[i] = bus_space_read_1(iot, ioh, EL_EAW); 162 } 163 DPRINTF(("Address is %s\n", ether_sprintf(station_addr))); 164 165 /* 166 * If the vendor code is ok, return a 1. We'll assume that whoever 167 * configured this system is right about the IRQ. 168 */ 169 if (station_addr[0] != 0x02 || station_addr[1] != 0x60 || 170 station_addr[2] != 0x8c) { 171 DPRINTF(("Bad vendor code.\n")); 172 goto out; 173 } 174 DPRINTF(("Vendor code ok.\n")); 175 176 ia->ia_nio = 1; 177 ia->ia_io[0].ir_size = 16; 178 179 ia->ia_nirq = 1; 180 181 ia->ia_niomem = 0; 182 ia->ia_ndrq = 0; 183 184 rval = 1; 185 186 out: 187 bus_space_unmap(iot, ioh, 16); 188 return rval; 189 } 190 191 /* 192 * Attach the interface to the kernel data structures. By the time this is 193 * called, we know that the card exists at the given I/O address. We still 194 * assume that the IRQ given is correct. 195 */ 196 void 197 elattach(device_t parent, device_t self, void *aux) 198 { 199 struct el_softc *sc = device_private(self); 200 struct isa_attach_args *ia = aux; 201 bus_space_tag_t iot = ia->ia_iot; 202 bus_space_handle_t ioh; 203 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 204 u_int8_t myaddr[ETHER_ADDR_LEN]; 205 u_int8_t i; 206 207 sc->sc_dev = self; 208 209 printf("\n"); 210 211 DPRINTF(("Attaching %s...\n", device_xname(sc->sc_dev))); 212 213 /* Map i/o space. */ 214 if (bus_space_map(iot, ia->ia_io[0].ir_addr, 16, 0, &ioh)) { 215 aprint_error_dev(self, "can't map i/o space\n"); 216 return; 217 } 218 219 sc->sc_iot = iot; 220 sc->sc_ioh = ioh; 221 222 /* Reset the board. */ 223 bus_space_write_1(iot, ioh, EL_AC, EL_AC_RESET); 224 delay(5); 225 bus_space_write_1(iot, ioh, EL_AC, 0); 226 227 /* Now read the address. */ 228 for (i = 0; i < ETHER_ADDR_LEN; i++) { 229 bus_space_write_1(iot, ioh, EL_GPBL, i); 230 myaddr[i] = bus_space_read_1(iot, ioh, EL_EAW); 231 } 232 233 /* Stop the board. */ 234 elstop(sc); 235 236 /* Initialize ifnet structure. */ 237 strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); 238 ifp->if_softc = sc; 239 ifp->if_start = elstart; 240 ifp->if_ioctl = elioctl; 241 ifp->if_watchdog = elwatchdog; 242 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; 243 IFQ_SET_READY(&ifp->if_snd); 244 245 /* Now we can attach the interface. */ 246 DPRINTF(("Attaching interface...\n")); 247 if_attach(ifp); 248 ether_ifattach(ifp, myaddr); 249 250 /* Print out some information for the user. */ 251 printf("%s: address %s\n", device_xname(self), ether_sprintf(myaddr)); 252 253 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq, 254 IST_EDGE, IPL_NET, elintr, sc); 255 256 DPRINTF(("Attaching to random...\n")); 257 rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), 258 RND_TYPE_NET, RND_FLAG_DEFAULT); 259 260 DPRINTF(("elattach() finished.\n")); 261 } 262 263 /* 264 * Reset interface. 265 */ 266 void 267 elreset(struct el_softc *sc) 268 { 269 int s; 270 271 DPRINTF(("elreset()\n")); 272 s = splnet(); 273 elstop(sc); 274 elinit(sc); 275 splx(s); 276 } 277 278 /* 279 * Stop interface. 280 */ 281 void 282 elstop(struct el_softc *sc) 283 { 284 285 bus_space_write_1(sc->sc_iot, sc->sc_ioh, EL_AC, 0); 286 } 287 288 /* 289 * Do a hardware reset of the board, and upload the ethernet address again in 290 * case the board forgets. 291 */ 292 static inline void 293 el_hardreset(struct el_softc *sc) 294 { 295 bus_space_tag_t iot = sc->sc_iot; 296 bus_space_handle_t ioh = sc->sc_ioh; 297 int i; 298 299 bus_space_write_1(iot, ioh, EL_AC, EL_AC_RESET); 300 delay(5); 301 bus_space_write_1(iot, ioh, EL_AC, 0); 302 303 for (i = 0; i < ETHER_ADDR_LEN; i++) 304 bus_space_write_1(iot, ioh, i, 305 CLLADDR(sc->sc_ethercom.ec_if.if_sadl)[i]); 306 } 307 308 /* 309 * Initialize interface. 310 */ 311 void 312 elinit(struct el_softc *sc) 313 { 314 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 315 bus_space_tag_t iot = sc->sc_iot; 316 bus_space_handle_t ioh = sc->sc_ioh; 317 318 /* First, reset the board. */ 319 el_hardreset(sc); 320 321 /* Configure rx. */ 322 DPRINTF(("Configuring rx...\n")); 323 if (ifp->if_flags & IFF_PROMISC) 324 bus_space_write_1(iot, ioh, EL_RXC, 325 EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | 326 EL_RXC_DOFLOW | EL_RXC_PROMISC); 327 else 328 bus_space_write_1(iot, ioh, EL_RXC, 329 EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | 330 EL_RXC_DOFLOW | EL_RXC_ABROAD); 331 bus_space_write_1(iot, ioh, EL_RBC, 0); 332 333 /* Configure TX. */ 334 DPRINTF(("Configuring tx...\n")); 335 bus_space_write_1(iot, ioh, EL_TXC, 0); 336 337 /* Start reception. */ 338 DPRINTF(("Starting reception...\n")); 339 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); 340 341 /* Set flags appropriately. */ 342 ifp->if_flags |= IFF_RUNNING; 343 ifp->if_flags &= ~IFF_OACTIVE; 344 345 /* And start output. */ 346 elstart(ifp); 347 } 348 349 /* 350 * Start output on interface. Get datagrams from the queue and output them, 351 * giving the receiver a chance between datagrams. Call only from splnet or 352 * interrupt level! 353 */ 354 void 355 elstart(struct ifnet *ifp) 356 { 357 struct el_softc *sc = ifp->if_softc; 358 bus_space_tag_t iot = sc->sc_iot; 359 bus_space_handle_t ioh = sc->sc_ioh; 360 struct mbuf *m, *m0; 361 int s, i, off, retries; 362 363 DPRINTF(("elstart()...\n")); 364 s = splnet(); 365 366 /* Don't do anything if output is active. */ 367 if ((ifp->if_flags & IFF_OACTIVE) != 0) { 368 splx(s); 369 return; 370 } 371 372 ifp->if_flags |= IFF_OACTIVE; 373 374 /* 375 * The main loop. They warned me against endless loops, but would I 376 * listen? NOOO.... 377 */ 378 for (;;) { 379 /* Dequeue the next datagram. */ 380 IFQ_DEQUEUE(&ifp->if_snd, m0); 381 382 /* If there's nothing to send, return. */ 383 if (m0 == 0) 384 break; 385 386 /* Give the packet to the bpf, if any. */ 387 bpf_mtap(ifp, m0); 388 389 /* Disable the receiver. */ 390 bus_space_write_1(iot, ioh, EL_AC, EL_AC_HOST); 391 bus_space_write_1(iot, ioh, EL_RBC, 0); 392 393 /* Transfer datagram to board. */ 394 DPRINTF(("el: xfr pkt length=%d...\n", m0->m_pkthdr.len)); 395 off = EL_BUFSIZ - max(m0->m_pkthdr.len, 396 ETHER_MIN_LEN - ETHER_CRC_LEN); 397 #ifdef DIAGNOSTIC 398 if ((off & 0xffff) != off) 399 printf("%s: bogus off 0x%x\n", 400 device_xname(sc->sc_dev), off); 401 #endif 402 bus_space_write_1(iot, ioh, EL_GPBL, off & 0xff); 403 bus_space_write_1(iot, ioh, EL_GPBH, (off >> 8) & 0xff); 404 405 /* Copy the datagram to the buffer. */ 406 for (m = m0; m != 0; m = m->m_next) 407 bus_space_write_multi_1(iot, ioh, EL_BUF, 408 mtod(m, u_int8_t *), m->m_len); 409 for (i = 0; 410 i < ETHER_MIN_LEN - ETHER_CRC_LEN - m0->m_pkthdr.len; i++) 411 bus_space_write_1(iot, ioh, EL_BUF, 0); 412 413 m_freem(m0); 414 415 /* Now transmit the datagram. */ 416 retries = 0; 417 for (;;) { 418 bus_space_write_1(iot, ioh, EL_GPBL, off & 0xff); 419 bus_space_write_1(iot, ioh, EL_GPBH, (off >> 8) & 0xff); 420 if (el_xmit(sc)) { 421 ifp->if_oerrors++; 422 break; 423 } 424 /* Check out status. */ 425 i = bus_space_read_1(iot, ioh, EL_TXS); 426 DPRINTF(("tx status=0x%x\n", i)); 427 if ((i & EL_TXS_READY) == 0) { 428 DPRINTF(("el: err txs=%x\n", i)); 429 if (i & (EL_TXS_COLL | EL_TXS_COLL16)) { 430 ifp->if_collisions++; 431 if ((i & EL_TXC_DCOLL16) == 0 && 432 retries < 15) { 433 retries++; 434 bus_space_write_1(iot, ioh, 435 EL_AC, EL_AC_HOST); 436 } 437 } else { 438 ifp->if_oerrors++; 439 break; 440 } 441 } else { 442 ifp->if_opackets++; 443 break; 444 } 445 } 446 447 /* 448 * Now give the card a chance to receive. 449 * Gotta love 3c501s... 450 */ 451 (void)bus_space_read_1(iot, ioh, EL_AS); 452 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); 453 splx(s); 454 /* Interrupt here. */ 455 s = splnet(); 456 } 457 458 (void)bus_space_read_1(iot, ioh, EL_AS); 459 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); 460 ifp->if_flags &= ~IFF_OACTIVE; 461 splx(s); 462 } 463 464 /* 465 * This function actually attempts to transmit a datagram downloaded to the 466 * board. Call at splnet or interrupt, after downloading data! Returns 0 on 467 * success, non-0 on failure. 468 */ 469 static int 470 el_xmit(struct el_softc *sc) 471 { 472 bus_space_tag_t iot = sc->sc_iot; 473 bus_space_handle_t ioh = sc->sc_ioh; 474 int i; 475 476 /* 477 * XXX 478 * This busy-waits for the tx completion. Can we get an interrupt 479 * instead? 480 */ 481 482 DPRINTF(("el: xmit...")); 483 bus_space_write_1(iot, ioh, EL_AC, EL_AC_TXFRX); 484 i = 20000; 485 while ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_TXBUSY) && (i > 0)) 486 i--; 487 if (i == 0) { 488 DPRINTF(("tx not ready\n")); 489 return -1; 490 } 491 DPRINTF(("%d cycles.\n", 20000 - i)); 492 return 0; 493 } 494 495 /* 496 * Controller interrupt. 497 */ 498 int 499 elintr(void *arg) 500 { 501 struct el_softc *sc = arg; 502 bus_space_tag_t iot = sc->sc_iot; 503 bus_space_handle_t ioh = sc->sc_ioh; 504 u_int8_t rxstat; 505 int len; 506 507 DPRINTF(("elintr: ")); 508 509 /* Check board status. */ 510 if ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_RXBUSY) != 0) { 511 (void)bus_space_read_1(iot, ioh, EL_RXC); 512 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); 513 return 0; 514 } 515 516 for (;;) { 517 rxstat = bus_space_read_1(iot, ioh, EL_RXS); 518 if (rxstat & EL_RXS_STALE) 519 break; 520 521 /* If there's an overflow, reinit the board. */ 522 if ((rxstat & EL_RXS_NOFLOW) == 0) { 523 DPRINTF(("overflow.\n")); 524 el_hardreset(sc); 525 /* Put board back into receive mode. */ 526 if (sc->sc_ethercom.ec_if.if_flags & IFF_PROMISC) 527 bus_space_write_1(iot, ioh, EL_RXC, 528 EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | 529 EL_RXC_DOFLOW | EL_RXC_PROMISC); 530 else 531 bus_space_write_1(iot, ioh, EL_RXC, 532 EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | 533 EL_RXC_DOFLOW | EL_RXC_ABROAD); 534 (void)bus_space_read_1(iot, ioh, EL_AS); 535 bus_space_write_1(iot, ioh, EL_RBC, 0); 536 break; 537 } 538 539 /* Incoming packet. */ 540 len = bus_space_read_1(iot, ioh, EL_RBL); 541 len |= bus_space_read_1(iot, ioh, EL_RBH) << 8; 542 DPRINTF(("receive len=%d rxstat=%x ", len, rxstat)); 543 bus_space_write_1(iot, ioh, EL_AC, EL_AC_HOST); 544 545 /* Pass data up to upper levels. */ 546 elread(sc, len); 547 548 /* Is there another packet? */ 549 if ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_RXBUSY) != 0) 550 break; 551 552 rnd_add_uint32(&sc->rnd_source, rxstat); 553 554 DPRINTF(("<rescan> ")); 555 } 556 557 (void)bus_space_read_1(iot, ioh, EL_RXC); 558 bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); 559 return 1; 560 } 561 562 /* 563 * Pass a packet to the higher levels. 564 */ 565 void 566 elread(struct el_softc *sc, int len) 567 { 568 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 569 struct mbuf *m; 570 571 if (len <= sizeof(struct ether_header) || 572 len > ETHER_MAX_LEN) { 573 printf("%s: invalid packet size %d; dropping\n", 574 device_xname(sc->sc_dev), len); 575 ifp->if_ierrors++; 576 return; 577 } 578 579 /* Pull packet off interface. */ 580 m = elget(sc, len); 581 if (m == 0) { 582 ifp->if_ierrors++; 583 return; 584 } 585 586 ifp->if_ipackets++; 587 588 /* 589 * Check if there's a BPF listener on this interface. 590 * If so, hand off the raw packet to BPF. 591 */ 592 bpf_mtap(ifp, m); 593 594 (*ifp->if_input)(ifp, m); 595 } 596 597 /* 598 * Pull read data off a interface. Len is length of data, with local net 599 * header stripped. We copy the data into mbufs. When full cluster sized 600 * units are present we copy into clusters. 601 */ 602 struct mbuf * 603 elget(struct el_softc *sc, int totlen) 604 { 605 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 606 bus_space_tag_t iot = sc->sc_iot; 607 bus_space_handle_t ioh = sc->sc_ioh; 608 struct mbuf *m, *m0, *newm; 609 int len; 610 611 MGETHDR(m0, M_DONTWAIT, MT_DATA); 612 if (m0 == 0) 613 return (0); 614 m0->m_pkthdr.rcvif = ifp; 615 m0->m_pkthdr.len = totlen; 616 len = MHLEN; 617 m = m0; 618 619 bus_space_write_1(iot, ioh, EL_GPBL, 0); 620 bus_space_write_1(iot, ioh, EL_GPBH, 0); 621 622 while (totlen > 0) { 623 if (totlen >= MINCLSIZE) { 624 MCLGET(m, M_DONTWAIT); 625 if ((m->m_flags & M_EXT) == 0) 626 goto bad; 627 len = MCLBYTES; 628 } 629 630 m->m_len = len = min(totlen, len); 631 bus_space_read_multi_1(iot, ioh, EL_BUF, mtod(m, u_int8_t *), len); 632 633 totlen -= len; 634 if (totlen > 0) { 635 MGET(newm, M_DONTWAIT, MT_DATA); 636 if (newm == 0) 637 goto bad; 638 len = MLEN; 639 m = m->m_next = newm; 640 } 641 } 642 643 bus_space_write_1(iot, ioh, EL_RBC, 0); 644 bus_space_write_1(iot, ioh, EL_AC, EL_AC_RX); 645 646 return (m0); 647 648 bad: 649 m_freem(m0); 650 return (0); 651 } 652 653 /* 654 * Process an ioctl request. This code needs some work - it looks pretty ugly. 655 */ 656 int 657 elioctl(struct ifnet *ifp, u_long cmd, void *data) 658 { 659 struct el_softc *sc = ifp->if_softc; 660 struct ifaddr *ifa = (struct ifaddr *)data; 661 int s, error = 0; 662 663 s = splnet(); 664 665 switch (cmd) { 666 667 case SIOCINITIFADDR: 668 ifp->if_flags |= IFF_UP; 669 670 elinit(sc); 671 switch (ifa->ifa_addr->sa_family) { 672 #ifdef INET 673 case AF_INET: 674 arp_ifinit(ifp, ifa); 675 break; 676 #endif 677 default: 678 break; 679 } 680 break; 681 682 case SIOCSIFFLAGS: 683 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 684 break; 685 /* XXX re-use ether_ioctl() */ 686 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { 687 case IFF_RUNNING: 688 /* 689 * If interface is marked down and it is running, then 690 * stop it. 691 */ 692 elstop(sc); 693 ifp->if_flags &= ~IFF_RUNNING; 694 break; 695 case IFF_UP: 696 /* 697 * If interface is marked up and it is stopped, then 698 * start it. 699 */ 700 elinit(sc); 701 break; 702 default: 703 /* 704 * Some other important flag might have changed, so 705 * reset. 706 */ 707 elreset(sc); 708 break; 709 } 710 break; 711 712 default: 713 error = ether_ioctl(ifp, cmd, data); 714 break; 715 } 716 717 splx(s); 718 return error; 719 } 720 721 /* 722 * Device timeout routine. 723 */ 724 void 725 elwatchdog(struct ifnet *ifp) 726 { 727 struct el_softc *sc = ifp->if_softc; 728 729 log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev)); 730 sc->sc_ethercom.ec_if.if_oerrors++; 731 732 elreset(sc); 733 } 734