1 /* $NetBSD: if_smap.c,v 1.32 2020/01/29 05:32:04 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 * 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.32 2020/01/29 05:32:04 thorpej 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_WAITOK); 197 rxbuf = malloc(ETHER_MAX_LEN + SMAP_FIFO_ALIGN + 16, 198 M_DEVBUF, M_WAITOK); 199 sc->tx_buf = (u_int32_t *)ROUND16((vaddr_t)txbuf); 200 sc->rx_buf = (u_int32_t *)ROUND16((vaddr_t)rxbuf); 201 202 /* 203 * setup MI layer 204 */ 205 strcpy(ifp->if_xname, DEVNAME); 206 ifp->if_softc = sc; 207 ifp->if_start = smap_start; 208 ifp->if_ioctl = smap_ioctl; 209 ifp->if_init = smap_init; 210 ifp->if_stop = smap_stop; 211 ifp->if_watchdog= smap_watchdog; 212 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 213 IFQ_SET_READY(&ifp->if_snd); 214 215 /* ifmedia setup. */ 216 mii->mii_ifp = ifp; 217 mii->mii_readreg = emac3_phy_readreg; 218 mii->mii_writereg = emac3_phy_writereg; 219 mii->mii_statchg = emac3_phy_statchg; 220 sc->ethercom.ec_mii = mii; 221 ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus); 222 mii_attach(&emac3->dev, mii, 0xffffffff, MII_PHY_ANY, 223 MII_OFFSET_ANY, 0); 224 225 /* Choose a default media. */ 226 if (LIST_FIRST(&mii->mii_phys) == NULL) { 227 ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); 228 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); 229 } else { 230 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 231 } 232 233 if_attach(ifp); 234 if_deferred_start_init(ifp, NULL); 235 ether_ifattach(ifp, emac3->eaddr); 236 237 spd_intr_establish(SPD_NIC, smap_intr, sc); 238 239 rnd_attach_source(&sc->rnd_source, DEVNAME, 240 RND_TYPE_NET, RND_FLAG_DEFAULT); 241 } 242 243 int 244 smap_ioctl(struct ifnet *ifp, u_long command, void *data) 245 { 246 struct smap_softc *sc = ifp->if_softc; 247 int error, s; 248 249 s = splnet(); 250 251 error = ether_ioctl(ifp, command, data); 252 253 if (error == ENETRESET) { 254 if (ifp->if_flags & IFF_RUNNING) 255 emac3_setmulti(&sc->emac3, &sc->ethercom); 256 error = 0; 257 } 258 259 splx(s); 260 261 return (error); 262 } 263 264 int 265 smap_intr(void *arg) 266 { 267 struct smap_softc *sc = arg; 268 struct ifnet *ifp; 269 u_int16_t cause, disable, r; 270 271 cause = _reg_read_2(SPD_INTR_STATUS_REG16) & 272 _reg_read_2(SPD_INTR_ENABLE_REG16); 273 274 disable = cause & (SPD_INTR_RXDNV | SPD_INTR_TXDNV); 275 if (disable) { 276 r = _reg_read_2(SPD_INTR_ENABLE_REG16); 277 r &= ~disable; 278 _reg_write_2(SPD_INTR_ENABLE_REG16, r); 279 280 printf("%s: invalid descriptor. (%c%c)\n", DEVNAME, 281 disable & SPD_INTR_RXDNV ? 'R' : '_', 282 disable & SPD_INTR_TXDNV ? 'T' : '_'); 283 284 if (disable & SPD_INTR_RXDNV) 285 smap_rxeof(arg); 286 287 _reg_write_2(SPD_INTR_CLEAR_REG16, disable); 288 } 289 290 if (cause & SPD_INTR_TXEND) { 291 _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_TXEND); 292 if (_reg_read_1(SMAP_RXFIFO_FRAME_REG8) > 0) 293 cause |= SPD_INTR_RXEND; 294 smap_txeof(arg); 295 } 296 297 if (cause & SPD_INTR_RXEND) { 298 _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND); 299 smap_rxeof(arg); 300 if (sc->tx_desc_cnt > 0 && 301 sc->tx_desc_cnt > _reg_read_1(SMAP_TXFIFO_FRAME_REG8)) 302 smap_txeof(arg); 303 } 304 305 if (cause & SPD_INTR_EMAC3) 306 emac3_intr(arg); 307 308 /* if transmission is pending, start here */ 309 ifp = &sc->ethercom.ec_if; 310 if_schedule_deferred_start(ifp); 311 rnd_add_uint32(&sc->rnd_source, cause | sc->tx_fifo_ptr << 16); 312 313 return (1); 314 } 315 316 void 317 smap_rxeof(void *arg) 318 { 319 struct smap_softc *sc = arg; 320 struct smap_desc *d; 321 struct ifnet *ifp = &sc->ethercom.ec_if; 322 struct mbuf *m; 323 u_int16_t r16, stat; 324 u_int32_t *p; 325 int i, j, sz, rxsz, cnt; 326 327 FUNC_ENTER(); 328 329 i = sc->rx_done_index; 330 331 for (cnt = 0;; cnt++, i = (i + 1) & 0x3f) { 332 m = NULL; 333 d = &sc->rx_desc[i]; 334 stat = d->stat; 335 336 if ((stat & SMAP_RXDESC_EMPTY) != 0) { 337 break; 338 } else if (stat & 0x7fff) { 339 if_statinc(ifp, if_ierrors); 340 goto next_packet; 341 } 342 343 sz = d->sz; 344 rxsz = ROUND4(sz); 345 346 KDASSERT(sz >= ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN); 347 KDASSERT(sz <= ETHER_MAX_LEN); 348 349 /* load data from FIFO */ 350 _reg_write_2(SMAP_RXFIFO_PTR_REG16, d->ptr & 0x3ffc); 351 p = sc->rx_buf; 352 for (j = 0; j < rxsz; j += sizeof(u_int32_t)) { 353 *p++ = _reg_read_4(SMAP_RXFIFO_DATA_REG); 354 } 355 356 /* put to mbuf */ 357 MGETHDR(m, M_DONTWAIT, MT_DATA); 358 if (m == NULL) { 359 printf("%s: unable to allocate Rx mbuf\n", DEVNAME); 360 if_statinc(ifp, if_ierrors); 361 goto next_packet; 362 } 363 364 if (sz > (MHLEN - 2)) { 365 MCLGET(m, M_DONTWAIT); 366 if ((m->m_flags & M_EXT) == 0) { 367 printf("%s: unable to allocate Rx cluster\n", 368 DEVNAME); 369 m_freem(m); 370 m = NULL; 371 if_statinc(ifp, if_ierrors); 372 goto next_packet; 373 } 374 } 375 376 m->m_data += 2; /* for alignment */ 377 m_set_rcvif(m, ifp); 378 m->m_pkthdr.len = m->m_len = sz; 379 memcpy(mtod(m, void *), (void *)sc->rx_buf, sz); 380 381 next_packet: 382 _reg_write_1(SMAP_RXFIFO_FRAME_DEC_REG8, 1); 383 384 /* free descriptor */ 385 d->sz = 0; 386 d->ptr = 0; 387 d->stat = SMAP_RXDESC_EMPTY; 388 _wbflush(); 389 390 if (m != NULL) 391 if_percpuq_enqueue(ifp->if_percpuq, m); 392 } 393 sc->rx_done_index = i; 394 395 r16 = _reg_read_2(SPD_INTR_ENABLE_REG16); 396 if (((r16 & SPD_INTR_RXDNV) == 0) && cnt > 0) { 397 r16 |= SPD_INTR_RXDNV; 398 _reg_write_2(SPD_INTR_ENABLE_REG16, r16); 399 } 400 401 FUNC_EXIT(); 402 } 403 404 void 405 smap_txeof(void *arg) 406 { 407 struct smap_softc *sc = arg; 408 struct ifnet *ifp = &sc->ethercom.ec_if; 409 struct smap_desc *d; 410 int i; 411 412 FUNC_ENTER(); 413 414 /* clear the timeout timer. */ 415 ifp->if_timer = 0; 416 417 /* garbage collect */ 418 for (i = sc->tx_done_index;; i = (i + 1) & 0x3f) { 419 u_int16_t stat; 420 421 d = &sc->tx_desc[i]; 422 stat = d->stat; 423 if (stat & SMAP_TXDESC_READY) { 424 /* all descriptor processed. */ 425 break; 426 } else if (stat & 0x7fff) { 427 if (stat & (SMAP_TXDESC_ECOLL | SMAP_TXDESC_LCOLL | 428 SMAP_TXDESC_MCOLL | SMAP_TXDESC_SCOLL)) 429 if_statinc(ifp, if_collisions); 430 else 431 if_statinc(ifp, if_oerrors); 432 } else { 433 if_statinc(ifp, if_opackets); 434 } 435 436 if (sc->tx_desc_cnt == 0) 437 break; 438 439 sc->tx_buf_freesize += ROUND4(d->sz); 440 sc->tx_desc_cnt--; 441 442 d->sz = 0; 443 d->ptr = 0; 444 d->stat = 0; 445 _wbflush(); 446 } 447 sc->tx_done_index = i; 448 449 /* OK to start transmit */ 450 ifp->if_flags &= ~IFF_OACTIVE; 451 452 FUNC_EXIT(); 453 } 454 455 void 456 smap_start(struct ifnet *ifp) 457 { 458 struct smap_softc *sc = ifp->if_softc; 459 struct smap_desc *d; 460 struct mbuf *m0, *m; 461 u_int8_t *p, *q; 462 u_int32_t *r; 463 int i, sz, pktsz; 464 u_int16_t fifop; 465 u_int16_t r16; 466 467 KDASSERT(ifp->if_flags & IFF_RUNNING); 468 FUNC_ENTER(); 469 470 while (1) { 471 IFQ_POLL(&ifp->if_snd, m0); 472 if (m0 == NULL) 473 goto end; 474 475 pktsz = m0->m_pkthdr.len; 476 KDASSERT(pktsz <= ETHER_MAX_LEN - ETHER_CRC_LEN); 477 sz = ROUND4(pktsz); 478 479 if (sz > sc->tx_buf_freesize || 480 sc->tx_desc_cnt >= SMAP_DESC_MAX || 481 emac3_tx_done() != 0) { 482 ifp->if_flags |= IFF_OACTIVE; 483 goto end; 484 } 485 486 IFQ_DEQUEUE(&ifp->if_snd, m0); 487 KDASSERT(m0 != NULL); 488 bpf_mtap(ifp, m0, BPF_D_OUT); 489 490 p = (u_int8_t *)sc->tx_buf; 491 q = p + sz; 492 /* copy to temporary buffer area */ 493 for (m = m0; m != 0; m = m->m_next) { 494 memcpy(p, mtod(m, void *), m->m_len); 495 p += m->m_len; 496 } 497 m_freem(m0); 498 499 /* zero padding area */ 500 for (; p < q; p++) 501 *p = 0; 502 503 /* put to FIFO */ 504 fifop = sc->tx_fifo_ptr; 505 KDASSERT((fifop & 3) == 0); 506 _reg_write_2(SMAP_TXFIFO_PTR_REG16, fifop); 507 sc->tx_fifo_ptr = (fifop + sz) & 0xfff; 508 509 r = sc->tx_buf; 510 for (i = 0; i < sz; i += sizeof(u_int32_t)) 511 *(volatile u_int32_t *)SMAP_TXFIFO_DATA_REG = *r++; 512 _wbflush(); 513 514 /* put FIFO to EMAC3 */ 515 d = &sc->tx_desc[sc->tx_start_index]; 516 KDASSERT((d->stat & SMAP_TXDESC_READY) == 0); 517 518 d->sz = pktsz; 519 d->ptr = fifop + SMAP_TXBUF_BASE; 520 d->stat = SMAP_TXDESC_READY | SMAP_TXDESC_GENFCS | 521 SMAP_TXDESC_GENPAD; 522 _wbflush(); 523 524 sc->tx_buf_freesize -= sz; 525 sc->tx_desc_cnt++; 526 sc->tx_start_index = (sc->tx_start_index + 1) & 0x3f; 527 _reg_write_1(SMAP_TXFIFO_FRAME_INC_REG8, 1); 528 529 emac3_tx_kick(); 530 r16 = _reg_read_2(SPD_INTR_ENABLE_REG16); 531 if ((r16 & SPD_INTR_TXDNV) == 0) { 532 r16 |= SPD_INTR_TXDNV; 533 _reg_write_2(SPD_INTR_ENABLE_REG16, r16); 534 } 535 } 536 end: 537 /* set watchdog timer */ 538 ifp->if_timer = 5; 539 540 FUNC_EXIT(); 541 } 542 543 void 544 smap_watchdog(struct ifnet *ifp) 545 { 546 struct smap_softc *sc = ifp->if_softc; 547 548 printf("%s: watchdog timeout\n", DEVNAME); 549 if_statinc(ifp, if_oerrors); 550 551 smap_fifo_init(sc); 552 smap_desc_init(sc); 553 emac3_reset(&sc->emac3); 554 } 555 556 int 557 smap_init(struct ifnet *ifp) 558 { 559 struct smap_softc *sc = ifp->if_softc; 560 u_int16_t r16; 561 int rc; 562 563 smap_fifo_init(sc); 564 emac3_reset(&sc->emac3); 565 smap_desc_init(sc); 566 567 _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND | SPD_INTR_TXEND | 568 SPD_INTR_RXDNV); 569 emac3_intr_clear(); 570 571 r16 = _reg_read_2(SPD_INTR_ENABLE_REG16); 572 r16 |= SPD_INTR_EMAC3 | SPD_INTR_RXEND | SPD_INTR_TXEND | 573 SPD_INTR_RXDNV; 574 _reg_write_2(SPD_INTR_ENABLE_REG16, r16); 575 emac3_intr_enable(); 576 577 emac3_enable(); 578 579 /* Program the multicast filter, if necessary. */ 580 emac3_setmulti(&sc->emac3, &sc->ethercom); 581 582 /* Set current media. */ 583 if ((rc = mii_mediachg(&sc->emac3.mii)) == ENXIO) 584 rc = 0; 585 else if (rc != 0) 586 return rc; 587 588 ifp->if_flags |= IFF_RUNNING; 589 590 return (0); 591 } 592 593 void 594 smap_stop(struct ifnet *ifp, int disable) 595 { 596 struct smap_softc *sc = ifp->if_softc; 597 598 mii_down(&sc->emac3.mii); 599 600 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 601 602 if (disable) 603 emac3_disable(); 604 } 605 606 /* 607 * FIFO 608 */ 609 int 610 smap_fifo_init(struct smap_softc *sc) 611 { 612 613 if (smap_fifo_reset(SMAP_TXFIFO_CTRL_REG8) != 0) 614 goto error; 615 616 if (smap_fifo_reset(SMAP_RXFIFO_CTRL_REG8) != 0) 617 goto error; 618 619 return (0); 620 error: 621 printf("%s: FIFO reset not complete.\n", DEVNAME); 622 623 return (1); 624 } 625 626 int 627 smap_fifo_reset(bus_addr_t a) 628 { 629 int retry = 10000; 630 631 _reg_write_1(a, SMAP_FIFO_RESET); 632 633 while ((_reg_read_1(a) & SMAP_FIFO_RESET) && --retry > 0) 634 ; 635 636 return (retry == 0); 637 } 638 639 /* 640 * Buffer descriptor 641 */ 642 void 643 smap_desc_init(struct smap_softc *sc) 644 { 645 struct smap_desc *d; 646 int i; 647 648 sc->tx_desc = (void *)SMAP_TXDESC_BASE; 649 sc->rx_desc = (void *)SMAP_RXDESC_BASE; 650 651 sc->tx_buf_freesize = SMAP_TXBUF_SIZE; 652 sc->tx_fifo_ptr = 0; 653 sc->tx_start_index = 0; 654 sc->tx_done_index = 0; 655 sc->rx_done_index = 0; 656 657 /* initialize entry */ 658 d = sc->tx_desc; 659 for (i = 0; i < SMAP_DESC_MAX; i++, d++) { 660 d->stat = 0; 661 d->__reserved = 0; 662 d->sz = 0; 663 d->ptr = 0; 664 } 665 666 d = sc->rx_desc; 667 for (i = 0; i < SMAP_DESC_MAX; i++, d++) { 668 d->stat = SMAP_RXDESC_EMPTY; 669 d->__reserved = 0; 670 d->sz = 0; 671 d->ptr = 0; 672 } 673 _wbflush(); 674 } 675 676 677 /* 678 * EEPROM 679 */ 680 int 681 smap_get_eaddr(struct smap_softc *sc, u_int8_t *eaddr) 682 { 683 u_int16_t checksum, *p = (u_int16_t *)eaddr; 684 685 spd_eeprom_read(0, p, 3); 686 spd_eeprom_read(3, &checksum, 1); 687 688 if (checksum != (u_int16_t)(p[0] + p[1] + p[2])) { 689 printf("%s: Ethernet address checksum error.(%s)\n", 690 DEVNAME, ether_sprintf(eaddr)); 691 return (1); 692 } 693 694 return (0); 695 } 696 697 #ifdef SMAP_DEBUG 698 #include <mips/locore.h> 699 void 700 __smap_lock_check(const char *func, int enter) 701 { 702 static int cnt; 703 static const char *last; 704 705 cnt += enter ? 1 : -1; 706 707 if (cnt < 0 || cnt > 1) 708 panic("%s cnt=%d last=%s", func, cnt, last); 709 710 last = func; 711 } 712 713 void 714 __smap_status(int msg) 715 { 716 static int cnt; 717 __gsfb_print(1, "%d: tx=%d rx=%d txcnt=%d free=%d cnt=%d\n", msg, 718 _reg_read_1(SMAP_TXFIFO_FRAME_REG8), 719 _reg_read_1(SMAP_RXFIFO_FRAME_REG8), __sc->tx_desc_cnt, 720 __sc->tx_buf_freesize, cnt++); 721 } 722 #endif /* SMAP_DEBUG */ 723