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