> -----Original Message-----
> From: [EMAIL PROTECTED] [mailto:ecos-discuss-
> [EMAIL PROTECTED] On Behalf Of Lambrecht Jürgen
> Sent: zondag 1 juni 2008 1:22
> To: Andrew Lunn; I-Yanaslov
> Cc: [EMAIL PROTECTED]
> Subject: RE: [ECOS] bugs in AT91 Ethernet driver
> 
> Thanks for your replies.
> 
> > -----Original Message-----
> > From: [EMAIL PROTECTED] [mailto:ecos-discuss-
> > [EMAIL PROTECTED] On Behalf Of Andrew Lunn
> > Sent: zaterdag 31 mei 2008 14:04
> > To: I-Yanaslov
> > Cc: Andrew Lunn; [EMAIL PROTECTED]
> > Subject: Re: [ECOS] bugs in AT91 Ethernet driver
> >
> > On Sat, May 31, 2008 at 03:49:24PM +0400, I-Yanaslov wrote:
> > >
> > >> However, you are wrong about the TX buffers being on the heap. The
> > >> buffer is inside the at91_eth_priv_t structure. This is allocated
> at
> > >> the end of if_at91.c. It will be placed in the data segment.
> > >
> > > at91_eth_priv structure is contains only RX buffers, RX buffer
> > > descriptors and "TX buffer descriptors". No contains "TX buffers".
> > >
> > > at91_eth_send() shows " priv->tbd[priv->curr_tbd_idx].addr =
> > > sg_list[i].buf; " - no memory copy, only address assigment.
> > > But, sg_list[] it is mbuf, dynamically allocated in TCP/IP stack.
> >
> > Ah, OK. My error. That makes it more messy.
> >
> > How big is the SRAM on these ARM9 devices? 32K, 64K? If it is big
> > enough maybe we can move net_mbufs_area[] into the SRAM. Otherwise a
> > copy is needed for every packet to be transmitted.
> >
> The AT91SAM9620 has only 2 SRAMs of 4kB each.
> (The AT91SAM9621 has 160kB of SRAM, but no EMAC and LCD controller
> instead)
> So it will have to be the last option.
> To have a reliable driver, the fix is needed, but that (errata) is not
> why my TX does not work.
> The AT91SAM9620 errata is only valid at heavy network load (when there
> is RX and TX at the same time and then an SDRAM refresh or SDRAM bank
> opening or so). I only do a ping on a private network for test.
> And moreover, the Ethernet driver works in Redboot RAM (ok, not that
> well, 9% of the pings get lost).
> 
> I will further debug tomorrow...
In attachment ' if_at91_jtagram_ecos1.01.06_sg1TXsram1.txt ' with a log.
It was compiled with if_at91.c patched as below.
You can see that at startup a gratuitous ARP is sent out, and I receive the 
packet on my laptop with Wireshark.
The next TX (ARP reply as reply on RX of ARP request) is sent out by the TCP/IP 
stack, but does not leave the board as I don't see it in Wireshark.
It gets stuck somewhere. Maybe the driver is waiting on something, or maybe the 
TX DMA is blocked??

> And then copy every packet to SRAM before doing DMA...
> 
In attachment my patch.
It contains
- in at91_eth_send(): modification (#ifdef SRAM1_ORIGIN) to copy sg_list[i].buf 
first to internal SRAM, and only then do a DMA to the EMAC
- in at91_eth_recv(): bugfix described in previous mail
- general: I don't have a PHY attached but a switch. The MII is always up at 
100Mbps, so no need to use SMI to read the link status in the phy registers. So 
put '#ifdef PHY_PRESENT' around those parts of the code

I tested it with my AT91SAM9620-EK based board. And it works just as before 
(see above).

Kind regards,
Juergen
«¬}¹•Ñ}¥¹¥ÑuInit: mbinit(0x00000000)
[cyg_net_init] Init: cyg_net_init_devs(0x00000000)
Init device 'at91'
[cyg_net_init] Init: loopattach(0x00000000)
[cyg_net_init] Init: ifinit(0x00000000)
[cyg_net_init] Init: domaininit(0x00000000)
[cyg_net_init] Init: cyg_net_add_domain(0x200a71f8)
New domain internet at 0x00000000
[cyg_net_init] Init: cyg_net_add_domain(0x200a6ba8)
New domain route at 0x00000000
[cyg_net_init] Init: call_route_init(0x00000000)
[cyg_net_init] Done


Televic Echo-Test Application
Juergen Lambrecht, 1.09.11, built 21:45:42, Jun  1 2008

BOOTP[eth0] op: REPLY
       htype: Ethernet
        hlen: 6
        hops: 0
         xid: 0x0
        secs: 0
       flags: 0x0
       hw_addr: 00:0e:3d:01:03:00
     client IP: 10.0.54.249
         my IP: 10.0.54.249
     server IP: 10.0.56.4
    gateway IP: 10.0.127.254
  options:
        subnet mask: 255.255.0.0
       IP broadcast: 10.0.255.255
            gateway: 10.0.127.254
Sending 42 bytes
xmit 42 bytes at 0x200fd856 sg[1]                           //JL: I see this 
packet in Wireshark
200FD856: FF FF FF FF FF FF 00 0E  3D 01 03 00 08 06 00 01  |........=.......|
200FD866: 08 00 06 04 00 01 00 0E  3D 01 03 00 0A 00 36 F9  |........=.....6.|
200FD876: 00 00 00 00 00 00 0A 00  36 F9                    |........6.      |
at91_eth_control.702: key 110
[eth_drv_ioctl] Warning: Driver can't set multi-cast mode
at91_eth_control.702: key 110
[eth_drv_ioctl] Warning: Driver can't set multi-cast mode
at91_eth_control.702: key 110
[eth_drv_ioctl] Warning: Driver can't set multi-cast mode
End of initializations
rx 14 bytes at 20160afc sg[0]
20160AFC: FF FF FF FF FF FF 00 1D  09 B4 CA 6A 08 06        |...........j..  |
rx 50 bytes at 200fd82c sg[1]
200FD82C: 00 01 08 00 06 04 00 01  00 1D 09 B4 CA 6A 0A 00  |.............j..|
200FD83C: 38 31 00 00 00 00 00 00  0A 00 36 F9 00 00 00 00  |81........6.....|
200FD84C: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 DE 09  |................|
200FD85C: EC 66                                             |.f              |
Sending 42 bytes
xmit 42 bytes at 0x200fd7d6 sg[1]                           //JL: I DONT see 
this packet in Wireshark??
200FD7D6: FF FF FF FF FF FF 00 0E  3D 01 03 00 08 06 00 01  |........=.......|
200FD7E6: 08 00 06 04 00 01 00 0E  3D 01 03 00 0A 00 36 F9  |........=.....6.|
200FD7F6: 00 00 00 00 00 00 0A 00  36 F9                    |........6.      |
rx 14 bytes at 20160afc sg[0]
20160AFC: FF FF FF FF FF FF 00 1D  09 B4 CA 6A 08 06        |...........j..  |
rx 50 bytes at 200fd6ac sg[1]
200FD6AC: 00 01 08 00 06 04 00 01  00 1D 09 B4 CA 6A 0A 00  |.............j..|
200FD6BC: 38 31 00 00 00 00 00 00  0A 00 36 F9 00 00 00 00  |81........6.....|
200FD6CC: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 DE 09  |................|
200FD6DC: EC 66                                             |.f              |
.14 bytes at 20160afc sg[0]
20160AFC: FF FF FF FF FF FF 00 1D  09 B4 CA 6A 08 00        |...........j..  |
rx 244 bytes at 2011e7c8 sg[1]
2011E7C8: 45 00 00 F0 B3 BE 00 00  80 11 3A 0E 0A 00 38 31  |E.........:...81|
2011E7D8: 0A 00 FF FF 00 8A 00 8A  00 DC D3 B8 11 0E 81 14  |................|
2011E7E8: 0A 00 38 31 00 8A 00 C6  00 00 20 46 45 45 4D 46  |..81...... FEEMF|
2011E7F8: 47 43 4E 46 45 46 45 46  44 43 4E 45 4B 45 4D 44  |GCNFEFEFDCNEKEMD|
2011E808: 42 43 41 43 41 43 41 43  41 41 41 00 20 41 42 41  |BCACACACAAA. ABA|
2011E818: 43 46 50 46 50 45 4E 46  44 45 43 46 43 45 50 46  |CFPFPENFDECFCEPF|
2011E828: 48 46 44 45 46 46 50 46  50 41 43 41 42 00 FF 53  |HFDEFFPFPACAB..S|
2011E838: 4D 42 25 00 00 00 00 00  00 00 00 00 00 00 00 00  |MB%.............|
2011E848: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 11 00  |................|
2011E858: 00 2C 00 00 00 00 00 00  00 00 00 E8 03 00 00 00  |.,..............|
2011E868: 00 00 00 00 00 2C 00 56  00 03 00 01 00 01 00 02  |.....,.V........|
2011E878: 00 3D 00 5C 4D 41 49 4C  53 4C 4F 54 5C 42 52 4F  |.=.\MAILSLOT\BRO|
2011E888: 57 53 45 00 0C 00 E0 93  04 00 54 45 4C 45 56 49  |WSE.......TELEVI|
2011E898: 43 00 00 00 C8 35 11 00  00 10 03 0A 00 10 00 80  |C....5..........|
2011E8A8: 00 10 F8 7F 54 4C 56 2D  54 54 53 2D 4A 4C 31 00  |....TLV-TTS-JL1.|
2011E8B8: B9 81 0D 08                                       |....            |
--- F:\version_ecos\packages\devs\eth\arm\at91\current\src\if_at91.c    
2008-03-07 08:35:36.000000000 +-0200
+++ F:\ecos_ronetix\packages\devs\eth\arm\at91\current\src\if_at91.c    
2008-06-01 23:09:54.000000000 +-0200
@@ -64,13 +66,15 @@
 #include <cyg/infra/cyg_type.h>
 #include <cyg/infra/cyg_ass.h>
 #include <cyg/infra/diag.h>
 #include <cyg/io/eth/netdev.h>
 #include <cyg/io/eth/eth_drv.h>
 #include <cyg/io/eth/eth_drv_stats.h>
+#ifdef PHY_PRESENT
 #include <cyg/io/eth_phy.h>
+#endif
 #include <errno.h>
 #include <string.h>
 
 // Set up the level of debug output
 #if CYGPKG_DEVS_ETH_ARM_AT91_DEBUG_LEVEL > 0
    #define debug1_printf(args...) diag_printf(args)
@@ -165,13 +169,15 @@
 typedef struct at91_eth_priv_s 
 {
    cyg_uint32    intr_vector;
    char *esa_key;      // RedBoot 'key' for device ESA
    cyg_uint8 *enaddr;
    cyg_uint32 base;    // Base address of device
+#ifdef PHY_PRESENT
    eth_phy_access_t *phy;
+#endif
    rbd_t rbd[CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS];
    rb_t  rb[CYGNUM_DEVS_ETH_ARM_AT91_RX_BUFS];
    tbd_t tbd[CYGNUM_DEVS_ETH_ARM_AT91_TX_BUFS];
    unsigned long curr_tx_key;
    cyg_bool tx_busy;
    cyg_uint32 last_tbd_idx;
@@ -298,18 +304,19 @@
       CYG_FAIL("Unable to program MII clock");
    }
 
    HAL_WRITE_UINT32(AT91_EMAC + AT91_EMAC_NCFG, cfg);
 }
 
