1/* ********************************************************************* 2 * SB1250_ETHERNET 3 * 4 * CFE Ethernet Driver File: DEV_SB1250_ETHERNET.C 5 * 6 * Author: Mitch Lichtenberg 7 * 8 * This is the console monitor Ethernet driver for the SB1250 9 * 10 ********************************************************************* 11 * 12 * Copyright 2000,2001,2002,2003 13 * Broadcom Corporation. All rights reserved. 14 * 15 * This software is furnished under license and may be used and 16 * copied only in accordance with the following terms and 17 * conditions. Subject to these conditions, you may download, 18 * copy, install, use, modify and distribute modified or unmodified 19 * copies of this software in source and/or binary form. No title 20 * or ownership is transferred hereby. 21 * 22 * 1) Any source code used, modified or distributed must reproduce 23 * and retain this copyright notice and list of conditions 24 * as they appear in the source file. 25 * 26 * 2) No right is granted to use any trade name, trademark, or 27 * logo of Broadcom Corporation. The "Broadcom Corporation" 28 * name may not be used to endorse or promote products derived 29 * from this software without the prior written permission of 30 * Broadcom Corporation. 31 * 32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 44 * THE POSSIBILITY OF SUCH DAMAGE. 45 ********************************************************************* */ 46 47#undef SIBYTE_HDR_FEATURES /* we want all constants here */ 48 49#include "cfe.h" 50#include "sbmips.h" 51 52#include "env_subr.h" 53 54#include "net_enet.h" 55 56#include "sb1250_defs.h" 57#include "sb1250_regs.h" 58#include "sb1250_mac.h" 59#include "sb1250_dma.h" 60#include "mii.h" 61 62/* ********************************************************************* 63 * Simple types 64 ********************************************************************* */ 65 66#ifdef __long64 67typedef volatile uint64_t sbeth_port_t; 68typedef uint64_t sbeth_physaddr_t; 69#define SBETH_PORT(x) PHYS_TO_K1(x) 70#else 71typedef volatile uint32_t sbeth_port_t; 72typedef uint32_t sbeth_physaddr_t; 73#define SBETH_PORT(x) PHYS_TO_K1(x) 74#endif 75 76#define SBETH_READCSR(t) (*((volatile uint64_t *) (t))) 77#define SBETH_WRITECSR(t,v) *((volatile uint64_t *) (t)) = (v) 78 79#define SBETH_MAX_TXDESCR 8 80#define SBETH_MAX_RXDESCR 8 81#define SBETH_MIN_RCV_RING 4 82#define SBETH_PKTPOOL_SIZE 16 83#define SBETH_DMA_CHANNELS 1 84#define SBETH_PKT_SIZE (ENET_MAX_PKT+ENET_CRC_SIZE) 85#define SBETH_PKTBUF_SIZE 2048 86 87#if CFG_L2_RAM 88#define SBETH_VTOP(x) ((sbeth_physaddr_t)0xD0000000 + (sbeth_physaddr_t)(x)) 89#else 90#define SBETH_VTOP(x) (K1_TO_PHYS((sbeth_physaddr_t)(x))) 91#endif 92 93 94typedef enum { sbeth_speed_10, sbeth_speed_100, 95 sbeth_speed_1000 } sbeth_speed_t; 96 97typedef enum { sbeth_duplex_half, 98 sbeth_duplex_full } sbeth_duplex_t; 99 100typedef enum { sbeth_fc_disabled, sbeth_fc_frame, 101 sbeth_fc_collision, sbeth_fc_carrier } sbeth_fc_t; 102 103typedef enum { sbeth_state_uninit, sbeth_state_off, sbeth_state_on, 104 sbeth_state_broken } sbeth_state_t; 105 106typedef uint64_t sbeth_enetaddr_t; 107 108typedef struct sbeth_s sbeth_t; /* forward reference */ 109 110static int sbeth_setspeed(sbeth_t *s,sbeth_speed_t speed); 111static int sbeth_set_duplex(sbeth_t *s,sbeth_duplex_t duplex,sbeth_fc_t fc); 112static int sb1250_ether_ioctl_speed(sbeth_t *s,int speed); 113 114#define SBETH_MIIPOLL_TIMER (4*CFE_HZ) 115 116/* ********************************************************************* 117 * Descriptor structure 118 ********************************************************************* */ 119 120typedef struct sbdmadscr_s { 121 uint64_t dscr_a; 122 uint64_t dscr_b; 123} sbdmadscr_t; 124 125/* ********************************************************************* 126 * DMA structure 127 ********************************************************************* */ 128 129typedef struct sbethdma_s { 130 131 /* 132 * This stuff is used to identify the channel and the registers 133 * associated with it. 134 */ 135 136 sbeth_t *sbdma_eth; /* back pointer to associated MAC */ 137 int sbdma_channel; /* channel number */ 138 int sbdma_txdir; /* direction (1=transmit) */ 139 int sbdma_maxdescr; /* total # of descriptors in ring */ 140 sbeth_port_t sbdma_config0; /* DMA config register 0 */ 141 sbeth_port_t sbdma_config1; /* DMA config register 1 */ 142 sbeth_port_t sbdma_dscrbase; /* Descriptor base address */ 143 sbeth_port_t sbdma_dscrcnt; /* Descriptor count register */ 144 sbeth_port_t sbdma_curdscr; /* current descriptor address */ 145 146 /* 147 * This stuff is for maintenance of the ring 148 */ 149 150 sbdmadscr_t *sbdma_dscrtable; /* base of descriptor table */ 151 sbdmadscr_t *sbdma_dscrtable_end; /* end of descriptor table */ 152 153 void **sbdma_ctxtable; /* context table, one per descr */ 154 155 int sbdma_onring; /* count of packets on ring */ 156 157 sbeth_physaddr_t sbdma_dscrtable_phys; /* and also the phys addr */ 158 sbdmadscr_t *sbdma_addptr; /* next dscr for sw to add */ 159 sbdmadscr_t *sbdma_remptr; /* next dscr for sw to remove */ 160 161 void (*sbdma_upcall)(void *ifctx,int chan,void *ctx, 162 uint64_t status,unsigned int length); 163} sbethdma_t; 164 165typedef struct sbeth_pkt_s { 166 struct sbeth_pkt_s *next; 167 void *devctx; 168 unsigned char *buffer; 169 int length; 170 /* packet data goes here */ 171} sbeth_pkt_t; 172 173/* ********************************************************************* 174 * Ethernet controller structure 175 ********************************************************************* */ 176 177struct sbeth_s { 178 cfe_devctx_t *sbe_devctx; 179 sbeth_port_t sbe_baseaddr; /* base address */ 180 181 sbeth_state_t sbe_state; /* current state */ 182 183 sbeth_port_t sbe_macenable; /* MAC Enable Register */ 184 sbeth_port_t sbe_maccfg; /* MAC Configuration Register */ 185 sbeth_port_t sbe_fifocfg; /* FIFO configuration register */ 186 sbeth_port_t sbe_framecfg; /* Frame configuration register */ 187 sbeth_port_t sbe_rxfilter; /* receive filter register */ 188 sbeth_port_t sbe_isr; /* Interrupt status register */ 189 sbeth_port_t sbe_imr; /* Interrupt mask register */ 190 sbeth_port_t sbe_mdio; /* PHY control stuff */ 191 192 sbeth_speed_t sbe_speed; /* current speed */ 193 sbeth_duplex_t sbe_duplex; /* current duplex */ 194 sbeth_fc_t sbe_fc; /* current flow control setting */ 195 int sbe_rxflags; /* received packet flags */ 196 int sbe_autospeed; /* true for automatic speed setting */ 197 int sbe_curspeed; /* value for GET SPEED ioctl */ 198 int sbe_loopback; /* IOCTL LOOPBACK stuff */ 199 int sbe_linkstat; /* Current link status */ 200 201 sbethdma_t sbe_txdma[SBETH_DMA_CHANNELS]; /* one for each channel */ 202 sbethdma_t sbe_rxdma[SBETH_DMA_CHANNELS]; 203 void *sbe_ifctx; 204 205 int sbe_minrxring; /* min packets to keep on RX ring */ 206 207 sbeth_pkt_t *sbe_rxqueue; /* received packet queue */ 208 209 sbeth_pkt_t *sbe_freelist; /* free packet list */ 210 211 unsigned char *sbe_pktpool; 212 213 unsigned char sbe_hwaddr[ENET_ADDR_LEN]; 214 215 int sbe_phyaddr; 216 uint32_t sbe_phyvendor; 217 uint32_t sbe_phydevice; 218 int sbe_zerormon; 219 220 uint32_t sbe_phy_oldbmsr; 221 uint32_t sbe_phy_oldbmcr; 222 uint32_t sbe_phy_oldanlpar; 223 uint32_t sbe_phy_oldk1stsr; 224 225 int64_t sbe_linkstat_timer; 226 int fifo_mode; /* true if in packet fifo mode */ 227 228}; 229 230 231/* ********************************************************************* 232 * Prototypes 233 ********************************************************************* */ 234 235static int sbeth_transmit(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg); 236static int sbeth_addrcvbuf(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg); 237static int sbeth_initctx(sbeth_t *s,unsigned long baseaddr,void *ifctx); 238 239static void sbeth_start(sbeth_t *s); 240static void sbeth_stop(sbeth_t *s); 241 242static void sbeth_initfreelist(sbeth_t *s); 243static sbeth_pkt_t *sbeth_alloc_pkt(sbeth_t *s); 244static void sbeth_free_pkt(sbeth_t *s,sbeth_pkt_t *pkt); 245static void sbeth_tx_callback(void *ifctx,int chan,void *ctx, 246 uint64_t status,unsigned int pktsize); 247static void sbeth_rx_callback(void *ifctx,int chan,void *ctx, 248 uint64_t status,unsigned int pktsize); 249static void sbeth_fillrxring(sbeth_t *s,int chan); 250static void sb1250_ether_probe(cfe_driver_t *drv, 251 unsigned long probe_a, unsigned long probe_b, 252 void *probe_ptr); 253 254static void sbeth_setaddr(sbeth_t *s,uint8_t *addr); 255 256/* ********************************************************************* 257 * Macros 258 ********************************************************************* */ 259 260#define sbdma_nextbuf(d,f) ((((d)->f+1) == (d)->sbdma_dscrtable_end) ? \ 261 (d)->sbdma_dscrtable : (d)->f+1) 262 263#define SBDMA_CACHESIZE 32 /* wants to be somewhere else */ 264#define SBDMA_NUMCACHEBLKS(x) ((x+SBDMA_CACHESIZE-1)/SBDMA_CACHESIZE) 265 266#define STRAP_PHY1 0x0800 267#define STRAP_NCMODE 0x0400 268#define STRAP_MANMSCFG 0x0200 269#define STRAP_ANENABLE 0x0100 270#define STRAP_MSVAL 0x0080 271#define STRAP_1KHDXADV 0x0010 272#define STRAP_1KFDXADV 0x0008 273#define STRAP_100ADV 0x0004 274#define STRAP_SPEEDSEL 0x0000 275#define STRAP_SPEED100 0x0001 276 277#define PHYSUP_SPEED1000 0x10 278#define PHYSUP_SPEED100 0x08 279#define PHYSUP_SPEED10 0x00 280#define PHYSUP_LINKUP 0x04 281#define PHYSUP_FDX 0x02 282 283#define M_MAC_MDIO_DIR_OUTPUT 0 /* for clarity */ 284 285 286/* ********************************************************************** */ 287 288 289 290/* ********************************************************************* 291 * SBETH_MII_SYNC(s) 292 * 293 * Synchronize with the MII - send a pattern of bits to the MII 294 * that will guarantee that it is ready to accept a command. 295 * 296 * Input parameters: 297 * s - sbmac structure 298 * 299 * Return value: 300 * nothing 301 ********************************************************************* */ 302 303static void sbeth_mii_sync(sbeth_t *s) 304{ 305 int cnt; 306 uint64_t bits; 307 int mac_mdio_genc; 308 309 mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC; 310 311 bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT; 312 313 SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc); 314 315 for (cnt = 0; cnt < 32; cnt++) { 316 SBETH_WRITECSR(s->sbe_mdio,bits | M_MAC_MDC | mac_mdio_genc); 317 SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc); 318 } 319 320} 321 322/* ********************************************************************* 323 * SBETH_MII_SENDDATA(s,data,bitcnt) 324 * 325 * Send some bits to the MII. The bits to be sent are right- 326 * justified in the 'data' parameter. 327 * 328 * Input parameters: 329 * s - sbmac structure 330 * data - data to send 331 * bitcnt - number of bits to send 332 ********************************************************************* */ 333 334static void sbeth_mii_senddata(sbeth_t *s,unsigned int data, int bitcnt) 335{ 336 int i; 337 uint64_t bits; 338 unsigned int curmask; 339 int mac_mdio_genc; 340 341 mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC; 342 343 bits = M_MAC_MDIO_DIR_OUTPUT; 344 SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc); 345 346 curmask = 1 << (bitcnt - 1); 347 348 for (i = 0; i < bitcnt; i++) { 349 if (data & curmask) bits |= M_MAC_MDIO_OUT; 350 else bits &= ~M_MAC_MDIO_OUT; 351 SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc); 352 SBETH_WRITECSR(s->sbe_mdio,bits | M_MAC_MDC | mac_mdio_genc); 353 SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc); 354 curmask >>= 1; 355 } 356} 357 358 359 360/* ********************************************************************* 361 * SBETH_MII_READ(s,phyaddr,regidx) 362 * 363 * Read a PHY register. 364 * 365 * Input parameters: 366 * s - sbmac structure 367 * phyaddr - PHY's address 368 * regidx = index of register to read 369 * 370 * Return value: 371 * value read, or 0 if an error occured. 372 ********************************************************************* */ 373 374static unsigned int sbeth_mii_read(sbeth_t *s,int phyaddr,int regidx) 375{ 376 int idx; 377 int error; 378 int regval; 379 int mac_mdio_genc; 380 381 /* 382 * Synchronize ourselves so that the PHY knows the next 383 * thing coming down is a command 384 */ 385 386 sbeth_mii_sync(s); 387 388 /* 389 * Send the data to the PHY. The sequence is 390 * a "start" command (2 bits) 391 * a "read" command (2 bits) 392 * the PHY addr (5 bits) 393 * the register index (5 bits) 394 */ 395 396 sbeth_mii_senddata(s,MII_COMMAND_START, 2); 397 sbeth_mii_senddata(s,MII_COMMAND_READ, 2); 398 sbeth_mii_senddata(s,phyaddr, 5); 399 sbeth_mii_senddata(s,regidx, 5); 400 401 mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC; 402 403 /* 404 * Switch the port around without a clock transition. 405 */ 406 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc); 407 408 /* 409 * Send out a clock pulse to signal we want the status 410 */ 411 412 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc); 413 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc); 414 415 /* 416 * If an error occured, the PHY will signal '1' back 417 */ 418 error = SBETH_READCSR(s->sbe_mdio) & M_MAC_MDIO_IN; 419 420 /* 421 * Issue an 'idle' clock pulse, but keep the direction 422 * the same. 423 */ 424 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc); 425 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc); 426 427 regval = 0; 428 429 for (idx = 0; idx < 16; idx++) { 430 regval <<= 1; 431 432 if (error == 0) { 433 if (SBETH_READCSR(s->sbe_mdio) & M_MAC_MDIO_IN) regval |= 1; 434 } 435 436 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc); 437 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc); 438 } 439 440 /* Switch back to output */ 441 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc); 442 443 if (error == 0) return regval; 444 return 0; 445} 446 447 448/* ********************************************************************* 449 * SBETH_MII_WRITE(s,phyaddr,regidx,regval) 450 * 451 * Write a value to a PHY register. 452 * 453 * Input parameters: 454 * s - sbmac structure 455 * phyaddr - PHY to use 456 * regidx - register within the PHY 457 * regval - data to write to register 458 * 459 * Return value: 460 * nothing 461 ********************************************************************* */ 462 463void sbeth_mii_write(sbeth_t *s,int phyaddr,int regidx, 464 unsigned int regval); 465void sbeth_mii_write(sbeth_t *s,int phyaddr,int regidx, 466 unsigned int regval) 467{ 468 int mac_mdio_genc; 469 470 sbeth_mii_sync(s); 471 472 sbeth_mii_senddata(s,MII_COMMAND_START,2); 473 sbeth_mii_senddata(s,MII_COMMAND_WRITE,2); 474 sbeth_mii_senddata(s,phyaddr, 5); 475 sbeth_mii_senddata(s,regidx, 5); 476 sbeth_mii_senddata(s,MII_COMMAND_ACK,2); 477 sbeth_mii_senddata(s,regval,16); 478 479 mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC; 480 481 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc); 482} 483 484 485/* ********************************************************************* 486 * SBETH_PHY_DUMP(s) 487 * 488 * Dump out the MII registers 489 * 490 * Input parameters: 491 * s - sbeth structure 492 * phy_addr - phy address 493 * label - text for banner line 494 * 495 * Return value: 496 * nothing 497 ********************************************************************* */ 498 499#if 0 500static void 501sbeth_phy_dump(sbeth_t *sc, unsigned int phy_addr, const char *label) 502{ 503 int i; 504 uint16_t r, r1; 505 uint16_t id1, id2; 506 uint32_t phy_vendor; 507 uint16_t phy_device; 508 509 xprintf("%s, MII(%d):\n", label, phy_addr); 510 511 id1 = sbeth_mii_read(sc, phy_addr, MII_PHYIDR1); 512 id2 = sbeth_mii_read(sc, phy_addr, MII_PHYIDR2); 513 phy_vendor = ((uint32_t)id1 << 6) | ((id2 >> 10) & 0x3F); 514 phy_device = (id2 >> 4) & 0x3F; 515 516 /* Required registers */ 517 for (i = 0x0; i <= 0x6; ++i) { 518 r = sbeth_mii_read(sc, phy_addr, i); 519 r1 = sbeth_mii_read(sc, phy_addr, i); 520 xprintf(" REG%02X: %04X", i, r); 521 if (r1 != r) 522 xprintf("/%04X", r1); 523 if (i == 3 || i == 6) 524 xprintf("\n"); 525 } 526 527 /* GMII extensions */ 528 for (i = 0x9; i <= 0xA; ++i) { 529 r = sbeth_mii_read(sc, phy_addr, i); 530 xprintf(" REG%02X: %04X", i, r); 531 } 532 r = sbeth_mii_read(sc, phy_addr, 0xF); 533 xprintf(" REG%02X: %04X\n", 0xF, r); 534 535 /* Broadcom extensions (54xx family) */ 536 if (phy_vendor == OUI_BCM) { 537 for (i = 0x10; i <= 0x14; i++) { 538 r = sbeth_mii_read(sc, phy_addr, i); 539 xprintf(" REG%02X: %04X", i, r); 540 } 541 xprintf("\n"); 542 for (i = 0x18; i <= 0x1A; i++) { 543 r = sbeth_mii_read(sc, phy_addr, i); 544 xprintf(" REG%02X: %04X", i, r); 545 } 546 xprintf("\n"); 547 548 if (phy_device == DEV_BCM5461 || phy_device == DEV_BCM5464) { 549 uint16_t shadow, shadow1; 550 551 xprintf(" REG1C/\n"); 552 553 for (i = 0x18; i <= 0x1F; i++) { 554 shadow = (i << 10); 555 sbeth_mii_write(sc, phy_addr, 0x1C, shadow); 556 shadow = sbeth_mii_read(sc, phy_addr, 0x1C); 557 shadow1 = sbeth_mii_read(sc, phy_addr, 0x1C); 558 xprintf(" %02X: %04X", i, shadow); 559 if (shadow1 != shadow) 560 xprintf("/%04X", shadow1); 561 if (i % 4 == 3) xprintf("\n"); 562 } 563 } 564 } 565} 566#else 567#define sbeth_phy_dump(sc,phy_addr,label) 568#endif 569 570 571/* ********************************************************************* 572 * SBDMA_INITCHAN(s,d) 573 * 574 * Initialize the DMA channel, programming the CSRs to the 575 * values calculated in the SBDMA_INITCTX routine. 576 * 577 * Input parameters: 578 * s - sbeth structure 579 * d - sbdma structure 580 * 581 * Return value: 582 * nothing 583 ********************************************************************* */ 584static void sbdma_initchan(sbeth_t *s, 585 sbethdma_t *d) 586{ 587 /* 588 * Turn on the DMA channel 589 */ 590 591 SBETH_WRITECSR(d->sbdma_config1,0); 592 593 SBETH_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys); 594 595 SBETH_WRITECSR(d->sbdma_config0, 596 V_DMA_RINGSZ(d->sbdma_maxdescr) | 597 0); 598 599} 600 601/* ********************************************************************* 602 * SBDMA_INITCTX(s,d,chan,txrx,maxdescr,callback) 603 * 604 * Initialize a DMA channel context. Since there are potentially 605 * eight DMA channels per MAC, it's nice to do this in a standard 606 * way. 607 * 608 * Input parameters: 609 * s - sbeth_t structure (pointer to a MAC) 610 * d - sbethdma_t structure (DMA channel context) 611 * chan - channel number (0..1 right now) 612 * txrx - Identifies DMA_TX or DMA_RX for channel direction 613 * maxdescr - number of descriptors to allocate for the ring 614 * 615 * Return value: 616 * nothing 617 ********************************************************************* */ 618 619static void sbdma_initctx(sbeth_t *s, 620 sbethdma_t *d, 621 int chan, 622 int txrx, 623 int maxdescr, 624 void (*callback)(void *,int,void *,uint64_t,unsigned int)) 625{ 626 /* 627 * Save away interesting stuff in the structure 628 */ 629 630 d->sbdma_eth = s; 631 d->sbdma_channel = chan; 632 d->sbdma_txdir = txrx; 633 d->sbdma_maxdescr = maxdescr; 634 635 /* 636 * initialize register pointers 637 */ 638 639 d->sbdma_config0 = SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0)); 640 d->sbdma_config1 = SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1)); 641 d->sbdma_dscrbase = SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE)); 642 d->sbdma_dscrcnt = SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT)); 643 d->sbdma_curdscr = SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR)); 644 645 /* 646 * initialize the ring 647 */ 648 649 d->sbdma_dscrtable = (sbdmadscr_t *) 650 KMALLOC(maxdescr*sizeof(sbdmadscr_t),sizeof(sbdmadscr_t)); 651 d->sbdma_dscrtable_end = d->sbdma_dscrtable + maxdescr; 652 653 d->sbdma_dscrtable_phys = SBETH_VTOP(d->sbdma_dscrtable); 654 d->sbdma_addptr = d->sbdma_dscrtable; 655 d->sbdma_remptr = d->sbdma_dscrtable; 656 657 d->sbdma_ctxtable = (void **) 658 KMALLOC(maxdescr*sizeof(void *),sizeof(void *)); 659 660 /* 661 * install callback 662 */ 663 664 d->sbdma_upcall = callback; 665 666 667} 668 669 670 671/* ********************************************************************* 672 * SBDMA_RESET(d) 673 * 674 * Reset the software-maintained state for the specified 675 * DMA channel. 676 * 677 * Input parameters: 678 * d - dma channel 679 * 680 * Return value: 681 * nothing 682 ********************************************************************* */ 683 684static void sbdma_reset(sbethdma_t *d) 685{ 686 d->sbdma_addptr = d->sbdma_dscrtable; 687 d->sbdma_remptr = d->sbdma_dscrtable; 688 d->sbdma_onring = 0; 689} 690 691/* ********************************************************************* 692 * SBDMA_PROCBUFFERS(d,procfunc) 693 * 694 * Process "completed" buffers on the specified DMA channel. 695 * This is normally called within the interrupt service routine. 696 * Note that this isn't really ideal for priority channels, since 697 * it processes all of the packets on a given channel before 698 * returning. 699 * 700 * Input parameters: 701 * d - DMA channel context 702 * procfunc - routine to call for each completed buffer. This 703 * is called with the context for the completed buffer, 704 * the status from the descriptor, and the length from 705 * the descriptor. 706 * 707 * Return value: 708 * number of packets processed. 709 ********************************************************************* */ 710 711static int sbdma_procbuffers(sbethdma_t *d, 712 void (*procfunc)(void *ifctx,int chan,void *ctx, 713 uint64_t status, 714 unsigned int pktlen)) 715{ 716 int curidx; 717 int hwidx; 718 int count = 0; 719 sbdmadscr_t *dsc; 720 721 for (;;) { 722 /* 723 * figure out where we are (as an index) and where 724 * the hardware is (also as an index) 725 * 726 * This could be done faster if (for example) the 727 * descriptor table was page-aligned and contiguous in 728 * both virtual and physical memory -- you could then 729 * just compare the low-order bits of the virtual address 730 * (sbdma_remptr) and the physical address (sbdma_curdscr CSR) 731 */ 732 733 curidx = d->sbdma_remptr - d->sbdma_dscrtable; 734 { 735 uint64_t tmp; 736 tmp = SBETH_READCSR(d->sbdma_curdscr); 737 if (!tmp) { 738 break; 739 } 740 hwidx = (int) (((tmp & M_DMA_CURDSCR_ADDR) - 741 d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t)); 742 } 743 744 /* 745 * If they're the same, that means we've processed all 746 * of the descriptors up to (but not including) the one that 747 * the hardware is working on right now. 748 */ 749 750 if (curidx == hwidx) break; 751 752 /* 753 * Remove packet from the on-ring count. 754 */ 755 756 d->sbdma_onring--; 757 758 /* 759 * Otherwise, issue the upcall. 760 */ 761 762 dsc = &(d->sbdma_dscrtable[curidx]); 763 (*procfunc)(d->sbdma_eth->sbe_ifctx, 764 d->sbdma_channel, 765 d->sbdma_ctxtable[curidx], 766 dsc->dscr_a & M_DMA_DSCRA_STATUS, 767 (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b)); 768 count++; 769 770 /* 771 * .. and advance to the next buffer. 772 */ 773 774 d->sbdma_remptr = sbdma_nextbuf(d,sbdma_remptr); 775 776 } 777 778 return count; 779} 780 781/* ********************************************************************* 782 * SBDMA_ADDBUFFER(d,ptr,length,ctx) 783 * 784 * Add a buffer to the specified DMA channel. For transmit channels, 785 * this causes a transmission to start. For receive channels, 786 * this queues a buffer for inbound packets. 787 * 788 * Input parameters: 789 * d - DMA channel descriptor 790 * ptr - pointer to buffer (must by physically contiguous) 791 * length - length of buffer 792 * ctx - arbitrary data to be passed back when descriptor completes 793 * (for example, mbuf pointers, etc.) 794 * 795 * Return value: 796 * 0 if buffer could not be added (ring is full) 797 * 1 if buffer added successfully 798 ********************************************************************* */ 799 800static int sbdma_addbuffer(sbethdma_t *d,uint8_t *ptr,int length,void *ctx) 801{ 802 sbdmadscr_t *dsc; 803 sbdmadscr_t *nextdsc; 804 805 sbeth_t *s = d->sbdma_eth; 806 807 /* get pointer to our current place in the ring */ 808 dsc = d->sbdma_addptr; 809 nextdsc = sbdma_nextbuf(d,sbdma_addptr); 810 811 /* 812 * figure out if the ring is full - if the next descriptor 813 * is the same as the one that we're going to remove from 814 * the ring, the ring is full 815 */ 816 817 if (nextdsc == d->sbdma_remptr) { 818 return 0; 819 } 820 821 /* 822 * fill in the descriptor 823 */ 824 825 if (d->sbdma_txdir) { 826 /* transmitting: set outbound options and length */ 827 dsc->dscr_a = SBETH_VTOP(ptr) | 828 V_DMA_DSCRA_A_SIZE(SBDMA_NUMCACHEBLKS(((uint64_t) length))) | 829 M_DMA_DSCRA_INTERRUPT | 830 M_DMA_ETHTX_SOP; 831 832 if (s->fifo_mode) { 833 dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_NOMODS) | 834 V_DMA_DSCRB_PKT_SIZE(length); 835 } 836 else { 837 dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) | 838 V_DMA_DSCRB_PKT_SIZE(length); 839 } 840 841 } 842 else { 843 /* receiving: no options */ 844 dsc->dscr_a = SBETH_VTOP(ptr) | 845 V_DMA_DSCRA_A_SIZE(SBDMA_NUMCACHEBLKS(((uint64_t) length))) | 846 M_DMA_DSCRA_INTERRUPT; 847 dsc->dscr_b = 0; 848 } 849 850 /* 851 * fill in the context 852 */ 853 854 d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = ctx; 855 856 /* 857 * point at next packet 858 */ 859 860 d->sbdma_addptr = nextdsc; 861 862 /* 863 * Give the packet to the hardware 864 */ 865 866 d->sbdma_onring++; 867 SBETH_WRITECSR(d->sbdma_dscrcnt,1); 868 869 return 1; /* we did it */ 870} 871 872 873/* ********************************************************************* 874 * SBETH_INITFREELIST(s) 875 * 876 * Initialize the buffer free list for this mac. The memory 877 * allocated to the free list is carved up and placed on a linked 878 * list of buffers for use by the mac. 879 * 880 * Input parameters: 881 * s - sbeth structure 882 * 883 * Return value: 884 * nothing 885 ********************************************************************* */ 886 887static void sbeth_initfreelist(sbeth_t *s) 888{ 889 int idx; 890 unsigned char *ptr; 891 sbeth_pkt_t *pkt; 892 893 s->sbe_freelist = NULL; 894 895 /* Must empty rxqueue, as we're about to free all the pkts on it */ 896 s->sbe_rxqueue = NULL; 897 898 ptr = s->sbe_pktpool; 899 900 for (idx = 0; idx < SBETH_PKTPOOL_SIZE; idx++) { 901 pkt = (sbeth_pkt_t *) ptr; 902 sbeth_free_pkt(s,pkt); 903 ptr += SBETH_PKTBUF_SIZE; 904 } 905} 906 907 908/* ********************************************************************* 909 * SBETH_ALLOC_PKT(s) 910 * 911 * Allocate a packet from the free list. 912 * 913 * Input parameters: 914 * s - sbeth structure 915 * 916 * Return value: 917 * pointer to packet structure, or NULL if none available 918 ********************************************************************* */ 919 920static sbeth_pkt_t *sbeth_alloc_pkt(sbeth_t *s) 921{ 922 uintptr_t addr; 923 sbeth_pkt_t *pkt = s->sbe_freelist; 924 925 if (!pkt) return NULL; 926 927 s->sbe_freelist = pkt->next; 928 pkt->next = NULL; 929 930 addr = (uintptr_t) (pkt+1); 931 if (addr & (SBDMA_CACHESIZE-1)) { 932 addr = (addr + SBDMA_CACHESIZE) & ~(SBDMA_CACHESIZE-1); 933 } 934 935 pkt->buffer = (unsigned char *) addr; 936 pkt->length = SBETH_PKT_SIZE; 937 938 return pkt; 939} 940 941/* ********************************************************************* 942 * SBETH_FREE_PKT(s,pkt) 943 * 944 * Return a packet to the free list 945 * 946 * Input parameters: 947 * s - sbmac structure 948 * pkt - packet to return 949 * 950 * Return value: 951 * nothing 952 ********************************************************************* */ 953static void sbeth_free_pkt(sbeth_t *s,sbeth_pkt_t *pkt) 954{ 955 pkt->next = s->sbe_freelist; 956 s->sbe_freelist = pkt; 957} 958 959/* ********************************************************************* 960 * SBETH_TX_CALLBACK(ifctx,chan,ctx,status,pktsize) 961 * 962 * Transmit callback routine. This routine is invoked when a 963 * queued transmit operation completes. In this simple driver, 964 * all we do is free the packet and try to re-fill the receive ring. 965 * 966 * Input parameters: 967 * ifctx - interface context (sbeth structure) 968 * chan - DMA Channel 969 * ctx - packet context (sbeth_pkt structure) 970 * status - Ethernet status from descriptor 971 * pktsize - length of packet (unused for transmits) 972 * 973 * Return value: 974 * nothing 975 ********************************************************************* */ 976 977static void sbeth_tx_callback(void *ifctx,int chan,void *ctx, 978 uint64_t status,unsigned int pktsize) 979{ 980 sbeth_t *s = ifctx; 981 sbeth_pkt_t *pkt = ctx; 982 983 sbeth_free_pkt(s,pkt); /* return packet to pool */ 984 985 sbeth_fillrxring(s,chan); /* re-fill the receive ring */ 986} 987 988/* ********************************************************************* 989 * SBETH_RX_CALLBACK(ifctx,chan,ctx,status,pktsize) 990 * 991 * Receive callback routine. This routine is invoked when a 992 * buffer queued for receives is filled. In this simple driver, 993 * all we do is add the packet to a per-MAC queue for later 994 * processing, and try to put a new packet in the place of the one 995 * that was removed from the queue. 996 * 997 * Input parameters: 998 * ifctx - interface context (sbeth structure) 999 * chan - DMA Channel 1000 * ctx - packet context (sbeth_pkt structure) 1001 * status - Ethernet status from descriptor 1002 * pktsize - length of packet (unused for transmits) 1003 * 1004 * Return value: 1005 * nothing 1006 ********************************************************************* */ 1007static void sbeth_rx_callback(void *ifctx,int chan,void *ctx, 1008 uint64_t status,unsigned int pktsize) 1009{ 1010 sbeth_t *s = ifctx; 1011 sbeth_pkt_t *pkt = ctx; 1012 sbeth_pkt_t *listptr; 1013 1014 if (!(status & M_DMA_ETHRX_BAD)) { 1015 pkt->next = NULL; 1016 pkt->length = pktsize; 1017 1018 if (s->sbe_rxqueue == NULL) { 1019 s->sbe_rxqueue = pkt; 1020 } 1021 else { 1022 listptr = s->sbe_rxqueue; 1023 while (listptr->next) listptr = listptr->next; 1024 listptr->next = pkt; 1025 } 1026 } 1027 else { 1028 sbeth_free_pkt(s,pkt); 1029 } 1030 1031 sbeth_fillrxring(s,chan); 1032} 1033 1034 1035/* ********************************************************************* 1036 * SBETH_INITCHAN(s) 1037 * 1038 * Initialize the Ethernet channel (program the CSRs to 1039 * get the channel set up) 1040 * 1041 * Input parameters: 1042 * s - sbeth structure 1043 * 1044 * Return value: 1045 * nothing 1046 ********************************************************************* */ 1047 1048static void sbeth_initchan(sbeth_t *s) 1049{ 1050 sbeth_port_t port; 1051 int idx; 1052 uint64_t cfg,fifo,framecfg; 1053 1054 /* 1055 * Bring the controller out of reset, and set the "must be one" 1056 * bits. 1057 */ 1058 1059 SBETH_WRITECSR(s->sbe_macenable,0); 1060 1061 /* 1062 * Set up some stuff in the control registers, but do not 1063 * enable the channel 1064 */ 1065 1066 cfg = M_MAC_RETRY_EN | 1067 M_MAC_TX_HOLD_SOP_EN | 1068 V_MAC_TX_PAUSE_CNT_16K | 1069 V_MAC_SPEED_SEL_100MBPS | 1070 M_MAC_AP_STAT_EN | 1071 M_MAC_FAST_SYNC | 1072 M_MAC_SS_EN | 1073 0; 1074 1075 fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */ 1076 V_MAC_TX_RD_THRSH(8) | 1077 V_MAC_TX_RL_THRSH(4) | 1078 V_MAC_RX_PL_THRSH(4) | 1079 V_MAC_RX_RD_THRSH(4) | /* Must be '4' */ 1080 V_MAC_RX_PL_THRSH(4) | 1081 V_MAC_RX_RL_THRSH(8) | 1082 0; 1083 1084 framecfg = V_MAC_MIN_FRAMESZ_DEFAULT | 1085 V_MAC_MAX_FRAMESZ_DEFAULT | 1086 V_MAC_BACKOFF_SEL(1); 1087 1088 /* 1089 * Clear out the hash address map 1090 */ 1091 1092 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_HASH_BASE); 1093 for (idx = 0; idx < MAC_HASH_COUNT; idx++) { 1094 SBETH_WRITECSR(port,0); 1095 port += sizeof(uint64_t); 1096 } 1097 1098 /* 1099 * Clear out the exact-match table 1100 */ 1101 1102 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ADDR_BASE); 1103 for (idx = 0; idx < MAC_ADDR_COUNT; idx++) { 1104 SBETH_WRITECSR(port,0); 1105 port += sizeof(uint64_t); 1106 } 1107 1108 /* 1109 * Clear out the DMA Channel mapping table registers 1110 */ 1111 1112 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_CHUP0_BASE); 1113 for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { 1114 SBETH_WRITECSR(port,0); 1115 port += sizeof(uint64_t); 1116 } 1117 1118 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_CHLO0_BASE); 1119 for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { 1120 SBETH_WRITECSR(port,0); 1121 port += sizeof(uint64_t); 1122 } 1123 1124 if (!s->sbe_zerormon) { 1125 s->sbe_zerormon =1; 1126 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_BYTES),0); 1127 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_COLLISIONS),0); 1128 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_LATE_COL),0); 1129 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_EX_COL),0); 1130 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_FCS_ERROR),0); 1131 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_ABORT),0); 1132 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_BAD),0); 1133 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_GOOD),0); 1134 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_RUNT),0); 1135 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_OVERSIZE),0); 1136 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_BYTES),0); 1137 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_MCAST),0); 1138 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_BCAST),0); 1139 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_BAD),0); 1140 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_GOOD),0); 1141 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_RUNT),0); 1142 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_OVERSIZE),0); 1143 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_FCS_ERROR),0); 1144 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_LENGTH_ERROR),0); 1145 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_CODE_ERROR),0); 1146 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_ALIGN_ERROR),0); 1147 } 1148 1149 /* 1150 * Configure the receive filter for no packets 1151 */ 1152 1153 SBETH_WRITECSR(s->sbe_rxfilter,0); 1154 SBETH_WRITECSR(s->sbe_imr,0); 1155 SBETH_WRITECSR(s->sbe_framecfg,framecfg); 1156 SBETH_WRITECSR(s->sbe_fifocfg,fifo); 1157 SBETH_WRITECSR(s->sbe_maccfg,cfg); 1158 1159} 1160 1161/* ********************************************************************* 1162 * SBETH_INITCTX(s,mac) 1163 * 1164 * Initialize an Ethernet context structure - this is called 1165 * once per MAC on the 1250. 1166 * 1167 * Input parameters: 1168 * s - sbeth context structure 1169 * mac - number of this MAC (0,1,2) 1170 * ifctx - interface context (reference saved by driver) 1171 * 1172 * Return value: 1173 * 0 1174 ********************************************************************* */ 1175static int sbeth_initctx(sbeth_t *s,unsigned long baseaddr,void *ifctx) 1176{ 1177 1178 /* 1179 * Start with all zeroes 1180 */ 1181 memset(s,0,sizeof(sbeth_t)); 1182 1183 /* 1184 * Identify ourselves 1185 */ 1186 1187 s->sbe_baseaddr = baseaddr; 1188 s->sbe_ifctx = ifctx; 1189 1190 s->sbe_minrxring = 8; 1191 1192 /* 1193 * Set default hardware address. This is in case there is *no* environment. 1194 */ 1195 1196 s->sbe_hwaddr[0] = 0x02; 1197 s->sbe_hwaddr[1] = 0x10; 1198 s->sbe_hwaddr[2] = 0x18; 1199 s->sbe_hwaddr[3] = (s->sbe_baseaddr >> 24) & 0xFF; 1200 s->sbe_hwaddr[4] = (s->sbe_baseaddr >> 16) & 0xFF; 1201 s->sbe_hwaddr[5] = (s->sbe_baseaddr >> 8) & 0xFF; 1202 1203 /* 1204 * figure out the addresses of some ports 1205 */ 1206 s->sbe_macenable = SBETH_PORT(s->sbe_baseaddr + R_MAC_ENABLE); 1207 s->sbe_maccfg = SBETH_PORT(s->sbe_baseaddr + R_MAC_CFG); 1208 s->sbe_fifocfg = SBETH_PORT(s->sbe_baseaddr + R_MAC_THRSH_CFG); 1209 s->sbe_framecfg = SBETH_PORT(s->sbe_baseaddr + R_MAC_FRAMECFG); 1210 s->sbe_rxfilter = SBETH_PORT(s->sbe_baseaddr + R_MAC_ADFILTER_CFG); 1211 1212 s->sbe_isr = SBETH_PORT(s->sbe_baseaddr + R_MAC_STATUS); 1213 s->sbe_imr = SBETH_PORT(s->sbe_baseaddr + R_MAC_INT_MASK); 1214 1215 s->sbe_mdio = SBETH_PORT(s->sbe_baseaddr + R_MAC_MDIO); 1216 1217 /* 1218 * Initialize the DMA channels. 1219 */ 1220 1221 sbdma_initctx(s,&(s->sbe_txdma[0]),0,DMA_TX,SBETH_MAX_TXDESCR,sbeth_tx_callback); 1222 sbdma_initctx(s,&(s->sbe_rxdma[0]),0,DMA_RX,SBETH_MAX_RXDESCR,sbeth_rx_callback); 1223#if (SBETH_DMA_CHANNELS == 2) 1224 sbdma_initctx(s,&(s->sbe_txdma[1]),1,DMA_TX,SBETH_MAX_TXDESCR,sbeth_tx_callback); 1225 sbdma_initctx(s,&(s->sbe_rxdma[1]),1,DMA_RX,SBETH_MAX_RXDESCR,sbeth_rx_callback); 1226#endif 1227 1228 /* 1229 * initialize free list 1230 */ 1231 1232 s->sbe_freelist = NULL; 1233 s->sbe_rxqueue = NULL; 1234 1235 s->sbe_pktpool = KMALLOC(SBETH_PKTBUF_SIZE*SBETH_PKTPOOL_SIZE, 1236 SBDMA_CACHESIZE); 1237 1238 /* 1239 * Set values for the PHY so that when we poll the phy status 1240 * we'll notice that it has changed. 1241 */ 1242 1243 s->sbe_phy_oldbmsr = 0xFFFFFFFF; 1244 s->sbe_phy_oldbmcr = 0xFFFFFFFF; 1245 s->sbe_phy_oldanlpar = 0xFFFFFFFF; 1246 s->sbe_phy_oldk1stsr = 0xFFFFFFFF; 1247 1248 /* 1249 * initial state is OFF 1250 */ 1251 1252 s->sbe_state = sbeth_state_off; 1253 1254 return 0; 1255} 1256 1257 1258/* ********************************************************************* 1259 * SBETH_START(s) 1260 * 1261 * Start packet processing on this MAC. 1262 * 1263 * Input parameters: 1264 * s - sbeth structure 1265 * 1266 * Return value: 1267 * nothing 1268 ********************************************************************* */ 1269 1270static void sbeth_start(sbeth_t *s) 1271{ 1272 uint64_t ctl; 1273 1274 sbdma_initchan(s,&(s->sbe_txdma[0])); 1275 sbdma_initchan(s,&(s->sbe_rxdma[0])); 1276#if (SBETH_DMA_CHANNELS == 2) 1277 sbdma_initchan(s,&(s->sbe_txdma[1])); 1278 sbdma_initchan(s,&(s->sbe_rxdma[1])); 1279#endif 1280 sbeth_initchan(s); 1281 1282 sbeth_setspeed(s,s->sbe_speed); 1283 sbeth_set_duplex(s,s->sbe_duplex,s->sbe_fc); 1284 1285 SBETH_WRITECSR(s->sbe_rxfilter,0); 1286 1287 ctl = SBETH_READCSR(s->sbe_macenable); 1288 1289 ctl |= M_MAC_RXDMA_EN0 | 1290 M_MAC_TXDMA_EN0 | 1291#if (SBETH_DMA_CHANNELS == 2) 1292 M_MAC_TXDMA_EN1 | 1293 M_MAC_RXDMA_EN1 | 1294#endif 1295 M_MAC_RX_ENABLE | 1296 M_MAC_TX_ENABLE | 1297 0; 1298 1299 sbeth_initfreelist(s); 1300 1301 SBETH_WRITECSR(s->sbe_macenable,ctl); 1302 1303 sbeth_setaddr(s,s->sbe_hwaddr); 1304 1305#ifdef _SB1250_PASS1_WORKAROUNDS_ 1306 /* Must set the Ethernet address to zero in pass1 */ 1307 do { 1308 sbeth_port_t port; 1309 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ETHERNET_ADDR); 1310 SBETH_WRITECSR(port,0); 1311 } while (0); 1312#endif 1313 1314 sbeth_fillrxring(s,0); 1315 1316 SBETH_WRITECSR(s->sbe_rxfilter,M_MAC_UCAST_EN | M_MAC_BCAST_EN | 1317 V_MAC_IPHDR_OFFSET(15) | 1318 /* M_MAC_ALLPKT_EN |*/ /* uncomment for promisc mode */ 1319 0 1320 ); 1321 1322 s->sbe_state = sbeth_state_on; 1323 1324} 1325 1326/* ********************************************************************* 1327 * SBETH_STOP(s) 1328 * 1329 * Stop packet processing on this MAC. 1330 * 1331 * Input parameters: 1332 * s - sbeth structure 1333 * 1334 * Return value: 1335 * nothing 1336 ********************************************************************* */ 1337 1338static void sbeth_stop(sbeth_t *s) 1339{ 1340 uint64_t ctl; 1341 int mac_mdio_genc; 1342 1343 SBETH_WRITECSR(s->sbe_rxfilter,0); 1344 1345 ctl = SBETH_READCSR(s->sbe_macenable); 1346 1347 ctl &= ~(M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0 | M_MAC_RXDMA_EN1 | M_MAC_TXDMA_EN1 | 1348 M_MAC_RX_ENABLE | M_MAC_TX_ENABLE); 1349 1350 SBETH_WRITECSR(s->sbe_macenable,ctl); 1351 1352 /* 1353 * The genc bit on the MAC MDIO register needs to be preserved through reset. 1354 * Read the MAC MDIO register and mask out genc bit. 1355 */ 1356 mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC; 1357 1358 ctl |= M_MAC_PORT_RESET; 1359 1360 SBETH_WRITECSR(s->sbe_macenable,ctl); 1361 1362 /* Write back value of genc bit */ 1363 SBETH_WRITECSR(s->sbe_mdio,mac_mdio_genc); 1364 1365 s->sbe_state = sbeth_state_off; 1366 1367 sbdma_reset(&(s->sbe_txdma[0])); 1368 sbdma_reset(&(s->sbe_rxdma[0])); 1369 1370 1371} 1372 1373 1374/* ********************************************************************* 1375 * SBETH_SETADDR(s,addr) 1376 * 1377 * Set the ethernet address for the specified MAC 1378 * 1379 * Input parameters: 1380 * s - sbeth structure 1381 * addr - Ethernet address 1382 * 1383 * Return value: 1384 * nothing 1385 ********************************************************************* */ 1386 1387static void sbeth_setaddr(sbeth_t *s,uint8_t *addr) 1388{ 1389 sbeth_port_t port; 1390 uint64_t regval = 0; 1391 int idx; 1392 1393 /* 1394 * Pack the bytes into the register, with the first byte transmitted 1395 * in the lowest-order 8 bits of the register. 1396 */ 1397 1398 for (idx = 0; idx < 6; idx++) { 1399 regval |= (((uint64_t) (*addr)) << (idx*8)); 1400 addr++; 1401 } 1402 1403 /* 1404 * Write to the port. 1405 */ 1406 1407 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ETHERNET_ADDR); 1408 SBETH_WRITECSR(port,regval); 1409 1410 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ADDR_BASE); 1411 SBETH_WRITECSR(port,regval); 1412 1413} 1414 1415/* ********************************************************************* 1416 * SBETH_SETSPEED(s,speed) 1417 * 1418 * Configure LAN speed for the specified MAC 1419 * 1420 * Input parameters: 1421 * s - sbeth structure 1422 * speed - speed to set MAC to (see sbeth_speed_t enum) 1423 * 1424 * Return value: 1425 * 1 if successful 1426 * 0 indicates invalid parameters 1427 ********************************************************************* */ 1428 1429static int sbeth_setspeed(sbeth_t *s,sbeth_speed_t speed) 1430{ 1431 uint64_t cfg; 1432 uint64_t framecfg; 1433 1434 /* 1435 * Read current register values 1436 */ 1437 1438 cfg = SBETH_READCSR(s->sbe_maccfg); 1439 framecfg = SBETH_READCSR(s->sbe_framecfg); 1440 1441 /* 1442 * Mask out the stuff we want to change 1443 */ 1444 1445 cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL); 1446 framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH | 1447 M_MAC_SLOT_SIZE); 1448 1449 /* 1450 * Now add in the new bits 1451 */ 1452 1453 switch (speed) { 1454 case sbeth_speed_10: 1455 framecfg |= V_MAC_IFG_RX_10 | 1456 V_MAC_IFG_TX_10 | 1457 K_MAC_IFG_THRSH_10 | 1458 V_MAC_SLOT_SIZE_10; 1459 cfg |= V_MAC_SPEED_SEL_10MBPS; 1460 break; 1461 1462 case sbeth_speed_100: 1463 framecfg |= V_MAC_IFG_RX_100 | 1464 V_MAC_IFG_TX_100 | 1465 V_MAC_IFG_THRSH_100 | 1466 V_MAC_SLOT_SIZE_100; 1467 cfg |= V_MAC_SPEED_SEL_100MBPS ; 1468 break; 1469 1470 case sbeth_speed_1000: 1471 framecfg |= V_MAC_IFG_RX_1000 | 1472 V_MAC_IFG_TX_1000 | 1473 V_MAC_IFG_THRSH_1000 | 1474 V_MAC_SLOT_SIZE_1000; 1475 cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN; 1476 break; 1477 1478 default: 1479 return 0; 1480 } 1481 1482 /* 1483 * Send the bits back to the hardware 1484 */ 1485 1486 SBETH_WRITECSR(s->sbe_framecfg,framecfg); 1487 SBETH_WRITECSR(s->sbe_maccfg,cfg); 1488 1489 return 1; 1490 1491} 1492 1493/* ********************************************************************* 1494 * SBETH_SET_DUPLEX(s,duplex,fc) 1495 * 1496 * Set Ethernet duplex and flow control options for this MAC 1497 * 1498 * Input parameters: 1499 * s - sbeth structure 1500 * duplex - duplex setting (see sbeth_duplex_t) 1501 * fc - flow control setting (see sbeth_fc_t) 1502 * 1503 * Return value: 1504 * 1 if ok 1505 * 0 if an invalid parameter combination was specified 1506 ********************************************************************* */ 1507 1508static int sbeth_set_duplex(sbeth_t *s,sbeth_duplex_t duplex,sbeth_fc_t fc) 1509{ 1510 uint64_t cfg; 1511 1512 /* 1513 * Read current register values 1514 */ 1515 1516 cfg = SBETH_READCSR(s->sbe_maccfg); 1517 1518 /* 1519 * Mask off the stuff we're about to change 1520 */ 1521 1522 cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN); 1523 1524 switch (duplex) { 1525 case sbeth_duplex_half: 1526 switch (fc) { 1527 case sbeth_fc_disabled: 1528 cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED; 1529 break; 1530 1531 case sbeth_fc_collision: 1532 cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED; 1533 break; 1534 1535 case sbeth_fc_carrier: 1536 cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR; 1537 break; 1538 1539 case sbeth_fc_frame: /* not valid in half duplex */ 1540 default: /* invalid selection */ 1541 return 0; 1542 } 1543 break; 1544 1545 case sbeth_duplex_full: 1546 switch (fc) { 1547 case sbeth_fc_disabled: 1548 cfg |= V_MAC_FC_CMD_DISABLED; 1549 break; 1550 1551 case sbeth_fc_frame: 1552 cfg |= V_MAC_FC_CMD_ENABLED; 1553 break; 1554 1555 case sbeth_fc_collision: /* not valid in full duplex */ 1556 case sbeth_fc_carrier: /* not valid in full duplex */ 1557 /* fall through */ 1558 default: 1559 return 0; 1560 } 1561 break; 1562 } 1563 1564 /* 1565 * Send the bits back to the hardware 1566 */ 1567 1568 SBETH_WRITECSR(s->sbe_maccfg,cfg); 1569 1570 return 1; 1571} 1572 1573 1574/* ********************************************************************* 1575 * SBETH_TRANSMIT(s,pkt,len,arg) 1576 * 1577 * Transmits a packet. 1578 * 1579 * Input parameters: 1580 * s - mac to tramsmit on 1581 * chan - DMA Channel number (0 or 1) 1582 * pkt,len - buffer and length 1583 * arg - arg for callback 1584 * 1585 * Return value: 1586 * 1 if packet was queued 1587 * 0 if packet was not queued 1588 ********************************************************************* */ 1589static int sbeth_transmit(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg) 1590{ 1591 return sbdma_addbuffer(&(s->sbe_txdma[chan]),pkt,length,arg); 1592} 1593 1594/* ********************************************************************* 1595 * SBETH_ADDRCVBUF(s,pkt,len,arg) 1596 * 1597 * Add a receive buffer to the ring 1598 * 1599 * Input parameters: 1600 * s - mac to add rx buffer to 1601 * chan - DMA Channel number (0 or 1) 1602 * pkt,len - buffer and length 1603 * arg - arg for callback 1604 * 1605 * Return value: 1606 * 1 if packet was queued 1607 * 0 if packet was not queued 1608 ********************************************************************* */ 1609static int sbeth_addrcvbuf(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg) 1610{ 1611 return sbdma_addbuffer(&(s->sbe_rxdma[chan]),pkt,length,arg); 1612} 1613 1614 1615/* ********************************************************************* 1616 * SBETH_FILLRXRING(s,chan) 1617 * 1618 * Make sure there are at least "sbe_minrxring" packets on the 1619 * receive ring for this device. 1620 * 1621 * Input parameters: 1622 * s - mac structure 1623 * 1624 * Return value: 1625 * nothing 1626 ********************************************************************* */ 1627 1628static void sbeth_fillrxring(sbeth_t *s,int chan) 1629{ 1630 sbeth_pkt_t *pkt; 1631 1632 while (s->sbe_rxdma[chan].sbdma_onring < s->sbe_minrxring) { 1633 pkt = sbeth_alloc_pkt(s); 1634 if (!pkt) break; 1635 if (!sbeth_addrcvbuf(s,chan,pkt->buffer,pkt->length,pkt)) { 1636 sbeth_free_pkt(s,pkt); 1637 break; 1638 } 1639 } 1640} 1641 1642 1643 1644/* ********************************************************************* 1645 * SBETH_ISR() 1646 * 1647 * Interrupt handler for MAC interrupts 1648 * 1649 * Input parameters: 1650 * MAC structure 1651 * 1652 * Return value: 1653 * nothing 1654 ********************************************************************* */ 1655static void sbeth_isr(sbeth_t *s) 1656{ 1657 uint64_t isr; 1658 for (;;) { 1659 1660 /* 1661 * Read the ISR (this clears the bits in the real register) 1662 */ 1663 1664 isr = SBETH_READCSR(s->sbe_isr); 1665 1666 if (isr == 0) { 1667 break; 1668 } 1669 1670 /* 1671 * for now, don't bother asking why we were interrupted, 1672 * just process the descriptors in any event. 1673 */ 1674 1675 /* 1676 * Transmits on channel 0 1677 */ 1678 1679 if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) { 1680 sbdma_procbuffers(&(s->sbe_txdma[0]),s->sbe_txdma[0].sbdma_upcall); 1681 } 1682 1683#if (SBETH_DMA_CHANNELS == 2) 1684 /* 1685 * Transmits on channel 1 1686 */ 1687 1688 if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH1)) { 1689 sbdma_procbuffers(&(s->sbe_txdma[1]),s->sbe_txdma[1].sbdma_upcall); 1690 } 1691#endif 1692 1693 /* 1694 * Receives on channel 0 1695 */ 1696 1697 if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) { 1698 sbdma_procbuffers(&(s->sbe_rxdma[0]),s->sbe_rxdma[0].sbdma_upcall); 1699 } 1700 1701#if (SBETH_DMA_CHANNELS == 2) 1702 /* 1703 * Receives on channel 1 1704 */ 1705 1706 if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH1)) { 1707 sbdma_procbuffers(&(s->sbe_rxdma[1]),s->sbe_rxdma[1].sbdma_upcall); 1708 } 1709#endif 1710 } 1711 1712} 1713 1714 1715/* ********************************************************************* 1716 * SBETH_MII_FINDROBO(s) 1717 * 1718 * Check if MII is hooked up to a RoboSwitch. 1719 * 1720 * Input parameters: 1721 * s - sbeth structure 1722 * 1723 * Return value: 1724 * true if RoboSwitch found 1725 ********************************************************************* */ 1726static int sbeth_mii_findrobo(sbeth_t *s) 1727{ 1728 int phy; 1729 int cnt; 1730 uint16_t bmsr; 1731 1732 for (phy = 0, cnt = 0; phy < 31; phy++) { 1733 bmsr = sbeth_mii_read(s,phy,MII_BMSR); 1734 if (bmsr != 0) { 1735 cnt++; 1736 } 1737 } 1738 1739 return (cnt >= 5); 1740} 1741 1742/* ********************************************************************* 1743 * SBETH_MII_FINDPHY(s) 1744 * 1745 * Find the first available PHY. 1746 * 1747 * Input parameters: 1748 * s - sbeth structure 1749 * 1750 * Return value: 1751 * nothing 1752 ********************************************************************* */ 1753static void sbeth_mii_findphy(sbeth_t *s) 1754{ 1755 int phy; 1756 uint16_t bmsr; 1757 uint16_t id1, id2; 1758 1759 for (phy = 0; phy < 31; phy++) { 1760 bmsr = sbeth_mii_read(s,phy,MII_BMSR); 1761 if (bmsr != 0) { 1762 s->sbe_phyaddr = phy; 1763 id1 = sbeth_mii_read(s,phy,MII_PHYIDR1); 1764 id2 = sbeth_mii_read(s,phy,MII_PHYIDR2); 1765 s->sbe_phyvendor = ((uint32_t)id1 << 6) | ((id2 >> 10) & 0x3F); 1766 s->sbe_phydevice = (id2 >> 4) & 0x3F; 1767 xprintf("sbeth: found phy %d, vendor %06X part %02X\n", 1768 phy, s->sbe_phyvendor, s->sbe_phydevice); 1769 return; 1770 } 1771 } 1772 1773 s->sbe_phyaddr = 0; 1774} 1775 1776/* ********************************************************************* 1777 * SBETH_MII_POLL(s) 1778 * 1779 * Ask the PHY what is going on, and configure speed appropriately. 1780 * For the moment, we only support automatic configuration. 1781 * 1782 * Input parameters: 1783 * s - sbeth structure 1784 * noisy - display console messages 1785 * 1786 * Return value: 1787 * 1 if something has changed and we should restart the channel 1788 * 0 if nothing has changed. 1789 ********************************************************************* */ 1790static int sbeth_mii_poll(sbeth_t *s,int noisy) 1791{ 1792 uint16_t bmsr,bmcr,k1stsr,anlpar; 1793 int chg; 1794 char buffer[100]; 1795 char *p = buffer; 1796 char *devname; 1797 1798 /* Read the mode status and mode control registers. */ 1799 bmsr = sbeth_mii_read(s,s->sbe_phyaddr,MII_BMSR); 1800 bmcr = sbeth_mii_read(s,s->sbe_phyaddr,MII_BMCR); 1801 1802 /* get the link partner status */ 1803 anlpar = sbeth_mii_read(s,s->sbe_phyaddr,MII_ANLPAR); 1804 1805 /* if supported, read the 1000baseT register */ 1806 if (bmsr & BMSR_1000BT_XSR) { 1807 k1stsr = sbeth_mii_read(s,s->sbe_phyaddr,MII_K1STSR); 1808 } 1809 else { 1810 k1stsr = 0; 1811 } 1812 1813 chg = 0; 1814 1815 if ((s->sbe_phy_oldbmsr != bmsr) || 1816 (s->sbe_phy_oldbmcr != bmcr) || 1817 (s->sbe_phy_oldanlpar != anlpar) || 1818 (s->sbe_phy_oldk1stsr != k1stsr)) { 1819 s->sbe_phy_oldbmsr = bmsr; 1820 s->sbe_phy_oldbmcr = bmcr; 1821 s->sbe_phy_oldanlpar = anlpar; 1822 s->sbe_phy_oldk1stsr = k1stsr; 1823 chg = 1; 1824 } 1825 1826 if (chg == 0) return 0; 1827 1828 if (!s->sbe_autospeed) return 0; 1829 1830 p += xsprintf(p,"Link speed: "); 1831 1832 if (k1stsr & K1STSR_LP1KFD) { 1833 s->sbe_speed = sbeth_speed_1000; 1834 s->sbe_duplex = sbeth_duplex_full; 1835 s->sbe_fc = sbeth_fc_frame; 1836 s->sbe_linkstat = ETHER_SPEED_1000FDX; 1837 p += xsprintf(p,"1000BaseT FDX"); 1838 } 1839 else if (k1stsr & K1STSR_LP1KHD) { 1840 s->sbe_speed = sbeth_speed_1000; 1841 s->sbe_duplex = sbeth_duplex_half; 1842 s->sbe_fc = sbeth_fc_disabled; 1843 s->sbe_linkstat = ETHER_SPEED_1000HDX; 1844 p += xsprintf(p,"1000BaseT HDX"); 1845 } 1846 else if (anlpar & ANLPAR_TXFD) { 1847 s->sbe_speed = sbeth_speed_100; 1848 s->sbe_duplex = sbeth_duplex_full; 1849 s->sbe_fc = (anlpar & ANLPAR_PAUSE) ? sbeth_fc_frame : sbeth_fc_disabled; 1850 s->sbe_linkstat = ETHER_SPEED_100FDX; 1851 p += xsprintf(p,"100BaseT FDX"); 1852 } 1853 else if (anlpar & ANLPAR_TXHD) { 1854 s->sbe_speed = sbeth_speed_100; 1855 s->sbe_duplex = sbeth_duplex_half; 1856 s->sbe_fc = sbeth_fc_disabled; 1857 s->sbe_linkstat = ETHER_SPEED_100HDX; 1858 p += xsprintf(p,"100BaseT HDX"); 1859 } 1860 else if (anlpar & ANLPAR_10FD) { 1861 s->sbe_speed = sbeth_speed_10; 1862 s->sbe_duplex = sbeth_duplex_full; 1863 s->sbe_fc = sbeth_fc_frame; 1864 s->sbe_linkstat = ETHER_SPEED_10FDX; 1865 p += xsprintf(p,"10BaseT FDX"); 1866 } 1867 else if (anlpar & ANLPAR_10HD) { 1868 s->sbe_speed = sbeth_speed_10; 1869 s->sbe_duplex = sbeth_duplex_half; 1870 s->sbe_fc = sbeth_fc_collision; 1871 s->sbe_linkstat = ETHER_SPEED_10HDX; 1872 p += xsprintf(p,"10BaseT HDX"); 1873 } 1874 else { 1875 s->sbe_linkstat = ETHER_SPEED_UNKNOWN; 1876 p += xsprintf(p,"Unknown"); 1877 } 1878 1879#if defined(_BCM91120C_DIAG_CFG_) || defined(_BCM91125C_DIAG_CFG_) || \ 1880 defined(_CSWARM_DIAG_CFG_) || defined(_CSWARM_DIAG3E_CFG_) || \ 1881 defined(_PTSWARM_DIAG_CFG_) || defined(_PTSWARM_CFG_) 1882 noisy = 0; 1883#endif 1884 1885 if (noisy) { 1886 devname = s->sbe_devctx ? cfe_device_name(s->sbe_devctx) : "eth?"; 1887 console_log("%s: %s",devname,buffer); 1888 } 1889 1890 return 1; 1891} 1892 1893 1894/* ********************************************************************* 1895 * SBETH_MII_SETUP(s) 1896 * 1897 * 1898 * Input parameters: 1899 * s - sbeth 1900 * 1901 * Various boards have PHYs that are incorrectly strapped or 1902 * need other preconfiguration to enable autonegotiation and 1903 * establish a valid link. 1904 * 1905 * Return value: 1906 * TRUE if we were on a 5411 1907 ********************************************************************* */ 1908 1909/* Helper routine for bcm546x extended register (0x1C shadow) access. */ 1910static void bcm546x_update(sbeth_t *s, unsigned int ext, 1911 uint16_t clear_bits, uint16_t set_bits) 1912{ 1913 uint16_t ext_val; 1914 int phy_addr = s->sbe_phyaddr; 1915 1916 ext_val = (ext << 10); 1917 sbeth_mii_write(s, phy_addr, 0x1C, ext_val); 1918 ext_val = sbeth_mii_read(s, phy_addr, 0x1C); 1919 ext_val |= (0x1 << 15); 1920 sbeth_mii_write(s, phy_addr, 0x1C, ext_val); /* needed? */ 1921 cfe_usleep(100); /* ditto */ 1922 ext_val &= ~clear_bits; 1923 ext_val |= set_bits; 1924 sbeth_mii_write(s, phy_addr, 0x1C, ext_val); 1925 cfe_usleep(100); 1926 ext_val &= ~(0x1 << 15); /* ditto */ 1927 sbeth_mii_write(s, phy_addr, 0x1C, ext_val); /* ditto */ 1928} 1929 1930/* Helper routines to restart autonegotiation. */ 1931static void sbeth_mii_restart_an(sbeth_t *s) 1932{ 1933 uint16_t anar, k1ctl, bmcr; 1934 int phy_addr = s->sbe_phyaddr; 1935 1936 /* Standard (copper mode) autonegotiation. */ 1937 anar = sbeth_mii_read(s, phy_addr, MII_ANAR); 1938 anar |= (ANAR_TXFD | ANAR_TXHD | ANAR_10FD | ANAR_10HD); 1939 sbeth_mii_write(s, phy_addr, MII_ANAR, anar); 1940 k1ctl = sbeth_mii_read(s, phy_addr, MII_K1CTL); 1941 k1ctl |= (K1TCR_1000BT_FDX | K1TCR_1000BT_HDX); 1942 sbeth_mii_write(s, phy_addr, MII_K1CTL, k1ctl); 1943 bmcr = sbeth_mii_read(s, phy_addr, MII_BMCR); 1944 bmcr |= (BMCR_ANENABLE | BMCR_RESTARTAN); 1945 sbeth_mii_write(s, phy_addr, MII_BMCR, bmcr); 1946} 1947 1948static int sbeth_mii_setup(sbeth_t *s) 1949{ 1950 if (s->sbe_phyvendor == OUI_BCM) { 1951 int phy_addr = s->sbe_phyaddr; 1952 1953 switch (s->sbe_phydevice) { 1954 case DEV_BCM5411: 1955 /* The CSWARM boards leave the PHYs in JTAG mode. The 1956 * sequence * below turns off JTAG mode and puts the 1957 * PHYs back * into their regular reset state. This 1958 * is only used with the BCM5411 1959 */ 1960 1961 /* clear ext loopback */ 1962 sbeth_mii_write(s,phy_addr,MII_AUXCTL,0x0420); 1963 1964 /* clear swap rx MDIX/TXHalfOut bits */ 1965 sbeth_mii_write(s,phy_addr,MII_AUXCTL,0x0004); 1966 1967 sbeth_mii_restart_an(s); 1968 break; 1969 1970 case DEV_BCM5421: 1971 /* 1972 * Make sure that the part is in GMII, not SGMII. 1973 * This was a problem with 5421 A0 silicon 1974 * the FDX pin 1975 */ 1976 sbeth_mii_write(s,phy_addr,0x18,0x0392); 1977 break; 1978 1979 case DEV_BCM5461: 1980 /* Note: The bcm5461 and bcm5461S have the same device 1981 code. The following is for a 5461S. */ 1982#if defined(_BCM91125CPCI_) 1983 /* The 5461S attached to the 1125 MAC is for GMII to 1984 copper but is strapped for GMII to SerDes with 1985 autodetect enabled. That leaves the wrong set of 1986 PHY registers visible. */ 1987 1988 /* Undo autodetect. */ 1989 bcm546x_update(s, 0x1E, (0x1 << 0), 0); 1990 /* Force copper. */ 1991 bcm546x_update(s, 0x1F, ((0x3 << 1)|(0x1 << 0)), 0); 1992 1993 /* Redo the autonegotiation. */ 1994 sbeth_mii_restart_an(s); 1995 1996 /* Remap LINKSPD[1] selector to Link Quality. */ 1997 bcm546x_update(s, 0x0D, (0xF << 0), 0x7); 1998#else 1999 (void)bcm546x_update; /* keep compiler happy */ 2000#endif 2001 break; 2002 2003 case DEV_BCM5464: 2004 /* Defaults are ok in current applications. */ 2005 break; 2006 } 2007 } 2008 2009 return 0; 2010} 2011 2012 2013/* ********************************************************************* 2014 * Declarations for CFE Device Driver Interface routines 2015 ********************************************************************* */ 2016 2017static int sb1250_ether_open(cfe_devctx_t *ctx); 2018static int sb1250_ether_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 2019static int sb1250_ether_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat); 2020static int sb1250_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 2021static int sb1250_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 2022static int sb1250_ether_close(cfe_devctx_t *ctx); 2023static void sb1250_ether_poll(cfe_devctx_t *ctx,int64_t ticks); 2024static void sb1250_ether_reset(void *softc); 2025 2026/* ********************************************************************* 2027 * CFE Device Driver dispatch structure 2028 ********************************************************************* */ 2029 2030const static cfe_devdisp_t sb1250_ether_dispatch = { 2031 sb1250_ether_open, 2032 sb1250_ether_read, 2033 sb1250_ether_inpstat, 2034 sb1250_ether_write, 2035 sb1250_ether_ioctl, 2036 sb1250_ether_close, 2037 sb1250_ether_poll, 2038 sb1250_ether_reset 2039}; 2040 2041/* ********************************************************************* 2042 * CFE Device Driver descriptor 2043 ********************************************************************* */ 2044 2045const cfe_driver_t sb1250_ether = { 2046 "SiByte Ethernet", 2047 "eth", 2048 CFE_DEV_NETWORK, 2049 &sb1250_ether_dispatch, 2050 sb1250_ether_probe 2051}; 2052 2053 2054/* ********************************************************************* 2055 * SB1250_ETHER_PROBE(drv,probe_a,probe_b,probe_ptr) 2056 * 2057 * Probe and install an Ethernet device driver. This routine 2058 * creates a context structure and attaches to the specified 2059 * MAC device. 2060 * 2061 * Input parameters: 2062 * drv - driver descriptor 2063 * probe_a - base address of MAC to probe 2064 * probe_b - not used 2065 * probe_ptr - string pointer to hardware address for this 2066 * MAC, in the form xx:xx:xx:xx:xx:xx 2067 * 2068 * Return value: 2069 * nothing 2070 ********************************************************************* */ 2071 2072static void sb1250_ether_probe(cfe_driver_t *drv, 2073 unsigned long probe_a, unsigned long probe_b, 2074 void *probe_ptr) 2075{ 2076 sbeth_t *softc; 2077 char descr[100]; 2078 2079 softc = (sbeth_t *) KMALLOC(sizeof(sbeth_t),0); 2080 2081 if (softc) { 2082 sbeth_initctx(softc,probe_a,softc); 2083 if (probe_ptr) { 2084 enet_parse_hwaddr((char *) probe_ptr,softc->sbe_hwaddr); 2085 } 2086 xsprintf(descr,"%s at 0x%X (%a)",drv->drv_description,probe_a, 2087 softc->sbe_hwaddr); 2088 2089 sbeth_mii_findphy(softc); 2090 sbeth_mii_setup(softc); 2091 cfe_attach(drv,softc,NULL,descr); 2092 sbeth_setaddr(softc,softc->sbe_hwaddr); 2093 } 2094} 2095 2096 2097/* ********************************************************************* 2098 * SB1250_ETHER_READENV(ctx) 2099 * 2100 * Read the environment variable that corresponds to this 2101 * interface to pick up the hardware address. Note that the way 2102 * we do this is somewhat slimey. 2103 * 2104 * Input parameters: 2105 * ctx - device context 2106 * 2107 * Return value: 2108 * nothing 2109 ********************************************************************* */ 2110 2111static void sb1250_ether_readenv(cfe_devctx_t *ctx) 2112{ 2113 sbeth_t *softc = ctx->dev_softc; 2114 char envbuf[100]; 2115 char *hwaddr; 2116 2117 /* 2118 * Gross - we should *not* be reaching into these data 2119 * structures like this! 2120 */ 2121 2122 xsprintf(envbuf,"%s_HWADDR",cfe_device_name(ctx)); 2123 strupr(envbuf); 2124 2125 hwaddr = env_getenv(envbuf); 2126 2127 if (hwaddr) { 2128 enet_parse_hwaddr(hwaddr,softc->sbe_hwaddr); 2129 } 2130 2131} 2132 2133/* ********************************************************************* 2134 * SB1250_ETHER_OPEN(ctx) 2135 * 2136 * Open the Ethernet device. The MAC is reset, initialized, and 2137 * prepared to receive and send packets. 2138 * 2139 * Input parameters: 2140 * ctx - device context (includes ptr to our softc) 2141 * 2142 * Return value: 2143 * status, 0 = ok 2144 ********************************************************************* */ 2145 2146static int sb1250_ether_open(cfe_devctx_t *ctx) 2147{ 2148 sbeth_t *softc = ctx->dev_softc; 2149 2150 softc->sbe_devctx = ctx; 2151 2152 sbeth_stop(softc); 2153 2154 /* 2155 * Look for RoboSwitch on MII interface and set fixed speed 2156 * if found, otherwise go ahead and look for a normal PHY. 2157 */ 2158 2159 if (sbeth_mii_findrobo(softc)) { 2160 sb1250_ether_ioctl_speed(softc,ETHER_SPEED_100FDX); 2161 } 2162 else { 2163 sbeth_mii_findphy(softc); 2164 softc->sbe_autospeed = TRUE; 2165 } 2166 2167 /* 2168 * Note: The Phy can take several seconds to become ready! 2169 * This gross code pounds on the phy until it says it is 2170 * ready, but it still takes 2 more seconds after this 2171 * before the link is usable. We're better off letting the 2172 * dhcp/arp retries do the right thing here. 2173 */ 2174 2175#if 0 2176 do { 2177 int64_t timer; 2178 TIMER_SET(timer,2*CFE_HZ); 2179 while (!TIMER_EXPIRED(timer)) { 2180 sbeth_mii_poll(softc,FALSE); 2181 if (softc->sbe_linkstat != ETHER_SPEED_UNKNOWN) break; 2182 } 2183 } while (0); 2184#else 2185 if (softc->sbe_linkstat == ETHER_SPEED_UNKNOWN) { 2186 sbeth_mii_poll(softc,TRUE); 2187 } 2188#endif 2189 2190 sb1250_ether_readenv(ctx); 2191 2192 TIMER_SET(softc->sbe_linkstat_timer,SBETH_MIIPOLL_TIMER); 2193 softc->fifo_mode = FALSE; 2194 2195 /* Make sure we see a change with autospeed set (rework?) */ 2196 softc->sbe_phy_oldbmsr &= ~BMSR_ANCOMPLETE; 2197 2198 sbeth_start(softc); 2199 2200 return 0; 2201} 2202 2203/* ********************************************************************* 2204 * SB1250_ETHER_READ(ctx,buffer) 2205 * 2206 * Read a packet from the Ethernet device. If no packets are 2207 * available, the read will succeed but return 0 bytes. 2208 * 2209 * Input parameters: 2210 * ctx - device context (includes ptr to our softc) 2211 * buffer - pointer to buffer descriptor. 2212 * 2213 * Return value: 2214 * status, 0 = ok 2215 ********************************************************************* */ 2216 2217static int sb1250_ether_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 2218{ 2219 sbeth_t *softc = ctx->dev_softc; 2220 sbeth_pkt_t *pkt; 2221 int blen; 2222 2223 if (softc->sbe_state != sbeth_state_on) return -1; 2224 2225 sbeth_isr(softc); 2226 2227 if (softc->sbe_rxqueue == NULL) { 2228 buffer->buf_retlen = 0; 2229 return 0; 2230 } 2231 2232 pkt = softc->sbe_rxqueue; 2233 softc->sbe_rxqueue = pkt->next; 2234 pkt->next = NULL; 2235 2236 blen = buffer->buf_length; 2237 if (blen > pkt->length) blen = pkt->length; 2238 2239 hs_memcpy_to_hs(buffer->buf_ptr,pkt->buffer,blen); 2240 buffer->buf_retlen = blen; 2241 2242 sbeth_free_pkt(softc,pkt); 2243 sbeth_fillrxring(softc,0); 2244 sbeth_isr(softc); 2245 2246 return 0; 2247} 2248 2249/* ********************************************************************* 2250 * SB1250_ETHER_INPSTAT(ctx,inpstat) 2251 * 2252 * Check for received packets on the Ethernet device 2253 * 2254 * Input parameters: 2255 * ctx - device context (includes ptr to our softc) 2256 * inpstat - pointer to input status structure 2257 * 2258 * Return value: 2259 * status, 0 = ok 2260 ********************************************************************* */ 2261static int sb1250_ether_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat) 2262{ 2263 sbeth_t *softc = ctx->dev_softc; 2264 2265 if (softc->sbe_state != sbeth_state_on) return -1; 2266 2267 sbeth_isr(softc); 2268 2269 inpstat->inp_status = (softc->sbe_rxqueue == NULL) ? 0 : 1; 2270 2271 return 0; 2272} 2273 2274/* ********************************************************************* 2275 * SB1250_ETHER_WRITE(ctx,buffer) 2276 * 2277 * Write a packet to the Ethernet device. 2278 * 2279 * Input parameters: 2280 * ctx - device context (includes ptr to our softc) 2281 * buffer - pointer to buffer descriptor. 2282 * 2283 * Return value: 2284 * status, 0 = ok 2285 ********************************************************************* */ 2286static int sb1250_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 2287{ 2288 sbeth_t *softc = ctx->dev_softc; 2289 sbeth_pkt_t *pkt; 2290 int blen; 2291 2292 if (softc->sbe_state != sbeth_state_on) return -1; 2293 2294 2295 if (!softc->fifo_mode) { 2296 /* Only do a speed check if not packet fifo mode*/ 2297 int chg; 2298 2299 if (softc->sbe_linkstat == ETHER_SPEED_UNKNOWN) { 2300 chg = sbeth_mii_poll(softc,TRUE); 2301 if (softc->sbe_linkstat == ETHER_SPEED_UNKNOWN) return -1; 2302 if (chg) { 2303 sbeth_stop(softc); 2304 sbeth_start(softc); 2305 } 2306 } 2307 } 2308 2309 pkt = sbeth_alloc_pkt(softc); 2310 if (!pkt) return CFE_ERR_NOMEM; 2311 2312 blen = buffer->buf_length; 2313 if (blen > pkt->length) blen = pkt->length; 2314 2315 hs_memcpy_from_hs(pkt->buffer,buffer->buf_ptr,blen); 2316 pkt->length = blen; 2317 2318 sbeth_isr(softc); 2319 2320 if (sbeth_transmit(softc,0,pkt->buffer,pkt->length,pkt) != 1) { 2321 sbeth_free_pkt(softc,pkt); 2322 return CFE_ERR_IOERR; 2323 } 2324 2325 sbeth_isr(softc); 2326 2327 buffer->buf_retlen = blen; 2328 2329 return 0; 2330} 2331 2332/* ********************************************************************* 2333 * SB1250_ETHER_IOCTL_LOOPBACK(s,loopback) 2334 * 2335 * Set loopback modes 2336 * 2337 * Input parameters: 2338 * s - sbeth structure 2339 * loopback - loopback modes 2340 * 2341 * Return value: 2342 * 0 if ok, else error 2343 ********************************************************************* */ 2344 2345static int sb1250_ether_ioctl_loopback(sbeth_t *s,int loopback) 2346{ 2347 unsigned int miireg; 2348 uint64_t regval; 2349 2350 switch (loopback) { 2351 case ETHER_LOOPBACK_OFF: 2352 miireg = sbeth_mii_read(s,s->sbe_phyaddr,MII_BMCR); 2353 if (miireg & BMCR_LOOPBACK) { 2354 miireg &= ~BMCR_LOOPBACK; 2355 miireg |= BMCR_RESTARTAN; 2356 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,miireg); 2357 } 2358 regval = SBETH_READCSR(s->sbe_maccfg); 2359 if (regval & M_MAC_LOOPBACK_SEL) { 2360 regval &= ~M_MAC_LOOPBACK_SEL; 2361 SBETH_WRITECSR(s->sbe_maccfg,regval); 2362 } 2363 break; 2364 2365 case ETHER_LOOPBACK_INT: 2366 regval = SBETH_READCSR(s->sbe_maccfg); 2367 regval |= M_MAC_LOOPBACK_SEL; 2368 SBETH_WRITECSR(s->sbe_maccfg,regval); 2369 break; 2370 2371 case ETHER_LOOPBACK_EXT: 2372 regval = SBETH_READCSR(s->sbe_maccfg); 2373 if (regval & M_MAC_LOOPBACK_SEL) { 2374 regval &= ~M_MAC_LOOPBACK_SEL; 2375 SBETH_WRITECSR(s->sbe_maccfg,regval); 2376 } 2377 miireg = sbeth_mii_read(s,s->sbe_phyaddr,MII_BMCR); 2378 miireg |= BMCR_LOOPBACK; 2379 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,miireg); 2380 break; 2381 } 2382 2383 s->sbe_loopback = loopback; 2384 2385 return 0; 2386} 2387 2388 2389/* ********************************************************************* 2390 * SB1250_ETHER_IOCTL_SPEED(s,speed) 2391 * 2392 * Set speed forcibly via the IOCTL command 2393 * 2394 * Input parameters: 2395 * s - sbeth structure 2396 * speed - speed IOCTL setting 2397 * 2398 * Return value: 2399 * 0 if ok, else error 2400 ********************************************************************* */ 2401 2402static int sb1250_ether_ioctl_speed(sbeth_t *s,int speed) 2403{ 2404 switch (speed) { 2405 case ETHER_SPEED_AUTO: 2406 s->sbe_autospeed = TRUE; 2407 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR, 2408 BMCR_ANENABLE|BMCR_RESTARTAN|BMCR_DUPLEX|BMCR_SPEED1); 2409 TIMER_SET(s->sbe_linkstat_timer,100); 2410 break; 2411 2412 case ETHER_SPEED_10HDX: 2413 s->sbe_autospeed = FALSE; 2414 s->sbe_speed = sbeth_speed_10; 2415 s->sbe_duplex = sbeth_duplex_half; 2416 s->sbe_fc = sbeth_fc_disabled; 2417 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR, 2418 BMCR_SPEED10); 2419 break; 2420 2421 case ETHER_SPEED_10FDX: 2422 s->sbe_autospeed = FALSE; 2423 s->sbe_speed = sbeth_speed_10; 2424 s->sbe_duplex = sbeth_duplex_full; 2425 s->sbe_fc = sbeth_fc_frame; 2426 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR, 2427 BMCR_SPEED10|BMCR_DUPLEX); 2428 break; 2429 2430 case ETHER_SPEED_100HDX: 2431 s->sbe_autospeed = FALSE; 2432 s->sbe_speed = sbeth_speed_100; 2433 s->sbe_duplex = sbeth_duplex_half; 2434 s->sbe_fc = sbeth_fc_disabled; 2435 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR, 2436 BMCR_SPEED100); 2437 break; 2438 2439 case ETHER_SPEED_100FDX: 2440 s->sbe_autospeed = FALSE; 2441 s->sbe_speed = sbeth_speed_100; 2442 s->sbe_duplex = sbeth_duplex_full; 2443 s->sbe_fc = sbeth_fc_frame; 2444 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR, 2445 BMCR_SPEED100|BMCR_DUPLEX); 2446 break; 2447 2448 case ETHER_SPEED_1000HDX: 2449 s->sbe_autospeed = FALSE; 2450 s->sbe_speed = sbeth_speed_1000; 2451 s->sbe_duplex = sbeth_duplex_half; 2452 s->sbe_fc = sbeth_fc_disabled; 2453 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR, 2454 BMCR_SPEED1000); 2455 break; 2456 2457 case ETHER_SPEED_1000FDX: 2458 s->sbe_autospeed = FALSE; 2459 s->sbe_speed = sbeth_speed_1000; 2460 s->sbe_duplex = sbeth_duplex_full; 2461 s->sbe_fc = sbeth_fc_frame; 2462 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR, 2463 BMCR_SPEED1000|BMCR_DUPLEX); 2464 break; 2465 2466 default: 2467 return -1; 2468 } 2469 2470 sbeth_stop(s); 2471 sbeth_start(s); 2472 2473 s->sbe_curspeed = speed; 2474 if (speed != ETHER_SPEED_AUTO) s->sbe_linkstat = speed; 2475 2476 return 0; 2477} 2478/* ********************************************************************* 2479 * SB1250_ETHER_IOCTL_PACKETFIFO(s,mode) 2480 * 2481 * Swtich to a packet fifo mode. 2482 * 2483 * 2484 * Input parameters: 2485 * s - sbeth structure 2486 * mode - 8 or 16 bit packet fifo mode. 2487 * 2488 * Return value: 2489 * 0 if ok, else error 2490 ********************************************************************* */ 2491static int sb1250_ether_ioctl_packetfifo(sbeth_t *s, int mode) 2492{ 2493 uint64_t cfg; 2494 uint64_t enb; 2495 uint64_t frame; 2496 2497 cfg = SBETH_READCSR(s->sbe_maccfg); 2498 switch (mode) { 2499 case ETHER_FIFO_8: 2500 cfg &= ~(M_MAC_BYPASS_SEL | M_MAC_AP_STAT_EN | M_MAC_SPEED_SEL | M_MAC_BURST_EN); 2501 cfg |= M_MAC_BYPASS_SEL | V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN; 2502 2503 /* disable rx/tx ethernet macs and enable rx/tx fifo engines */ 2504 enb = SBETH_READCSR(s->sbe_macenable); 2505 enb &= ~(M_MAC_RX_ENABLE | M_MAC_TX_ENABLE); 2506 enb |= M_MAC_BYP_RX_ENABLE | 2507 M_MAC_BYP_TX_ENABLE | 2508 0; 2509 SBETH_WRITECSR(s->sbe_macenable,enb); 2510 2511 /* accept all packets */ 2512 SBETH_WRITECSR(s->sbe_rxfilter, M_MAC_ALLPKT_EN | 0); 2513 2514 /* set min_frame_size to 9 bytes */ 2515 frame = SBETH_READCSR(s->sbe_framecfg); 2516 frame |= V_MAC_MIN_FRAMESZ_FIFO; 2517 SBETH_WRITECSR(s->sbe_framecfg,frame); 2518 2519 s->fifo_mode = TRUE; 2520 2521 break; 2522 2523 case ETHER_FIFO_16: 2524 cfg &= ~(M_MAC_BYPASS_SEL | M_MAC_BYPASS_16 | M_MAC_AP_STAT_EN | M_MAC_SPEED_SEL | M_MAC_BURST_EN); 2525 cfg |= M_MAC_BYPASS_SEL | M_MAC_BYPASS_16 | V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN; 2526 2527 /* disable rx/tx ethernet macs and enable rx/tx fifo engines */ 2528 enb = SBETH_READCSR(s->sbe_macenable); 2529 enb &= ~(M_MAC_RX_ENABLE | M_MAC_TX_ENABLE); 2530 enb |= M_MAC_BYP_RX_ENABLE | 2531 M_MAC_BYP_TX_ENABLE | 2532 0; 2533 SBETH_WRITECSR(s->sbe_macenable,enb); 2534 2535 /* accept all packets */ 2536 SBETH_WRITECSR(s->sbe_rxfilter, M_MAC_ALLPKT_EN | 0); 2537 2538 /* set min_frame_size to 9 bytes */ 2539 frame = SBETH_READCSR(s->sbe_framecfg); 2540 frame |= V_MAC_MIN_FRAMESZ_FIFO; 2541 SBETH_WRITECSR(s->sbe_framecfg,frame); 2542 2543 s->fifo_mode = TRUE; 2544 2545 break; 2546 2547 case ETHER_ETHER: 2548 cfg &= ~(M_MAC_BYPASS_SEL | M_MAC_BYPASS_16 | M_MAC_AP_STAT_EN ); 2549 cfg |= M_MAC_AP_STAT_EN; 2550 break; 2551 2552 default: 2553 return -1; 2554 } 2555 2556 SBETH_WRITECSR(s->sbe_maccfg,cfg); 2557 2558 return 0; 2559} 2560 2561/* ********************************************************************* 2562 * SB1250_ETHER_IOCTL_STROBESIGNAL 2563 * 2564 * Set the strobe signal that are used on both transmit and receive 2565 * interfaces in packet fifo mode. 2566 * 2567 * Input parameters: 2568 * s - sbeth structure 2569 * mode - GMII style, Encoded, SOP flagged, or EOP flagged mode. 2570 * 2571 * Return value: 2572 * 0 if ok, else error 2573 ********************************************************************* */ 2574static int sb1250_ether_ioctl_strobesignal(sbeth_t *s, int mode) 2575{ 2576 uint64_t cfg; 2577 2578 cfg = SBETH_READCSR(s->sbe_maccfg); 2579 2580 switch (mode) { 2581 case ETHER_STROBE_GMII: 2582 cfg &= ~(M_MAC_BYPASS_CFG); 2583 cfg |= V_MAC_BYPASS_CFG(K_MAC_BYPASS_GMII); 2584 break; 2585 2586 case ETHER_STROBE_ENCODED: 2587 cfg &= ~(M_MAC_BYPASS_CFG); 2588 cfg |= V_MAC_BYPASS_CFG(K_MAC_BYPASS_ENCODED); 2589 break; 2590 2591 case ETHER_STROBE_SOP: /* not valid in 16-bit fifo mode */ 2592 cfg &= ~(M_MAC_BYPASS_CFG); 2593 cfg |= V_MAC_BYPASS_CFG(K_MAC_BYPASS_SOP); 2594 break; 2595 2596 case ETHER_STROBE_EOP: /* not valid in 16-bit fifo mode */ 2597 cfg &= ~(M_MAC_BYPASS_CFG); 2598 cfg |= V_MAC_BYPASS_CFG(K_MAC_BYPASS_EOP); 2599 break; 2600 2601 default: 2602 return -1; 2603 } 2604 2605 SBETH_WRITECSR(s->sbe_maccfg,cfg); 2606 2607 return 0; 2608} 2609 2610/* ********************************************************************* 2611 * SB1250_ETHER_IOCTL(ctx,buffer) 2612 * 2613 * Do device-specific I/O control operations for the device 2614 * 2615 * Input parameters: 2616 * ctx - device context (includes ptr to our softc) 2617 * buffer - pointer to buffer descriptor. 2618 * 2619 * Return value: 2620 * status, 0 = ok 2621 ********************************************************************* */ 2622static int sb1250_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 2623{ 2624 sbeth_t *softc = ctx->dev_softc; 2625 int m; 2626 2627 switch ((int)buffer->buf_ioctlcmd) { 2628 case IOCTL_ETHER_GETHWADDR: 2629 hs_memcpy_to_hs(buffer->buf_ptr,softc->sbe_hwaddr,sizeof(softc->sbe_hwaddr)); 2630 break; 2631 2632 case IOCTL_ETHER_SETHWADDR: 2633 hs_memcpy_from_hs(softc->sbe_hwaddr,buffer->buf_ptr,sizeof(softc->sbe_hwaddr)); 2634 sbeth_setaddr(softc,softc->sbe_hwaddr); 2635#ifdef _SB1250_PASS1_WORKAROUNDS_ 2636 SBETH_WRITECSR(SBETH_PORT(softc->sbe_baseaddr + R_MAC_ETHERNET_ADDR),0); 2637#endif 2638 break; 2639 2640 case IOCTL_ETHER_GETSPEED: 2641 m = softc->sbe_curspeed; 2642 hs_memcpy_to_hs(buffer->buf_ptr,&m,sizeof(int)); 2643 break; 2644 2645 case IOCTL_ETHER_SETSPEED: 2646 hs_memcpy_from_hs(&m,buffer->buf_ptr,sizeof(int)); 2647 return sb1250_ether_ioctl_speed(softc,m); 2648 break; 2649 2650 case IOCTL_ETHER_GETLINK: 2651 m = softc->sbe_linkstat; 2652 hs_memcpy_to_hs(buffer->buf_ptr,&m,sizeof(int)); 2653 break; 2654 2655 case IOCTL_ETHER_GETLOOPBACK: 2656 m = softc->sbe_loopback; 2657 hs_memcpy_to_hs(buffer->buf_ptr,&m,sizeof(int)); 2658 break; 2659 2660 case IOCTL_ETHER_SETLOOPBACK: 2661 hs_memcpy_from_hs(&m,buffer->buf_ptr,sizeof(int)); 2662 return sb1250_ether_ioctl_loopback(softc,m); 2663 break; 2664 2665 case IOCTL_ETHER_SETPACKETFIFO: 2666 hs_memcpy_from_hs(&m,buffer->buf_ptr,sizeof(int)); 2667 return sb1250_ether_ioctl_packetfifo(softc,m); 2668 break; 2669 2670 case IOCTL_ETHER_SETSTROBESIG: 2671 hs_memcpy_from_hs(&m,buffer->buf_ptr,sizeof(int)); 2672 return sb1250_ether_ioctl_strobesignal(softc,m); 2673 break; 2674 2675 default: 2676 return -1; 2677 } 2678 2679 return 0; 2680} 2681 2682/* ********************************************************************* 2683 * SB1250_ETHER_CLOSE(ctx) 2684 * 2685 * Close the Ethernet device. 2686 * 2687 * Input parameters: 2688 * ctx - device context (includes ptr to our softc) 2689 * 2690 * Return value: 2691 * status, 0 = ok 2692 ********************************************************************* */ 2693static int sb1250_ether_close(cfe_devctx_t *ctx) 2694{ 2695 sbeth_t *softc = ctx->dev_softc; 2696 2697 sbeth_stop(softc); 2698 2699 /* Reprogram the default hardware address in case someone mucked with it */ 2700 sbeth_setaddr(softc,softc->sbe_hwaddr); 2701 2702 return 0; 2703} 2704 2705 2706/* ********************************************************************* 2707 * SB1250_ETHER_POLL(ctx,ticks) 2708 * 2709 * Check for changes in the PHY, so we can track speed changes. 2710 * 2711 * Input parameters: 2712 * ctx - device context (includes ptr to our softc) 2713 * ticks- current time in ticks 2714 * 2715 * Return value: 2716 * nothing 2717 ********************************************************************* */ 2718 2719static void sb1250_ether_poll(cfe_devctx_t *ctx,int64_t ticks) 2720{ 2721 sbeth_t *softc = ctx->dev_softc; 2722 int chg; 2723 2724 if (TIMER_RUNNING(softc->sbe_linkstat_timer) && 2725 TIMER_EXPIRED(softc->sbe_linkstat_timer)) { 2726 if (softc->sbe_autospeed) { 2727 chg = sbeth_mii_poll(softc,TRUE); 2728 if (chg) { 2729 if (softc->sbe_state == sbeth_state_on) { 2730 TIMER_CLEAR(softc->sbe_linkstat_timer); 2731 sbeth_stop(softc); 2732 sbeth_start(softc); 2733 } 2734 } 2735 } 2736 TIMER_SET(softc->sbe_linkstat_timer,SBETH_MIIPOLL_TIMER); 2737 } 2738 2739} 2740 2741/* ********************************************************************* 2742 * SB1250_ETHER_RESET(softc) 2743 * 2744 * This routine is called when CFE is restarted after a 2745 * program exits. We can clean up pending I/Os here. 2746 * 2747 * Input parameters: 2748 * softc - pointer to sbmac_t 2749 * 2750 * Return value: 2751 * nothing 2752 ********************************************************************* */ 2753 2754static void sb1250_ether_reset(void *softc) 2755{ 2756 sbeth_t *s = (sbeth_t *) softc; 2757 sbeth_port_t port; 2758 uint64_t regval = 0; 2759 int idx; 2760 uint8_t *addr; 2761 2762 /* 2763 * Turn off the Ethernet interface. 2764 */ 2765 2766 SBETH_WRITECSR(s->sbe_macenable,0); 2767 2768 /* 2769 * Reset the address. 2770 * Pack the bytes into the register, with the first byte transmitted 2771 * in the lowest-order 8 bits of the register. 2772 */ 2773 2774 addr = s->sbe_hwaddr; 2775 for (idx = 0; idx < 6; idx++) { 2776 regval |= (((uint64_t) (*addr)) << (idx*8)); 2777 addr++; 2778 } 2779 2780 /* 2781 * Write to the port. 2782 */ 2783 2784 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ETHERNET_ADDR); 2785 SBETH_WRITECSR(port,regval); 2786 2787} 2788