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