1 /* $NetBSD: if_ie.c,v 1.4 2002/01/16 05:56:54 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Melvin Tang-Richardson. 5 * All rights reserved. 6 * 7 * This driver is a major hash up of src/sys/dev/isa/if_ie.c and 8 * src/sys/arch/acorn32/podulebus/kgdb_ie.c Please refer to copyright 9 * notices from them too. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by RiscBSD. 22 * 4. The name of the company nor the name of the author may be used to 23 * endorse or promote products derived from this software without specific 24 * prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY RISCBSD ``AS IS'' AND ANY EXPRESS OR IMPLIED 27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL RISCBSD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 30 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * RiscBSD kernel project 39 * 40 * if_ie.c 41 * 42 * Ether 1 podule driver 43 * 44 * Created : 26/06/95 45 */ 46 47 /* 48 * This driver is at it's last beta release. It should not cause 49 * any problems (Touch wood) 50 * 51 * If it passes field tests again. This will constitute the realse 52 * version. 53 */ 54 55 #define IGNORE_ETHER1_IDROM_CHECKSUM 56 57 /* Standard podule includes */ 58 59 #include "opt_inet.h" 60 #include "opt_ns.h" 61 62 #include <sys/param.h> 63 #include <sys/systm.h> 64 #include <sys/kernel.h> 65 #include <sys/conf.h> 66 #include <sys/malloc.h> 67 #include <sys/device.h> 68 #include <machine/io.h> 69 #include <machine/intr.h> 70 #include <arm/arm32/katelib.h> 71 #include <acorn32/podulebus/podulebus.h> 72 #include <dev/podulebus/podules.h> 73 74 /* Include for interface to the net and ethernet subsystems */ 75 76 #include <sys/socket.h> 77 #include <sys/syslog.h> 78 #include <sys/ioctl.h> 79 #include <sys/mbuf.h> 80 81 #include <net/if.h> 82 #include <net/if_types.h> 83 #include <net/if_dl.h> 84 #include <net/if_ether.h> 85 86 #ifdef INET 87 #include <netinet/in.h> 88 #include <netinet/in_systm.h> 89 #include <netinet/in_var.h> 90 #include <netinet/ip.h> 91 #include <netinet/if_inarp.h> 92 #endif 93 94 #ifdef NS 95 #include <netns/ns.h> 96 #include <netns/ns_if.h> 97 #endif 98 99 /* Import our data structres */ 100 101 #include "if_iereg.h" 102 103 /* BPF support */ 104 105 #include "bpfilter.h" 106 #if NBPFILTER > 0 107 #include <net/bpf.h> 108 #include <net/bpfdesc.h> 109 #endif 110 111 /* Some useful defines and macros */ 112 113 #define PODULE_IRQ_PENDING (1) 114 #define NFRAMES (16) /* number of frame to allow for receive */ 115 #define NRXBUF (48) /* number of receive buffers to allocate */ 116 #define IE_RXBUF_SIZE (256) /* receive buf size */ 117 #define NTXBUF (2) /* number of transmit buffers to allocate */ 118 #define IE_TXBUF_SIZE (1522) /* size of tx buffer */ 119 120 #define PWriteShort(a,b) WriteWord(a,(b)<<16|(b)) 121 122 #define xoffsetof(type, member) (offsetof(type, member) << 1) 123 124 /* Some data structres local to this file */ 125 126 struct ie_softc { 127 struct device sc_dev; 128 int sc_podule_number; 129 podule_t *sc_podule; 130 irqhandler_t sc_ih; 131 int sc_flags; 132 #define IE_BROKEN 1 133 int sc_iobase; 134 int sc_fastbase; 135 int sc_rom; 136 int sc_ram; 137 int sc_control; 138 struct ethercom sc_ethercom; 139 int promisc; 140 int sc_irqmode; 141 142 u_long rframes[NFRAMES]; 143 u_long rbuffs[NRXBUF]; 144 u_long cbuffs[NRXBUF]; 145 int rfhead, rftail, rbhead, rbtail; 146 147 u_long xmit_cmds[NTXBUF]; 148 u_long xmit_buffs[NTXBUF]; 149 u_long xmit_cbuffs[NTXBUF]; 150 int xmit_count; 151 int xmit_free; 152 int xchead; 153 int xctail; 154 }; 155 156 /* Function and data prototypes */ 157 158 static void host2ie __P(( struct ie_softc *sc, void *src, u_long dest, int size )); 159 static void ie2host __P(( struct ie_softc *sc, u_long src, void *dest, int size )); 160 static void iezero __P(( struct ie_softc *sc, u_long p, int size )); 161 void iereset __P(( struct ie_softc *sc )); 162 void iewatchdog __P(( struct ifnet *ifp )); 163 int ieioctl __P(( struct ifnet *ifp, u_long cmd, caddr_t data )); 164 void iestart __P(( struct ifnet *ifp )); 165 int iestop __P(( struct ie_softc *sc )); 166 int ieinit __P(( struct ie_softc *sc )); 167 int ieintr __P(( void *arg )); 168 void ietint __P(( struct ie_softc *sc )); 169 170 /* A whopper of a function */ 171 static int command_and_wait __P(( struct ie_softc *sc, u_short cmd, 172 struct ie_sys_ctl_block *pscb, 173 void *pcmd, int ocmd, int scmd, int mask )); 174 175 int ieprobe __P((struct device *, struct cfdata *, void *)); 176 void ieattach __P((struct device *, struct device *, void *)); 177 178 /* 179 * Our cfattach structure for the autoconfig system to chew on 180 */ 181 182 struct cfattach ie_ca = { 183 sizeof(struct ie_softc), ieprobe, ieattach 184 }; 185 186 /* Let's go! */ 187 188 /* 189 * Clear all pending interrupts from the i82586 chip 190 */ 191 192 static __inline void 193 ie_cli(sc) 194 struct ie_softc *sc; 195 { 196 WriteByte(sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_CLI); 197 } 198 199 /* 200 * Cool down the i82586, like its namesake, it gets very hot 201 */ 202 203 static __inline void 204 ie_cooldown(temperature) 205 int temperature; 206 { 207 } 208 209 /* 210 * Wake the i82586 chip up and get it to do something 211 */ 212 213 static __inline void 214 ieattn(sc) 215 struct ie_softc *sc; 216 { 217 WriteByte ( sc->sc_control + (IE_CONTROL<<2), IE_CONT_ATTN ); 218 } 219 220 /* 221 * Set the podule page register to bring a given address into view 222 */ 223 224 static __inline void 225 setpage(sc, off) 226 struct ie_softc *sc; 227 u_long off; 228 { 229 WriteByte ( sc->sc_control + (IE_PAGE<<2), IE_COFF2PAGE(off) ); 230 } 231 232 /* 233 * Ack the i82586 234 */ 235 236 static void 237 ie_ack(sc, mask) 238 struct ie_softc *sc; 239 u_short mask; 240 { 241 u_short stat; 242 int i; 243 setpage(sc, IE_IBASE + IE_SCB_OFF ); 244 245 stat = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 246 (xoffsetof(struct ie_sys_ctl_block, ie_status)) ); 247 248 PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 249 (xoffsetof(struct ie_sys_ctl_block, ie_command)), 250 stat & mask ); 251 252 ieattn(sc); 253 254 for ( i=4000; --i>=0; ) { 255 if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 256 (xoffsetof(struct ie_sys_ctl_block, ie_command))) ) 257 break; 258 delay(100); 259 } 260 261 if ( i<=0 ) 262 printf ( "ie: command timed out\n" ); 263 ie_cli(sc); 264 } 265 266 /* 267 * This routine does the checksumming for the idrom 268 */ 269 270 #ifndef IGNORE_ETHER1_IDROM_CHECKSUM 271 static u_long 272 crc32(p, l) 273 u_char *p; 274 int l; 275 { 276 u_long crc=-1; 277 int i, b; 278 while ( --l >= 0 ) { 279 b = *p++; 280 for ( i=8; --i >= 0; b>>=1 ) 281 if ((b&1)^(crc>>31)) 282 crc=(crc<<1)^0x4c11db7; 283 else 284 crc<<=1; 285 } 286 return crc; 287 } 288 #endif 289 290 /* 291 * Probe for the ether1 card. return 1 on success 0 on failure 292 */ 293 294 int 295 ieprobe(struct device *parent, struct cfdata *cf, void *aux) 296 { 297 struct podule_attach_args *pa = (void *)aux; 298 299 /* Look for a network slot interface */ 300 301 if (matchpodule(pa, MANUFACTURER_ACORN, PODULE_ACORN_ETHER1, -1) == 0) 302 return(0); 303 304 return(1); 305 } 306 307 /* 308 * Attach our driver to the interfaces it uses 309 */ 310 311 void ieattach ( struct device *parent, struct device *self, void *aux ) 312 { 313 struct ie_softc *sc = (void *)self; 314 struct podule_attach_args *pa = (void *)aux; 315 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 316 int i; 317 char idrom[32]; 318 u_int8_t hwaddr[ETHER_ADDR_LEN]; 319 320 /* Check a few things about the attach args */ 321 322 if (pa->pa_podule_number == -1) 323 panic("Podule has disappeared !"); 324 325 sc->sc_podule_number = pa->pa_podule_number; 326 sc->sc_podule = pa->pa_podule; 327 podules[sc->sc_podule_number].attached = 1; 328 329 /* 330 * MESS MESS MESS 331 * 332 * This needs a serious clean up. Alot of this code was in the probe function 333 * but required the softc structure. As a temporary measure until I rewrite it 334 * I have just bolted in the probe code here. 335 */ 336 337 /* Index some podule areas */ 338 sc->sc_iobase = sc->sc_podule->sync_base; /* OBSOLETE */ 339 sc->sc_fastbase = sc->sc_podule->fast_base; /* OBSOLETE */ 340 sc->sc_rom = sc->sc_podule->sync_base; 341 sc->sc_control = sc->sc_podule->fast_base; 342 sc->sc_ram = sc->sc_podule->fast_base + IE_MEMOFF; 343 344 /* Set the page mask to something know and neutral */ 345 setpage(sc, IE_SCB_OFF); 346 347 /* Fetch the first part of the idrom */ 348 for ( i=0; i<16; i++ ) 349 idrom[i] = ReadByte ( sc->sc_rom + (i<<2) ); 350 351 /* Verify the podulebus probe incase RiscOS lied */ 352 if ( ReadByte ( sc->sc_rom + (3<<2) ) != 0x03 ) { 353 printf(": Ether1 ROM probablly broken. ECID corrupt\n"); 354 sc->sc_flags |= IE_BROKEN; 355 return; 356 } 357 358 /* Reset the 82586 */ 359 WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_RESET ); 360 delay(1000); 361 WriteByte ( sc->sc_fastbase + (IE_CONTROL<<2), 0 ); 362 delay(10000); 363 364 /* Clear pending interrupts */ 365 ie_cli (sc); 366 367 /* Setup SCP */ 368 { 369 struct ie_sys_conf_ptr scp; 370 bzero (&scp, sizeof(scp) ); 371 scp.ie_iscp_ptr = (caddr_t)IE_ISCP_ADDR; 372 host2ie(sc, &scp, IE_SCP_ADDR, sizeof (scp) ); 373 } 374 375 /* Setup ISCP */ 376 { 377 struct ie_int_sys_conf_ptr iscp; 378 bzero ( &iscp, sizeof(iscp) ); 379 iscp.ie_busy = 1; 380 iscp.ie_base = (caddr_t)IE_IBASE; 381 iscp.ie_scb_offset = IE_SCB_OFF; 382 host2ie(sc, &iscp, IE_ISCP_ADDR, sizeof(iscp) ); 383 } 384 385 /* Initialise the control block */ 386 iezero ( sc, IE_IBASE + IE_SCB_OFF, sizeof(struct ie_sys_ctl_block) ); 387 ieattn(sc); 388 389 /* Wait for not busy */ 390 setpage ( sc, IE_ISCP_ADDR ); 391 for ( i=10000; --i>=0; ) { 392 if ( !ReadShort( sc->sc_ram + IE_COFF2POFF(IE_ISCP_ADDR) + 393 ( xoffsetof(struct ie_int_sys_conf_ptr, ie_busy)) ) ) 394 break; 395 delay (10); 396 } 397 398 /* If the busy didn't go low, the i82586 is broken or too slow */ 399 if ( i<=0 ) { 400 printf ( ": ether1 chipset didn't respond\n" ); 401 sc->sc_flags |= IE_BROKEN; 402 return; 403 } 404 405 /* Ensure that the podule sends interrupts */ 406 for ( i=1000; --i>=0 ; ) { 407 if ( ReadByte(sc->sc_rom + 0) & PODULE_IRQ_PENDING ) 408 break; 409 delay (10); 410 } 411 412 /* If we didn't see the interrupt then the IRQ line is broken */ 413 if ( i<=0 ) { 414 printf ( ": interrupt from chipset didn't reach host\n" ); 415 sc->sc_flags |= IE_BROKEN; 416 return; 417 } 418 419 /* Ack our little test operation */ 420 ie_ack(sc,IE_ST_WHENCE); 421 ie_cli (sc); 422 423 /* Get second part of idrom */ 424 for ( i=16; i<32; i++ ) 425 idrom[i] = ReadByte ( sc->sc_rom + (i<<2) ); 426 427 /* This checksum always fails. For some reason the first 16 */ 428 /* bytes are duplicated in the second 16 bytes, the checksum */ 429 /* should be at location 28 it is clearly not */ 430 431 /* It is possible that this ether1 card is buggered */ 432 433 #ifndef IGNORE_ETHER1_IDROM_CHECKSUM 434 if ( crc32(idrom,28) != *(u_long *)(idrom+28) ) 435 { 436 printf ( "ie: ether1 idrom failed checksum %08x!=%08x\n", 437 crc32(idrom,28), *(u_long *)(idrom+28)); 438 for ( i=0; i<32; i+=8 ) { 439 printf ( "IDROM: %02x %02x %02x %02x %02x %02x %02x %02x\n", 440 idrom[0+i], idrom[1+i], idrom[2+i], idrom[3+i], 441 idrom[4+i], idrom[5+i], idrom[6+i], idrom[7+i] ); 442 } 443 printf ( "ie: I'll ignore this fact for now!\n" ); 444 } 445 #endif 446 447 /* Get our ethernet address. Do explicit copy */ 448 for ( i=0; i<ETHER_ADDR_LEN; i++ ) 449 hwaddr[i] = idrom[9+i]; 450 451 /* Fill in my application form to attach to the inet system */ 452 453 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 454 ifp->if_softc = sc; 455 ifp->if_start = iestart; 456 ifp->if_ioctl = ieioctl; 457 ifp->if_watchdog = iewatchdog; 458 ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS; 459 460 /* Signed, dated then sent */ 461 if_attach (ifp); 462 ether_ifattach(ifp, hwaddr); 463 464 /* "Hmm," said nuts, "what if the attach fails" */ 465 466 /* Write some pretty things on the annoucement line */ 467 printf ( ": %s using %dk card ram", 468 ether_sprintf(hwaddr), 469 ((NRXBUF*IE_RXBUF_SIZE)+(NTXBUF*IE_TXBUF_SIZE))/1024 ); 470 471 sc->sc_ih.ih_func = ieintr; 472 sc->sc_ih.ih_arg = sc; 473 sc->sc_ih.ih_level = IPL_NET; 474 sc->sc_ih.ih_name = "net: ie"; 475 sc->sc_ih.ih_maskaddr = sc->sc_podule->irq_addr; 476 sc->sc_ih.ih_maskbits = sc->sc_podule->irq_mask; 477 478 if (irq_claim(sc->sc_podule->interrupt, &sc->sc_ih)) { 479 sc->sc_irqmode = 0; 480 printf(" POLLED"); 481 panic("%s: Cannot install IRQ handler\n", sc->sc_dev.dv_xname); 482 } else { 483 sc->sc_irqmode = 1; 484 printf(" IRQ"); 485 } 486 487 printf("\n"); 488 } 489 490 491 /* 492 * Oh no!! Where's my shorts!!! I'm sure I put them on this morning 493 */ 494 495 void 496 PWriteShorts(src, dest, cnt) 497 char *src; 498 char *dest; 499 int cnt; 500 { 501 for (cnt /= 2; --cnt >= 0; ) { 502 PWriteShort(dest, *(u_short *)src); 503 src+=2; 504 dest+=4; 505 } 506 } 507 508 void 509 ReadShorts(src, dest, cnt) 510 char *src; 511 char *dest; 512 int cnt; 513 { 514 for (cnt /= 2; --cnt >= 0; ) { 515 *(u_short *)dest = ReadShort(src); 516 src+=4; 517 dest+=2; 518 } 519 } 520 521 /* 522 * A bcopy or memcpy to adapter ram. It handles the page register for you 523 * so you dont have to worry about the ram windowing 524 */ 525 526 static void 527 host2ie(sc, src, dest, size) 528 struct ie_softc *sc; 529 void *src; 530 u_long dest; 531 int size; 532 { 533 int cnt; 534 char *sptr = src; 535 536 #ifdef DIAGNOSTIC 537 if (size & 1) 538 panic("host2ie"); 539 #endif 540 541 while (size > 0) { 542 cnt = IE_PAGESIZE - dest % IE_PAGESIZE; 543 if (cnt > size) 544 cnt = size; 545 setpage(sc, dest); 546 PWriteShorts(sptr, (char *)sc->sc_ram + IE_COFF2POFF(dest), cnt); 547 sptr+=cnt; 548 dest+=cnt; 549 size-=cnt; 550 } 551 } 552 553 static void 554 ie2host(sc, src, dest, size) 555 struct ie_softc *sc; 556 u_long src; 557 void *dest; 558 int size; 559 { 560 int cnt; 561 char *dptr = dest; 562 563 #ifdef DIAGNOSTIC 564 if (size & 1) 565 panic ( "ie2host" ); 566 #endif 567 568 while (size > 0) { 569 cnt = IE_PAGESIZE - src % IE_PAGESIZE; 570 if (cnt > size) 571 cnt = size; 572 setpage(sc, src); 573 ReadShorts((char *)sc->sc_ram + IE_COFF2POFF(src), dptr, cnt); 574 src+=cnt; 575 dptr+=cnt; 576 size-=cnt; 577 } 578 } 579 580 /* 581 * Like a bzero or memset 0 for adapter memory. It handles the page 582 * register so you dont have to worry about it 583 */ 584 585 static void 586 iezero(sc, p, size) 587 struct ie_softc *sc; 588 u_long p; 589 int size; 590 { 591 int cnt; 592 593 while (size > 0) { 594 cnt = IE_PAGESIZE - p % IE_PAGESIZE; 595 if (cnt > size) 596 cnt=size; 597 setpage(sc, p); 598 bzero((char *)sc->sc_ram + IE_COFF2POFF(p), 2*cnt); 599 p += cnt; 600 size -= cnt; 601 } 602 } 603 604 /* 605 * I/O Control interface to the kernel, entry point here 606 */ 607 608 int 609 ieioctl(ifp, cmd, data) 610 struct ifnet *ifp; 611 u_long cmd; 612 caddr_t data; 613 { 614 struct ie_softc *sc = ifp->if_softc; 615 struct ifaddr *ifa = (struct ifaddr *)data; 616 /* struct ifreq *ifr = (struct ifreq *)data;*/ 617 int s; 618 int error=0; 619 620 s=splnet(); 621 622 switch ( cmd ) 623 { 624 case SIOCSIFADDR: 625 ifp->if_flags |= IFF_UP; 626 switch ( ifa->ifa_addr->sa_family ) { 627 #ifdef INET 628 case AF_INET: 629 ieinit(sc); 630 arp_ifinit(ifp, ifa ); 631 break; 632 #endif 633 default: 634 ieinit(sc); 635 break; 636 } 637 break; 638 639 #define IZSET(a,b) ((a->if_flags&b)!=0) 640 #define IZCLR(a,b) ((a->if_flags&b)==0) 641 #define DOSET(a,b) (a->if_flags|=b) 642 #define DOCLR(a,b) (a->if_flags&=~b) 643 644 case SIOCSIFFLAGS: 645 sc->promisc = ifp->if_flags & ( IFF_PROMISC | IFF_ALLMULTI ); 646 647 if ( IZCLR(ifp,IFF_UP) && IZSET(ifp,IFF_RUNNING) ) 648 { 649 /* Interface was marked down and its running so stop it */ 650 iestop(sc); 651 DOCLR(ifp,IFF_RUNNING); 652 } 653 else if ( IZSET(ifp,IFF_UP) && IZCLR(ifp,IFF_RUNNING) ) 654 { 655 /* Just marked up and we're not running so start it */ 656 ieinit(sc); 657 } 658 else 659 { 660 /* else reset to invoke changes in other registers */ 661 iestop(sc); 662 ieinit(sc); 663 } 664 665 default: 666 error = EINVAL; 667 } 668 (void)splx(s); 669 return error; 670 } 671 672 /* 673 * Reset the card. Completely. 674 */ 675 676 void 677 iereset(sc) 678 struct ie_softc *sc; 679 { 680 struct ie_sys_ctl_block scb; 681 int s = splnet(); 682 683 iestop(sc); 684 685 ie2host(sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb); 686 687 if (command_and_wait(sc, IE_RU_ABORT|IE_CU_ABORT, 0, 0, 0, 0, 0)) 688 printf("ie0: abort commands timed out\n"); 689 690 if (command_and_wait(sc, IE_RU_DISABLE|IE_CU_STOP, 0, 0, 0, 0, 0)) 691 printf("ie0: abort commands timed out\n"); 692 693 ieinit(sc); 694 695 (void)splx(s); 696 } 697 698 /* 699 * Watchdog entry point. This is the entry for the kernel to call us 700 */ 701 702 void 703 iewatchdog(ifp) 704 struct ifnet *ifp; 705 { 706 struct ie_softc *sc = ifp->if_softc; 707 708 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 709 ++ifp->if_oerrors; 710 iereset(sc); 711 } 712 713 /* 714 * Start the time-domain-refloctometer running 715 */ 716 717 static void 718 run_tdr(sc) 719 struct ie_softc *sc; 720 { 721 struct ie_sys_ctl_block scb; 722 u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb; 723 struct ie_tdr_cmd cmd; 724 int result; 725 726 bzero ( &scb, sizeof(scb) ); 727 bzero ( &cmd, sizeof(cmd) ); 728 729 cmd.com.ie_cmd_status = 0; 730 cmd.com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST; 731 cmd.com.ie_cmd_link = 0xffff; 732 cmd.ie_tdr_time = 0; 733 734 scb.ie_command_list = (u_short)ptr; 735 736 result=0; 737 if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd, 738 IE_STAT_COMPL) ) 739 { 740 result = 0x10000; 741 } 742 else if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) ) 743 { 744 result = 0x10000; 745 } 746 747 if ( result==0 ) 748 result = cmd.ie_tdr_time; 749 750 ie_ack ( sc, IE_ST_WHENCE ); 751 752 if (result & IE_TDR_SUCCESS ) 753 return; 754 755 /* Very messy. I'll tidy it later */ 756 757 if ( result & 0x10000 ) 758 { 759 printf ( "ie: TDR command failed\n" ); 760 } 761 else if ( result & IE_TDR_XCVR ) 762 { 763 printf ( "ie: tranceiver problem. Is it plugged in?\n" ); 764 } 765 else if ( result & IE_TDR_OPEN ) 766 { 767 if ((result & IE_TDR_TIME)>0) 768 printf ( "ie: TDR detected an open %d clocks away.\n", 769 result & IE_TDR_TIME ); 770 } 771 else if ( result & IE_TDR_SHORT ) 772 { 773 if ((result & IE_TDR_TIME)>0) 774 printf ( "ie: TDR detected a short %d clock away.\n", 775 result & IE_TDR_TIME ); 776 } 777 else 778 { 779 printf ( "ie: TDR returned unknown status %x\n", result ); 780 } 781 } 782 783 u_long 784 setup_rfa(sc, ptr) 785 struct ie_softc *sc; 786 u_long ptr; 787 { 788 int i; 789 { 790 /* Receive frame descriptors */ 791 struct ie_recv_frame_desc rfd; 792 bzero( &rfd, sizeof rfd ); 793 for ( i=0; i<NFRAMES; i++ ) 794 { 795 sc->rframes[i] = ptr; 796 rfd.ie_fd_next = ptr + sizeof rfd; 797 host2ie(sc, (char *)&rfd, ptr, sizeof rfd); 798 ptr += sizeof rfd; 799 } 800 rfd.ie_fd_next = sc->rframes[0]; 801 rfd.ie_fd_last |= IE_FD_LAST; 802 host2ie(sc, (char *)&rfd, sc->rframes[NFRAMES-1], sizeof rfd ); 803 804 ie2host(sc, sc->rframes[0], (char *)&rfd, sizeof rfd ); 805 rfd.ie_fd_buf_desc = (u_short) ptr; 806 host2ie(sc, (char *)&rfd, sc->rframes[0], sizeof rfd ); 807 } 808 809 { 810 /* Receive frame descriptors */ 811 struct ie_recv_buf_desc rbd; 812 bzero(&rbd, sizeof rbd); 813 for ( i=0; i<NRXBUF; i++ ) 814 { 815 sc->rbuffs[i] = ptr; 816 rbd.ie_rbd_length = IE_RXBUF_SIZE; 817 rbd.ie_rbd_buffer = (caddr_t)(ptr + sizeof rbd); 818 rbd.ie_rbd_next = (u_short)(ptr + sizeof rbd + IE_RXBUF_SIZE); 819 host2ie(sc, &rbd, ptr, sizeof rbd); 820 ptr+=sizeof rbd; 821 822 sc->cbuffs[i] = ptr; 823 ptr+=IE_RXBUF_SIZE; 824 } 825 rbd.ie_rbd_next = sc->rbuffs[0]; 826 rbd.ie_rbd_length |= IE_RBD_LAST; 827 host2ie(sc, &rbd, sc->rbuffs[NRXBUF-1], sizeof rbd); 828 } 829 830 sc->rfhead = 0; 831 sc->rftail = NFRAMES-1; 832 sc->rbhead = 0; 833 sc->rbtail = NRXBUF-1; 834 835 { 836 struct ie_sys_ctl_block scb; 837 bzero ( &scb, sizeof scb ); 838 scb.ie_recv_list = (u_short)sc->rframes[0]; 839 host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb ); 840 } 841 return ptr; 842 } 843 844 static void 845 start_receiver(sc) 846 struct ie_softc *sc; 847 { 848 struct ie_sys_ctl_block scb; 849 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 850 scb.ie_recv_list = (u_short)sc->rframes[0]; 851 command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0); 852 ie_ack(sc, IE_ST_WHENCE ); 853 } 854 855 /* 856 * Take our configuration and update all the other data structures that 857 * require information from the driver. 858 * 859 * CALL AT SPLIMP OR HIGHER 860 */ 861 862 int 863 ieinit(sc) 864 struct ie_softc *sc; 865 { 866 struct ifnet *ifp; 867 struct ie_sys_ctl_block scb; 868 struct ie_config_cmd cmd; 869 struct ie_iasetup_cmd iasetup_cmd; 870 u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb; 871 int n; 872 873 ifp = &sc->sc_ethercom.ec_if; 874 875 bzero ( &scb, sizeof(scb) ); 876 877 /* Send the configure command */ 878 879 cmd.com.ie_cmd_status = 0; 880 cmd.com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST; 881 cmd.com.ie_cmd_link = 0xffff; 882 883 cmd.ie_config_count = 0x0c; 884 cmd.ie_fifo = 8; 885 cmd.ie_save_bad = 0x40; 886 cmd.ie_addr_len = 0x2e; 887 cmd.ie_priority = 0; 888 cmd.ie_ifs = 0x60; 889 cmd.ie_slot_low = 0; 890 cmd.ie_slot_high = 0xf2; 891 cmd.ie_promisc = 0; /* Hey nuts, look at this! */ 892 cmd.ie_crs_cdt = 0; 893 cmd.ie_min_len = 64; 894 cmd.ie_junk = 0xff; 895 896 scb.ie_command_list = (u_short)ptr; 897 898 if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd, 899 IE_STAT_COMPL) ) 900 { 901 printf ( "%s: command failed: timeout\n", sc->sc_dev.dv_xname ); 902 return 0; 903 } 904 905 if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) ) 906 { 907 printf ( "%s: command failed: !IE_STAT_OK\n", sc->sc_dev.dv_xname ); 908 return 0; 909 } 910 911 /* Individual address setup command */ 912 913 iasetup_cmd.com.ie_cmd_status = 0; 914 iasetup_cmd.com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST; 915 iasetup_cmd.com.ie_cmd_link = 0xffff; 916 917 bcopy ( LLADDR(ifp->if_sadl), (caddr_t) &iasetup_cmd.ie_address, 918 sizeof (iasetup_cmd.ie_address) ); 919 920 if ( command_and_wait(sc, IE_CU_START, &scb, &iasetup_cmd, ptr, sizeof cmd, 921 IE_STAT_COMPL) ) 922 { 923 printf ( "%s: iasetup failed : timeout\n", sc->sc_dev.dv_xname ); 924 return 0; 925 } 926 927 if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) ) 928 { 929 printf ( "%s: iasetup failed : !IE_STAT_OK\n", sc->sc_dev.dv_xname ); 930 return 0; 931 } 932 933 ie_ack ( sc, IE_ST_WHENCE ); 934 935 /* Run the time-domain refloctometer */ 936 run_tdr ( sc ); 937 938 ie_ack ( sc, IE_ST_WHENCE ); 939 940 /* meminit */ 941 ptr = setup_rfa(sc, ptr); 942 943 ifp->if_flags |= IFF_RUNNING; 944 ifp->if_flags &= ~IFF_OACTIVE; 945 946 /* Setup transmit buffers */ 947 948 for ( n=0; n<NTXBUF; n++ ) { 949 sc->xmit_cmds[n] = ptr; 950 iezero(sc, ptr, sizeof(struct ie_xmit_cmd) ); 951 ptr += sizeof(struct ie_xmit_cmd); 952 953 sc->xmit_buffs[n] = ptr; 954 iezero(sc, ptr, sizeof(struct ie_xmit_buf)); 955 ptr += sizeof(struct ie_xmit_buf); 956 } 957 958 for ( n=0; n<NTXBUF; n++ ) { 959 sc->xmit_cbuffs[n] = ptr; 960 ptr += IE_TXBUF_SIZE; 961 } 962 963 sc->xmit_free = NTXBUF; 964 sc->xchead = sc->xctail = 0; 965 966 { 967 struct ie_xmit_cmd xmcmd; 968 bzero ( &xmcmd, sizeof xmcmd ); 969 xmcmd.ie_xmit_status = IE_STAT_COMPL; 970 host2ie(sc, &xmcmd, sc->xmit_cmds[0], sizeof xmcmd); 971 } 972 973 start_receiver (sc); 974 975 return 0; 976 } 977 978 int 979 iestop(sc) 980 struct ie_softc *sc; 981 { 982 struct ie_sys_ctl_block scb; 983 int s = splnet(); 984 985 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 986 987 if ( command_and_wait(sc, IE_RU_DISABLE, &scb, 0, 0, 0, 0) ) 988 printf ( "ie0: abort commands timed out\n" ); 989 990 (void)splx(s); 991 return(0); 992 } 993 994 /* 995 * Send a command to the card and awaits it's completion. 996 * Timeout if it's taking too long 997 */ 998 999 /*CAW*/ 1000 1001 static int 1002 command_and_wait(sc, cmd, pscb, pcmd, ocmd, scmd, mask) 1003 struct ie_softc *sc; 1004 u_short cmd; 1005 struct ie_sys_ctl_block *pscb; 1006 void *pcmd; 1007 int ocmd, scmd, mask; 1008 { 1009 int i=0; 1010 1011 /* Copy the command to the card */ 1012 1013 if ( pcmd ) 1014 host2ie(sc, pcmd, ocmd, scmd); /* transfer the command to the card */ 1015 1016 /* Copy the scb to the card */ 1017 1018 if ( pscb ) { 1019 pscb->ie_command = cmd; 1020 host2ie(sc, pscb, IE_IBASE + IE_SCB_OFF, sizeof *pscb); 1021 } 1022 else 1023 { 1024 setpage ( sc, IE_IBASE + IE_SCB_OFF ); 1025 PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 1026 (xoffsetof(struct ie_sys_ctl_block, ie_command)), cmd ); 1027 } 1028 1029 /* Prod the card to act on the newly loaded command */ 1030 ieattn(sc); 1031 1032 /* Wait for the command to complete */ 1033 if ( IE_ACTION_COMMAND(cmd) && pcmd ) 1034 { 1035 setpage(sc,ocmd); 1036 for ( i=4000; --i>=0; ) { 1037 if ( ReadShort(sc->sc_ram + IE_COFF2POFF(ocmd) + 1038 (xoffsetof(struct ie_config_cmd, ie_config_status))) & mask) 1039 break; 1040 delay(100); 1041 } 1042 } 1043 else 1044 { 1045 for ( i=4000; --i>=0; ) { 1046 if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 1047 (xoffsetof(struct ie_sys_ctl_block, ie_command))) ) 1048 break; 1049 delay(100); 1050 } 1051 } 1052 1053 /* Update the host structures to reflect the state on the card */ 1054 if ( pscb ) 1055 ie2host(sc, IE_IBASE + IE_SCB_OFF, pscb, sizeof *pscb ); 1056 if ( pcmd ) 1057 ie2host(sc, ocmd, pcmd, scmd); 1058 1059 return i < 0; 1060 } 1061 1062 #define READ_MEMBER(sc,type,member,ptr,dest) \ 1063 setpage(sc, ptr); \ 1064 dest = ReadShort(sc->sc_ram + IE_COFF2POFF(ptr) + \ 1065 (xoffsetof(type, member)) ); 1066 1067 #define WRITE_MEMBER(sc,type,member,ptr,dest) \ 1068 setpage(sc, ptr); \ 1069 PWriteShort(sc->sc_ram + IE_COFF2POFF(ptr) + \ 1070 (xoffsetof(type, member)), dest ); 1071 1072 static __inline int 1073 ie_buflen(sc, head) 1074 struct ie_softc *sc; 1075 int head; 1076 { 1077 int actual; 1078 1079 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, 1080 sc->rbuffs[head], actual ); 1081 1082 return(actual & (IE_RXBUF_SIZE | (IE_RXBUF_SIZE-1))) ; 1083 } 1084 1085 static __inline int 1086 ie_packet_len(sc) 1087 struct ie_softc *sc; 1088 { 1089 int i; 1090 int actual; 1091 int head = sc->rbhead; 1092 int acc=0; 1093 1094 do { 1095 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, 1096 sc->rbuffs[sc->rbhead], actual ); 1097 if (!(actual&IE_RBD_USED)) 1098 { 1099 return (-1); 1100 } 1101 1102 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, 1103 sc->rbuffs[head], i ); 1104 i = i & IE_RBD_LAST; 1105 1106 acc += ie_buflen(sc, head); 1107 head = (head+1) % NRXBUF; 1108 } while (!i); 1109 1110 return acc; 1111 } 1112 1113 struct mbuf * 1114 ieget(struct ie_softc *sc, int *to_bpf ) 1115 { 1116 struct mbuf *top, **mp, *m; 1117 int head; 1118 int resid, totlen, thisrboff, thismboff; 1119 int len; 1120 struct ether_header eh; 1121 1122 totlen = ie_packet_len(sc); 1123 1124 if ( totlen > ETHER_MAX_LEN ) 1125 { 1126 printf ( "ie: Gosh that packet was s-o-o-o big.\n" ); 1127 return 0; 1128 } 1129 1130 if ( totlen<=0 ) 1131 return 0; 1132 1133 head = sc->rbhead; 1134 1135 /* Read the ethernet header */ 1136 ie2host ( sc, sc->cbuffs[head], (caddr_t)&eh, sizeof eh ); 1137 1138 /* Check if the packet is for us */ 1139 1140 resid = totlen; 1141 1142 MGETHDR ( m, M_DONTWAIT, MT_DATA ); 1143 if ( m==0 ) 1144 return 0; 1145 1146 m->m_pkthdr.rcvif = &sc->sc_ethercom.ec_if; 1147 m->m_pkthdr.len = totlen; 1148 len = MHLEN; 1149 top = 0; 1150 mp = ⊤ 1151 1152 /* 1153 * This loop goes through and allocates mbufs for all the data we will 1154 * be copying in. It does not actually do the copying yet. 1155 */ 1156 while (totlen > 0) { 1157 if (top) { 1158 MGET(m, M_DONTWAIT, MT_DATA); 1159 if (m == 0) { 1160 m_freem(top); 1161 return 0; 1162 } 1163 len = MLEN; 1164 } 1165 if (totlen >= MINCLSIZE) { 1166 MCLGET(m, M_DONTWAIT); 1167 if (m->m_flags & M_EXT) 1168 len = MCLBYTES; 1169 } 1170 1171 if (mp == &top) { 1172 caddr_t newdata = (caddr_t) 1173 ALIGN(m->m_data + sizeof(struct ether_header)) - 1174 sizeof(struct ether_header); 1175 len -= newdata - m->m_data; 1176 m->m_data = newdata; 1177 } 1178 1179 m->m_len = len = min(totlen, len); 1180 1181 totlen -= len; 1182 *mp = m; 1183 mp = &m->m_next; 1184 } 1185 1186 m = top; 1187 thismboff = 0; 1188 1189 /* 1190 * Copy the Ethernet header into the mbuf chain. 1191 */ 1192 memcpy(mtod(m, caddr_t), &eh, sizeof(struct ether_header)); 1193 thismboff = sizeof(struct ether_header); 1194 thisrboff = sizeof(struct ether_header); 1195 resid -= sizeof(struct ether_header); 1196 1197 /* 1198 * Now we take the mbuf chain (hopefully only one mbuf most of the 1199 * time) and stuff the data into it. There are no possible failures at 1200 * or after this point. 1201 */ 1202 while (resid > 0) { 1203 int thisrblen = ie_buflen(sc, head) - thisrboff, 1204 thismblen = m->m_len - thismboff; 1205 len = min(thisrblen, thismblen); 1206 1207 /* bcopy((caddr_t)(sc->cbuffs[head] + thisrboff), 1208 mtod(m, caddr_t) + thismboff, (u_int)len); */ 1209 1210 1211 if ( len&1 ) 1212 { 1213 ie2host(sc, sc->cbuffs[head]+thisrboff, 1214 mtod(m, caddr_t) + thismboff, (u_int)len+1); 1215 } 1216 else 1217 { 1218 ie2host(sc, sc->cbuffs[head]+thisrboff, 1219 mtod(m, caddr_t) + thismboff, (u_int)len); 1220 } 1221 1222 resid -= len; 1223 1224 if (len == thismblen) { 1225 m = m->m_next; 1226 thismboff = 0; 1227 } else 1228 thismboff += len; 1229 1230 if (len == thisrblen) { 1231 head = (head + 1) % NRXBUF; 1232 thisrboff = 0; 1233 } else 1234 thisrboff += len; 1235 } 1236 1237 1238 return top; 1239 } 1240 1241 void 1242 ie_drop_packet_buffer(sc) 1243 struct ie_softc *sc; 1244 { 1245 int i, actual, last; 1246 1247 do { 1248 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, 1249 sc->rbuffs[sc->rbhead], actual ); 1250 if (!(actual&IE_RBD_USED)) 1251 { 1252 iereset(sc); 1253 return; 1254 } 1255 1256 i = actual & IE_RBD_LAST; 1257 1258 READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, 1259 sc->rbuffs[sc->rbhead], last ); 1260 last |= IE_RBD_LAST; 1261 WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, 1262 sc->rbuffs[sc->rbhead], last ); 1263 1264 WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_actual, 1265 sc->rbuffs[sc->rbhead], 0 ); 1266 1267 sc->rbhead = ( sc->rbhead + 1 ) % NRXBUF; 1268 1269 READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, 1270 sc->rbuffs[sc->rbtail], last ); 1271 last &= ~IE_RBD_LAST; 1272 WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, 1273 sc->rbuffs[sc->rbtail], last ); 1274 1275 sc->rbtail = ( sc->rbtail + 1 ) % NRXBUF; 1276 } while (!i); 1277 } 1278 1279 void 1280 ie_read_frame(sc, num) 1281 struct ie_softc *sc; 1282 int num; 1283 { 1284 int status; 1285 struct ie_recv_frame_desc rfd; 1286 struct mbuf *m=0; 1287 struct ifnet *ifp; 1288 int last; 1289 1290 ifp = &sc->sc_ethercom.ec_if; 1291 1292 ie2host(sc, sc->rframes[num], &rfd, sizeof rfd ); 1293 status = rfd.ie_fd_status; 1294 1295 /* Advance the RFD list, since we're done with this descriptor */ 1296 1297 WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status, 1298 sc->rframes[num], 0 ); 1299 1300 READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, 1301 sc->rframes[num], last ); 1302 last |= IE_FD_LAST; 1303 WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, 1304 sc->rframes[num], last ); 1305 1306 READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, 1307 sc->rframes[sc->rftail], last ); 1308 last &= ~IE_FD_LAST; 1309 WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, 1310 sc->rframes[sc->rftail], last ); 1311 1312 sc->rftail = ( sc->rftail + 1 ) % NFRAMES; 1313 sc->rfhead = ( sc->rfhead + 1 ) % NFRAMES; 1314 1315 if ( status & IE_FD_OK ) { 1316 m = ieget(sc, 0); 1317 ie_drop_packet_buffer(sc); 1318 } 1319 1320 if ( m==0 ) { 1321 ifp->if_ierrors++; 1322 return; 1323 } 1324 1325 ifp->if_ipackets++; 1326 1327 #if NBPFILTER > 0 1328 if ( ifp->if_bpf ) { 1329 bpf_mtap(ifp->if_bpf, m ); 1330 }; 1331 #endif 1332 1333 (*ifp->if_input)(ifp, m); 1334 } 1335 1336 void 1337 ierint(sc) 1338 struct ie_softc *sc; 1339 { 1340 int i; 1341 int times_thru = 1024; 1342 struct ie_sys_ctl_block scb; 1343 int status; 1344 int safety_catch = 0; 1345 1346 i = sc->rfhead; 1347 for (;;) { 1348 1349 if ( (safety_catch++)>100 ) 1350 { 1351 printf ( "ie: ierint safety catch tripped\n" ); 1352 iereset(sc); 1353 return; 1354 } 1355 1356 READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status, 1357 sc->rframes[i],status); 1358 1359 if ((status&IE_FD_COMPLETE)&&(status&IE_FD_OK)) { 1360 if ( !--times_thru ) { 1361 printf ( "IERINT: Uh oh. Nuts, look at this bit!!!\n" ); 1362 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 1363 sc->sc_ethercom.ec_if.if_ierrors += scb.ie_err_crc + 1364 scb.ie_err_align + 1365 scb.ie_err_resource + 1366 scb.ie_err_overrun; 1367 scb.ie_err_crc = scb.ie_err_align = 0; 1368 scb.ie_err_resource = scb.ie_err_overrun = 0; 1369 host2ie(sc, &scb, IE_SCP_ADDR, sizeof (scb) ); 1370 } 1371 ie_read_frame(sc, i); 1372 } else { 1373 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 1374 1375 if ( ((status&IE_FD_RNR)!=0) && ((scb.ie_status&IE_RU_READY)==0) ) 1376 { 1377 WRITE_MEMBER(sc,struct ie_recv_frame_desc, ie_fd_buf_desc, 1378 sc->rframes[0], sc->rbuffs[0] ); 1379 1380 scb.ie_recv_list = sc->rframes[0]; 1381 host2ie(sc, (char *)&scb, IE_IBASE + IE_SCB_OFF, sizeof (scb) ); 1382 command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0); 1383 } 1384 break; 1385 } 1386 i = (i + 1) % NFRAMES; 1387 } 1388 } 1389 1390 static int in_intr = 0; 1391 1392 int 1393 ieintr(arg) 1394 void *arg; 1395 { 1396 struct ie_softc *sc = arg; 1397 u_short status; 1398 int safety_catch = 0; 1399 static int safety_net = 0; 1400 1401 if (in_intr == 1) 1402 panic ( "ie: INTERRUPT REENTERED\n" ); 1403 1404 /* Clear the interrrupt */ 1405 ie_cli (sc); 1406 1407 setpage(sc, IE_IBASE + IE_SCB_OFF ); 1408 status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 1409 (xoffsetof(struct ie_sys_ctl_block, ie_status)) ); 1410 1411 status = status & IE_ST_WHENCE; 1412 1413 if (status == 0) { 1414 in_intr = 0; 1415 return(0); 1416 } 1417 1418 loop: 1419 1420 ie_ack(sc, status); 1421 1422 if (status & (IE_ST_FR | IE_ST_RNR)) 1423 ierint(sc); 1424 1425 if (status & IE_ST_CX) 1426 ietint(sc); 1427 1428 if (status & IE_ST_RNR) { 1429 printf ( "ie: receiver not ready\n" ); 1430 sc->sc_ethercom.ec_if.if_ierrors++; 1431 iereset(sc); 1432 } 1433 1434 setpage(sc, IE_IBASE + IE_SCB_OFF ); 1435 status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 1436 (xoffsetof(struct ie_sys_ctl_block, ie_status)) ); 1437 status = status & IE_ST_WHENCE; 1438 1439 ie_cli(sc); 1440 1441 if (status == 0) { 1442 in_intr = 0; 1443 return(0); 1444 } 1445 1446 /* This is prehaps a little over cautious */ 1447 if ( safety_catch++ > 10 ) 1448 { 1449 printf ( "ie: Interrupt couldn't be cleared\n" ); 1450 delay ( 1000 ); 1451 ie_cli(sc); 1452 if ( safety_net++ > 50 ) 1453 { 1454 /* printf ( "ie: safety net catches driver, shutting down\n" ); 1455 disable_irq ( IRQ_PODULE );*/ 1456 } 1457 in_intr = 0; 1458 return(0); 1459 } 1460 1461 goto loop; 1462 } 1463 1464 void 1465 iexmit(sc) 1466 struct ie_softc *sc; 1467 { 1468 /* int actual;*/ 1469 struct ie_sys_ctl_block scb; 1470 1471 struct ie_xmit_cmd xc; 1472 struct ie_xmit_buf xb; 1473 1474 ie2host(sc, sc->xmit_buffs[sc->xctail], (char *)&xb, sizeof xb ); 1475 xb.ie_xmit_flags |= IE_XMIT_LAST; 1476 xb.ie_xmit_next = 0xffff; 1477 xb.ie_xmit_buf = (caddr_t)sc->xmit_cbuffs[sc->xctail]; 1478 host2ie(sc, &xb, sc->xmit_buffs[sc->xctail], sizeof xb ); 1479 1480 bzero ( &xc, sizeof xc ); 1481 xc.com.ie_cmd_link = 0xffff; 1482 xc.com.ie_cmd_cmd = IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST; 1483 xc.ie_xmit_status = 0x0000; 1484 xc.ie_xmit_desc = sc->xmit_buffs[sc->xctail]; 1485 host2ie(sc, (char *)&xc, sc->xmit_cmds[sc->xctail], sizeof xc ); 1486 1487 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 1488 scb.ie_command_list = sc->xmit_cmds[sc->xctail]; 1489 host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb ); 1490 1491 command_and_wait(sc, IE_CU_START, &scb, &xc, sc->xmit_cmds[sc->xctail] 1492 , sizeof xc, IE_STAT_COMPL); 1493 1494 sc->sc_ethercom.ec_if.if_timer = 5; 1495 } 1496 /* 1497 * Start sending all the queued buffers. 1498 */ 1499 1500 void 1501 iestart(ifp) 1502 struct ifnet *ifp; 1503 { 1504 struct ie_softc *sc = ifp->if_softc; 1505 struct mbuf *m0, *m; 1506 u_char *buffer; 1507 u_short len; 1508 char txbuf[IE_TXBUF_SIZE]; 1509 int safety_catch = 0; 1510 1511 if ((ifp->if_flags & IFF_OACTIVE) != 0) 1512 return; 1513 1514 for (;;) { 1515 if ( (safety_catch++)>100 ) 1516 { 1517 printf ( "ie: iestart safety catch tripped\n" ); 1518 iereset(sc); 1519 return; 1520 } 1521 if (sc->xmit_free == 0) { 1522 ifp->if_flags |= IFF_OACTIVE; 1523 break; 1524 } 1525 1526 IF_DEQUEUE(&ifp->if_snd, m); 1527 if (!m) 1528 break; 1529 1530 /* TODO: Write directly to the card */ 1531 len = 0; 1532 /* buffer = sc->xmit_cbuffs[sc->xchead]; */ 1533 buffer = txbuf; 1534 1535 for (m0 = m; m && (len + m->m_len) < IE_TXBUF_SIZE; 1536 m = m->m_next) { 1537 bcopy(mtod(m, caddr_t), buffer, m->m_len); 1538 buffer += m->m_len; 1539 len += m->m_len; 1540 } 1541 1542 #if NBPFILTER > 0 1543 if ( ifp->if_bpf ) 1544 bpf_mtap(ifp->if_bpf, m0); 1545 #endif 1546 1547 m_freem(m0); 1548 len = max(len, ETHER_MIN_LEN); 1549 1550 /* When we write directly to the card we dont need this */ 1551 if (len&1) 1552 host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len+1 ); 1553 else 1554 host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len ); 1555 1556 /* sc->xmit_buffs[sc->xchead]->ie_xmit_flags = len; */ 1557 1558 WRITE_MEMBER(sc,struct ie_xmit_buf, ie_xmit_flags, 1559 sc->xmit_buffs[sc->xchead], len) 1560 1561 /* Start the first packet transmitting. */ 1562 if (sc->xmit_free == NTXBUF) 1563 iexmit(sc); 1564 1565 sc->xchead = (sc->xchead + 1) % NTXBUF; 1566 sc->xmit_free--; 1567 } 1568 } 1569 1570 void 1571 ietint(sc) 1572 struct ie_softc *sc; 1573 { 1574 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1575 1576 int status; 1577 1578 ifp->if_timer=0; 1579 ifp->if_flags &= ~IFF_OACTIVE; 1580 1581 READ_MEMBER(sc,struct ie_xmit_cmd, ie_xmit_status, 1582 sc->xmit_cmds[sc->xctail], status ); 1583 1584 if (!(status&IE_STAT_COMPL) || (status & IE_STAT_BUSY) ) 1585 printf ( "ietint: command still busy!\n" ); 1586 1587 if ( status & IE_STAT_OK ) { 1588 ifp->if_opackets++; 1589 ifp->if_collisions += status & IE_XS_MAXCOLL; 1590 } else { 1591 ifp->if_oerrors++; 1592 if ( status & IE_STAT_ABORT ) 1593 printf ( "ie: send aborted\n" ); 1594 if ( status & IE_XS_LATECOLL ) 1595 printf ( "ie: late collision\n" ); 1596 if ( status & IE_XS_NOCARRIER ) 1597 printf ( "ie: no carrier\n" ); 1598 if ( status & IE_XS_LOSTCTS ) 1599 printf ( "ie: lost CTS\n" ); 1600 if ( status & IE_XS_UNDERRUN ) 1601 printf ( "ie: DMA underrun\n" ); 1602 if ( status & IE_XS_EXCMAX ) 1603 printf ( "ie: too many collisions\n" ); 1604 ifp->if_collisions+=16; 1605 } 1606 /* Done with the buffer */ 1607 sc->xmit_free++; 1608 sc->xctail = (sc->xctail + 1 ) % NTXBUF; 1609 1610 /* Start the next packet transmitting, if any */ 1611 if ( sc->xmit_free<NTXBUF ) 1612 iexmit(sc); 1613 1614 iestart(ifp); 1615 } 1616 1617 /* End of if_ie.c */ 1618