1 /* $NetBSD: if_ie.c,v 1.25 2009/03/18 17:06:41 cegger 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 #include <sys/cdefs.h> 56 __KERNEL_RCSID(0, "$NetBSD: if_ie.c,v 1.25 2009/03/18 17:06:41 cegger Exp $"); 57 58 #define IGNORE_ETHER1_IDROM_CHECKSUM 59 60 /* Standard podule includes */ 61 62 #include "opt_inet.h" 63 #include "opt_ns.h" 64 65 #include <sys/param.h> 66 67 #include <sys/systm.h> 68 #include <sys/kernel.h> 69 #include <sys/conf.h> 70 #include <sys/malloc.h> 71 #include <sys/device.h> 72 #include <machine/io.h> 73 #include <machine/intr.h> 74 #include <arm/arm32/katelib.h> 75 #include <acorn32/podulebus/podulebus.h> 76 #include <dev/podulebus/podules.h> 77 78 /* Include for interface to the net and ethernet subsystems */ 79 80 #include <sys/socket.h> 81 #include <sys/syslog.h> 82 #include <sys/ioctl.h> 83 #include <sys/mbuf.h> 84 85 #include <net/if.h> 86 #include <net/if_types.h> 87 #include <net/if_dl.h> 88 #include <net/if_ether.h> 89 90 #ifdef INET 91 #include <netinet/in.h> 92 #include <netinet/in_systm.h> 93 #include <netinet/in_var.h> 94 #include <netinet/ip.h> 95 #include <netinet/if_inarp.h> 96 #endif 97 98 #ifdef NS 99 #include <netns/ns.h> 100 #include <netns/ns_if.h> 101 #endif 102 103 /* Import our data structres */ 104 105 #include "if_iereg.h" 106 107 /* BPF support */ 108 109 #include "bpfilter.h" 110 #if NBPFILTER > 0 111 #include <net/bpf.h> 112 #include <net/bpfdesc.h> 113 #endif 114 115 /* Some useful defines and macros */ 116 117 #define PODULE_IRQ_PENDING (1) 118 #define NFRAMES (16) /* number of frame to allow for receive */ 119 #define NRXBUF (48) /* number of receive buffers to allocate */ 120 #define IE_RXBUF_SIZE (256) /* receive buf size */ 121 #define NTXBUF (2) /* number of transmit buffers to allocate */ 122 #define IE_TXBUF_SIZE (1522) /* size of tx buffer */ 123 124 #define PWriteShort(a,b) WriteWord(a,(b)<<16|(b)) 125 126 #define xoffsetof(type, member) (offsetof(type, member) << 1) 127 128 /* Some data structres local to this file */ 129 130 struct ie_softc { 131 struct device sc_dev; 132 int sc_podule_number; 133 podule_t *sc_podule; 134 irqhandler_t sc_ih; 135 int sc_flags; 136 #define IE_BROKEN 1 137 int sc_iobase; 138 int sc_fastbase; 139 int sc_rom; 140 int sc_ram; 141 int sc_control; 142 struct ethercom sc_ethercom; 143 int promisc; 144 int sc_irqmode; 145 146 u_long rframes[NFRAMES]; 147 u_long rbuffs[NRXBUF]; 148 u_long cbuffs[NRXBUF]; 149 int rfhead, rftail, rbhead, rbtail; 150 151 u_long xmit_cmds[NTXBUF]; 152 u_long xmit_buffs[NTXBUF]; 153 u_long xmit_cbuffs[NTXBUF]; 154 int xmit_count; 155 int xmit_free; 156 int xchead; 157 int xctail; 158 }; 159 160 /* Function and data prototypes */ 161 162 static void host2ie( struct ie_softc *sc, void *src, u_long dest, int size ); 163 static void ie2host( struct ie_softc *sc, u_long src, void *dest, int size ); 164 static void iezero( struct ie_softc *sc, u_long p, int size ); 165 void iereset( struct ie_softc *sc ); 166 void iewatchdog( struct ifnet *ifp ); 167 int ieioctl( struct ifnet *ifp, u_long cmd, void *data ); 168 void iestart( struct ifnet *ifp ); 169 int iestop( struct ie_softc *sc ); 170 int ieinit( struct ie_softc *sc ); 171 int ieintr( void *arg ); 172 void ietint( struct ie_softc *sc ); 173 174 /* A whopper of a function */ 175 static int command_and_wait( struct ie_softc *sc, u_short cmd, 176 struct ie_sys_ctl_block *pscb, 177 void *pcmd, int ocmd, int scmd, int mask ); 178 179 int ieprobe(struct device *, struct cfdata *, void *); 180 void ieattach(struct device *, struct device *, void *); 181 182 static inline void ie_cli(struct ie_softc *); 183 static inline void ieattn(struct ie_softc *); 184 static inline void setpage(struct ie_softc *, u_long); 185 static void ie_ack(struct ie_softc *, u_short); 186 void PWriteShorts(char *, char *, int); 187 void ReadShorts(char *, char *, int); 188 static void run_tdr(struct ie_softc *); 189 u_long setup_rfa(struct ie_softc *, u_long); 190 static inline int ie_buflen(struct ie_softc *, int); 191 static inline int ie_packet_len(struct ie_softc *); 192 struct mbuf *ieget(struct ie_softc *, int *); 193 void ie_drop_packet_buffer(struct ie_softc *); 194 void ie_read_frame(struct ie_softc *, int num); 195 void ierint(struct ie_softc *); 196 void iexmit(struct ie_softc *); 197 static void start_receiver(struct ie_softc *); 198 199 200 /* 201 * Our cfattach structure for the autoconfig system to chew on 202 */ 203 204 CFATTACH_DECL(ie, sizeof(struct ie_softc), 205 ieprobe, ieattach, NULL, NULL); 206 207 /* Let's go! */ 208 209 /* 210 * Clear all pending interrupts from the i82586 chip 211 */ 212 213 static inline void 214 ie_cli(struct ie_softc *sc) 215 { 216 WriteByte(sc->sc_fastbase + (IE_CONTROL<<2), IE_CONT_CLI); 217 } 218 219 /* 220 * Wake the i82586 chip up and get it to do something 221 */ 222 223 static inline void 224 ieattn(struct ie_softc *sc) 225 { 226 WriteByte ( sc->sc_control + (IE_CONTROL<<2), IE_CONT_ATTN ); 227 } 228 229 /* 230 * Set the podule page register to bring a given address into view 231 */ 232 233 static inline void 234 setpage(struct ie_softc *sc, u_long off) 235 { 236 WriteByte ( sc->sc_control + (IE_PAGE<<2), IE_COFF2PAGE(off) ); 237 } 238 239 /* 240 * Ack the i82586 241 */ 242 243 static void 244 ie_ack(struct ie_softc *sc, u_short mask) 245 { 246 u_short stat; 247 int i; 248 setpage(sc, IE_IBASE + IE_SCB_OFF ); 249 250 stat = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 251 (xoffsetof(struct ie_sys_ctl_block, ie_status)) ); 252 253 PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 254 (xoffsetof(struct ie_sys_ctl_block, ie_command)), 255 stat & mask ); 256 257 ieattn(sc); 258 259 for ( i=4000; --i>=0; ) { 260 if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 261 (xoffsetof(struct ie_sys_ctl_block, ie_command))) ) 262 break; 263 delay(100); 264 } 265 266 if ( i<=0 ) 267 printf ( "ie: command timed out\n" ); 268 ie_cli(sc); 269 } 270 271 /* 272 * This routine does the checksumming for the idrom 273 */ 274 275 #ifndef IGNORE_ETHER1_IDROM_CHECKSUM 276 static u_long 277 crc32(u_char *p, int l) 278 { 279 u_long crc=-1; 280 int i, b; 281 while ( --l >= 0 ) { 282 b = *p++; 283 for ( i=8; --i >= 0; b>>=1 ) 284 if ((b&1)^(crc>>31)) 285 crc=(crc<<1)^0x4c11db7; 286 else 287 crc<<=1; 288 } 289 return crc; 290 } 291 #endif 292 293 /* 294 * Probe for the ether1 card. return 1 on success 0 on failure 295 */ 296 297 int 298 ieprobe(struct device *parent, struct cfdata *cf, void *aux) 299 { 300 struct podule_attach_args *pa = (void *)aux; 301 302 /* Look for a network slot interface */ 303 304 return (pa->pa_product == PODULE_ETHER1); 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 = (void *)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 = (void *)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 memcpy( ifp->if_xname, sc->sc_dev.dv_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", 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(char *src, char *dest, int cnt) 497 { 498 for (cnt /= 2; --cnt >= 0; ) { 499 PWriteShort(dest, *(u_short *)src); 500 src+=2; 501 dest+=4; 502 } 503 } 504 505 void 506 ReadShorts(char *src, char *dest, int cnt) 507 { 508 for (cnt /= 2; --cnt >= 0; ) { 509 *(u_short *)dest = ReadShort(src); 510 src+=4; 511 dest+=2; 512 } 513 } 514 515 /* 516 * A bcopy or memcpy to adapter ram. It handles the page register for you 517 * so you dont have to worry about the ram windowing 518 */ 519 520 static void 521 host2ie(struct ie_softc *sc, void *src, u_long dest, int size) 522 { 523 int cnt; 524 char *sptr = src; 525 526 #ifdef DIAGNOSTIC 527 if (size & 1) 528 panic("host2ie"); 529 #endif 530 531 while (size > 0) { 532 cnt = IE_PAGESIZE - dest % IE_PAGESIZE; 533 if (cnt > size) 534 cnt = size; 535 setpage(sc, dest); 536 PWriteShorts(sptr, (char *)sc->sc_ram + IE_COFF2POFF(dest), cnt); 537 sptr+=cnt; 538 dest+=cnt; 539 size-=cnt; 540 } 541 } 542 543 static void 544 ie2host(struct ie_softc *sc, u_long src, void *dest, int size) 545 { 546 int cnt; 547 char *dptr = dest; 548 549 #ifdef DIAGNOSTIC 550 if (size & 1) 551 panic ( "ie2host" ); 552 #endif 553 554 while (size > 0) { 555 cnt = IE_PAGESIZE - src % IE_PAGESIZE; 556 if (cnt > size) 557 cnt = size; 558 setpage(sc, src); 559 ReadShorts((char *)sc->sc_ram + IE_COFF2POFF(src), dptr, cnt); 560 src+=cnt; 561 dptr+=cnt; 562 size-=cnt; 563 } 564 } 565 566 /* 567 * Like a bzero or memset 0 for adapter memory. It handles the page 568 * register so you dont have to worry about it 569 */ 570 571 static void 572 iezero(struct ie_softc *sc, u_long p, int size) 573 { 574 int cnt; 575 576 while (size > 0) { 577 cnt = IE_PAGESIZE - p % IE_PAGESIZE; 578 if (cnt > size) 579 cnt=size; 580 setpage(sc, p); 581 memset((char *)sc->sc_ram + IE_COFF2POFF(p), 0, 2*cnt); 582 p += cnt; 583 size -= cnt; 584 } 585 } 586 587 /* 588 * I/O Control interface to the kernel, entry point here 589 */ 590 591 int 592 ieioctl(struct ifnet *ifp, unsigned long cmd, void *data) 593 { 594 struct ie_softc *sc = ifp->if_softc; 595 struct ifaddr *ifa = (struct ifaddr *)data; 596 int s; 597 int error=0; 598 599 s=splnet(); 600 601 switch ( cmd ) 602 { 603 case SIOCINITIFADDR: 604 ifp->if_flags |= IFF_UP; 605 switch (ifa->ifa_addr->sa_family ) { 606 #ifdef INET 607 case AF_INET: 608 ieinit(sc); 609 arp_ifinit(ifp, ifa ); 610 break; 611 #endif 612 default: 613 ieinit(sc); 614 break; 615 } 616 break; 617 618 #define IZSET(a,b) ((a->if_flags&b)!=0) 619 #define IZCLR(a,b) ((a->if_flags&b)==0) 620 #define DOSET(a,b) (a->if_flags|=b) 621 #define DOCLR(a,b) (a->if_flags&=~b) 622 623 case SIOCSIFFLAGS: 624 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 625 return error; 626 sc->promisc = ifp->if_flags & ( IFF_PROMISC | IFF_ALLMULTI ); 627 628 if ( IZCLR(ifp,IFF_UP) && IZSET(ifp,IFF_RUNNING) ) 629 { 630 /* Interface was marked down and its running so stop it */ 631 iestop(sc); 632 DOCLR(ifp,IFF_RUNNING); 633 } 634 else if ( IZSET(ifp,IFF_UP) && IZCLR(ifp,IFF_RUNNING) ) 635 { 636 /* Just marked up and we're not running so start it */ 637 ieinit(sc); 638 } 639 else 640 { 641 /* else reset to invoke changes in other registers */ 642 iestop(sc); 643 ieinit(sc); 644 } 645 646 default: 647 error = ether_ioctl(ifp, cmd, data); 648 break; 649 } 650 (void)splx(s); 651 return error; 652 } 653 654 /* 655 * Reset the card. Completely. 656 */ 657 658 void 659 iereset(struct ie_softc *sc) 660 { 661 struct ie_sys_ctl_block scb; 662 int s = splnet(); 663 664 iestop(sc); 665 666 ie2host(sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb); 667 668 if (command_and_wait(sc, IE_RU_ABORT|IE_CU_ABORT, 0, 0, 0, 0, 0)) 669 printf("ie0: abort commands timed out\n"); 670 671 if (command_and_wait(sc, IE_RU_DISABLE|IE_CU_STOP, 0, 0, 0, 0, 0)) 672 printf("ie0: abort commands timed out\n"); 673 674 ieinit(sc); 675 676 (void)splx(s); 677 } 678 679 /* 680 * Watchdog entry point. This is the entry for the kernel to call us 681 */ 682 683 void 684 iewatchdog(struct ifnet *ifp) 685 { 686 struct ie_softc *sc = ifp->if_softc; 687 688 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 689 ++ifp->if_oerrors; 690 iereset(sc); 691 } 692 693 /* 694 * Start the time-domain-refloctometer running 695 */ 696 697 static void 698 run_tdr(struct ie_softc *sc) 699 { 700 struct ie_sys_ctl_block scb; 701 u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb; 702 struct ie_tdr_cmd cmd; 703 int result; 704 705 bzero ( &scb, sizeof(scb) ); 706 bzero ( &cmd, sizeof(cmd) ); 707 708 cmd.com.ie_cmd_status = 0; 709 cmd.com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST; 710 cmd.com.ie_cmd_link = 0xffff; 711 cmd.ie_tdr_time = 0; 712 713 scb.ie_command_list = (u_short)ptr; 714 715 result=0; 716 if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd, 717 IE_STAT_COMPL) ) 718 { 719 result = 0x10000; 720 } 721 else if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) ) 722 { 723 result = 0x10000; 724 } 725 726 if ( result==0 ) 727 result = cmd.ie_tdr_time; 728 729 ie_ack ( sc, IE_ST_WHENCE ); 730 731 if (result & IE_TDR_SUCCESS ) 732 return; 733 734 /* Very messy. I'll tidy it later */ 735 736 if ( result & 0x10000 ) 737 { 738 printf ( "ie: TDR command failed\n" ); 739 } 740 else if ( result & IE_TDR_XCVR ) 741 { 742 printf ( "ie: tranceiver problem. Is it plugged in?\n" ); 743 } 744 else if ( result & IE_TDR_OPEN ) 745 { 746 if ((result & IE_TDR_TIME)>0) 747 printf ( "ie: TDR detected an open %d clocks away.\n", 748 result & IE_TDR_TIME ); 749 } 750 else if ( result & IE_TDR_SHORT ) 751 { 752 if ((result & IE_TDR_TIME)>0) 753 printf ( "ie: TDR detected a short %d clock away.\n", 754 result & IE_TDR_TIME ); 755 } 756 else 757 { 758 printf ( "ie: TDR returned unknown status %x\n", result ); 759 } 760 } 761 762 u_long 763 setup_rfa(struct ie_softc *sc, u_long ptr) 764 { 765 int i; 766 { 767 /* Receive frame descriptors */ 768 struct ie_recv_frame_desc rfd; 769 memset( &rfd, 0, sizeof rfd ); 770 for ( i=0; i<NFRAMES; i++ ) 771 { 772 sc->rframes[i] = ptr; 773 rfd.ie_fd_next = ptr + sizeof rfd; 774 host2ie(sc, (char *)&rfd, ptr, sizeof rfd); 775 ptr += sizeof rfd; 776 } 777 rfd.ie_fd_next = sc->rframes[0]; 778 rfd.ie_fd_last |= IE_FD_LAST; 779 host2ie(sc, (char *)&rfd, sc->rframes[NFRAMES-1], sizeof rfd ); 780 781 ie2host(sc, sc->rframes[0], (char *)&rfd, sizeof rfd ); 782 rfd.ie_fd_buf_desc = (u_short) ptr; 783 host2ie(sc, (char *)&rfd, sc->rframes[0], sizeof rfd ); 784 } 785 786 { 787 /* Receive frame descriptors */ 788 struct ie_recv_buf_desc rbd; 789 memset(&rbd, 0, sizeof rbd); 790 for ( i=0; i<NRXBUF; i++ ) 791 { 792 sc->rbuffs[i] = ptr; 793 rbd.ie_rbd_length = IE_RXBUF_SIZE; 794 rbd.ie_rbd_buffer = (void *)(ptr + sizeof rbd); 795 rbd.ie_rbd_next = (u_short)(ptr + sizeof rbd + IE_RXBUF_SIZE); 796 host2ie(sc, &rbd, ptr, sizeof rbd); 797 ptr+=sizeof rbd; 798 799 sc->cbuffs[i] = ptr; 800 ptr+=IE_RXBUF_SIZE; 801 } 802 rbd.ie_rbd_next = sc->rbuffs[0]; 803 rbd.ie_rbd_length |= IE_RBD_LAST; 804 host2ie(sc, &rbd, sc->rbuffs[NRXBUF-1], sizeof rbd); 805 } 806 807 sc->rfhead = 0; 808 sc->rftail = NFRAMES-1; 809 sc->rbhead = 0; 810 sc->rbtail = NRXBUF-1; 811 812 { 813 struct ie_sys_ctl_block scb; 814 bzero ( &scb, sizeof scb ); 815 scb.ie_recv_list = (u_short)sc->rframes[0]; 816 host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb ); 817 } 818 return ptr; 819 } 820 821 static void 822 start_receiver(struct ie_softc *sc) 823 { 824 struct ie_sys_ctl_block scb; 825 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 826 scb.ie_recv_list = (u_short)sc->rframes[0]; 827 command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0); 828 ie_ack(sc, IE_ST_WHENCE ); 829 } 830 831 /* 832 * Take our configuration and update all the other data structures that 833 * require information from the driver. 834 * 835 * CALL AT SPLIMP OR HIGHER 836 */ 837 838 int 839 ieinit(struct ie_softc *sc) 840 { 841 struct ifnet *ifp; 842 struct ie_sys_ctl_block scb; 843 struct ie_config_cmd cmd; 844 struct ie_iasetup_cmd iasetup_cmd; 845 u_long ptr = IE_IBASE + IE_SCB_OFF + sizeof scb; 846 int n; 847 848 ifp = &sc->sc_ethercom.ec_if; 849 850 bzero ( &scb, sizeof(scb) ); 851 852 /* Send the configure command */ 853 854 cmd.com.ie_cmd_status = 0; 855 cmd.com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST; 856 cmd.com.ie_cmd_link = 0xffff; 857 858 cmd.ie_config_count = 0x0c; 859 cmd.ie_fifo = 8; 860 cmd.ie_save_bad = 0x40; 861 cmd.ie_addr_len = 0x2e; 862 cmd.ie_priority = 0; 863 cmd.ie_ifs = 0x60; 864 cmd.ie_slot_low = 0; 865 cmd.ie_slot_high = 0xf2; 866 cmd.ie_promisc = 0; /* Hey nuts, look at this! */ 867 cmd.ie_crs_cdt = 0; 868 cmd.ie_min_len = 64; 869 cmd.ie_junk = 0xff; 870 871 scb.ie_command_list = (u_short)ptr; 872 873 if ( command_and_wait(sc, IE_CU_START, &scb, &cmd, ptr, sizeof cmd, 874 IE_STAT_COMPL) ) 875 { 876 printf ( "%s: command failed: timeout\n", sc->sc_dev.dv_xname ); 877 return 0; 878 } 879 880 if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) ) 881 { 882 printf ( "%s: command failed: !IE_STAT_OK\n", sc->sc_dev.dv_xname ); 883 return 0; 884 } 885 886 /* Individual address setup command */ 887 888 iasetup_cmd.com.ie_cmd_status = 0; 889 iasetup_cmd.com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST; 890 iasetup_cmd.com.ie_cmd_link = 0xffff; 891 892 bcopy ( CLLADDR(ifp->if_sadl), (void *) &iasetup_cmd.ie_address, 893 sizeof (iasetup_cmd.ie_address) ); 894 895 if ( command_and_wait(sc, IE_CU_START, &scb, &iasetup_cmd, ptr, sizeof cmd, 896 IE_STAT_COMPL) ) 897 { 898 printf ( "%s: iasetup failed : timeout\n", sc->sc_dev.dv_xname ); 899 return 0; 900 } 901 902 if ( !(cmd.com.ie_cmd_status & IE_STAT_OK) ) 903 { 904 printf ( "%s: iasetup failed : !IE_STAT_OK\n", sc->sc_dev.dv_xname ); 905 return 0; 906 } 907 908 ie_ack ( sc, IE_ST_WHENCE ); 909 910 /* Run the time-domain refloctometer */ 911 run_tdr ( sc ); 912 913 ie_ack ( sc, IE_ST_WHENCE ); 914 915 /* meminit */ 916 ptr = setup_rfa(sc, ptr); 917 918 ifp->if_flags |= IFF_RUNNING; 919 ifp->if_flags &= ~IFF_OACTIVE; 920 921 /* Setup transmit buffers */ 922 923 for ( n=0; n<NTXBUF; n++ ) { 924 sc->xmit_cmds[n] = ptr; 925 iezero(sc, ptr, sizeof(struct ie_xmit_cmd) ); 926 ptr += sizeof(struct ie_xmit_cmd); 927 928 sc->xmit_buffs[n] = ptr; 929 iezero(sc, ptr, sizeof(struct ie_xmit_buf)); 930 ptr += sizeof(struct ie_xmit_buf); 931 } 932 933 for ( n=0; n<NTXBUF; n++ ) { 934 sc->xmit_cbuffs[n] = ptr; 935 ptr += IE_TXBUF_SIZE; 936 } 937 938 sc->xmit_free = NTXBUF; 939 sc->xchead = sc->xctail = 0; 940 941 { 942 struct ie_xmit_cmd xmcmd; 943 bzero ( &xmcmd, sizeof xmcmd ); 944 xmcmd.ie_xmit_status = IE_STAT_COMPL; 945 host2ie(sc, &xmcmd, sc->xmit_cmds[0], sizeof xmcmd); 946 } 947 948 start_receiver (sc); 949 950 return 0; 951 } 952 953 int 954 iestop(struct ie_softc *sc) 955 { 956 struct ie_sys_ctl_block scb; 957 int s = splnet(); 958 959 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 960 961 if ( command_and_wait(sc, IE_RU_DISABLE, &scb, 0, 0, 0, 0) ) 962 printf ( "ie0: abort commands timed out\n" ); 963 964 (void)splx(s); 965 return(0); 966 } 967 968 /* 969 * Send a command to the card and awaits it's completion. 970 * Timeout if it's taking too long 971 */ 972 973 /*CAW*/ 974 975 static int 976 command_and_wait(struct ie_softc *sc, u_short cmd, struct ie_sys_ctl_block *pscb, void *pcmd, int ocmd, int scmd, int mask) 977 { 978 int i=0; 979 980 /* Copy the command to the card */ 981 982 if ( pcmd ) 983 host2ie(sc, pcmd, ocmd, scmd); /* transfer the command to the card */ 984 985 /* Copy the scb to the card */ 986 987 if ( pscb ) { 988 pscb->ie_command = cmd; 989 host2ie(sc, pscb, IE_IBASE + IE_SCB_OFF, sizeof *pscb); 990 } 991 else 992 { 993 setpage ( sc, IE_IBASE + IE_SCB_OFF ); 994 PWriteShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 995 (xoffsetof(struct ie_sys_ctl_block, ie_command)), cmd ); 996 } 997 998 /* Prod the card to act on the newly loaded command */ 999 ieattn(sc); 1000 1001 /* Wait for the command to complete */ 1002 if ( IE_ACTION_COMMAND(cmd) && pcmd ) 1003 { 1004 setpage(sc,ocmd); 1005 for ( i=4000; --i>=0; ) { 1006 if ( ReadShort(sc->sc_ram + IE_COFF2POFF(ocmd) + 1007 (xoffsetof(struct ie_config_cmd, ie_config_status))) & mask) 1008 break; 1009 delay(100); 1010 } 1011 } 1012 else 1013 { 1014 for ( i=4000; --i>=0; ) { 1015 if ( !ReadShort(sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 1016 (xoffsetof(struct ie_sys_ctl_block, ie_command))) ) 1017 break; 1018 delay(100); 1019 } 1020 } 1021 1022 /* Update the host structures to reflect the state on the card */ 1023 if ( pscb ) 1024 ie2host(sc, IE_IBASE + IE_SCB_OFF, pscb, sizeof *pscb ); 1025 if ( pcmd ) 1026 ie2host(sc, ocmd, pcmd, scmd); 1027 1028 return i < 0; 1029 } 1030 1031 #define READ_MEMBER(sc,type,member,ptr,dest) \ 1032 setpage(sc, ptr); \ 1033 dest = ReadShort(sc->sc_ram + IE_COFF2POFF(ptr) + \ 1034 (xoffsetof(type, member)) ); 1035 1036 #define WRITE_MEMBER(sc,type,member,ptr,dest) \ 1037 setpage(sc, ptr); \ 1038 PWriteShort(sc->sc_ram + IE_COFF2POFF(ptr) + \ 1039 (xoffsetof(type, member)), dest ); 1040 1041 static inline int 1042 ie_buflen(struct ie_softc *sc, int head) 1043 { 1044 int actual; 1045 1046 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, 1047 sc->rbuffs[head], actual ); 1048 1049 return(actual & (IE_RXBUF_SIZE | (IE_RXBUF_SIZE-1))) ; 1050 } 1051 1052 static inline int 1053 ie_packet_len(struct ie_softc *sc) 1054 { 1055 int i; 1056 int actual; 1057 int head = sc->rbhead; 1058 int acc=0; 1059 1060 do { 1061 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, 1062 sc->rbuffs[sc->rbhead], actual ); 1063 if (!(actual&IE_RBD_USED)) 1064 { 1065 return (-1); 1066 } 1067 1068 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, 1069 sc->rbuffs[head], i ); 1070 i = i & IE_RBD_LAST; 1071 1072 acc += ie_buflen(sc, head); 1073 head = (head+1) % NRXBUF; 1074 } while (!i); 1075 1076 return acc; 1077 } 1078 1079 struct mbuf * 1080 ieget(struct ie_softc *sc, int *to_bpf ) 1081 { 1082 struct mbuf *top, **mp, *m; 1083 int head; 1084 int resid, totlen, thisrboff, thismboff; 1085 int len; 1086 struct ether_header eh; 1087 1088 totlen = ie_packet_len(sc); 1089 1090 if ( totlen > ETHER_MAX_LEN ) 1091 { 1092 printf ( "ie: Gosh that packet was s-o-o-o big.\n" ); 1093 return 0; 1094 } 1095 1096 if ( totlen<=0 ) 1097 return 0; 1098 1099 head = sc->rbhead; 1100 1101 /* Read the ethernet header */ 1102 ie2host ( sc, sc->cbuffs[head], (void *)&eh, sizeof eh ); 1103 1104 /* Check if the packet is for us */ 1105 1106 resid = totlen; 1107 1108 MGETHDR ( m, M_DONTWAIT, MT_DATA ); 1109 if ( m==0 ) 1110 return 0; 1111 1112 m->m_pkthdr.rcvif = &sc->sc_ethercom.ec_if; 1113 m->m_pkthdr.len = totlen; 1114 len = MHLEN; 1115 top = 0; 1116 mp = ⊤ 1117 1118 /* 1119 * This loop goes through and allocates mbufs for all the data we will 1120 * be copying in. It does not actually do the copying yet. 1121 */ 1122 while (totlen > 0) { 1123 if (top) { 1124 MGET(m, M_DONTWAIT, MT_DATA); 1125 if (m == 0) { 1126 m_freem(top); 1127 return 0; 1128 } 1129 len = MLEN; 1130 } 1131 if (totlen >= MINCLSIZE) { 1132 MCLGET(m, M_DONTWAIT); 1133 if (m->m_flags & M_EXT) 1134 len = MCLBYTES; 1135 } 1136 1137 if (mp == &top) { 1138 void *newdata = (void *) 1139 ALIGN(m->m_data + sizeof(struct ether_header)) - 1140 sizeof(struct ether_header); 1141 len -= newdata - m->m_data; 1142 m->m_data = newdata; 1143 } 1144 1145 m->m_len = len = min(totlen, len); 1146 1147 totlen -= len; 1148 *mp = m; 1149 mp = &m->m_next; 1150 } 1151 1152 m = top; 1153 thismboff = 0; 1154 1155 /* 1156 * Copy the Ethernet header into the mbuf chain. 1157 */ 1158 memcpy(mtod(m, void *), &eh, sizeof(struct ether_header)); 1159 thismboff = sizeof(struct ether_header); 1160 thisrboff = sizeof(struct ether_header); 1161 resid -= sizeof(struct ether_header); 1162 1163 /* 1164 * Now we take the mbuf chain (hopefully only one mbuf most of the 1165 * time) and stuff the data into it. There are no possible failures at 1166 * or after this point. 1167 */ 1168 while (resid > 0) { 1169 int thisrblen = ie_buflen(sc, head) - thisrboff, 1170 thismblen = m->m_len - thismboff; 1171 len = min(thisrblen, thismblen); 1172 1173 /* bcopy((void *)(sc->cbuffs[head] + thisrboff), 1174 mtod(m, void *) + thismboff, (u_int)len); */ 1175 1176 1177 if ( len&1 ) 1178 { 1179 ie2host(sc, sc->cbuffs[head]+thisrboff, 1180 mtod(m, void *) + thismboff, (u_int)len+1); 1181 } 1182 else 1183 { 1184 ie2host(sc, sc->cbuffs[head]+thisrboff, 1185 mtod(m, void *) + thismboff, (u_int)len); 1186 } 1187 1188 resid -= len; 1189 1190 if (len == thismblen) { 1191 m = m->m_next; 1192 thismboff = 0; 1193 } else 1194 thismboff += len; 1195 1196 if (len == thisrblen) { 1197 head = (head + 1) % NRXBUF; 1198 thisrboff = 0; 1199 } else 1200 thisrboff += len; 1201 } 1202 1203 1204 return top; 1205 } 1206 1207 void 1208 ie_drop_packet_buffer(struct ie_softc *sc) 1209 { 1210 int i, actual, last; 1211 1212 do { 1213 READ_MEMBER(sc,struct ie_recv_buf_desc, ie_rbd_actual, 1214 sc->rbuffs[sc->rbhead], actual ); 1215 if (!(actual&IE_RBD_USED)) 1216 { 1217 iereset(sc); 1218 return; 1219 } 1220 1221 i = actual & IE_RBD_LAST; 1222 1223 READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, 1224 sc->rbuffs[sc->rbhead], last ); 1225 last |= IE_RBD_LAST; 1226 WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, 1227 sc->rbuffs[sc->rbhead], last ); 1228 1229 WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_actual, 1230 sc->rbuffs[sc->rbhead], 0 ); 1231 1232 sc->rbhead = ( sc->rbhead + 1 ) % NRXBUF; 1233 1234 READ_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, 1235 sc->rbuffs[sc->rbtail], last ); 1236 last &= ~IE_RBD_LAST; 1237 WRITE_MEMBER(sc,struct ie_recv_buf_desc,ie_rbd_length, 1238 sc->rbuffs[sc->rbtail], last ); 1239 1240 sc->rbtail = ( sc->rbtail + 1 ) % NRXBUF; 1241 } while (!i); 1242 } 1243 1244 void 1245 ie_read_frame(struct ie_softc *sc, int num) 1246 { 1247 int status; 1248 struct ie_recv_frame_desc rfd; 1249 struct mbuf *m=0; 1250 struct ifnet *ifp; 1251 int last; 1252 1253 ifp = &sc->sc_ethercom.ec_if; 1254 1255 ie2host(sc, sc->rframes[num], &rfd, sizeof rfd ); 1256 status = rfd.ie_fd_status; 1257 1258 /* Advance the RFD list, since we're done with this descriptor */ 1259 1260 WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status, 1261 sc->rframes[num], 0 ); 1262 1263 READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, 1264 sc->rframes[num], last ); 1265 last |= IE_FD_LAST; 1266 WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, 1267 sc->rframes[num], last ); 1268 1269 READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, 1270 sc->rframes[sc->rftail], last ); 1271 last &= ~IE_FD_LAST; 1272 WRITE_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_last, 1273 sc->rframes[sc->rftail], last ); 1274 1275 sc->rftail = ( sc->rftail + 1 ) % NFRAMES; 1276 sc->rfhead = ( sc->rfhead + 1 ) % NFRAMES; 1277 1278 if ( status & IE_FD_OK ) { 1279 m = ieget(sc, 0); 1280 ie_drop_packet_buffer(sc); 1281 } 1282 1283 if ( m==0 ) { 1284 ifp->if_ierrors++; 1285 return; 1286 } 1287 1288 ifp->if_ipackets++; 1289 1290 #if NBPFILTER > 0 1291 if ( ifp->if_bpf ) { 1292 bpf_mtap(ifp->if_bpf, m ); 1293 }; 1294 #endif 1295 1296 (*ifp->if_input)(ifp, m); 1297 } 1298 1299 void 1300 ierint(struct ie_softc *sc) 1301 { 1302 int i; 1303 int times_thru = 1024; 1304 struct ie_sys_ctl_block scb; 1305 int status; 1306 int safety_catch = 0; 1307 1308 i = sc->rfhead; 1309 for (;;) { 1310 1311 if ( (safety_catch++)>100 ) 1312 { 1313 printf ( "ie: ierint safety catch tripped\n" ); 1314 iereset(sc); 1315 return; 1316 } 1317 1318 READ_MEMBER(sc,struct ie_recv_frame_desc,ie_fd_status, 1319 sc->rframes[i],status); 1320 1321 if ((status&IE_FD_COMPLETE)&&(status&IE_FD_OK)) { 1322 if ( !--times_thru ) { 1323 printf ( "IERINT: Uh oh. Nuts, look at this bit!!!\n" ); 1324 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 1325 sc->sc_ethercom.ec_if.if_ierrors += scb.ie_err_crc + 1326 scb.ie_err_align + 1327 scb.ie_err_resource + 1328 scb.ie_err_overrun; 1329 scb.ie_err_crc = scb.ie_err_align = 0; 1330 scb.ie_err_resource = scb.ie_err_overrun = 0; 1331 host2ie(sc, &scb, IE_SCP_ADDR, sizeof (scb) ); 1332 } 1333 ie_read_frame(sc, i); 1334 } else { 1335 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 1336 1337 if ( ((status&IE_FD_RNR)!=0) && ((scb.ie_status&IE_RU_READY)==0) ) 1338 { 1339 WRITE_MEMBER(sc,struct ie_recv_frame_desc, ie_fd_buf_desc, 1340 sc->rframes[0], sc->rbuffs[0] ); 1341 1342 scb.ie_recv_list = sc->rframes[0]; 1343 host2ie(sc, (char *)&scb, IE_IBASE + IE_SCB_OFF, sizeof (scb) ); 1344 command_and_wait(sc, IE_RU_START, &scb, 0, 0, 0, 0); 1345 } 1346 break; 1347 } 1348 i = (i + 1) % NFRAMES; 1349 } 1350 } 1351 1352 static int in_intr = 0; 1353 1354 int 1355 ieintr(void *arg) 1356 { 1357 struct ie_softc *sc = arg; 1358 u_short status; 1359 int safety_catch = 0; 1360 static int safety_net = 0; 1361 1362 if (in_intr == 1) 1363 panic ( "ie: INTERRUPT REENTERED\n" ); 1364 1365 /* Clear the interrrupt */ 1366 ie_cli (sc); 1367 1368 setpage(sc, IE_IBASE + IE_SCB_OFF ); 1369 status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 1370 (xoffsetof(struct ie_sys_ctl_block, ie_status)) ); 1371 1372 status = status & IE_ST_WHENCE; 1373 1374 if (status == 0) { 1375 in_intr = 0; 1376 return(0); 1377 } 1378 1379 loop: 1380 1381 ie_ack(sc, status); 1382 1383 if (status & (IE_ST_FR | IE_ST_RNR)) 1384 ierint(sc); 1385 1386 if (status & IE_ST_CX) 1387 ietint(sc); 1388 1389 if (status & IE_ST_RNR) { 1390 printf ( "ie: receiver not ready\n" ); 1391 sc->sc_ethercom.ec_if.if_ierrors++; 1392 iereset(sc); 1393 } 1394 1395 setpage(sc, IE_IBASE + IE_SCB_OFF ); 1396 status = ReadShort ( sc->sc_ram + IE_COFF2POFF(IE_IBASE+IE_SCB_OFF) + 1397 (xoffsetof(struct ie_sys_ctl_block, ie_status)) ); 1398 status = status & IE_ST_WHENCE; 1399 1400 ie_cli(sc); 1401 1402 if (status == 0) { 1403 in_intr = 0; 1404 return(0); 1405 } 1406 1407 /* This is prehaps a little over cautious */ 1408 if ( safety_catch++ > 10 ) 1409 { 1410 printf ( "ie: Interrupt couldn't be cleared\n" ); 1411 delay ( 1000 ); 1412 ie_cli(sc); 1413 if ( safety_net++ > 50 ) 1414 { 1415 /* printf ( "ie: safety net catches driver, shutting down\n" ); 1416 disable_irq ( IRQ_PODULE );*/ 1417 } 1418 in_intr = 0; 1419 return(0); 1420 } 1421 1422 goto loop; 1423 } 1424 1425 void 1426 iexmit(struct ie_softc *sc) 1427 { 1428 /* int actual;*/ 1429 struct ie_sys_ctl_block scb; 1430 1431 struct ie_xmit_cmd xc; 1432 struct ie_xmit_buf xb; 1433 1434 ie2host(sc, sc->xmit_buffs[sc->xctail], (char *)&xb, sizeof xb ); 1435 xb.ie_xmit_flags |= IE_XMIT_LAST; 1436 xb.ie_xmit_next = 0xffff; 1437 xb.ie_xmit_buf = (void *)sc->xmit_cbuffs[sc->xctail]; 1438 host2ie(sc, &xb, sc->xmit_buffs[sc->xctail], sizeof xb ); 1439 1440 bzero ( &xc, sizeof xc ); 1441 xc.com.ie_cmd_link = 0xffff; 1442 xc.com.ie_cmd_cmd = IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST; 1443 xc.ie_xmit_status = 0x0000; 1444 xc.ie_xmit_desc = sc->xmit_buffs[sc->xctail]; 1445 host2ie(sc, (char *)&xc, sc->xmit_cmds[sc->xctail], sizeof xc ); 1446 1447 ie2host ( sc, IE_IBASE + IE_SCB_OFF, &scb, sizeof scb ); 1448 scb.ie_command_list = sc->xmit_cmds[sc->xctail]; 1449 host2ie(sc, (char *)&scb, (IE_IBASE + IE_SCB_OFF), sizeof scb ); 1450 1451 command_and_wait(sc, IE_CU_START, &scb, &xc, sc->xmit_cmds[sc->xctail] 1452 , sizeof xc, IE_STAT_COMPL); 1453 1454 sc->sc_ethercom.ec_if.if_timer = 5; 1455 } 1456 /* 1457 * Start sending all the queued buffers. 1458 */ 1459 1460 void 1461 iestart(struct ifnet *ifp) 1462 { 1463 struct ie_softc *sc = ifp->if_softc; 1464 struct mbuf *m0, *m; 1465 u_char *buffer; 1466 u_short len; 1467 char txbuf[IE_TXBUF_SIZE]; 1468 int safety_catch = 0; 1469 1470 if ((ifp->if_flags & IFF_OACTIVE) != 0) 1471 return; 1472 1473 for (;;) { 1474 if ( (safety_catch++)>100 ) 1475 { 1476 printf ( "ie: iestart safety catch tripped\n" ); 1477 iereset(sc); 1478 return; 1479 } 1480 if (sc->xmit_free == 0) { 1481 ifp->if_flags |= IFF_OACTIVE; 1482 break; 1483 } 1484 1485 IF_DEQUEUE(&ifp->if_snd, m); 1486 if (!m) 1487 break; 1488 1489 /* TODO: Write directly to the card */ 1490 len = 0; 1491 /* buffer = sc->xmit_cbuffs[sc->xchead]; */ 1492 buffer = txbuf; 1493 1494 for (m0 = m; m && (len + m->m_len) < IE_TXBUF_SIZE; 1495 m = m->m_next) { 1496 memcpy( buffer, mtod(m, void *), m->m_len); 1497 buffer += m->m_len; 1498 len += m->m_len; 1499 } 1500 1501 #if NBPFILTER > 0 1502 if ( ifp->if_bpf ) 1503 bpf_mtap(ifp->if_bpf, m0); 1504 #endif 1505 1506 m_freem(m0); 1507 if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) { 1508 memset(buffer, 0, ETHER_MIN_LEN - ETHER_CRC_LEN - len); 1509 len = ETHER_MIN_LEN - ETHER_CRC_LEN; 1510 buffer += ETHER_MIN_LEN - ETHER_CRC_LEN; 1511 } 1512 1513 /* When we write directly to the card we dont need this */ 1514 if (len&1) 1515 host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len+1 ); 1516 else 1517 host2ie(sc, txbuf, sc->xmit_cbuffs[sc->xchead], len ); 1518 1519 /* sc->xmit_buffs[sc->xchead]->ie_xmit_flags = len; */ 1520 1521 WRITE_MEMBER(sc,struct ie_xmit_buf, ie_xmit_flags, 1522 sc->xmit_buffs[sc->xchead], len) 1523 1524 /* Start the first packet transmitting. */ 1525 if (sc->xmit_free == NTXBUF) 1526 iexmit(sc); 1527 1528 sc->xchead = (sc->xchead + 1) % NTXBUF; 1529 sc->xmit_free--; 1530 } 1531 } 1532 1533 void 1534 ietint(struct ie_softc *sc) 1535 { 1536 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1537 1538 int status; 1539 1540 ifp->if_timer=0; 1541 ifp->if_flags &= ~IFF_OACTIVE; 1542 1543 READ_MEMBER(sc,struct ie_xmit_cmd, ie_xmit_status, 1544 sc->xmit_cmds[sc->xctail], status ); 1545 1546 if (!(status&IE_STAT_COMPL) || (status & IE_STAT_BUSY) ) 1547 printf ( "ietint: command still busy!\n" ); 1548 1549 if ( status & IE_STAT_OK ) { 1550 ifp->if_opackets++; 1551 ifp->if_collisions += status & IE_XS_MAXCOLL; 1552 } else { 1553 ifp->if_oerrors++; 1554 if ( status & IE_STAT_ABORT ) 1555 printf ( "ie: send aborted\n" ); 1556 if ( status & IE_XS_LATECOLL ) 1557 printf ( "ie: late collision\n" ); 1558 if ( status & IE_XS_NOCARRIER ) 1559 printf ( "ie: no carrier\n" ); 1560 if ( status & IE_XS_LOSTCTS ) 1561 printf ( "ie: lost CTS\n" ); 1562 if ( status & IE_XS_UNDERRUN ) 1563 printf ( "ie: DMA underrun\n" ); 1564 if ( status & IE_XS_EXCMAX ) 1565 printf ( "ie: too many collisions\n" ); 1566 ifp->if_collisions+=16; 1567 } 1568 /* Done with the buffer */ 1569 sc->xmit_free++; 1570 sc->xctail = (sc->xctail + 1 ) % NTXBUF; 1571 1572 /* Start the next packet transmitting, if any */ 1573 if ( sc->xmit_free<NTXBUF ) 1574 iexmit(sc); 1575 1576 iestart(ifp); 1577 } 1578 1579 /* End of if_ie.c */ 1580