1#include "lib_types.h" 2#include "lib_malloc.h" 3#include "lib_string.h" 4#include "lib_printf.h" 5 6#include "cfe_iocb.h" 7#include "cfe_ioctl.h" 8#include "cfe_timer.h" 9#include "cfe_device.h" 10#include "cfe_devfuncs.h" 11 12#include "dev_bcm4413.h" 13#include "dev_bcm4413_mii.h" 14 15#ifdef EBIDMA 16 #include "bcmdma.h" 17#endif 18 19#ifdef __MIPSEB 20 #define SWAP_ENDIAN 21#endif 22 23#ifdef SWAP_ENDIAN 24#define SWAP16(x) ( ((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8) ) 25#define SWAP32(x) ( (x<<24)|((x<<8)&0x00FF0000)|((x>>8)&0x0000FF00)|(x>>24) ) 26#endif 27 28 29#define BCM4413ERROR( x, y ... ) xprintf( "BCM4413 ERROR : " x, ##y ) 30 31 32#ifdef DEBUG 33 34 #define BCMDEBUG( x, y ... ) xprintf( "BCM4413 : " x, ##y ) 35 #define BCM4413TRACE( x, y ... ) 36 //#define BCM4413TRACE( x, y ... ) xprintf( "BCM4413 : " x, ##y ) 37 38 #define BCM4413INFO( x, y ... ) 39 //#define BCM4413INFO( x, y ... ) xprintf( "BCM4413 ERROR : " x, ##y ) 40 41#else 42 43 #define BCM4413TRACE( x, y ... ) 44 45#endif 46 47 48#define K0_TO_PHYS(p) ((uint32_t)(p) & ((uint32_t)0x1fffffff)) 49 50#define BCM4412_DEVICE_ID 0x4412 /* bcm44xx family pci enet */ 51 52#define PHYS_BCM44XX_BASE 0x1B400000 53#define BCM44XX_BASE (0xA0000000 | PHYS_BCM44XX_BASE) 54#define BCM44XX_ENET_BASE (BCM44XX_BASE + 0x1800) 55 56/* 57 * The number of bytes in an ethernet (MAC) address. 58 */ 59#define ETHER_ADDR_LEN 6 60 61/* 62 * The number of bytes in the type field. 63 */ 64#define ETHER_TYPE_LEN 2 65 66/* 67 * The number of bytes in the trailing CRC field. 68 */ 69#define ETHER_CRC_LEN 4 70 71/* 72 * The length of the combined header. 73 */ 74#define ETHER_HDR_LEN (ETHER_ADDR_LEN*2+ETHER_TYPE_LEN) 75 76 77/* TODO -- This value probably isn't right */ 78#define ETHER_MAX_DATA 1500 79 80/* 81 * The maximum packet length. 82 */ 83//#define ETHER_MAX_LEN 1518 84#define ETHER_MAX_LEN 1514 85 86/* Broadcom's rxhdr */ 87#define HWRXOFF 30 88 89#define DST_BUF_SIZE 1514 90#define BRCM_PACKET_SIZE DST_BUF_SIZE + HWRXOFF + ETHER_CRC_LEN 91 92 93 94static void bcm4413_ether_probe( cfe_driver_t * drv, unsigned long probe_a, 95 unsigned long probe_b, void * probe_ptr ); 96static int bcm4413_ether_open(cfe_devctx_t *ctx); 97static int bcm4413_ether_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 98static int bcm4413_ether_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat); 99static int bcm4413_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 100static int bcm4413_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer); 101static int bcm4413_ether_close(cfe_devctx_t *ctx); 102 103 104const static cfe_devdisp_t bcm4413_ether_dispatch = { 105 bcm4413_ether_open, 106 bcm4413_ether_read, 107 bcm4413_ether_inpstat, 108 bcm4413_ether_write, 109 bcm4413_ether_ioctl, 110 bcm4413_ether_close, 111 NULL, 112 NULL 113}; 114 115const cfe_driver_t bcm4413drv = { 116 "BCM4413 Ethernet", 117 "eth", 118 CFE_DEV_NETWORK, 119 &bcm4413_ether_dispatch, 120 bcm4413_ether_probe 121}; 122 123 124typedef struct bcm4413_softc { 125 bcmenetregs_t * regs; 126 127 unsigned char * txbuffer; 128 unsigned char * rxbuffer; 129 130 uint8_t hwaddr[ETHER_ADDR_LEN]; 131} bcm4413_softc; 132 133 134/* 135 * Structure of a 10Mb/s Ethernet header. 136 */ 137typedef struct ether_header { 138 uint8_t ether_dhost[ETHER_ADDR_LEN]; 139 uint8_t ether_shost[ETHER_ADDR_LEN]; 140 uint16_t ether_type; 141} ether_header __attribute__((packed)); 142 143/* 144 * Structure of a 48-bit Ethernet address. 145 */ 146struct ether_addr { 147 uint8_t octet[ETHER_ADDR_LEN]; 148} __attribute__((packed)); 149 150 151 152static int bcm7115_getmacaddr( char * macaddr ) 153{ 154 int retval; 155 uint8_t chksum; 156 uint32_t brdtype; 157 uint16_t * src; 158 159 BCM4413TRACE( "getmacaddr entered\n" ); 160 161 /* Check checksum */ 162 chksum = 0; 163 for( src = (uint16_t *)(0xBAFFF800); src <= (uint16_t *)(0xBAFFF88A); ) { 164 chksum += ((*src) & 0xFF00) >> 8; 165 chksum += (*src) & 0x00FF; 166 src++; 167 } 168 169#ifdef __MIPSEB 170 171 if( chksum != ((*src) & 0x00FF) ) { 172 BCM4413ERROR( "Flash checksum failed.\n" ); 173 return 0; 174 } 175 176 brdtype = (((*((uint16_t *)(0xBAFFF800))) & 0x00FF) << 16) 177 | ((*((uint16_t *)(0xBAFFF800))) & 0xFF00) 178 | ((*((uint16_t *)(0xBAFFF802))) & 0x00FF); 179 180#else 181 182 if( chksum != (((*src) & 0xFF00) >> 8) ) { 183 BCM4413ERROR( "Flash checksum failed.\n" ); 184 return 0; 185 } 186 187 brdtype = ( (*((uint16_t *)(0xBAFFF800))) << 8 ) 188 | (((*((uint16_t *)(0xBAFFF802))) & 0xFF00) >> 8); 189 190#endif 191 192 if( brdtype == 0x00097115 ) { 193 for( src = (uint16_t *)(0xBAFFF80C); src < (uint16_t *)(0xBAFFF812); ) { 194 *((uint16_t *)macaddr) = (((*src) & 0xFF00) >> 8) 195 | (((*src) & 0x00FF) << 8); 196 macaddr += 2; 197 src++; 198 } 199 retval = 1; 200 } else { 201 BCM4413ERROR( "Wrong board type (0x%X).\n", brdtype ); 202 retval = 0; 203 } 204 205 BCM4413TRACE( "getmacaddr exited\n" ); 206 207 return retval; 208} 209 210 211static void bcm4413_writecam(bcmenetregs_t * regs, struct ether_addr *ea, 212 unsigned int camindex); 213static void bcm4413_writecam(bcmenetregs_t * regs, struct ether_addr *ea, 214 unsigned int camindex) 215{ 216 uint32_t w; 217 uint16_t *camcontrol; 218 219 BCM4413TRACE( "bcm4413_writecam entered\n" ); 220 221#ifdef DEBUG 222 if( (R_REG(NULL, ®s->camcontrol) & (CC_CB | CC_CE)) != 0 ) { 223 BCM4413ERROR( "Cannot write MAC address to CAM.\n" ); 224 } 225#endif 226 227 w = (ea->octet[2] << 24) | (ea->octet[3] << 16) | (ea->octet[4] << 8) 228 | ea->octet[5]; 229 W_REG(NULL, ®s->camdatalo, w ); 230 231 w = CD_V | (ea->octet[0] << 8) | ea->octet[1]; 232 W_REG(NULL, ®s->camdatahi, w ); 233 234 w = (camindex << CC_INDEX_SHIFT) | CC_WR; 235 236 camcontrol = (unsigned short *) (®s->camcontrol); 237 W_REG(NULL, &camcontrol[1], (w >> 16) & 0xffff ); 238 W_REG(NULL, &camcontrol[0], w & 0xffff ); 239 240 /* Return when done */ 241 while( R_REG(NULL, ®s->camcontrol) & CC_CB ) { 242 cfe_usleep( 10 ); 243 } 244 245 BCM4413TRACE( "bcm4413_writecam exited\n" ); 246} 247 248 249static void bcm4413_reset( bcmenetregs_t * regs ); 250static void bcm4413_reset( bcmenetregs_t * regs ) 251{ 252 BCM4413TRACE( "bcm4413_reset entered\n" ); 253 254 /* Put the chip in a reset state */ 255 W_REG(NULL, ®s->devcontrol, DC_RS ); 256 257 /* We have to wait 10 msec before we can reaquire. */ 258 /* Update : cached mode needs to wait longer. */ 259 cfe_usleep( 100 ); 260 261 /* Bring it back out to a dormant state. */ 262 W_REG(NULL, ®s->devcontrol, 0 ); 263 264 cfe_usleep( 100 ); 265 266 /* 267 * We want the phy registers to be accessible even when 268 * the driver is "downed" so initialize enough for this here. 269 */ 270 W_REG(NULL, ((unsigned short *) (®s->mdiocontrol)), (MC_PE | 0x1f) ); 271 272 BCM4413TRACE( "bcm4413_reset exited\n" ); 273} 274 275 276static void bcm4413_init( bcm4413_softc * softc ) 277{ 278 bcmenetregs_t * regs; 279 280 BCM4413TRACE( "bcm4413_init entered\n" ); 281 282 regs = softc->regs; 283 284 mii_init( regs ); 285 286 /* enable crc32 generation */ 287 OR_REG(NULL, ®s->emaccontrol, EMC_CG ); 288 289 /* enable 802.3x tx flow control (honor received PAUSE frames) */ 290 W_REG(NULL, ®s->rxcontrol, ERC_FE | ERC_UF ); 291 292#ifdef PROMISC 293 OR_REG(NULL, ®s->rxcontrol, ERC_PE ); 294#else 295 /* our local address */ 296 bcm4413_writecam(regs, (struct ether_addr *)(softc->hwaddr), 0 ); 297 298 /* Accept multicast frames */ 299 OR_REG(NULL, ®s->rxcontrol, ERC_AM ); 300 301 /* Enable CAM */ 302 OR_REG(NULL, ®s->camcontrol, CC_CE ); 303#endif 304 305 /* set max frame lengths - account for possible vlan tag */ 306 W_REG(NULL, ®s->rxmaxlength, (ETHER_MAX_LEN + 32) ); 307 W_REG(NULL, ®s->txmaxlength, (ETHER_MAX_LEN + 32) ); 308 309 /* set tx watermark */ 310 W_REG(NULL, (unsigned short *)(®s->txwatermark), 56 ); 311 312 /* Set TX to full duplex */ 313 W_REG(NULL, ®s->txcontrol, EXC_FD ); 314 315 /* turn on the emac */ 316 OR_REG(NULL, ®s->enetcontrol, EC_EE ); 317 318 mii_setspeed( regs ); 319 320 /* Enable recieves in Fifo Mode */ 321 W_REG(NULL, ®s->rcvcontrol, RC_FM ); 322 323#ifdef __MIPSEB 324 OR_REG(NULL, ®s->devcontrol, DC_BS ); 325#endif 326 327 /* Enable transmit and recieve */ 328 OR_REG(NULL, ®s->devcontrol, DC_XE | DC_RE ); 329 330 BCM4413TRACE( "bcm4413_init exited\n" ); 331} 332 333 334#define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU) 335static void chiperrors( bcmenetregs_t * regs, bcm4413_softc * softc ); 336static void chiperrors( bcmenetregs_t * regs, bcm4413_softc * softc ) 337{ 338 uint32_t intstatus; 339 340 intstatus = R_REG(NULL, ®s->intstatus ); 341 342 BCM4413INFO( "chiperrors: intstatus 0x%x\n", intstatus ); 343 344 if (intstatus & I_PC) { 345 BCM4413INFO( "\tpci descriptor error\n"); 346 } 347 348 if (intstatus & I_PD) { 349 BCM4413INFO( "\tpci data error\n"); 350 } 351 352 if (intstatus & I_DE) { 353 BCM4413INFO("\tdescriptor protocol error\n"); 354 } 355 356 if (intstatus & I_RU) { 357 BCM4413INFO("\treceive descriptor underflow\n"); 358 } 359 360 if (intstatus & I_RO) { 361 BCM4413INFO("\treceive fifo overflow\n"); 362 363 /* in pio mode, just bang the rx fifo */ 364 AND_REG(NULL, ®s->devcontrol, ~DC_RE); 365 cfe_usleep( 10 ); 366 OR_REG(NULL, ®s->devcontrol, DC_RE); 367 return; 368 } 369 370 if (intstatus & I_XU) { 371 BCM4413INFO("\ttransmit fifo underflow\n"); 372 } 373 374 /* big hammer */ 375 bcm4413_reset( regs ); 376 bcm4413_init( softc ); 377} 378 379 380static void bcm4413_ether_probe( cfe_driver_t * drv, unsigned long probe_a, 381 unsigned long probe_b, void * probe_ptr ) 382{ 383 bcmenetregs_t * regs; 384 bcm4413_softc * softc; 385 char descr[100]; 386 387 BCM4413TRACE( "probe entered\n" ); 388 389 softc = (bcm4413_softc *) KMALLOC( sizeof(bcm4413_softc), 0 ); 390 if( softc == NULL ) { 391 BCM4413ERROR( "BCM4413 : Failed to allocate softc memory.\n" ); 392 return; 393 } 394 395 memset( softc, 0, sizeof(bcm4413_softc) ); 396 397 softc->regs = (bcmenetregs_t *)BCM44XX_ENET_BASE; 398 regs = softc->regs; 399 400 bcm4413_reset( regs ); 401 402 bcm7115_getmacaddr( softc->hwaddr ); 403 404#ifdef DEBUG 405 xprintf( "BCM4413 :\n" ); 406 xprintf( "\tvendorID = 0x%X\n", R_REG(NULL, ®s->pcicfg[0]) ); 407 xprintf( "\tdeviceID = 0x%X\n", R_REG(NULL, ®s->pcicfg[1]) ); 408 xprintf( "\tchiprev = 0x%X\n", R_REG(NULL, ®s->devstatus) & DS_RI_MASK ); 409#endif 410 411 xsprintf( descr, "%s at 0x%X", drv->drv_description, probe_a ); 412 cfe_attach( drv, softc, NULL, descr ); 413 414 BCM4413TRACE( "probe exited\n" ); 415} 416 417 418static int bcm4413_ether_open(cfe_devctx_t *ctx) 419{ 420 bcmenetregs_t * regs; 421 bcm4413_softc * softc = (bcm4413_softc *) ctx->dev_softc; 422 423 BCM4413TRACE( "open entered\n" ); 424 425 /* THESE BUFFERS MUST BE 4-BYTE ALIGNED */ 426 softc->txbuffer = (unsigned char *)KMALLOC( BRCM_PACKET_SIZE, 4 ); 427 if( softc->txbuffer == NULL ) { 428 BCM4413ERROR( "BCM4413 : Failed to allocate TX buffer memory.\n" ); 429 return 0; 430 } 431 432 softc->rxbuffer = (unsigned char *)KMALLOC( BRCM_PACKET_SIZE, 4 ); 433 if( softc->rxbuffer == NULL ) { 434 BCM4413ERROR( "BCM4413 : Failed to allocate RX buffer memory.\n" ); 435 KFREE( softc->txbuffer ); 436 return 0; 437 } 438 439#ifdef DEBUG 440 memset( softc->txbuffer, 0, BRCM_PACKET_SIZE ); 441 memset( softc->rxbuffer, 0, BRCM_PACKET_SIZE ); 442#endif 443 444 regs = softc->regs; 445 446#ifdef DEBUG 447 if( (R_REG(NULL, ®s->emaccontrol) & EMC_PD) != 0 || 448 (R_REG(NULL, ®s->devcontrol) & DC_PD) != 0 ) { 449 BCM4413ERROR( "ERROR : Internal ephy has no power or clock.\n" ); 450 } 451#endif 452 453 mii_init( regs ); 454 455 /* enable crc32 generation */ 456 OR_REG(NULL, ®s->emaccontrol, EMC_CG ); 457 458 /* enable 802.3x tx flow control (honor received PAUSE frames) */ 459 W_REG(NULL, ®s->rxcontrol, ERC_FE | ERC_UF ); 460 461#ifdef PROMISC 462 OR_REG(NULL, ®s->rxcontrol, ERC_PE ); 463#else 464 465 /* our local address */ 466 bcm4413_writecam(regs, (struct ether_addr *)(softc->hwaddr), 0 ); 467 468 /* Accept multicast frames */ 469 OR_REG(NULL, ®s->rxcontrol, ERC_AM ); 470 471 /* enable cam */ 472 OR_REG(NULL, ®s->camcontrol, CC_CE ); 473#endif 474 475 /* set max frame lengths - account for possible vlan tag */ 476 W_REG(NULL, ®s->rxmaxlength, (ETHER_MAX_LEN + 32) ); 477 W_REG(NULL, ®s->txmaxlength, (ETHER_MAX_LEN + 32) ); 478 479 /* set tx watermark */ 480 W_REG(NULL, (unsigned short *)(®s->txwatermark), 56 ); 481 482 /* Set TX to full duplex */ 483 W_REG(NULL, ®s->txcontrol, EXC_FD ); 484 485 /* turn on the emac */ 486 OR_REG(NULL, ®s->enetcontrol, EC_EE ); 487 488 mii_setspeed( regs ); 489 490 /* Enable recieves in Fifo Mode */ 491 W_REG(NULL, ®s->rcvcontrol, RC_FM ); 492 493#ifdef __MIPSEB 494 OR_REG(NULL, ®s->devcontrol, DC_BS ); 495#endif 496 497 /* Enable transmit and recieve */ 498 OR_REG(NULL, ®s->devcontrol, DC_XE | DC_RE ); 499 500 BCM4413TRACE( "open exited\n" ); 501 502 return 0; 503} 504 505 506static int bcm4413_ether_read( cfe_devctx_t * ctx, iocb_buffer_t * buffer ) 507{ 508 int i; 509 uint16_t type; 510 uint16_t flags; 511 uint16_t rawlen; 512 uint16_t length; 513 uint16_t * dst16; 514 bcmenetregs_t * regs; 515 bcmenetrxhdr_t * hdr; 516 bcm4413_softc * softc = (bcm4413_softc *) ctx->dev_softc; 517 ether_header * ethhdr; 518 519 BCM4413TRACE( "read entered\n" ); 520 521#ifdef DEBUG 522 /* ============================= ASSERTIONS ============================= */ 523 524 if( ctx == NULL ) { 525 xprintf( "No context\n" ); 526 return -1; 527 } 528 529 if( buffer == NULL ) { 530 xprintf( "No dst buffer\n" ); 531 return -1; 532 } 533 534 if( buffer->buf_length != DST_BUF_SIZE ) { 535 xprintf( "dst buffer too small.\n" ); 536 xprintf( "actual size is %d\n", buffer->buf_length ); 537 return -1; 538 } 539 540 if( softc == NULL ) { 541 xprintf( "softc has not been initialized.\n" ); 542 return -1; 543 } 544 545 /* ====================================================================== */ 546#endif 547 548 regs = softc->regs; 549 550#ifdef DEBUG 551 if( !(R_REG(NULL, ®s->rcvfifocontrol) & RFC_FR) ) { 552 BCM4413ERROR( "4413 NOT READY TO RECEIVE!\n" ); 553 return -1; 554 } 555#endif 556 557 /* Clear frame ready */ 558 W_REG(NULL, ®s->rcvfifocontrol, RFC_FR ); 559 560 /* Wait for the hardware to make the data available */ 561 while( !(R_REG(NULL, ®s->rcvfifocontrol) & RFC_DR) ) {} 562 563 rawlen = R_REG(NULL, ®s->rcvfifodata ); 564 565#ifdef SWAP_ENDIAN 566 length = SWAP16( rawlen ); 567#else 568 length = rawlen; 569#endif 570 571 /* TODO -- Check this test. */ 572 if( length < ETHER_HDR_LEN || length > (BRCM_PACKET_SIZE - HWRXOFF) ) { 573 BCM4413INFO( "Extreme incoming packet size.\n" ); 574 BCM4413INFO( "length = %d, rawlen = %d\n", length, rawlen ); 575 576 buffer->buf_retlen = 0; 577 578 W_REG(NULL, ®s->rcvfifocontrol, RFC_DR ); 579 580 return 0; 581 } 582 583 /* read the rxheader from the fifo first */ 584 dst16 = (uint16_t *)(softc->rxbuffer); 585 *dst16++ = rawlen; 586 i = (RXHDR_LEN / 2) - 1; 587 while (i--) { 588 *dst16++ = R_REG(NULL, ®s->rcvfifodata); 589 } 590 591 /* read the frame */ 592 dst16 = (uint16_t *)(softc->rxbuffer + HWRXOFF); 593 i = length / 2; 594 while (i--) { 595 *dst16++ = R_REG(NULL, ®s->rcvfifodata); 596 } 597 598 /* Read the odd byte */ 599 if( length & 0x1 ) { 600 *dst16 = R_REG(NULL, ®s->rcvfifodata) & 0xFF; 601 } 602 603 /* Notify the hardware that we're done. */ 604 W_REG(NULL, ®s->rcvfifocontrol, RFC_DR ); 605 606 hdr = (bcmenetrxhdr_t *)(softc->rxbuffer); 607 ethhdr = (struct ether_header *)(softc->rxbuffer + HWRXOFF); 608 609#ifdef SWAP_ENDIAN 610 flags = SWAP16( hdr->flags ); 611#else 612 flags = hdr->flags; 613#endif 614 615 /* TODO -- Should we reset the chip here? */ 616 if( flags & (RXF_NO | RXF_RXER | RXF_CRC | RXF_OV) ) { 617 BCM4413INFO( "Packet recieve error (0x%X)\n", flags ); 618 buffer->buf_retlen = 0; 619 return -1; 620 } 621 622 /* 802.3 4.3.2: discard frames with inconsistent length field value */ 623#ifdef SWAP_ENDIAN 624 type = SWAP32( ethhdr->ether_type ); 625#else 626 type = ethhdr->ether_type; 627#endif 628 if( (type <= ETHER_MAX_DATA) && (type > (length - ETHER_HDR_LEN)) ) { 629 BCM4413INFO( "Inconsistent length field value.\n" ); 630 buffer->buf_retlen = 0; 631 return -1; 632 } 633 634 /* Strip off the CRC */ 635 length -= ETHER_CRC_LEN; 636 637 /* TODO -- This check shouldn't be necessary. */ 638 if( length >= DST_BUF_SIZE ) { 639 BCM4413INFO( "\nIncoming packet too big : length = %d\n", length ); 640 buffer->buf_retlen = 0; 641 return -1; 642 } 643 644 memcpy( buffer->buf_ptr, softc->rxbuffer + HWRXOFF, length ); 645 646 buffer->buf_retlen = length; 647 648 /* Check for any error conditions */ 649 if( R_REG(NULL, ®s->intstatus) & I_ERRORS ) { 650 chiperrors( regs, softc ); 651 } 652 653 BCM4413TRACE( "read exited\n" ); 654 655 return 0; 656} 657 658 659static int bcm4413_ether_inpstat( cfe_devctx_t * ctx, iocb_inpstat_t * inpstat ) 660{ 661 cfe_uint_t stat; 662 bcm4413_softc * softc = (bcm4413_softc *) ctx->dev_softc; 663 664 /* Check whenever a full frame is ready. */ 665 stat = (R_REG(NULL, &softc->regs->rcvfifocontrol) & RFC_FR) ? 1 : 0; 666 inpstat->inp_status = stat; 667 668 return 0; 669} 670 671 672static int bcm4413_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 673{ 674 uint16_t length; 675 uint16_t * src16; 676 bcm4413_softc * softc; 677 bcmenetregs_t * regs; 678 679 BCM4413TRACE( "write entered\n", ctx ); 680 681 softc = (bcm4413_softc *) ctx->dev_softc; 682 regs = softc->regs; 683 684#ifdef DEBUG 685 /* TODO -- Should we wait until the hardware _is_ ready? */ 686 if( !(R_REG(NULL, ®s->xmtfifocontrol) & XFC_FR) ) { 687 BCM4413ERROR( "4413 NOT READY TO SEND!\n" ); 688 return -1; 689 } 690#endif 691 692 /* Clear frameready */ 693 W_REG(NULL, ®s->xmtfifocontrol, XFC_FR ); 694 695 /* When writing 16 bit values, both 8-bit data bytes are valid. */ 696 W_REG(NULL, ®s->xmtfifocontrol, XFC_BOTH ); 697 698 length = (buffer->buf_length) & ~1; 699 700 /* SEND IT! */ 701 src16 = (uint16_t *)(buffer->buf_ptr); 702 length /= 2; 703 while( length-- ) { 704 W_REG(NULL, ®s->xmtfifodata, *src16++ ); 705 } 706 707 /* Write last odd byte. */ 708 if( buffer->buf_length & 1 ) { 709 W_REG(NULL, ®s->xmtfifocontrol, XFC_LO ); 710 W_REG(NULL, ®s->xmtfifodata, *src16 ); 711 } 712 713 /* Tell the hardware we're done. */ 714 W_REG(NULL, ®s->xmtfifocontrol, XFC_EF ); 715 716 /* Check for any error conditions */ 717 if( R_REG(NULL, ®s->intstatus) & I_ERRORS ) { 718 chiperrors( regs, softc ); 719 } 720 721 BCM4413TRACE( "write exited\n" ); 722 723 return 0; 724} 725 726 727static int bcm4413_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer) 728{ 729 int retval = 0; 730 bcm4413_softc * softc = ctx->dev_softc; 731 732 switch( (int)buffer->buf_ioctlcmd ) { 733 case IOCTL_ETHER_GETHWADDR: 734 BCM4413TRACE( "IOCTL_ETHER_GETHWADDR called.\n" ); 735 memcpy( buffer->buf_ptr, softc->hwaddr, sizeof(softc->hwaddr) ); 736 break; 737 case IOCTL_ETHER_SETHWADDR: 738 BCM4413TRACE( "IOCTL_ETHER_SETHWADDR called.\n" ); 739 bcm4413_writecam( softc->regs, (struct ether_addr *)buffer->buf_ptr, 0 ); 740 memcpy( softc->hwaddr, buffer->buf_ptr, sizeof(softc->hwaddr) ); 741 break; 742 default: 743 xprintf( "Invalid IOCTL to bcm4413_ether_ioctl.\n" ); 744 retval = -1; 745 } 746 747 return retval; 748} 749 750 751static int bcm4413_ether_close(cfe_devctx_t *ctx) 752{ 753 bcm4413_softc * softc = (bcm4413_softc *) ctx->dev_softc; 754 755 bcm4413_reset( softc->regs ); 756 757 KFREE( softc->rxbuffer ); 758 softc->rxbuffer = NULL; 759 760 KFREE( softc->txbuffer ); 761 softc->txbuffer = NULL; 762 763 return 0; 764} 765