1 /* $NetBSD: if_le.c,v 1.13 2014/06/21 02:02:40 tsutsui Exp $ */ 2 3 /* 4 * Copyright (c) 1993 Adam Glass 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Adam Glass. 18 * 4. The name of the Author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include <sys/param.h> 35 #include <sys/types.h> 36 37 #include <net/if_ether.h> 38 #include <netinet/in.h> 39 #include <netinet/in_systm.h> 40 41 #include <lib/libsa/stand.h> 42 #include <lib/libsa/net.h> 43 #include <lib/libsa/netif.h> 44 45 #include <lib/libkern/libkern.h> 46 47 #include <hp300/stand/common/device.h> 48 #include <hp300/stand/common/if_lereg.h> 49 #include <hp300/stand/common/samachdep.h> 50 51 #ifndef NLE 52 #define NLE 1 53 #endif 54 55 struct le_softc { 56 struct lereg0 *sc_r0; /* DIO registers */ 57 struct lereg1 *sc_r1; /* LANCE registers */ 58 void *sc_mem; 59 struct init_block *sc_init; 60 struct mds *sc_rd, *sc_td; 61 u_char *sc_rbuf, *sc_tbuf; 62 int sc_next_rd, sc_next_td; 63 u_char sc_addr[ETHER_ADDR_LEN]; 64 }; 65 66 struct le_sel { 67 int le_id; 68 int le_regs; 69 int le_mem; 70 int le_nvram; 71 int le_heat; 72 int le_bonus; 73 }; 74 75 int le_probe(struct netif *, void *); 76 int le_match(struct netif *, void *); 77 void le_init(struct iodesc *, void *); 78 int le_get(struct iodesc *, void *, size_t, saseconds_t); 79 int le_put(struct iodesc *, void *, size_t); 80 void le_end(struct netif *); 81 82 static inline void lewrcsr(struct le_softc *, uint16_t, uint16_t); 83 static inline uint16_t lerdcsr(struct le_softc *, uint16_t); 84 85 static void leinit(void); 86 static void le_error(int, char *, uint16_t); 87 static void lememinit(struct le_softc *); 88 static void le_reset(int, u_char *); 89 static int le_poll(struct iodesc *, void *, int); 90 91 #ifdef LE_DEBUG 92 int le_debug = 0; 93 #endif 94 95 struct le_sel le0conf[] = { 96 /* offsets for: ID REGS MEM NVRAM le_heat le_bonus*/ 97 { 0, 0x4000, 0x8000, 0xC008, 1, 10 } 98 }; 99 #define NLE0CONF (sizeof(le0conf) / sizeof(le0conf[0])) 100 101 extern struct netif_stats le_stats[]; 102 103 struct netif_dif le_ifs[] = { 104 /* dif_unit dif_nsel dif_stats dif_private */ 105 { 0, NLE0CONF, &le_stats[0], le0conf, }, 106 }; 107 #define NLE_IFS (sizeof(le_ifs) / sizeof(le_ifs[0])) 108 109 struct netif_stats le_stats[NLE_IFS]; 110 111 struct netif_driver le_driver = { 112 "le", /* netif_bname */ 113 le_match, /* netif_match */ 114 le_probe, /* netif_probe */ 115 le_init, /* netif_init */ 116 le_get, /* netif_get */ 117 le_put, /* netif_put */ 118 le_end, /* netif_end */ 119 le_ifs, /* netif_ifs */ 120 NLE_IFS /* netif_nifs */ 121 }; 122 123 struct le_softc le_softc[NLE]; 124 125 static inline void 126 lewrcsr(struct le_softc *sc, uint16_t port, uint16_t val) 127 { 128 struct lereg0 *ler0 = sc->sc_r0; 129 struct lereg1 *ler1 = sc->sc_r1; 130 131 do { 132 ler1->ler1_rap = port; 133 } while ((ler0->ler0_status & LE_ACK) == 0); 134 do { 135 ler1->ler1_rdp = val; 136 } while ((ler0->ler0_status & LE_ACK) == 0); 137 } 138 139 static inline uint16_t 140 lerdcsr(struct le_softc *sc, uint16_t port) 141 { 142 struct lereg0 *ler0 = sc->sc_r0; 143 struct lereg1 *ler1 = sc->sc_r1; 144 uint16_t val; 145 146 do { 147 ler1->ler1_rap = port; 148 } while ((ler0->ler0_status & LE_ACK) == 0); 149 do { 150 val = ler1->ler1_rdp; 151 } while ((ler0->ler0_status & LE_ACK) == 0); 152 return val; 153 } 154 155 static void 156 leinit(void) 157 { 158 struct hp_hw *hw; 159 struct le_softc *sc; 160 struct le_sel *sels; 161 int i, n; 162 char *cp; 163 164 i = 0; 165 166 for (hw = sc_table; i < NLE && hw < &sc_table[MAXCTLRS]; hw++) { 167 #ifdef LE_DEBUG 168 if (le_debug) 169 printf("found type %x\n", hw->hw_type); 170 #endif 171 172 #if 0 173 if (!HW_ISDEV(hw, D_LAN)) 174 continue; 175 #endif 176 177 sels = (struct le_sel *)le_ifs[i].dif_private; 178 179 sc = &le_softc[i]; 180 sc->sc_r0 = (struct lereg0 *)(sels->le_id + (int)hw->hw_kva); 181 182 if (sc->sc_r0->ler0_id != LEID) 183 continue; 184 185 sc->sc_r1 = (struct lereg1 *)(sels->le_regs + (int)hw->hw_kva); 186 sc->sc_mem = (struct lereg2 *)(sels->le_mem + (int)hw->hw_kva); 187 188 #ifdef LE_DEBUG 189 if (le_debug) 190 printf("le%d: DIO=%x regs=%x mem=%x\n", 191 i, sc->sc_r0, sc->sc_r1, sc->sc_mem); 192 #endif 193 194 /* 195 * Read the ethernet address off the board, one nibble at a time. 196 */ 197 cp = (char *)(sels->le_nvram + (int)hw->hw_kva); 198 for (n = 0; n < sizeof(sc->sc_addr); n++) { 199 sc->sc_addr[n] = (*++cp & 0xF) << 4; 200 cp++; 201 sc->sc_addr[n] |= *++cp & 0xF; 202 cp++; 203 } 204 #ifdef LE_DEBUG 205 if (le_debug) 206 printf("le%d at sc%d physical address %s\n", 207 i, hw->hw_sc, ether_sprintf(sc->sc_addr)); 208 #endif 209 hw->hw_pa = (void *) i; /* XXX for autoconfig */ 210 i++; 211 } 212 } 213 214 int 215 le_match(struct netif *nif, void *machdep_hint) 216 { 217 struct le_sel *sels; 218 char *name = machdep_hint; 219 int rv = 0; 220 221 if (nif->nif_sel < le_ifs[nif->nif_unit].dif_nsel) { 222 sels = (struct le_sel *)le_ifs[nif->nif_unit].dif_private; 223 rv = sels[nif->nif_sel].le_heat; 224 if (name && !strncmp(le_driver.netif_bname, name, 2)) 225 rv += sels[nif->nif_sel].le_bonus; 226 } 227 #ifdef LE_DEBUG 228 if (le_debug) 229 printf("le%d: sel %d --> %d\n", nif->nif_unit, nif->nif_sel, 230 rv); 231 #endif 232 return rv; 233 } 234 235 int 236 le_probe(struct netif *nif, void *machdep_hint) 237 { 238 #if 0 239 char *cp; 240 int i; 241 #endif 242 243 /* the set unit is the current unit */ 244 #ifdef LE_DEBUG 245 if (le_debug) 246 printf("le%d.%d: le_probe called\n", nif->nif_unit, nif->nif_sel); 247 #endif 248 /* XXX reset controller */ 249 return 0; 250 } 251 252 #ifdef MEM_SUMMARY 253 void 254 le_mem_summary(int unit) 255 { 256 struct lereg1 *ler1 = le_softc.sc_r1; 257 struct lereg2 *ler2 = le_softc.sc_r2; 258 int i; 259 260 printf("le%d: ler1 = %x\n", unit, ler1); 261 printf("le%d: ler2 = %x\n", unit, ler2); 262 263 #if 0 264 ler1->ler1_rap = LE_CSR0; 265 ler1->ler1_rdp = LE_STOP; 266 printf("le%d: csr0 = %x\n", unit, ler1->ler1_rdp); 267 ler1->ler1_rap = LE_CSR1; 268 printf("le%d: csr1 = %x\n", unit, ler1->ler1_rdp); 269 ler1->ler1_rap = LE_CSR2; 270 printf("le%d: csr2 = %x\n", unit, ler1->ler1_rdp); 271 ler1->ler1_rap = LE_CSR3; 272 printf("le%d: csr3 = %x\n", unit, ler1->ler1_rdp); 273 #endif 274 printf("le%d: ladrf[0] = %x\n", unit, ler2->ler2_ladrf[0]); 275 printf("le%d: ladrf[1] = %x\n", unit, ler2->ler2_ladrf[1]); 276 printf("le%d: ler2_rdra = %x\n", unit, ler2->ler2_rdra); 277 printf("le%d: ler2_rlen = %x\n", unit, ler2->ler2_rlen); 278 printf("le%d: ler2_tdra = %x\n", unit, ler2->ler2_tdra); 279 printf("le%d: ler2_tlen = %x\n", unit, ler2->ler2_tlen); 280 281 for (i = 0; i < LERBUF; i++) { 282 printf("le%d: ler2_rmd[%d].rmd0 (ladr) = %x\n", unit, i, 283 ler2->ler2_rmd[i].rmd0); 284 printf("le%d: ler2_rmd[%d].rmd1 = %x\n", unit, i, 285 ler2->ler2_rmd[i].rmd1); 286 printf("le%d: ler2_rmd[%d].rmd2 (-bcnt) = %x\n", unit, i, 287 ler2->ler2_rmd[i].rmd2); 288 printf("le%d: ler2_rmd[%d].rmd3 (mcnt) = %x\n", unit, i, 289 ler2->ler2_rmd[i].rmd3); 290 printf("le%d: ler2_rbuf[%d] addr = %x\n", unit, i, 291 &ler2->ler2_rbuf[i]); 292 } 293 for (i = 0; i < LETBUF; i++) { 294 printf("le%d: ler2_tmd[%d].tmd0 = %x\n", unit, i, 295 ler2->ler2_tmd[i].tmd0); 296 printf("le%d: ler2_tmd[%d].tmd1 = %x\n", unit, i, 297 ler2->ler2_tmd[i].tmd1); 298 printf("le%d: ler2_tmd[%d].tmd2 (bcnt) = %x\n", unit, i, 299 ler2->ler2_tmd[i].tmd2); 300 printf("le%d: ler2_tmd[%d].tmd3 = %x\n", unit, i, 301 ler2->ler2_tmd[i].tmd3); 302 printf("le%d: ler2_tbuf[%d] addr = %x\n", unit, i, 303 &ler2->ler2_tbuf[i]); 304 } 305 } 306 #else 307 #define le_mem_summary(u) 308 #endif 309 310 void 311 le_error(int unit, char *str, uint16_t stat) 312 { 313 314 if (stat & LE_BABL) 315 panic("le%d: been babbling, found by '%s'", unit, str); 316 if (stat & LE_CERR) 317 le_stats[unit].collision_error++; 318 if (stat & LE_MISS) 319 le_stats[unit].missed++; 320 if (stat & LE_MERR) { 321 printf("le%d: memory error in '%s'\n", unit, str); 322 le_mem_summary(unit); 323 panic("bye"); 324 } 325 } 326 327 #define LANCE_ADDR(sc, a) \ 328 ((u_long)(a) - (u_long)sc->sc_mem) 329 330 /* LANCE initialization block set up. */ 331 void 332 lememinit(struct le_softc *sc) 333 { 334 int i; 335 u_char *mem; 336 u_long a; 337 338 /* 339 * At this point we assume that the memory allocated to the Lance is 340 * quadword aligned. If it isn't then the initialisation is going 341 * fail later on. 342 */ 343 mem = sc->sc_mem; 344 345 sc->sc_init = (void *)mem; 346 sc->sc_init->mode = LE_NORMAL; 347 for (i = 0; i < ETHER_ADDR_LEN; i++) 348 sc->sc_init->padr[i] = sc->sc_addr[i^1]; 349 sc->sc_init->ladrf[0] = sc->sc_init->ladrf[1] = 0; 350 mem += sizeof(struct init_block); 351 352 sc->sc_rd = (void *)mem; 353 a = LANCE_ADDR(sc, mem); 354 sc->sc_init->rdra = a; 355 sc->sc_init->rlen = ((a >> 16) & 0xff) | (RLEN << 13); 356 mem += NRBUF * sizeof(struct mds); 357 358 sc->sc_td = (void *)mem; 359 a = LANCE_ADDR(sc, mem); 360 sc->sc_init->tdra = a; 361 sc->sc_init->tlen = ((a >> 16) & 0xff) | (TLEN << 13); 362 mem += NTBUF * sizeof(struct mds); 363 364 /* 365 * Set up receive ring descriptors. 366 */ 367 sc->sc_rbuf = mem; 368 for (i = 0; i < NRBUF; i++) { 369 a = LANCE_ADDR(sc, mem); 370 sc->sc_rd[i].addr = a; 371 sc->sc_rd[i].flags = ((a >> 16) & 0xff) | LE_OWN; 372 sc->sc_rd[i].bcnt = -BUFSIZE; 373 sc->sc_rd[i].mcnt = 0; 374 mem += BUFSIZE; 375 } 376 377 /* 378 * Set up transmit ring descriptors. 379 */ 380 sc->sc_tbuf = mem; 381 for (i = 0; i < NTBUF; i++) { 382 a = LANCE_ADDR(sc, mem); 383 sc->sc_td[i].addr = a; 384 sc->sc_td[i].flags = ((a >> 16) & 0xff); 385 sc->sc_td[i].bcnt = 0xf000; 386 sc->sc_td[i].mcnt = 0; 387 mem += BUFSIZE; 388 } 389 } 390 391 void 392 le_reset(int unit, u_char *myea) 393 { 394 struct le_softc *sc = &le_softc[unit]; 395 u_long a; 396 int timo = 100000; 397 398 #ifdef LE_DEBUG 399 if (le_debug) { 400 printf("le%d: le_reset called\n", unit); 401 printf(" r0=%x, r1=%x, mem=%x, addr=%x:%x:%x:%x:%x:%x\n", 402 sc->sc_r0, sc->sc_r1, sc->sc_mem, 403 sc->sc_addr[0], sc->sc_addr[1], sc->sc_addr[2], 404 sc->sc_addr[3], sc->sc_addr[4], sc->sc_addr[5]); 405 } 406 #endif 407 lewrcsr(sc, 0, LE_STOP); 408 for (timo = 1000; timo; timo--); 409 410 sc->sc_next_rd = sc->sc_next_td = 0; 411 412 /* Set up LANCE init block. */ 413 lememinit(sc); 414 415 if (myea) 416 memcpy(myea, sc->sc_addr, ETHER_ADDR_LEN); 417 418 /* Turn on byte swapping. */ 419 lewrcsr(sc, 3, LE_BSWP); 420 421 /* Give LANCE the physical address of its init block. */ 422 a = LANCE_ADDR(sc, sc->sc_init); 423 lewrcsr(sc, 1, a); 424 lewrcsr(sc, 2, (a >> 16) & 0xff); 425 426 #ifdef LE_DEBUG 427 if (le_debug) 428 printf("le%d: before init\n", unit); 429 #endif 430 431 /* Try to initialize the LANCE. */ 432 lewrcsr(sc, 0, LE_INIT); 433 434 /* Wait for initialization to finish. */ 435 for (timo = 100000; timo; timo--) 436 if (lerdcsr(sc, 0) & LE_IDON) 437 break; 438 439 if (lerdcsr(sc, 0) & LE_IDON) { 440 /* Start the LANCE. */ 441 lewrcsr(sc, 0, LE_INEA | LE_STRT | LE_IDON); 442 } else 443 printf("le%d: card failed to initialize\n", unit); 444 445 #ifdef LE_DEBUG 446 if (le_debug) 447 printf("le%d: after init\n", unit); 448 #endif 449 450 le_mem_summary(unit); 451 } 452 453 int 454 le_poll(struct iodesc *desc, void *pkt, int len) 455 { 456 int unit = /*nif->nif_unit*/0; 457 struct le_softc *sc = &le_softc[unit]; 458 int length; 459 volatile struct mds *cdm; 460 int stat; 461 462 #ifdef LE_DEBUG 463 if (/*le_debug*/0) 464 printf("le%d: le_poll called. next_rd=%d\n", unit, sc->sc_next_rd); 465 #endif 466 stat = lerdcsr(sc, 0); 467 lewrcsr(sc, 0, stat & (LE_BABL | LE_MISS | LE_MERR | LE_RINT)); 468 cdm = &sc->sc_rd[sc->sc_next_rd]; 469 if (cdm->flags & LE_OWN) 470 return 0; 471 #ifdef LE_DEBUG 472 if (le_debug) { 473 printf("next_rd %d\n", sc->sc_next_rd); 474 printf("cdm->flags %x\n", cdm->flags); 475 printf("cdm->bcnt %x, cdm->mcnt %x\n", cdm->bcnt, cdm->mcnt); 476 printf("cdm->rbuf msg %d buf %d\n", cdm->mcnt, -cdm->bcnt ); 477 } 478 #endif 479 if (stat & (LE_BABL | LE_CERR | LE_MISS | LE_MERR)) 480 le_error(unit, "le_poll", stat); 481 if (cdm->flags & (LE_FRAM | LE_OFLO | LE_CRC | LE_RBUFF)) { 482 printf("le%d_poll: rmd status 0x%x\n", unit, cdm->flags); 483 length = 0; 484 goto cleanup; 485 } 486 if ((cdm->flags & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) 487 panic("le_poll: chained packet"); 488 489 length = cdm->mcnt; 490 #ifdef LE_DEBUG 491 if (le_debug) 492 printf("le_poll: length %d\n", length); 493 #endif 494 if (length >= BUFSIZE) { 495 length = 0; 496 panic("csr0 when bad things happen: %x", stat); 497 goto cleanup; 498 } 499 if (!length) 500 goto cleanup; 501 length -= 4; 502 503 if (length > 0) { 504 /* 505 * If the length of the packet is greater than the size of the 506 * buffer, we have to truncate it, to avoid Bad Things. 507 * XXX Is this the right thing to do? 508 */ 509 if (length > len) 510 length = len; 511 512 memcpy(pkt, sc->sc_rbuf + (BUFSIZE * sc->sc_next_rd), length); 513 } 514 515 cleanup: 516 cdm->mcnt = 0; 517 cdm->flags |= LE_OWN; 518 if (++sc->sc_next_rd >= NRBUF) 519 sc->sc_next_rd = 0; 520 #ifdef LE_DEBUG 521 if (le_debug) 522 printf("new next_rd %d\n", sc->sc_next_rd); 523 #endif 524 525 return length; 526 } 527 528 int 529 le_put(struct iodesc *desc, void *pkt, size_t len) 530 { 531 int unit = /*nif->nif_unit*/0; 532 struct le_softc *sc = &le_softc[unit]; 533 volatile struct mds *cdm; 534 int timo, stat; 535 #if 0 536 int i; 537 #endif 538 539 le_put_loop: 540 timo = 100000; 541 542 #ifdef LE_DEBUG 543 if (le_debug) 544 printf("le%d: le_put called. next_td=%d\n", unit, sc->sc_next_td); 545 #endif 546 stat = lerdcsr(sc, 0); 547 lewrcsr(sc, 0, stat & (LE_BABL | LE_MISS | LE_MERR | LE_TINT)); 548 if (stat & (LE_BABL | LE_CERR | LE_MISS | LE_MERR)) 549 le_error(unit, "le_put(way before xmit)", stat); 550 cdm = &sc->sc_td[sc->sc_next_td]; 551 #if 0 552 i = 0; 553 while (cdm->flags & LE_OWN) { 554 if ((i % 100) == 0) 555 printf("le%d: output buffer busy - flags=%x\n", 556 unit, cdm->flags); 557 if (i++ > 500) break; 558 } 559 if (cdm->flags & LE_OWN) 560 getchar(); 561 #else 562 while (cdm->flags & LE_OWN); 563 #endif 564 memcpy(sc->sc_tbuf + (BUFSIZE * sc->sc_next_td), pkt, len); 565 if (len < ETHER_MIN_LEN) 566 cdm->bcnt = -ETHER_MIN_LEN; 567 else 568 cdm->bcnt = -len; 569 cdm->mcnt = 0; 570 cdm->flags |= LE_OWN | LE_STP | LE_ENP; 571 stat = lerdcsr(sc, 0); 572 if (stat & (LE_BABL | LE_CERR | LE_MISS | LE_MERR)) 573 le_error(unit, "le_put(before xmit)", stat); 574 lewrcsr(sc, 0, LE_TDMD); 575 stat = lerdcsr(sc, 0); 576 if (stat & (LE_BABL | LE_CERR | LE_MISS | LE_MERR)) 577 le_error(unit, "le_put(after xmit)", stat); 578 do { 579 if (--timo == 0) { 580 printf("le%d: transmit timeout, stat = 0x%x\n", 581 unit, stat); 582 if (stat & LE_SERR) 583 le_error(unit, "le_put(timeout)", stat); 584 if (stat & LE_INIT) { 585 printf("le%d: reset and retry packet\n", unit); 586 lewrcsr(sc, 0, LE_TINT); /* sanity */ 587 leinit(); 588 goto le_put_loop; 589 } 590 break; 591 } 592 stat = lerdcsr(sc, 0); 593 } while ((stat & LE_TINT) == 0); 594 lewrcsr(sc, 0, LE_TINT); 595 if (stat & (LE_BABL |/* LE_CERR |*/ LE_MISS | LE_MERR)) { 596 printf("le_put: xmit error, buf %d\n", sc->sc_next_td); 597 le_error(unit, "le_put(xmit error)", stat); 598 } 599 if (++sc->sc_next_td >= NTBUF) 600 sc->sc_next_td = 0; 601 if (cdm->flags & LE_DEF) 602 le_stats[unit].deferred++; 603 if (cdm->flags & LE_ONE) 604 le_stats[unit].collisions++; 605 if (cdm->flags & LE_MORE) 606 le_stats[unit].collisions += 2; 607 if (cdm->flags & LE_ERR) { 608 if (cdm->mcnt & LE_UFLO) 609 printf("le%d: transmit underflow\n", unit); 610 if (cdm->mcnt & LE_LCOL) 611 le_stats[unit].collisions++; 612 if (cdm->mcnt & LE_LCAR) 613 printf("le%d: lost carrier\n", unit); 614 if (cdm->mcnt & LE_RTRY) 615 le_stats[unit].collisions += 16; 616 return -1; 617 } 618 #ifdef LE_DEBUG 619 if (le_debug) { 620 printf("le%d: le_put() successful: sent %d\n", unit, len); 621 printf("le%d: le_put(): flags: %x mcnt: %x\n", unit, 622 (unsigned int) cdm->flags, 623 (unsigned int) cdm->mcnt); 624 } 625 #endif 626 return len; 627 } 628 629 630 int 631 le_get(struct iodesc *desc, void *pkt, size_t len, saseconds_t timeout) 632 { 633 satime_t t; 634 int cc; 635 636 t = getsecs(); 637 do { 638 cc = le_poll(desc, pkt, len); 639 } while (cc == 0 && (getsecs() - t) < timeout); 640 return cc; 641 } 642 643 void 644 le_init(struct iodesc *desc, void *machdep_hint) 645 { 646 struct netif *nif = desc->io_netif; 647 int unit = nif->nif_unit; 648 649 /* Get machine's common ethernet interface. This is done in leinit() */ 650 /* machdep_common_ether(myea); */ 651 leinit(); 652 653 #ifdef LE_DEBUG 654 if (le_debug) 655 printf("le%d: le_init called\n", unit); 656 #endif 657 unit = 0; 658 le_reset(unit, desc->myea); 659 } 660 661 void 662 le_end(struct netif *nif) 663 { 664 int unit = nif->nif_unit; 665 666 #ifdef LE_DEBUG 667 if (le_debug) 668 printf("le%d: le_end called\n", unit); 669 #endif 670 671 lewrcsr(&le_softc[unit], 0, LE_STOP); 672 } 673