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