4 Copyright (c) 2002 Broadcom Corporation
6 No portions of this material may be reproduced in any form without the
10 Irvine, California 92619
11 All information contained in this document is Broadcom Corporation
12 company private, proprietary, and trade secret.
16 //**************************************************************************
17 // File Name : bcm6352Enet.c
19 // Description: This is the CFE network driver for the BCM6352 Ethenet Switch
21 // Updates : 09/26/2001 jefchiao. Created.
22 // 05/21/2002 lat. Port to CFE.
23 //**************************************************************************
25 #define CARDNAME "BCM6352_ENET"
27 #define VER_STR "v" VERSION " " __DATE__ " " __TIME__
30 #include "lib_types.h"
31 #include "lib_malloc.h"
32 #include "lib_string.h"
33 #include "lib_printf.h"
36 #include "cfe_ioctl.h"
37 #include "cfe_device.h"
38 #include "cfe_devfuncs.h"
41 #include "dev_bcm635x_enet.h"
43 #include "dev_bcm63xx_flash.h"
46 extern cfe_driver_t flashdrv
;
47 extern void udelay(long us
);
48 extern NVRAM_DATA nvramData
;
51 static void bcm6352_enet_probe( cfe_driver_t
*drv
, unsigned long probe_a
,
52 unsigned long probe_b
, void *probe_ptr
);
53 static void ext_mii_check(void);
54 static void port_control(int portId
, int enable
);
55 static void init_arl(void);
56 static void init_mii(bcm6352enet_softc
*softc
);
57 static void init_dma(bcm6352enet_softc
*softc
);
58 static int bcm6352_init_dev(bcm6352enet_softc
*softc
);
59 int internal_open( bcm6352enet_softc
*softc
);
60 void write_mac_address( bcm6352enet_softc
*softc
);
61 static int bcm6352_enet_open(cfe_devctx_t
*ctx
);
62 static int bcm6352_enet_read( cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
);
63 static int bcm6352_enet_inpstat( cfe_devctx_t
*ctx
, iocb_inpstat_t
*inpstat
);
64 static int bcm6352_enet_write(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
65 static int bcm6352_enet_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
66 static int bcm6352_enet_close(cfe_devctx_t
*ctx
);
69 volatile uint32_t *swreg32
= (uint32_t *) ESWITCH_BASE
;
70 volatile uint16_t *swreg16
= (uint16_t *) ESWITCH_BASE
;
71 volatile unsigned char *swreg8
= (unsigned char *) ESWITCH_BASE
;
72 volatile BusBridge
*bridge
= (BusBridge
*) BB_BASE
;
74 const static cfe_devdisp_t bcm6352_enet_dispatch
=
86 const cfe_driver_t bcm6352_enet
=
91 &bcm6352_enet_dispatch
,
96 /* --------------------------------------------------------------------------
97 Name: bcm6352_enet_probe
98 Purpose: Initial call to this driver.
99 -------------------------------------------------------------------------- */
100 static void bcm6352_enet_probe( cfe_driver_t
*drv
, unsigned long probe_a
,
101 unsigned long probe_b
, void * probe_ptr
)
103 bcm6352enet_softc
*softc
;
106 softc
= (bcm6352enet_softc
*) KMALLOC( sizeof(bcm6352enet_softc
), 0 );
108 xprintf( "BCM6352 : Failed to allocate softc memory.\n" );
111 memset( softc
, 0, sizeof(bcm6352enet_softc
) );
113 if (internal_open( softc
) == -1)
114 xprintf("Failed initializing enet hardware\n");
117 cfe_attach( drv
, softc
, NULL
, descr
);
118 cfe_attach(&flashdrv
, softc
, NULL
, NULL
);
125 * ext_mii_check - checking external MII status, update MII port state override
126 * register if link up/down, duplex, or speed change.
128 static void ext_mii_check(void)
138 transtimer
= bridge
->status
;
139 bridge
->status
= transtimer
& ~0x3FF;
140 /* read auto-negotiation link partner ability */
141 miiaddr0a
= swreg16
[(PORT1_MII_dp
+ANLPA_d
)/2];
144 /* read auxiliary status summary */
145 miiaddr32
= swreg16
[(PORT1_MII_dp
+ASTSSUM_d
)/2];
148 /* read auxiliary control/status */
149 miiaddr30
= swreg16
[(PORT1_MII_dp
+ACTLSTS_d
)/2];
152 /* enable ISB abort timer */
153 transtimer
= bridge
->status
;
154 bridge
->status
= transtimer
| 0x3FF;
156 /* update link partner has pasue capability */
157 status
|= ((miiaddr0a
& 0x0400) != 0 ? 0x0008 : 0);
158 /* update current speed indication */
159 status
|= ((miiaddr32
& 0x0008) != 0 ? 0 : 0x0004);
160 /* update current link status */
161 status
|= ((miiaddr32
& 0x0004) != 0 ? 0x0001 : 0);
162 /* update current duplex indication */
163 status
|= ((miiaddr30
& 0x0001) != 0 ? 0x0002 : 0);
166 data16bit
= swreg16
[(CTLREG_dp
+MII_PSTS_d
)/2];
168 change
= (data16bit
^ status
) != 0 ? 1 : 0;
171 /* set MII port state override register for port 1 (external PHY) */
172 swreg16
[(CTLREG_dp
+MII_PSTS_d
)/2] = 0xfff0 | status
;
178 * port_control: enable/disable rx functions of the port at the MAC level
180 static void port_control(int portId
, int enable
)
182 unsigned char data8bit
;
197 * disable rx function.
198 * if disable tx function, it has potential race condition if DMA still
199 * has frames need to sending out and it will block the DMA.
201 data8bit
= swreg8
[(CTLREG_dp
+ addr
)];
203 data8bit
&= ~RX_DISABLE
; // clear RX_DISABLE bit
205 data8bit
|= RX_DISABLE
; // set RX_DISABLE bit
206 swreg8
[(CTLREG_dp
+ addr
)] = data8bit
;
211 * init_arl: initialise ARL table memory
217 * There are 1K entries in the arl table. However, they are not
218 * physically located consecutively. Each arl entry is a 64-bit
219 * word. It takes 10 bits to address 1K entries. The addressing
220 * scheme is as follows :
222 * Logical address : addr[9:0]
224 * Physical address : { addr[9:5], 3'b111, addr[4:0] }
226 * Please note that the addresses above are 64-bit word addresses,
227 * not byte addresses.
229 * Pattern for initializing table is:
231 * swreg32[(MEM_dp+MEMDAT_d)/4] = 0x0; (make DAT = 0)
232 * swreg32[(MEM_dp+MEMDAT_d+4)/4] = 0x0;
234 * swreg32[(MEM_dp+MEMADR_d)/4] = 0x800e0;
235 * swreg32[(MEM_dp+MEMADR_d)/4] = 0x800e1;
237 * swreg32[(MEM_dp+MEMADR_d)/4] = 0x800fe;
238 * swreg32[(MEM_dp+MEMADR_d)/4] = 0x800ff; (32 entries )
240 * swreg32[(MEM_dp+MEMADR_d)/4] = 0x801e0;
241 * swreg32[(MEM_dp+MEMADR_d)/4] = 0x801e1;
243 * swreg32[(MEM_dp+MEMADR_d)/4] = 0x801fe;
244 * swreg32[(MEM_dp+MEMADR_d)/4] = 0x801ff; (another 32 entries)
247 static void init_arl(void)
252 swreg32
[(MEM_dp
+MEMDAT_d
)/4] = 0x0; /*make DAT = 0*/
253 swreg32
[(MEM_dp
+MEMDAT_d
)/4 + 1] = 0x0;
255 for ( bits_9_5
= 0x0; bits_9_5
<= 0x1f; bits_9_5
++ ) {
256 for ( bits_4_0
= 0x0; bits_4_0
<= 0x1f; bits_4_0
++ ) {
257 swreg32
[(MEM_dp
+MEMADR_d
)/4] = 0x800e0 | bits_9_5
<< 8 | bits_4_0
;
264 * init_mii: Initializes the Ethernet Switch control registers
266 static void init_mii(bcm6352enet_softc
*softc
)
271 /* initialize the memeory */
272 init_arl(); /* clear ARL table */
274 /* set up SMP as the manamgement port */
275 swreg32
[(MNGMODE_dp
+GMNGCFG_d
)/4] = SMP_PORT
;
276 swreg32
[(MNGMODE_dp
+MNGPID_d
)/4] = SMP_PORT_ID
;
278 /* enable software forwarding */
279 if (test_bit(0, &softc
->dualMacMode
)) {
280 swreg32
[(CTLREG_dp
+TH_PCTL0_d
)/4] = FORWARDING_STATE
| RX_DISABLE
;
281 swreg32
[(CTLREG_dp
+TH_PCTL1_d
)/4] = FORWARDING_STATE
| RX_DISABLE
;
283 swreg32
[(CTLREG_dp
+TH_PCTL0_d
)/4] = FORWARDING_STATE
;
284 swreg32
[(CTLREG_dp
+TH_PCTL1_d
)/4] = FORWARDING_STATE
;
286 swreg32
[(CTLREG_dp
+SWMODE_d
)/4] = SW_FWDG_EN
|MANAGED_MODE
;
288 /* set the MIB autocast header length */
289 swreg32
[(MIBACST_dp
+ACSTHDLT_d
)/4] = 0x5555;
291 /* enable broadcast packets */
292 swreg32
[(CTLREG_dp
+SMP_CTL_d
) /4] = 0x04;
294 /* correct the default congestion registers to allow 10BT mode
295 * (the defaults will be fixed in B0) */
296 swreg16
[(CNGMREG_dp
+ 0x02) /2] = 0x0408;
297 swreg16
[(CNGMREG_dp
+ 0x04) /2] = 0x000D;
298 swreg16
[(CNGMREG_dp
+ 0x06) /2] = 0x070A;
299 swreg16
[(CNGMREG_dp
+ 0x08) /2] = 0x000D;
300 swreg16
[(CNGMREG_dp
+ 0x0e) /2] = 0x0C12;
301 swreg16
[(CNGMREG_dp
+ 0x10) /2] = 0x001D;
303 // disable ISB abort timer for MII port 1 access
304 // from/to external Ethernet PHY, the transaction will
305 // terminate prematurely due to an early timeout.
306 transtimer
= bridge
->status
;
307 bridge
->status
= transtimer
& ~0x3FF;
308 transtimer
= bridge
->status
;
310 // set MII Auxiliary Mode 2 register for port 1 (external PHY)
311 // set Activity/Link LED Mode bit for external PHY LED goes active
312 // upon acquiring link and pulses during receive or transmit activity
313 data16bit
= swreg16
[(PORT1_MII_dp
+AMODE2_d
)/2];
316 swreg16
[(PORT1_MII_dp
+AMODE2_d
)/2] = data16bit
;
319 /* advertise pause capability on MII port 1 */
320 data16bit
= swreg16
[(PORT1_MII_dp
+ANADV_d
)/2];
323 swreg16
[(PORT1_MII_dp
+ANADV_d
)/2] = data16bit
;
326 /* enable HP Auto-MDIX on MII port 1 */
327 data16bit
= swreg16
[(PORT1_MII_dp
+AEGSTS_d
)/2];
328 data16bit
&= ~0x0800;
330 swreg16
[(PORT1_MII_dp
+AEGSTS_d
)/2] = data16bit
;
333 // enable ISB abort timer
334 transtimer
= bridge
->status
;
335 bridge
->status
= transtimer
| 0x3FF;
336 transtimer
= bridge
->status
;
338 * set MII port state override register for port 1 (external PHY)
339 * set full duplex and 100Mbs (bit 2: 0 for 100Mbs, 1 for 10Mbs)
341 swreg16
[(CTLREG_dp
+MII_PSTS_d
)/2] = 0xfffb;
346 * init_dma: Initialize DMA control register
348 static void init_dma(bcm6352enet_softc
*softc
)
350 volatile DmaChannel
*txDma
= softc
->txDma
;
351 volatile DmaChannel
*rxDma
= softc
->rxDma
;
354 txDma
->cfg
= 0; /* initialize first (will enable later) */
355 txDma
->maxBurst
= DMA_MAX_BURST_LENGTH
;
356 txDma
->intMask
= 0; /* mask all ints */
357 txDma
->intStat
= DMA_DONE
|DMA_NO_DESC
|DMA_BUFF_DONE
;
358 txDma
->startAddr
= (uint32_t) K1_TO_PHYS((uint32_t)softc
->txBufPtr
);
361 rxDma
->cfg
= 0; // initialize first (will enable later)
362 rxDma
->maxBurst
= DMA_MAX_BURST_LENGTH
;
363 rxDma
->startAddr
= (uint32_t)K1_TO_PHYS((uint32_t)softc
->rxFirstBdPtr
);
364 rxDma
->length
= softc
->nrRxBds
;
365 rxDma
->fcThreshold
= 0;
367 rxDma
->intMask
= 0; /* mask all ints */
368 /* clr any pending interrupts on channel */
369 rxDma
->intStat
= DMA_DONE
|DMA_NO_DESC
|DMA_BUFF_DONE
;
370 /* set to interrupt on packet complete and no descriptor available */
372 /* configure DMA channels and enable Rx */
373 rxDma
->cfg
= DMA_CHAINING
|DMA_WRAP_EN
;
378 * bcm6352_init_dev: initialize Ethernet Switch device,
379 * allocate Tx/Rx buffer descriptors pool, Tx control block pool.
381 static int bcm6352_init_dev(bcm6352enet_softc
*softc
)
384 unsigned char *p
= NULL
;
386 /* make sure emac clock is on */
387 INTC
->blkEnables
|= (ESWITCH_CLK_EN
| EPHY_CLK_EN
);
389 /* setup buffer/pointer relationships here */
390 softc
->nrRxBds
= NR_RX_BDS
;
391 softc
->rxBufLen
= ENET_MAX_MTU_SIZE
;
393 /* init rx/tx dma channels */
394 softc
->dmaChannels
= (DmaChannel
*)(DMA_BASE
);
395 softc
->rxDma
= &softc
->dmaChannels
[EMAC_RX_CHAN
];
396 softc
->txDma
= &softc
->dmaChannels
[EMAC_TX_CHAN
];
398 p
= (unsigned char *) (((uint32_t) softc
->txBuf
+ 0x10) & ~0x0f);
399 softc
->txBufPtr
= (unsigned char *)K0_TO_K1((uint32_t) p
);
401 p
= (unsigned char *) (((uint32_t) softc
->rxMem
+ 0x10) & ~0x0f);
402 softc
->rxBds
= (DmaDesc
*)K0_TO_K1((uint32_t) p
);
403 p
+= softc
->nrRxBds
* sizeof(DmaDesc
);
404 softc
->rxBuffers
= (unsigned char *) K0_TO_PHYS((uint32_t) p
);
406 /* initialize rx ring pointer variables. */
407 softc
->rxBdAssignPtr
= softc
->rxBdReadPtr
= softc
->rxBds
;
408 softc
->rxFirstBdPtr
= softc
->rxBds
;
409 softc
->rxLastBdPtr
= softc
->rxFirstBdPtr
+ softc
->nrRxBds
- 1;
411 /* init the receive buffer descriptor ring */
412 for (i
= 0, j
= (unsigned long) softc
->rxBuffers
; i
< softc
->nrRxBds
;
413 i
++, j
+= softc
->rxBufLen
)
415 (softc
->rxFirstBdPtr
+ i
)->length
= softc
->rxBufLen
;
416 (softc
->rxFirstBdPtr
+ i
)->address
= j
;
417 (softc
->rxFirstBdPtr
+ i
)->status
= DMA_OWN
;
419 softc
->rxLastBdPtr
->status
= DMA_OWN
| DMA_WRAP
;
421 /* init dma registers */
424 /* init switch control registers */
427 softc
->rxDma
->cfg
|= DMA_ENABLE
;
429 /* if we reach this point, we've init'ed successfully */
435 * internal_open - initialize Ethernet device
437 int internal_open( bcm6352enet_softc
*softc
)
441 unsigned char macAddr
[ETH_ALEN
];
444 /* figure out which chip we're running on */
445 softc
->chipId
= (INTC
->RevID
& 0xFFFF0000) >> 16;
446 softc
->chipRev
= (INTC
->RevID
& 0xFF);
448 /* print the ChipID and module version info */
449 printf("Broadcom BCM%X%X Ethernet Network Device ",
450 softc
->chipId
, softc
->chipRev
);
451 printf(VER_STR
"\n");
453 clear_bit(0, &softc
->dualMacMode
);
455 /* read NVRam setting on route mode or switch mode */
456 dualMacMode
= nvramData
.ulEnetModeFlag
;
458 if (dualMacMode
== 1)
459 set_bit(0, &softc
->dualMacMode
);
461 printf("bcm6352Enet configure as %s mode\n",
462 softc
->dualMacMode
? "MAC Isolation" : "Switching");
464 if( (status
= bcm6352_init_dev(softc
)) == 0 )
466 /* Read first MAC address. Only use first MAC even if dual MAC is
470 memcpy(macAddr
, nvramData
.ucaBaseMacAddr
, sizeof(macAddr
));
472 if( macAddr
[0] == 0xff )
473 memcpy( macAddr
, "\x00\x10\x18\x00\x00\x01", 6 );
475 /* fill in the MAC address */
476 for (i
= 0; i
< 6; i
++)
477 softc
->macAddr
[i
] = macAddr
[i
];
479 printf( "MAC Address: %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
480 macAddr
[0], macAddr
[1], macAddr
[2], macAddr
[3], macAddr
[4],
481 macAddr
[5], macAddr
[6], macAddr
[7] );
483 write_mac_address(softc
);
491 * write_mac_address: store MAC address into ARL table
493 * NOTE: THE MAC ADDRESS MUST BE NIBBLE-SWAPPED AND BIT-FLIPPED FOR THE
496 void write_mac_address( bcm6352enet_softc
*softc
)
498 unsigned char data8bit
;
502 if (test_bit(0, &softc
->dualMacMode
)) {
505 /* set to dual mac mode if in single mac mode*/
506 if (!test_and_set_bit(1, &softc
->dualMacMode
)) {
507 /* set secure source port mask */
508 /* bit mask identifies port 0 and port 1 initiates a secure VPN session */
509 swreg16
[(ARLCTL_dp
+ SEC_SPMSK_d
) /2] = 0x0003;
510 /* set secure destination port mask */
512 *bit mask identifies SMP port which is designated as
513 * the secure destination
515 swreg16
[(ARLCTL_dp
+ SEC_DPMSK_d
) /2] = 0x0400;
517 /* disable unicast packets */
519 * if RX-UCST_EN bit enable, it will only receive unknown unicast.
520 * To receive known unicast, it should set MIRROR_ENABLE and
521 * IN_MIRROR_FILTER, or MULTIPORT VECTOR/ADDRESS registers
523 data8bit
= swreg8
[(CTLREG_dp
+ SMP_CTL_d
)];
524 data8bit
&= ~0x10; // disable RX_UCST_EN bit
525 swreg8
[(CTLREG_dp
+ SMP_CTL_d
)] = data8bit
;
527 /* Enable Multiport Address */
528 swreg8
[(ARLCTL_dp
+ GARLCFG_d
)] = 0x10;
530 /* Set Multiport Vector 1 to port 10 */
531 swreg16
[(ARLCTL_dp
+ PORTVEC1_d
)/2] = 0x0400;
533 /* Set Multiport Vector 2 to port 10 */
534 swreg16
[(ARLCTL_dp
+ PORTVEC2_d
)/2] = 0x0400;
537 /* Only set first MAC address */
539 addr
= softc
->macAddr
;
540 swreg32
[(ARLCTL_dp
+j
)/4] =
541 ((*(uint16_t *)(addr
+2))<<16) | *(uint16_t *)(addr
+4);
542 swreg16
[(ARLCTL_dp
+j
+4)/2] = *(uint16_t *)addr
;
545 unsigned char tempAddress
[ETH_ALEN
];
546 unsigned char flippedAddress
[ETH_ALEN
];
548 memset(flippedAddress
, 0x00, ETH_ALEN
);
549 /* set to single mac mode if in dual mac mode */
550 if (test_and_clear_bit(1, &softc
->dualMacMode
)) {
551 /* secure source port mask */
552 swreg16
[(ARLCTL_dp
+ SEC_SPMSK_d
) /2] = 0x0000;
553 /* secure destination port mask */
554 swreg16
[(ARLCTL_dp
+ SEC_DPMSK_d
) /2] = 0x0000;
556 /* enable unicast packets */
557 data8bit
= swreg8
[(CTLREG_dp
+ SMP_CTL_d
)];
558 data8bit
|= 0x10; // enable RX_UCST_EN bit
559 swreg8
[(CTLREG_dp
+ SMP_CTL_d
)] = data8bit
;
561 /* disable multiport address */
562 swreg8
[(ARLCTL_dp
+ GARLCFG_d
)] = 0x00;
565 memcpy(tempAddress
, softc
->macAddr
, ETH_ALEN
);
566 /* nibble-swap and bit-flip */
571 flippedAddress
[i
] |= tempAddress
[i
] & 0x01;
572 flippedAddress
[i
] <<= 1;
573 tempAddress
[i
] >>= 1;
575 flippedAddress
[i
] |= tempAddress
[i
] & 0x01;
578 /* storing to ARL table */
579 swreg32
[(ARLACCS_dp
+ARLA_ENTRY0_d
)/4] =
580 ((*(uint16_t *)&flippedAddress
[2])<<16) | *(uint16_t *)&flippedAddress
[4];
581 swreg32
[(ARLACCS_dp
+ARLA_ENTRY0_d
+4)/4] =
582 0xc0000000 | *(uint16_t *)&flippedAddress
[0] | (MANAGEMENT_PORT
<< 16);
583 swreg32
[(ARLACCS_dp
+ARLA_MAC_d
)/4] =
584 ((*(uint16_t *)&flippedAddress
[2])<<16) | *(uint16_t *)&flippedAddress
[4];
585 swreg32
[(ARLACCS_dp
+ARLA_MAC_d
+4)/4] = *(uint16_t *)&flippedAddress
[0];
586 swreg32
[(ARLACCS_dp
+ARLA_RWCTL_d
)/4] = 0x80;
591 /* --------------------------------------------------------------------------
592 Name: bcm6352_enet_open
593 Purpose: CFE driver open entry point.
594 -------------------------------------------------------------------------- */
595 static int bcm6352_enet_open(cfe_devctx_t
*ctx
)
597 bcm6352enet_softc
*softc
= (bcm6352enet_softc
*) ctx
->dev_softc
;
599 if ((softc
->chipId
== 0x6352) && (softc
->chipRev
== 0xa1))
602 if (test_bit(0, &softc
->dualMacMode
))
609 /* --------------------------------------------------------------------------
610 Name: bcm6352_enet_read
611 Purpose: Returns a recevied data buffer.
612 -------------------------------------------------------------------------- */
613 static int bcm6352_enet_read( cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
)
616 unsigned char *dstptr
;
617 unsigned char *srcptr
;
618 volatile DmaDesc
*CurrentBdPtr
;
619 bcm6352enet_softc
*softc
= (bcm6352enet_softc
*) ctx
->dev_softc
;
621 /* ============================= ASSERTIONS ============================= */
624 xprintf( "No context\n" );
628 if( buffer
== NULL
) {
629 xprintf( "No dst buffer\n" );
633 if( buffer
->buf_length
!= ENET_MAX_BUF_SIZE
) {
634 xprintf( "dst buffer too small.\n" );
635 xprintf( "actual size is %d\n", buffer
->buf_length
);
639 if( softc
== NULL
) {
640 xprintf( "softc has not been initialized.\n" );
644 /* ====================================================================== */
646 dstptr
= buffer
->buf_ptr
;
647 CurrentBdPtr
= softc
->rxBdReadPtr
;
649 if( (CurrentBdPtr
->status
& DMA_OWN
) == 1 )
652 srcptr
= (unsigned char *)( PHYS_TO_K1(CurrentBdPtr
->address
) );
653 memcpy( dstptr
, srcptr
, ETH_ALEN
* 2 );
654 dstptr
+= ETH_ALEN
* 2;
655 memcpy( dstptr
, srcptr
+ HEDR_LEN
, CurrentBdPtr
->length
- HEDR_LEN
- 8 );
657 /* length - header difference - 2 CRCs */
658 buffer
->buf_retlen
= CurrentBdPtr
->length
- 6 - 8;
660 CurrentBdPtr
->length
= ENET_MAX_MTU_SIZE
;
661 CurrentBdPtr
->status
&= DMA_WRAP
;
662 CurrentBdPtr
->status
|= DMA_OWN
;
664 IncRxBDptr(CurrentBdPtr
, softc
);
665 softc
->rxBdReadPtr
= CurrentBdPtr
;
667 rxEvents
= softc
->rxDma
->intStat
;
668 softc
->rxDma
->intStat
= rxEvents
;
670 softc
->rxDma
->cfg
= DMA_ENABLE
| DMA_CHAINING
| DMA_WRAP_EN
;
676 /* --------------------------------------------------------------------------
677 Name: bcm6352_enet_inpstat
678 Purpose: Indicates if data has been received.
679 -------------------------------------------------------------------------- */
680 static int bcm6352_enet_inpstat( cfe_devctx_t
*ctx
, iocb_inpstat_t
*inpstat
)
682 bcm6352enet_softc
*softc
;
683 volatile DmaDesc
*CurrentBdPtr
;
685 /* ============================= ASSERTIONS ============================= */
688 xprintf( "No context\n" );
692 if( inpstat
== NULL
) {
693 xprintf( "No inpstat buffer\n" );
697 softc
= (bcm6352enet_softc
*)ctx
->dev_softc
;
698 if( softc
== NULL
) {
699 xprintf( "softc has not been initialized.\n" );
703 /* ====================================================================== */
706 CurrentBdPtr
= softc
->rxBdReadPtr
;
708 /* inp_status == 1 -> data available */
709 inpstat
->inp_status
= (CurrentBdPtr
->status
& DMA_OWN
) ? 0 : 1;
715 /* --------------------------------------------------------------------------
716 Name: bcm6352_enet_write
717 Purpose: Sends a data buffer.
718 -------------------------------------------------------------------------- */
719 static int bcm6352_enet_write(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
723 unsigned char *dstptr
;
724 unsigned char *srcptr
;
725 bcm6352enet_softc
*softc
= (bcm6352enet_softc
*) ctx
->dev_softc
;
726 volatile DmaChannel
*txDma
= softc
->txDma
;
728 /* ============================= ASSERTIONS ============================= */
731 xprintf( "No context\n" );
735 if( buffer
== NULL
) {
736 xprintf( "No dst buffer\n" );
740 if( buffer
->buf_length
> ENET_MAX_BUF_SIZE
) {
741 xprintf( "src buffer too large.\n" );
742 xprintf( "size is %d\n", buffer
->buf_length
);
746 if( softc
== NULL
) {
747 xprintf( "softc has not been initialized.\n" );
751 /* ====================================================================== */
754 /******** Convert header to Broadcom's special header format. ********/
755 dstptr
= softc
->txBufPtr
;
756 srcptr
= buffer
->buf_ptr
;
757 srclen
= buffer
->buf_length
;
759 memcpy( dstptr
, srcptr
, ETH_ALEN
* 2 );
760 dstptr
+= ETH_ALEN
* 2;
761 srcptr
+= ETH_ALEN
* 2;
763 *((uint16_t *)dstptr
) = BRCM_TYPE
;
766 if( srclen
< 60 - 6 - 8 ) {
767 *((uint16_t *)dstptr
) = (uint16_t)60;
769 *((uint16_t *)dstptr
) = (uint16_t)(srclen
+ 6 + 8);
773 *((uint16_t *)dstptr
) = (uint16_t)MANAGEMENT_PORT
;
776 copycount
= srclen
- ETH_ALEN
* 2;
777 memcpy( dstptr
, srcptr
, copycount
);
781 memset( dstptr
, 0, 60 - srclen
);
784 txDma
->length
= srclen
+ 6;
787 /* Set status of DMA buffer to be transmitted. */
788 txDma
->bufStat
= DMA_SOP
| DMA_EOP
| DMA_APPEND_CRC
| DMA_OWN
;
790 /* Enable DMA for this channel. */
791 softc
->txDma
->cfg
|= DMA_ENABLE
;
793 /* poll the dma status until done. */
794 while( (txDma
->bufStat
& DMA_OWN
) == 0 )
802 /* --------------------------------------------------------------------------
803 Name: bcm6352_enet_ioctl
804 Purpose: I/O Control function.
805 -------------------------------------------------------------------------- */
806 static int bcm6352_enet_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
808 bcm6352enet_softc
*softc
= (bcm6352enet_softc
*) ctx
->dev_softc
;
811 switch( (int)buffer
->buf_ioctlcmd
) {
812 case IOCTL_ETHER_GETHWADDR
:
813 memcpy( buffer
->buf_ptr
, softc
->macAddr
, sizeof(softc
->macAddr
) );
815 case IOCTL_ETHER_SETHWADDR
:
816 memcpy( softc
->macAddr
, buffer
->buf_ptr
, sizeof(softc
->macAddr
) );
817 write_mac_address( softc
);
819 case IOCTL_ETHER_GETSPEED
:
820 xprintf( "BCM6352 : GETSPEED not implemented.\n" );
823 case IOCTL_ETHER_SETSPEED
:
824 xprintf( "BCM6352 : SETSPEED not implemented.\n" );
827 case IOCTL_ETHER_GETLINK
:
828 xprintf( "BCM6352 : GETLINK not implemented.\n" );
831 case IOCTL_ETHER_GETLOOPBACK
:
832 xprintf( "BCM6352 : GETLOOPBACK not implemented.\n" );
835 case IOCTL_ETHER_SETLOOPBACK
:
836 xprintf( "BCM6352 : SETLOOPBACK not implemented.\n" );
840 xprintf( "Invalid IOCTL to bcm6352_enet_ioctl.\n" );
848 /* --------------------------------------------------------------------------
849 Name: bcm6352_enet_close
850 Purpose: Uninitialize.
851 -------------------------------------------------------------------------- */
852 static int bcm6352_enet_close(cfe_devctx_t
*ctx
)
854 bcm6352enet_softc
*softc
= (bcm6352enet_softc
*) ctx
->dev_softc
;
857 printf( "Closing Ethernet.\n" );
859 if (test_bit(0, &softc
->dualMacMode
))
862 sts
= softc
->rxDma
->intStat
;
863 softc
->rxDma
->intStat
= sts
;
864 softc
->rxDma
->intMask
= 0;
865 softc
->rxDma
->cfg
= 0;
867 sts
= softc
->txDma
->intStat
;
868 softc
->txDma
->intStat
= sts
;
869 softc
->txDma
->intMask
= 0;
870 softc
->txDma
->cfg
= 0;