1 /* $NetBSD: if_smap.c,v 1.16 2014/06/29 11:18:40 mrg Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: if_smap.c,v 1.16 2014/06/29 11:18:40 mrg Exp $"); 34 35 #include "debug_playstation2.h" 36 37 #include "rnd.h" 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 42 #include <sys/syslog.h> 43 #include <sys/mbuf.h> 44 #include <sys/ioctl.h> 45 #include <sys/socket.h> 46 47 #include <playstation2/ee/eevar.h> 48 49 #if NRND > 0 50 #include <sys/rnd.h> 51 #endif 52 53 #include <net/if.h> 54 #include <net/if_dl.h> 55 #include <net/if_types.h> 56 57 #include <net/if_ether.h> 58 #include <net/if_media.h> 59 60 #include <dev/mii/mii.h> 61 #include <dev/mii/miivar.h> 62 63 #include <netinet/in.h> 64 #include <netinet/in_systm.h> 65 #include <netinet/in_var.h> 66 #include <netinet/ip.h> 67 #include <netinet/if_inarp.h> 68 69 #include <net/bpf.h> 70 #include <net/bpfdesc.h> 71 72 #include <playstation2/dev/spdvar.h> 73 #include <playstation2/dev/spdreg.h> 74 #include <playstation2/dev/emac3var.h> 75 #include <playstation2/dev/if_smapreg.h> 76 77 #ifdef SMAP_DEBUG 78 #include <playstation2/ee/gsvar.h> 79 int smap_debug = 0; 80 #define DPRINTF(fmt, args...) \ 81 if (smap_debug) \ 82 printf("%s: " fmt, __func__ , ##args) 83 #define DPRINTFN(n, arg) \ 84 if (smap_debug > (n)) \ 85 printf("%s: " fmt, __func__ , ##args) 86 #define STATIC 87 struct smap_softc *__sc; 88 void __smap_status(int); 89 void __smap_lock_check(const char *, int); 90 #define FUNC_ENTER() __smap_lock_check(__func__, 1) 91 #define FUNC_EXIT() __smap_lock_check(__func__, 0) 92 #else 93 #define DPRINTF(arg...) ((void)0) 94 #define DPRINTFN(n, arg...) ((void)0) 95 #define STATIC static 96 #define FUNC_ENTER() ((void)0) 97 #define FUNC_EXIT() ((void)0) 98 #endif 99 100 struct smap_softc { 101 struct emac3_softc emac3; 102 struct ethercom ethercom; 103 104 u_int32_t *tx_buf; 105 u_int32_t *rx_buf; 106 struct smap_desc *tx_desc; 107 struct smap_desc *rx_desc; 108 109 #define SMAP_FIFO_ALIGN 4 110 int tx_buf_freesize; /* buffer usage */ 111 int tx_desc_cnt; /* descriptor usage */ 112 u_int16_t tx_fifo_ptr; 113 int tx_done_index, tx_start_index; 114 int rx_done_index; 115 116 #if NRND > 0 117 rndsource_element_t rnd_source; 118 #endif 119 }; 120 121 #define DEVNAME (sc->emac3.dev.dv_xname) 122 #define ROUND4(x) (((x) + 3) & ~3) 123 #define ROUND16(x) (((x) + 15) & ~15) 124 125 STATIC int smap_match(struct device *, struct cfdata *, void *); 126 STATIC void smap_attach(struct device *, struct device *, void *); 127 128 CFATTACH_DECL(smap, sizeof (struct smap_softc), 129 smap_match, smap_attach, NULL, NULL); 130 131 STATIC int smap_intr(void *); 132 STATIC void smap_rxeof(void *); 133 STATIC void smap_txeof(void *); 134 STATIC void smap_start(struct ifnet *); 135 STATIC void smap_watchdog(struct ifnet *); 136 STATIC int smap_ioctl(struct ifnet *, u_long, void *); 137 STATIC int smap_init(struct ifnet *); 138 STATIC void smap_stop(struct ifnet *, int); 139 140 STATIC int smap_get_eaddr(struct smap_softc *, u_int8_t *); 141 STATIC int smap_fifo_init(struct smap_softc *); 142 STATIC int smap_fifo_reset(bus_addr_t); 143 STATIC void smap_desc_init(struct smap_softc *); 144 145 int 146 smap_match(struct device *parent, struct cfdata *cf, void *aux) 147 { 148 struct spd_attach_args *spa = aux; 149 150 if (spa->spa_slot != SPD_NIC) 151 return (0); 152 153 return (1); 154 } 155 156 void 157 smap_attach(struct device *parent, struct device *self, void *aux) 158 { 159 struct spd_attach_args *spa = aux; 160 struct smap_softc *sc = (void *)self; 161 struct emac3_softc *emac3 = &sc->emac3; 162 struct ifnet *ifp = &sc->ethercom.ec_if; 163 struct mii_data *mii = &emac3->mii; 164 void *txbuf, *rxbuf; 165 u_int16_t r; 166 167 #ifdef SMAP_DEBUG 168 __sc = sc; 169 #endif 170 171 printf(": %s\n", spa->spa_product_name); 172 173 /* SPD EEPROM */ 174 if (smap_get_eaddr(sc, emac3->eaddr) != 0) 175 return; 176 177 printf("%s: Ethernet address %s\n", DEVNAME, 178 ether_sprintf(emac3->eaddr)); 179 180 /* disable interrupts */ 181 r = _reg_read_2(SPD_INTR_ENABLE_REG16); 182 r &= ~(SPD_INTR_RXEND | SPD_INTR_TXEND | SPD_INTR_RXDNV | 183 SPD_INTR_EMAC3); 184 _reg_write_2(SPD_INTR_ENABLE_REG16, r); 185 emac3_intr_disable(); 186 187 /* clear pending interrupts */ 188 _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND | SPD_INTR_TXEND | 189 SPD_INTR_RXDNV); 190 emac3_intr_clear(); 191 192 /* buffer descriptor mode */ 193 _reg_write_1(SMAP_DESC_MODE_REG8, 0); 194 195 if (smap_fifo_init(sc) != 0) 196 return; 197 198 if (emac3_init(&sc->emac3) != 0) 199 return; 200 emac3_intr_disable(); 201 emac3_disable(); 202 203 smap_desc_init(sc); 204 205 /* allocate temporary buffer */ 206 txbuf = malloc(ETHER_MAX_LEN - ETHER_CRC_LEN + SMAP_FIFO_ALIGN + 16, 207 M_DEVBUF, M_NOWAIT); 208 if (txbuf == NULL) { 209 printf("%s: no memory.\n", DEVNAME); 210 return; 211 } 212 213 rxbuf = malloc(ETHER_MAX_LEN + SMAP_FIFO_ALIGN + 16, 214 M_DEVBUF, M_NOWAIT); 215 if (rxbuf == NULL) { 216 printf("%s: no memory.\n", DEVNAME); 217 free(txbuf, M_DEVBUF); 218 return; 219 } 220 221 sc->tx_buf = (u_int32_t *)ROUND16((vaddr_t)txbuf); 222 sc->rx_buf = (u_int32_t *)ROUND16((vaddr_t)rxbuf); 223 224 /* 225 * setup MI layer 226 */ 227 strcpy(ifp->if_xname, DEVNAME); 228 ifp->if_softc = sc; 229 ifp->if_start = smap_start; 230 ifp->if_ioctl = smap_ioctl; 231 ifp->if_init = smap_init; 232 ifp->if_stop = smap_stop; 233 ifp->if_watchdog= smap_watchdog; 234 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | 235 IFF_MULTICAST; 236 IFQ_SET_READY(&ifp->if_snd); 237 238 /* ifmedia setup. */ 239 mii->mii_ifp = ifp; 240 mii->mii_readreg = emac3_phy_readreg; 241 mii->mii_writereg = emac3_phy_writereg; 242 mii->mii_statchg = emac3_phy_statchg; 243 sc->ethercom.ec_mii = mii; 244 ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus); 245 mii_attach(&emac3->dev, mii, 0xffffffff, MII_PHY_ANY, 246 MII_OFFSET_ANY, 0); 247 248 /* Choose a default media. */ 249 if (LIST_FIRST(&mii->mii_phys) == NULL) { 250 ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_NONE, 0, NULL); 251 ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_NONE); 252 } else { 253 ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO); 254 } 255 256 if_attach(ifp); 257 ether_ifattach(ifp, emac3->eaddr); 258 259 spd_intr_establish(SPD_NIC, smap_intr, sc); 260 261 #if NRND > 0 262 rnd_attach_source(&sc->rnd_source, DEVNAME, 263 RND_TYPE_NET, 0); 264 #endif 265 } 266 267 int 268 smap_ioctl(struct ifnet *ifp, u_long command, void *data) 269 { 270 struct smap_softc *sc = ifp->if_softc; 271 struct ifreq *ifr = (struct ifreq *) data; 272 int error, s; 273 274 s = splnet(); 275 276 error = ether_ioctl(ifp, command, data); 277 278 if (error == ENETRESET) { 279 if (ifp->if_flags & IFF_RUNNING) 280 emac3_setmulti(&sc->emac3, &sc->ethercom); 281 error = 0; 282 } 283 284 splx(s); 285 286 return (error); 287 } 288 289 int 290 smap_intr(void *arg) 291 { 292 struct smap_softc *sc = arg; 293 struct ifnet *ifp; 294 u_int16_t cause, disable, r; 295 296 cause = _reg_read_2(SPD_INTR_STATUS_REG16) & 297 _reg_read_2(SPD_INTR_ENABLE_REG16); 298 299 disable = cause & (SPD_INTR_RXDNV | SPD_INTR_TXDNV); 300 if (disable) { 301 r = _reg_read_2(SPD_INTR_ENABLE_REG16); 302 r &= ~disable; 303 _reg_write_2(SPD_INTR_ENABLE_REG16, r); 304 305 printf("%s: invalid descriptor. (%c%c)\n", DEVNAME, 306 disable & SPD_INTR_RXDNV ? 'R' : '_', 307 disable & SPD_INTR_TXDNV ? 'T' : '_'); 308 309 if (disable & SPD_INTR_RXDNV) 310 smap_rxeof(arg); 311 312 _reg_write_2(SPD_INTR_CLEAR_REG16, disable); 313 } 314 315 if (cause & SPD_INTR_TXEND) { 316 _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_TXEND); 317 if (_reg_read_1(SMAP_RXFIFO_FRAME_REG8) > 0) 318 cause |= SPD_INTR_RXEND; 319 smap_txeof(arg); 320 } 321 322 if (cause & SPD_INTR_RXEND) { 323 _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND); 324 smap_rxeof(arg); 325 if (sc->tx_desc_cnt > 0 && 326 sc->tx_desc_cnt > _reg_read_1(SMAP_TXFIFO_FRAME_REG8)) 327 smap_txeof(arg); 328 } 329 330 if (cause & SPD_INTR_EMAC3) 331 emac3_intr(arg); 332 333 /* if transmission is pending, start here */ 334 ifp = &sc->ethercom.ec_if; 335 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 336 smap_start(ifp); 337 #if NRND > 0 338 rnd_add_uint32(&sc->rnd_source, cause | sc->tx_fifo_ptr << 16); 339 #endif 340 341 return (1); 342 } 343 344 void 345 smap_rxeof(void *arg) 346 { 347 struct smap_softc *sc = arg; 348 struct smap_desc *d; 349 struct ifnet *ifp = &sc->ethercom.ec_if; 350 struct mbuf *m; 351 u_int16_t r16, stat; 352 u_int32_t *p; 353 int i, j, sz, rxsz, cnt; 354 355 FUNC_ENTER(); 356 357 i = sc->rx_done_index; 358 359 for (cnt = 0;; cnt++, i = (i + 1) & 0x3f) { 360 m = NULL; 361 d = &sc->rx_desc[i]; 362 stat = d->stat; 363 364 if ((stat & SMAP_RXDESC_EMPTY) != 0) { 365 break; 366 } else if (stat & 0x7fff) { 367 ifp->if_ierrors++; 368 goto next_packet; 369 } 370 371 sz = d->sz; 372 rxsz = ROUND4(sz); 373 374 KDASSERT(sz >= ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN); 375 KDASSERT(sz <= ETHER_MAX_LEN); 376 377 /* load data from FIFO */ 378 _reg_write_2(SMAP_RXFIFO_PTR_REG16, d->ptr & 0x3ffc); 379 p = sc->rx_buf; 380 for (j = 0; j < rxsz; j += sizeof(u_int32_t)) { 381 *p++ = _reg_read_4(SMAP_RXFIFO_DATA_REG); 382 } 383 384 /* put to mbuf */ 385 MGETHDR(m, M_DONTWAIT, MT_DATA); 386 if (m == NULL) { 387 printf("%s: unable to allocate Rx mbuf\n", DEVNAME); 388 ifp->if_ierrors++; 389 goto next_packet; 390 } 391 392 if (sz > (MHLEN - 2)) { 393 MCLGET(m, M_DONTWAIT); 394 if ((m->m_flags & M_EXT) == 0) { 395 printf("%s: unable to allocate Rx cluster\n", 396 DEVNAME); 397 m_freem(m); 398 m = NULL; 399 ifp->if_ierrors++; 400 goto next_packet; 401 } 402 } 403 404 m->m_data += 2; /* for alignment */ 405 m->m_pkthdr.rcvif = ifp; 406 m->m_pkthdr.len = m->m_len = sz; 407 memcpy(mtod(m, void *), (void *)sc->rx_buf, sz); 408 409 next_packet: 410 ifp->if_ipackets++; 411 412 _reg_write_1(SMAP_RXFIFO_FRAME_DEC_REG8, 1); 413 414 /* free descriptor */ 415 d->sz = 0; 416 d->ptr = 0; 417 d->stat = SMAP_RXDESC_EMPTY; 418 _wbflush(); 419 420 if (m != NULL) { 421 if (ifp->if_bpf) 422 bpf_mtap(ifp->if_bpf, m); 423 (*ifp->if_input)(ifp, m); 424 } 425 } 426 sc->rx_done_index = i; 427 428 r16 = _reg_read_2(SPD_INTR_ENABLE_REG16); 429 if (((r16 & SPD_INTR_RXDNV) == 0) && cnt > 0) { 430 r16 |= SPD_INTR_RXDNV; 431 _reg_write_2(SPD_INTR_ENABLE_REG16, r16); 432 } 433 434 FUNC_EXIT(); 435 } 436 437 void 438 smap_txeof(void *arg) 439 { 440 struct smap_softc *sc = arg; 441 struct ifnet *ifp = &sc->ethercom.ec_if; 442 struct smap_desc *d; 443 int i; 444 445 FUNC_ENTER(); 446 447 /* clear the timeout timer. */ 448 ifp->if_timer = 0; 449 450 /* garbage collect */ 451 for (i = sc->tx_done_index;; i = (i + 1) & 0x3f) { 452 u_int16_t stat; 453 454 d = &sc->tx_desc[i]; 455 stat = d->stat; 456 if (stat & SMAP_TXDESC_READY) { 457 /* all descriptor processed. */ 458 break; 459 } else if (stat & 0x7fff) { 460 if (stat & (SMAP_TXDESC_ECOLL | SMAP_TXDESC_LCOLL | 461 SMAP_TXDESC_MCOLL | SMAP_TXDESC_SCOLL)) 462 ifp->if_collisions++; 463 else 464 ifp->if_oerrors++; 465 } else { 466 ifp->if_opackets++; 467 } 468 469 if (sc->tx_desc_cnt == 0) 470 break; 471 472 sc->tx_buf_freesize += ROUND4(d->sz); 473 sc->tx_desc_cnt--; 474 475 d->sz = 0; 476 d->ptr = 0; 477 d->stat = 0; 478 _wbflush(); 479 } 480 sc->tx_done_index = i; 481 482 /* OK to start transmit */ 483 ifp->if_flags &= ~IFF_OACTIVE; 484 485 FUNC_EXIT(); 486 } 487 488 void 489 smap_start(struct ifnet *ifp) 490 { 491 struct smap_softc *sc = ifp->if_softc; 492 struct smap_desc *d; 493 struct mbuf *m0, *m; 494 u_int8_t *p, *q; 495 u_int32_t *r; 496 int i, sz, pktsz; 497 u_int16_t fifop; 498 u_int16_t r16; 499 500 KDASSERT(ifp->if_flags & IFF_RUNNING); 501 FUNC_ENTER(); 502 503 while (1) { 504 IFQ_POLL(&ifp->if_snd, m0); 505 if (m0 == NULL) 506 goto end; 507 508 pktsz = m0->m_pkthdr.len; 509 KDASSERT(pktsz <= ETHER_MAX_LEN - ETHER_CRC_LEN); 510 sz = ROUND4(pktsz); 511 512 if (sz > sc->tx_buf_freesize || 513 sc->tx_desc_cnt >= SMAP_DESC_MAX || 514 emac3_tx_done() != 0) { 515 ifp->if_flags |= IFF_OACTIVE; 516 goto end; 517 } 518 519 IFQ_DEQUEUE(&ifp->if_snd, m0); 520 KDASSERT(m0 != NULL); 521 if (ifp->if_bpf) 522 bpf_mtap(ifp->if_bpf, m0); 523 524 p = (u_int8_t *)sc->tx_buf; 525 q = p + sz; 526 /* copy to temporary buffer area */ 527 for (m = m0; m != 0; m = m->m_next) { 528 memcpy(p, mtod(m, void *), m->m_len); 529 p += m->m_len; 530 } 531 m_freem(m0); 532 533 /* zero padding area */ 534 for (; p < q; p++) 535 *p = 0; 536 537 /* put to FIFO */ 538 fifop = sc->tx_fifo_ptr; 539 KDASSERT((fifop & 3) == 0); 540 _reg_write_2(SMAP_TXFIFO_PTR_REG16, fifop); 541 sc->tx_fifo_ptr = (fifop + sz) & 0xfff; 542 543 r = sc->tx_buf; 544 for (i = 0; i < sz; i += sizeof(u_int32_t)) 545 *(volatile u_int32_t *)SMAP_TXFIFO_DATA_REG = *r++; 546 _wbflush(); 547 548 /* put FIFO to EMAC3 */ 549 d = &sc->tx_desc[sc->tx_start_index]; 550 KDASSERT((d->stat & SMAP_TXDESC_READY) == 0); 551 552 d->sz = pktsz; 553 d->ptr = fifop + SMAP_TXBUF_BASE; 554 d->stat = SMAP_TXDESC_READY | SMAP_TXDESC_GENFCS | 555 SMAP_TXDESC_GENPAD; 556 _wbflush(); 557 558 sc->tx_buf_freesize -= sz; 559 sc->tx_desc_cnt++; 560 sc->tx_start_index = (sc->tx_start_index + 1) & 0x3f; 561 _reg_write_1(SMAP_TXFIFO_FRAME_INC_REG8, 1); 562 563 emac3_tx_kick(); 564 r16 = _reg_read_2(SPD_INTR_ENABLE_REG16); 565 if ((r16 & SPD_INTR_TXDNV) == 0) { 566 r16 |= SPD_INTR_TXDNV; 567 _reg_write_2(SPD_INTR_ENABLE_REG16, r16); 568 } 569 } 570 end: 571 /* set watchdog timer */ 572 ifp->if_timer = 5; 573 574 FUNC_EXIT(); 575 } 576 577 void 578 smap_watchdog(struct ifnet *ifp) 579 { 580 struct smap_softc *sc = ifp->if_softc; 581 582 printf("%s: watchdog timeout\n",DEVNAME); 583 sc->ethercom.ec_if.if_oerrors++; 584 585 smap_fifo_init(sc); 586 smap_desc_init(sc); 587 emac3_reset(&sc->emac3); 588 } 589 590 int 591 smap_init(struct ifnet *ifp) 592 { 593 struct smap_softc *sc = ifp->if_softc; 594 u_int16_t r16; 595 int rc; 596 597 smap_fifo_init(sc); 598 emac3_reset(&sc->emac3); 599 smap_desc_init(sc); 600 601 _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND | SPD_INTR_TXEND | 602 SPD_INTR_RXDNV); 603 emac3_intr_clear(); 604 605 r16 = _reg_read_2(SPD_INTR_ENABLE_REG16); 606 r16 |= SPD_INTR_EMAC3 | SPD_INTR_RXEND | SPD_INTR_TXEND | 607 SPD_INTR_RXDNV; 608 _reg_write_2(SPD_INTR_ENABLE_REG16, r16); 609 emac3_intr_enable(); 610 611 emac3_enable(); 612 613 /* Program the multicast filter, if necessary. */ 614 emac3_setmulti(&sc->emac3, &sc->ethercom); 615 616 /* Set current media. */ 617 if ((rc = mii_mediachg(&sc->emac3.mii)) == ENXIO) 618 rc = 0; 619 else if (rc != 0) 620 return rc; 621 622 ifp->if_flags |= IFF_RUNNING; 623 624 return (0); 625 } 626 627 void 628 smap_stop(struct ifnet *ifp, int disable) 629 { 630 struct smap_softc *sc = ifp->if_softc; 631 632 mii_down(&sc->emac3.mii); 633 634 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 635 636 if (disable) 637 emac3_disable(); 638 } 639 640 /* 641 * FIFO 642 */ 643 int 644 smap_fifo_init(struct smap_softc *sc) 645 { 646 647 if (smap_fifo_reset(SMAP_TXFIFO_CTRL_REG8) != 0) 648 goto error; 649 650 if (smap_fifo_reset(SMAP_RXFIFO_CTRL_REG8) != 0) 651 goto error; 652 653 return (0); 654 error: 655 printf("%s: FIFO reset not complete.\n", DEVNAME); 656 657 return (1); 658 } 659 660 int 661 smap_fifo_reset(bus_addr_t a) 662 { 663 int retry = 10000; 664 665 _reg_write_1(a, SMAP_FIFO_RESET); 666 667 while ((_reg_read_1(a) & SMAP_FIFO_RESET) && --retry > 0) 668 ; 669 670 return (retry == 0); 671 } 672 673 /* 674 * Buffer descriptor 675 */ 676 void 677 smap_desc_init(struct smap_softc *sc) 678 { 679 struct smap_desc *d; 680 int i; 681 682 sc->tx_desc = (void *)SMAP_TXDESC_BASE; 683 sc->rx_desc = (void *)SMAP_RXDESC_BASE; 684 685 sc->tx_buf_freesize = SMAP_TXBUF_SIZE; 686 sc->tx_fifo_ptr = 0; 687 sc->tx_start_index = 0; 688 sc->tx_done_index = 0; 689 sc->rx_done_index = 0; 690 691 /* intialize entry */ 692 d = sc->tx_desc; 693 for (i = 0; i < SMAP_DESC_MAX; i++, d++) { 694 d->stat = 0; 695 d->__reserved = 0; 696 d->sz = 0; 697 d->ptr = 0; 698 } 699 700 d = sc->rx_desc; 701 for (i = 0; i < SMAP_DESC_MAX; i++, d++) { 702 d->stat = SMAP_RXDESC_EMPTY; 703 d->__reserved = 0; 704 d->sz = 0; 705 d->ptr = 0; 706 } 707 _wbflush(); 708 } 709 710 711 /* 712 * EEPROM 713 */ 714 int 715 smap_get_eaddr(struct smap_softc *sc, u_int8_t *eaddr) 716 { 717 u_int16_t checksum, *p = (u_int16_t *)eaddr; 718 719 spd_eeprom_read(0, p, 3); 720 spd_eeprom_read(3, &checksum, 1); 721 722 if (checksum != (u_int16_t)(p[0] + p[1] + p[2])) { 723 printf("%s: Ethernet address checksum error.(%s)\n", 724 DEVNAME, ether_sprintf(eaddr)); 725 return (1); 726 } 727 728 return (0); 729 } 730 731 #ifdef SMAP_DEBUG 732 #include <mips/locore.h> 733 void 734 __smap_lock_check(const char *func, int enter) 735 { 736 static int cnt; 737 static const char *last; 738 739 cnt += enter ? 1 : -1; 740 741 if (cnt < 0 || cnt > 1) 742 panic("%s cnt=%d last=%s", func, cnt, last); 743 744 last = func; 745 } 746 747 void 748 __smap_status(int msg) 749 { 750 static int cnt; 751 __gsfb_print(1, "%d: tx=%d rx=%d txcnt=%d free=%d cnt=%d\n", msg, 752 _reg_read_1(SMAP_TXFIFO_FRAME_REG8), 753 _reg_read_1(SMAP_RXFIFO_FRAME_REG8), __sc->tx_desc_cnt, 754 __sc->tx_buf_freesize, cnt++); 755 } 756 #endif /* SMAP_DEBUG */ 757