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