1 /* $NetBSD: if_smap.c,v 1.21 2016/06/10 13:27:12 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.21 2016/06/10 13:27:12 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 ether_ifattach(ifp, emac3->eaddr); 250 251 spd_intr_establish(SPD_NIC, smap_intr, sc); 252 253 rnd_attach_source(&sc->rnd_source, DEVNAME, 254 RND_TYPE_NET, RND_FLAG_DEFAULT); 255 } 256 257 int 258 smap_ioctl(struct ifnet *ifp, u_long command, void *data) 259 { 260 struct smap_softc *sc = ifp->if_softc; 261 int error, s; 262 263 s = splnet(); 264 265 error = ether_ioctl(ifp, command, data); 266 267 if (error == ENETRESET) { 268 if (ifp->if_flags & IFF_RUNNING) 269 emac3_setmulti(&sc->emac3, &sc->ethercom); 270 error = 0; 271 } 272 273 splx(s); 274 275 return (error); 276 } 277 278 int 279 smap_intr(void *arg) 280 { 281 struct smap_softc *sc = arg; 282 struct ifnet *ifp; 283 u_int16_t cause, disable, r; 284 285 cause = _reg_read_2(SPD_INTR_STATUS_REG16) & 286 _reg_read_2(SPD_INTR_ENABLE_REG16); 287 288 disable = cause & (SPD_INTR_RXDNV | SPD_INTR_TXDNV); 289 if (disable) { 290 r = _reg_read_2(SPD_INTR_ENABLE_REG16); 291 r &= ~disable; 292 _reg_write_2(SPD_INTR_ENABLE_REG16, r); 293 294 printf("%s: invalid descriptor. (%c%c)\n", DEVNAME, 295 disable & SPD_INTR_RXDNV ? 'R' : '_', 296 disable & SPD_INTR_TXDNV ? 'T' : '_'); 297 298 if (disable & SPD_INTR_RXDNV) 299 smap_rxeof(arg); 300 301 _reg_write_2(SPD_INTR_CLEAR_REG16, disable); 302 } 303 304 if (cause & SPD_INTR_TXEND) { 305 _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_TXEND); 306 if (_reg_read_1(SMAP_RXFIFO_FRAME_REG8) > 0) 307 cause |= SPD_INTR_RXEND; 308 smap_txeof(arg); 309 } 310 311 if (cause & SPD_INTR_RXEND) { 312 _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND); 313 smap_rxeof(arg); 314 if (sc->tx_desc_cnt > 0 && 315 sc->tx_desc_cnt > _reg_read_1(SMAP_TXFIFO_FRAME_REG8)) 316 smap_txeof(arg); 317 } 318 319 if (cause & SPD_INTR_EMAC3) 320 emac3_intr(arg); 321 322 /* if transmission is pending, start here */ 323 ifp = &sc->ethercom.ec_if; 324 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 325 smap_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 ifp->if_ipackets++; 398 399 _reg_write_1(SMAP_RXFIFO_FRAME_DEC_REG8, 1); 400 401 /* free descriptor */ 402 d->sz = 0; 403 d->ptr = 0; 404 d->stat = SMAP_RXDESC_EMPTY; 405 _wbflush(); 406 407 if (m != NULL) { 408 if (ifp->if_bpf) 409 bpf_mtap(ifp, m); 410 if_percpuq_enqueue(ifp->if_percpuq, m); 411 } 412 } 413 sc->rx_done_index = i; 414 415 r16 = _reg_read_2(SPD_INTR_ENABLE_REG16); 416 if (((r16 & SPD_INTR_RXDNV) == 0) && cnt > 0) { 417 r16 |= SPD_INTR_RXDNV; 418 _reg_write_2(SPD_INTR_ENABLE_REG16, r16); 419 } 420 421 FUNC_EXIT(); 422 } 423 424 void 425 smap_txeof(void *arg) 426 { 427 struct smap_softc *sc = arg; 428 struct ifnet *ifp = &sc->ethercom.ec_if; 429 struct smap_desc *d; 430 int i; 431 432 FUNC_ENTER(); 433 434 /* clear the timeout timer. */ 435 ifp->if_timer = 0; 436 437 /* garbage collect */ 438 for (i = sc->tx_done_index;; i = (i + 1) & 0x3f) { 439 u_int16_t stat; 440 441 d = &sc->tx_desc[i]; 442 stat = d->stat; 443 if (stat & SMAP_TXDESC_READY) { 444 /* all descriptor processed. */ 445 break; 446 } else if (stat & 0x7fff) { 447 if (stat & (SMAP_TXDESC_ECOLL | SMAP_TXDESC_LCOLL | 448 SMAP_TXDESC_MCOLL | SMAP_TXDESC_SCOLL)) 449 ifp->if_collisions++; 450 else 451 ifp->if_oerrors++; 452 } else { 453 ifp->if_opackets++; 454 } 455 456 if (sc->tx_desc_cnt == 0) 457 break; 458 459 sc->tx_buf_freesize += ROUND4(d->sz); 460 sc->tx_desc_cnt--; 461 462 d->sz = 0; 463 d->ptr = 0; 464 d->stat = 0; 465 _wbflush(); 466 } 467 sc->tx_done_index = i; 468 469 /* OK to start transmit */ 470 ifp->if_flags &= ~IFF_OACTIVE; 471 472 FUNC_EXIT(); 473 } 474 475 void 476 smap_start(struct ifnet *ifp) 477 { 478 struct smap_softc *sc = ifp->if_softc; 479 struct smap_desc *d; 480 struct mbuf *m0, *m; 481 u_int8_t *p, *q; 482 u_int32_t *r; 483 int i, sz, pktsz; 484 u_int16_t fifop; 485 u_int16_t r16; 486 487 KDASSERT(ifp->if_flags & IFF_RUNNING); 488 FUNC_ENTER(); 489 490 while (1) { 491 IFQ_POLL(&ifp->if_snd, m0); 492 if (m0 == NULL) 493 goto end; 494 495 pktsz = m0->m_pkthdr.len; 496 KDASSERT(pktsz <= ETHER_MAX_LEN - ETHER_CRC_LEN); 497 sz = ROUND4(pktsz); 498 499 if (sz > sc->tx_buf_freesize || 500 sc->tx_desc_cnt >= SMAP_DESC_MAX || 501 emac3_tx_done() != 0) { 502 ifp->if_flags |= IFF_OACTIVE; 503 goto end; 504 } 505 506 IFQ_DEQUEUE(&ifp->if_snd, m0); 507 KDASSERT(m0 != NULL); 508 if (ifp->if_bpf) 509 bpf_mtap(ifp, m0); 510 511 p = (u_int8_t *)sc->tx_buf; 512 q = p + sz; 513 /* copy to temporary buffer area */ 514 for (m = m0; m != 0; m = m->m_next) { 515 memcpy(p, mtod(m, void *), m->m_len); 516 p += m->m_len; 517 } 518 m_freem(m0); 519 520 /* zero padding area */ 521 for (; p < q; p++) 522 *p = 0; 523 524 /* put to FIFO */ 525 fifop = sc->tx_fifo_ptr; 526 KDASSERT((fifop & 3) == 0); 527 _reg_write_2(SMAP_TXFIFO_PTR_REG16, fifop); 528 sc->tx_fifo_ptr = (fifop + sz) & 0xfff; 529 530 r = sc->tx_buf; 531 for (i = 0; i < sz; i += sizeof(u_int32_t)) 532 *(volatile u_int32_t *)SMAP_TXFIFO_DATA_REG = *r++; 533 _wbflush(); 534 535 /* put FIFO to EMAC3 */ 536 d = &sc->tx_desc[sc->tx_start_index]; 537 KDASSERT((d->stat & SMAP_TXDESC_READY) == 0); 538 539 d->sz = pktsz; 540 d->ptr = fifop + SMAP_TXBUF_BASE; 541 d->stat = SMAP_TXDESC_READY | SMAP_TXDESC_GENFCS | 542 SMAP_TXDESC_GENPAD; 543 _wbflush(); 544 545 sc->tx_buf_freesize -= sz; 546 sc->tx_desc_cnt++; 547 sc->tx_start_index = (sc->tx_start_index + 1) & 0x3f; 548 _reg_write_1(SMAP_TXFIFO_FRAME_INC_REG8, 1); 549 550 emac3_tx_kick(); 551 r16 = _reg_read_2(SPD_INTR_ENABLE_REG16); 552 if ((r16 & SPD_INTR_TXDNV) == 0) { 553 r16 |= SPD_INTR_TXDNV; 554 _reg_write_2(SPD_INTR_ENABLE_REG16, r16); 555 } 556 } 557 end: 558 /* set watchdog timer */ 559 ifp->if_timer = 5; 560 561 FUNC_EXIT(); 562 } 563 564 void 565 smap_watchdog(struct ifnet *ifp) 566 { 567 struct smap_softc *sc = ifp->if_softc; 568 569 printf("%s: watchdog timeout\n",DEVNAME); 570 sc->ethercom.ec_if.if_oerrors++; 571 572 smap_fifo_init(sc); 573 smap_desc_init(sc); 574 emac3_reset(&sc->emac3); 575 } 576 577 int 578 smap_init(struct ifnet *ifp) 579 { 580 struct smap_softc *sc = ifp->if_softc; 581 u_int16_t r16; 582 int rc; 583 584 smap_fifo_init(sc); 585 emac3_reset(&sc->emac3); 586 smap_desc_init(sc); 587 588 _reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND | SPD_INTR_TXEND | 589 SPD_INTR_RXDNV); 590 emac3_intr_clear(); 591 592 r16 = _reg_read_2(SPD_INTR_ENABLE_REG16); 593 r16 |= SPD_INTR_EMAC3 | SPD_INTR_RXEND | SPD_INTR_TXEND | 594 SPD_INTR_RXDNV; 595 _reg_write_2(SPD_INTR_ENABLE_REG16, r16); 596 emac3_intr_enable(); 597 598 emac3_enable(); 599 600 /* Program the multicast filter, if necessary. */ 601 emac3_setmulti(&sc->emac3, &sc->ethercom); 602 603 /* Set current media. */ 604 if ((rc = mii_mediachg(&sc->emac3.mii)) == ENXIO) 605 rc = 0; 606 else if (rc != 0) 607 return rc; 608 609 ifp->if_flags |= IFF_RUNNING; 610 611 return (0); 612 } 613 614 void 615 smap_stop(struct ifnet *ifp, int disable) 616 { 617 struct smap_softc *sc = ifp->if_softc; 618 619 mii_down(&sc->emac3.mii); 620 621 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 622 623 if (disable) 624 emac3_disable(); 625 } 626 627 /* 628 * FIFO 629 */ 630 int 631 smap_fifo_init(struct smap_softc *sc) 632 { 633 634 if (smap_fifo_reset(SMAP_TXFIFO_CTRL_REG8) != 0) 635 goto error; 636 637 if (smap_fifo_reset(SMAP_RXFIFO_CTRL_REG8) != 0) 638 goto error; 639 640 return (0); 641 error: 642 printf("%s: FIFO reset not complete.\n", DEVNAME); 643 644 return (1); 645 } 646 647 int 648 smap_fifo_reset(bus_addr_t a) 649 { 650 int retry = 10000; 651 652 _reg_write_1(a, SMAP_FIFO_RESET); 653 654 while ((_reg_read_1(a) & SMAP_FIFO_RESET) && --retry > 0) 655 ; 656 657 return (retry == 0); 658 } 659 660 /* 661 * Buffer descriptor 662 */ 663 void 664 smap_desc_init(struct smap_softc *sc) 665 { 666 struct smap_desc *d; 667 int i; 668 669 sc->tx_desc = (void *)SMAP_TXDESC_BASE; 670 sc->rx_desc = (void *)SMAP_RXDESC_BASE; 671 672 sc->tx_buf_freesize = SMAP_TXBUF_SIZE; 673 sc->tx_fifo_ptr = 0; 674 sc->tx_start_index = 0; 675 sc->tx_done_index = 0; 676 sc->rx_done_index = 0; 677 678 /* intialize entry */ 679 d = sc->tx_desc; 680 for (i = 0; i < SMAP_DESC_MAX; i++, d++) { 681 d->stat = 0; 682 d->__reserved = 0; 683 d->sz = 0; 684 d->ptr = 0; 685 } 686 687 d = sc->rx_desc; 688 for (i = 0; i < SMAP_DESC_MAX; i++, d++) { 689 d->stat = SMAP_RXDESC_EMPTY; 690 d->__reserved = 0; 691 d->sz = 0; 692 d->ptr = 0; 693 } 694 _wbflush(); 695 } 696 697 698 /* 699 * EEPROM 700 */ 701 int 702 smap_get_eaddr(struct smap_softc *sc, u_int8_t *eaddr) 703 { 704 u_int16_t checksum, *p = (u_int16_t *)eaddr; 705 706 spd_eeprom_read(0, p, 3); 707 spd_eeprom_read(3, &checksum, 1); 708 709 if (checksum != (u_int16_t)(p[0] + p[1] + p[2])) { 710 printf("%s: Ethernet address checksum error.(%s)\n", 711 DEVNAME, ether_sprintf(eaddr)); 712 return (1); 713 } 714 715 return (0); 716 } 717 718 #ifdef SMAP_DEBUG 719 #include <mips/locore.h> 720 void 721 __smap_lock_check(const char *func, int enter) 722 { 723 static int cnt; 724 static const char *last; 725 726 cnt += enter ? 1 : -1; 727 728 if (cnt < 0 || cnt > 1) 729 panic("%s cnt=%d last=%s", func, cnt, last); 730 731 last = func; 732 } 733 734 void 735 __smap_status(int msg) 736 { 737 static int cnt; 738 __gsfb_print(1, "%d: tx=%d rx=%d txcnt=%d free=%d cnt=%d\n", msg, 739 _reg_read_1(SMAP_TXFIFO_FRAME_REG8), 740 _reg_read_1(SMAP_RXFIFO_FRAME_REG8), __sc->tx_desc_cnt, 741 __sc->tx_buf_freesize, cnt++); 742 } 743 #endif /* SMAP_DEBUG */ 744