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