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