This is the mail archive of the ecos-discuss@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: LAN9218 driver porting problem


On 02/13/2010 10:16 PM, m mariga wrote:
> Hello,
> 
> Thank you,Gary,for your reply.
> But I am sorry I sill am not clear.
> I cannot get clear relations between cpd->rxpacket,len,and sg_len.What determines sg_len ?
> 
>> From your reply I infered.
> When I calls (sc->funs->eth_drv->recv)(sc, len) in lan91cxx_RxEvent(),
> len determins sg_len. Is that so ? (Question remains why sg_len=2?)
> 
> If len determins sg_len, then question arises.
> LAN91C111 calculate len of ONE block of DATA_FIFO,
> but as I said in LAN9218,when entered xxxx_RxEvent(),there are possibilities that several data in RX_Status_FIFO had been written that means recv_Data are several blocks in 
> RX_Data_FIFO.
> In that case how I caluculate len ? Do I sum len all blocks ?
> 
> Allow me to quote your flow.
>> Device generates interrupt
>> lan91cxx_RxEvent() runs, determines how many bytes are in the packet
> -----------------------------------------------
> here,if several data in RX_Status_FIFO had been written,should I sum len all blocks,
> and hand it to (sc->funs->eth_drv->recv) ? What value should I set cpd->rxpacket ?
> -----------------------------------------------
>> (sc->funs->eth_drv->recv)(sc, len) tells the network layer
>> ... time passes - maybe a lot of time - until the network input
>> thread has time/space to read the packet
>> lan91cxx_recv() is called from the network input thread
>> for each element in 'sg' (based on 'sg_len'), move the next
>> sg[n].len bytes from the device buffer into sg[n].buf
> -----------------------------------------------
> here,how should I gather recv_Data into sg[n].buf ?
> Isn't there no mismatch among hardware RX_Status_FIFO written counts and sg_len ?
> Could I rely on only sg_len ?
> -----------------------------------------------
> 
> I appreciate your help.

Please read the documentation - it explains this pretty well.

The assumption is that (sc->funs->eth_drv->recv)() is called once per complete
input packet.  Surely your hardware tells you when this has happened.  You
simply need to figure out from the hardware how many _bytes_ are in the packet.
The system will then allocate internal buffers for you to put the data into.
This is what is called the Scatter-Gather list.

sg_len is the number of Scatter Gather buffers allocated to hold your packet.
Each buffer in the SG list holds part of the packet.  It's up to your code
to move it from the device (FIFO) into the SG buffer.  e.g.
  for (i=0;  i < sg_len;  i++) {
    move next sg[i].len bytes from FIFO to sg[i].buf
  }