-
+#ifdef PHY_PRESENT
 ETH_PHY_REG_LEVEL_ACCESS_FUNS(at91_phy, 
                               at91_init_phy,
                               NULL,
                               at91_write_phy,
                               at91_read_phy);
-
+#endif
 //======================================================================
 // Receiver buffer handling
 
 // Initialize the receiver buffers and descriptors
 static void
 at91_rb_init(at91_eth_priv_t *priv)
@@ -482,13 +489,15 @@
 {
    struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
    at91_eth_priv_t *priv = (at91_eth_priv_t *)sc->driver_private;
    bool esa_ok = false;
    unsigned char enaddr[6] = { CYGPKG_DEVS_ETH_ARM_AT91_MACADDR};
    unsigned char enzero[6] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+#ifdef PHY_PRESENT
    unsigned short phy_state = 0;
+#endif
    cyg_uint32 ncfg = 0;
 
    debug1_printf("\nAT91_ETH: Initialising @ %x\n",priv->base);
 
    priv->tx_busy = false;
    priv->curr_tbd_idx = 0;
@@ -557,57 +566,64 @@
    // Setup the transmit descriptors
    at91_tb_init(priv);
 
    // And tell the EMAC where the first transmit buffer descriptor is
    HAL_WRITE_UINT32(priv->base + AT91_EMAC_TBQP, (cyg_uint32)priv->tbd);
 
+#ifdef PHY_PRESENT
    // Setup the PHY
    CYG_ASSERTC(priv->phy);
 
    at91_mdio_enable();
    if (!_eth_phy_init(priv->phy))
    {
       at91_mdio_disable();
+      debug2_printf("_eth_phy_init failed\n");
       return (false);
    }
 
    // Get the current mode and print it
    phy_state = _eth_phy_state(priv->phy);
+#endif
    at91_mdio_disable();
 
    HAL_READ_UINT32(priv->base + AT91_EMAC_NCFG,ncfg);
 
-
+#ifdef PHY_PRESENT
    if ((phy_state & ETH_PHY_STAT_LINK) != 0)
    {
       if (((phy_state & ETH_PHY_STAT_100MB) != 0))
       {
          debug1_printf("AT91_ETH: 100Mbyte/s");
+#endif
          ncfg |= AT91_EMAC_NCFG_SPD_100Mbps;
+#ifdef PHY_PRESENT
       }
       else
       {
          debug1_printf("AT91_ETH: 10Mbyte/s");
          ncfg &= ~(AT91_EMAC_NCFG_SPD_100Mbps);
       }
       if((phy_state & ETH_PHY_STAT_FDX))
       {
          debug1_printf(" Full Duplex\n");
+#endif
          ncfg |= AT91_EMAC_NCFG_FD;
+#ifdef PHY_PRESENT
       }
       else
       {
          debug1_printf(" Half Duplex\n");
          ncfg &= ~(AT91_EMAC_NCFG_FD);
       }
    }
    else
    {
       debug1_printf("AT91_ETH: No Link\n");
    }
-
+#endif
 
    //Setup the network configuration
    ncfg |= (AT91_EMAC_NCFG_RLCE);
 
    HAL_WRITE_UINT32(priv->base + AT91_EMAC_NCFG,ncfg);
 
@@ -721,20 +737,27 @@
 at91_eth_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len, 
               int total_len, unsigned long key)
 {
    at91_eth_priv_t *priv = (at91_eth_priv_t *)sc->driver_private;
    int i;
    cyg_uint32 sr;
-
+#ifdef SRAM1_ORIGIN /* define it in plf_io.h if present */
+   cyg_uint32 total_bytes = 0; /* position in SRAM1 */
+#endif
    priv->tx_busy = true;
 
    priv->last_tbd_idx = priv->curr_tbd_idx;
 
    for(i = 0;i<sg_len;i++)
    {
+#ifdef SRAM1_ORIGIN
+      memcpy((cyg_uint8 *)(SRAM1_ORIGIN+total_bytes), (cyg_uint8 
*)(sg_list[i].buf), sg_list[i].len);
+      priv->tbd[priv->curr_tbd_idx].addr = SRAM1_ORIGIN+total_bytes;
+#else
       priv->tbd[priv->curr_tbd_idx].addr = sg_list[i].buf;
+#endif
 
       sr = (sg_list[i].len & AT91_EMAC_TBD_SR_LEN_MASK);
       // Set the End Of Frame bit in the last descriptor
       if(i == (sg_len-1))
       {
          sr |= AT91_EMAC_TBD_SR_EOF;
@@ -747,12 +770,15 @@
       }
       else
       {
          priv->tbd[priv->curr_tbd_idx].sr = (sr | AT91_EMAC_TBD_SR_WRAP);
          priv->curr_tbd_idx = 0;
       }
+#ifdef SRAM1_ORIGIN
+      total_bytes += sg_list[i].len;
+#endif
    }
 
    // Store away the key for when the transmit has completed
    // and we need to tell the stack which transmit has completed.
    priv->curr_tx_key = key;
 
@@ -936,19 +962,22 @@
    cyg_uint32 total_bytes = 0;
 
 
 
    for(i = 0;i<sg_len;i++)
    {
+      bytes_in_list = 0; /* go to next list */
       while(bytes_in_list < sg_list[i].len)
       {
          bytes_needed_list = sg_list[i].len - bytes_in_list;
 
          if(priv->rbd[priv->curr_rbd_idx].sr & AT91_EMAC_RBD_SR_EOF)
          {
              bytes_in_buffer = 
                ((priv->rbd[priv->curr_rbd_idx].sr & AT91_EMAC_RBD_SR_LEN_MASK)
-                - total_bytes) - buffer_pos;
+                - total_bytes);
          }
          else
          {
             bytes_in_buffer = AT91_EMAC_RX_BUFF_SIZE - buffer_pos;
          }
 
@@ -1001,14 +1030,17 @@
    return(CYGNUM_HAL_INTERRUPT_EMAC);
 }
 
 at91_eth_priv_t at91_priv_data =
 {
    .intr_vector = CYGNUM_HAL_INTERRUPT_EMAC,
-   .base = AT91_EMAC,
+   .base = AT91_EMAC
+#ifdef PHY_PRESENT
+   ,
    .phy = &at91_phy
+#endif
 };
 
 ETH_DRV_SC(at91_sc,
            &at91_priv_data,       // Driver specific data
            "eth0",                // Name for this interface
            at91_eth_start,
-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

Reply via email to