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