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