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