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