>> On 02/12/2010 06:10 PM, m mariga wrote:
>>> Hello,
>>>
>>> In danger of calling off using eCos,
>>> again I implore you to lend me your knowledge.
>>> I am still studying your LAN91c111 driver.
>>> I am stuck in fatham of it. Please help me.
>>>
>>> I tried to dump cpd->rxpacket,len,sg_len variables in lan91cxx_RxEvent,and sg_len in lan91cxx_recv like below.
>>> And run nc_test_slave() test program. The result dropped me deeper into the fatham.
>>>
>>> lan91cxx_RxEvent(struct eth_drv_sc *sc)
>>> {
>>> |
>>> stat = get_reg(sc, LAN91CXX_FIFO_PORTS);
>>> // There is an Rx Packet ready
>>> cpd->rxpacket = 0xff & (stat >> 8);
>>> diag_printf("rxpacket=%x\n",cpd->rxpacket);
>>> |
>>> stat = get_data_short(sc);
>>> len = get_data_short(sc);
>>> len = len - 6; // minus header/footer words
>>> diag_printf("len=%x\n",len);
>>> (sc->funs->eth_drv->recv)(sc, len);
>>> }
>>>
>>> lan91cxx_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
>>> {
>>> |
>>> diag_printf("sg_len=%x\n",sg_len);
>>> }
>>>
>>> Here is part of the result.
>>> ---
>>> connection from 172.16.1.28.1226
>>> rxpacket=0
>>> len=5ea
>>> sg_len=2
>>> rxpacket=1
>>> len=5ea
>>> sg_len=2
>>> rxpacket=2
>>> len=5ea
>>> sg_len=2
>>> rxpacket=0
>>> len=5ea
>>> sg_len=2
>>> rxpacket=1
>>> len=5ea
>>> sg_len=2
>>> rxpacket=2
>>> len=5a
>>> sg_len=2
>>> rxpacket=1
>>> len=3c
>>> sg_len=2
>>> rxpacket=1
>>> len=3c
>>> sg_len=2
>>> rxpacket=1
>>> len=3c
>>> sg_len=2
>>> rxpacket=0
>>> len=3c
>>> sg_len=2
>>> rxpacket=1
>>> len=5ea
>>> sg_len=2
>>> rxpacket=0
>>> len=5ea
>>> sg_len=2
>>> rxpacket=2
>>> len=5ea
>>> sg_len=2
>>> rxpacket=3
>>> len=5ea
>>> sg_len=2
>>> rxpacket=1
>>> len=5a
>>> sg_len=2
>>> rxpacket=0
>>> len=5ea
>>> sg_len=2
>>> rxpacket=0
>>> len=5ea
>>> sg_len=2
>>> rxpacket=1
>>> len=5ea
>>> sg_len=2
>>> ---
>>>
>>> My question is,why sg_len is always 2 in spite of len being different.
>>> I know it is too difficult for me to understand your Scatter-Gather or something,but I need to make it work with LAN9218.
>>>
>>> Your LAN91c111 recv routine uses sg_len in whle loop and gather data into sg_list from DATA_FIFO.
>>>
>>> LAN9118/9218 has RX_Status_FIFO,RX_Data_FIFO seperately. RX_Status_FIFO tells packet length.
>>> We know packet number from calculating data count written in RX_Status_FIFO.
>>> I consulted LAN9118 SMSC Linux sample driver.
>>> Its recv routine is much easier to understand.
>>> Its operation like below.
>>>
>>> ------------> |
>>> | <While RX_Status_FIFO!=0>
>>> | |
>>> | alloc new packet to skb
>>> | //update counters
>>> | privateData->stats.rx_packets++;
>>> | |
>>> | copy data into new skb packet from RX_Data_FIFO
>>> | |
>>> --------------
>>>
>>> I rather I would prefer to this, instead of using enigmatic sg_len to receive data from FIFO.
>>> In xxx_recv routine,if I ignored sg_len and I coded like SMSC Sample(of course I use sg_list[i].buf instead of skb),do you think will it work properly(or permissably) ?
>>> What if there are mismatches between sg_len and data counts written in RX_Status_FIFO ?
>>> Please enlighten me.
>>
>> The parameter 'sg_len' indicates how many elements are present
>> in the sg_list 'sg'. Looking at 'sg', you'll see that it's
>> and array of scatter gather elements which look like this:
>> struct eth_drv_sg {
>> CYG_ADDRESS buf;
>> CYG_ADDRWORD len;
>> };
>>
>> What your function lan91cxx_recv() should do is to move the
>> data from the device, utilizing the sg list structure. The
>> higher level network code allocates this based on the callback
>> from your lan91cxx_RxEvent() function.
>>
>> To be clear, here's the flow:
>>
>> Device generates interrupt
>> lan91cxx_RxEvent() runs, determines how many bytes are in the packet
>> (sc->funs->eth_drv->recv)(sc, len) tells the network layer
>> ... time passes - maybe a lot of time - until the network input
>> thread has time/space to read the packet
>> lan91cxx_recv() is called from the network input thread
>> for each element in 'sg' (based on 'sg_len'), move the next
>> sg[n].len bytes from the device buffer into sg[n].buf
>>
>> -- 

-- 
------------------------------------------------------------
Gary Thomas                 |  Consulting for the
MLB Associates              |    Embedded world
------------------------------------------------------------

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]