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