source: soft/giet_vm/giet_drivers/nic_driver.c @ 447

Last change on this file since 447 was 437, checked in by alain, 10 years ago

Introducing dynamic allocation of peripheral channel(TTY, NIC, TIM, CMA)
Removint the ICU driver : ICU component not supported anymore.
Removing the FBF driver.

File size: 14.2 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : nic_driver.c
3// Date     : 23/05/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <giet_config.h>
9#include <nic_driver.h>
10#include <cma_driver.h>
11#include <utils.h>
12#include <ctx_handler.h>
13#include <vmem.h>
14
15#if !defined(GIET_USE_IOMMU)
16# error: You must define GIET_USE_IOMMU in the giet_config.h file
17#endif
18
19#if !defined(SEG_NIC_BASE)
20# error: You must define SEG_NIC_BASE in the hard_config.h file
21#endif
22
23#if !defined(NB_NIC_CHANNELS)
24# error: You must define NB_NIC_CHANNELS in the hard_config.h file
25#endif
26
27#if !defined(X_IO)
28# error: You must define X_IO in the hard_config.h file
29#endif
30
31#if !defined(Y_IO)
32# error: You must define Y_IO in the hard_config.h file
33#endif
34
35#if ( NB_NIC_CHANNELS > 8 )
36# error: NB_NIC_CHANNELS cannot be larger than 8
37#endif
38
39#if !defined(NB_CMA_CHANNELS)
40# error: You must define NB_CMA_CHANNELS in the hard_config.h file
41#endif
42
43#if ( NB_CMA_CHANNELS > 8 )
44# error: NB_CMA_CHANNELS cannot be larger than 8
45#endif
46
47#if !defined( USE_IOB )
48# error: You must define USE_IOB in the hard_config.h file
49#endif
50
51#if !defined( GIET_CHBUF_NBUFS )
52# error: You must define GIET_CHBUF_NBUFS in the giet_config.h file
53#endif
54
55#define in_unckdata __attribute__((section (".unckdata")))
56
57///////////////////////////////////////////////////////////////////////////////
58// This low_level function returns the value contained in a channel register.
59///////////////////////////////////////////////////////////////////////////////
60unsigned int _nic_get_channel_register( unsigned int channel,
61                                        unsigned int index )
62{
63    unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE + 
64                           NIC_CHANNEL_SPAN * channel + index;
65    return _io_extended_read( vaddr );
66}
67
68///////////////////////////////////////////////////////////////////////////////
69// This low-level function set a new value in a channel register.
70///////////////////////////////////////////////////////////////////////////////
71void _nic_set_channel_register( unsigned int channel,
72                                unsigned int index,
73                                unsigned int value ) 
74{
75    unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE + 
76                           NIC_CHANNEL_SPAN * channel + index;
77    _io_extended_write( vaddr, value );
78}
79
80///////////////////////////////////////////////////////////////////////////////
81// This low_level function returns the value contained in a global register.
82///////////////////////////////////////////////////////////////////////////////
83unsigned int _nic_get_global_register( unsigned int index )
84{
85    unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE + 
86                           NIC_CHANNEL_SPAN * NB_NIC_CHANNELS + index;
87    return _io_extended_read( vaddr );
88}
89
90///////////////////////////////////////////////////////////////////////////////
91// This low-level function set a new value in a global register.
92///////////////////////////////////////////////////////////////////////////////
93void _nic_set_global_register( unsigned int index,
94                               unsigned int value ) 
95{
96    unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE + 
97                           NIC_CHANNEL_SPAN * NB_NIC_CHANNELS + index;
98    _io_extended_write( vaddr, value );
99}
100
101////////////////////////////////////////////
102int _nic_global_init( unsigned int channels,
103                      unsigned int vis,
104                      unsigned int bc_enable,
105                      unsigned int bypass_enable )
106{
107    _nic_set_global_register( NIC_G_VIS          , vis );
108    _nic_set_global_register( NIC_G_NB_CHAN      , channels );
109    _nic_set_global_register( NIC_G_BC_ENABLE    , bc_enable );
110    _nic_set_global_register( NIC_G_BYPASS_ENABLE, bypass_enable );
111    _nic_set_global_register( NIC_G_ON           , 1 );
112
113    return 0;
114}
115
116////////////////////////////////////////////
117int _nic_channel_init( unsigned int index,
118                       unsigned int mac4,
119                       unsigned int mac2 )
120{
121    unsigned int base     = SEG_NIC_BASE;
122    unsigned int extend   = (X_IO << Y_WIDTH) + Y_IO;
123
124    _nic_set_channel_register( index, NIC_RX_DESC_LO_0 + 4096, base );
125    _nic_set_channel_register( index, NIC_RX_DESC_LO_1 + 4096, base + 0x1000 );
126    _nic_set_channel_register( index, NIC_TX_DESC_LO_0 + 4096, base + 0x2000 );
127    _nic_set_channel_register( index, NIC_TX_DESC_LO_1 + 4096, base + 0x3000 );
128
129    _nic_set_channel_register( index, NIC_RX_DESC_HI_0       , extend );
130    _nic_set_channel_register( index, NIC_RX_DESC_HI_1       , extend );
131    _nic_set_channel_register( index, NIC_TX_DESC_HI_0       , extend );
132    _nic_set_channel_register( index, NIC_TX_DESC_HI_1       , extend );
133
134    _nic_set_channel_register( index, NIC_MAC_4              , mac4 );
135    _nic_set_channel_register( index, NIC_MAC_2              , mac2 );
136   
137    _nic_set_channel_register( index, NIC_RX_RUN             , 1 );
138    _nic_set_channel_register( index, NIC_TX_RUN             , 1 );
139
140    return 0;
141}
142
143/////////////////////////////////////////////////////////////////////////////////////
144//             Synchronous access functions
145/////////////////////////////////////////////////////////////////////////////////////
146
147///////////////////////////////////////////////
148int _nic_sync_send( unsigned int        channel,
149                    unsigned long long  user_paddr )
150{
151    unsigned long long nic_paddr;   // nic buffer physical address
152    unsigned int       done = 0;
153    unsigned int       lsb;
154    unsigned int       msb;
155
156    if ( channel >= NB_NIC_CHANNELS )
157    {
158        _puts("[GIET ERROR] in _timer_sync_send()\n");
159        return -1;
160    }
161
162    // poll the NIC buffers
163    while ( done == 0 )
164    {
165        // test availability of NIC TX buffer 0
166        lsb  = _nic_get_channel_register( channel, NIC_TX_DESC_LO_0 );
167        msb  = _nic_get_channel_register( channel, NIC_TX_DESC_HI_0 );
168        if ( (msb & 0x80000000) == 0 )
169        {
170            msb  = msb & 0x0000FFFF;
171            done = 1;
172            continue;
173        }
174
175        // test availability of NIC TX buffer 1
176        lsb  = _nic_get_channel_register( channel, NIC_TX_DESC_LO_1 );
177        msb  = _nic_get_channel_register( channel, NIC_TX_DESC_HI_1 );
178        if ( (msb & 0x80000000) == 0 )
179        {
180            msb  = msb & 0x0000FFFF;
181            done = 1;
182            continue;
183        }
184
185        // random delay (average value: 380 cycle)
186        _random_wait( 8 );
187    }
188
189    // make the transfer
190    nic_paddr = (unsigned long long)lsb + (((unsigned long long)msb) << 32);
191
192    _physical_memcpy( nic_paddr , user_paddr, 4096 );
193
194    return 0;
195}
196
197///////////////////////////////////////////////////
198int _nic_sync_receive( unsigned int        channel,
199                       unsigned long long  user_paddr )
200{
201    unsigned long long nic_paddr;   // nic  buffer physical address
202    unsigned int       done = 0;
203    unsigned int       lsb;
204    unsigned int       msb;
205
206    if ( channel >= NB_NIC_CHANNELS )
207    {
208        _puts("[GIET ERROR] in _timer_sync_receive()\n");
209        return -1;
210    }
211
212    // polling the NIC buffers
213    while ( done == 0 )
214    {
215        // test availability of NIC RX buffer 0
216        lsb  = _nic_get_channel_register( channel, NIC_RX_DESC_LO_0 );
217        msb  = _nic_get_channel_register( channel, NIC_RX_DESC_HI_0 );
218        if ( (msb & 0x80000000) == 1 )
219        {
220            msb  = msb & 0x0000FFFF;
221            done = 1;
222            continue;
223        }
224
225        // test availability of NIC RX buffer 1
226        lsb  = _nic_get_channel_register( channel, NIC_RX_DESC_LO_1 );
227        msb  = _nic_get_channel_register( channel, NIC_RX_DESC_HI_1 );
228        if ( (msb & 0x80000000) == 1 )
229        {
230            msb  = msb & 0x0000FFFF;
231            done = 1;
232            continue;
233        }
234
235        // random delay (average value: 380 cycle)
236        _random_wait( 8 );
237    }
238
239    // make the transfer
240    nic_paddr = (unsigned long long)lsb + (((unsigned long long)msb) << 32);
241
242    _physical_memcpy( user_paddr, nic_paddr , 4096 );
243
244    return 0;
245}
246
247/////////////////////////////////////////////////////////////////////////////////////
248//             CMA access functions
249/////////////////////////////////////////////////////////////////////////////////////
250
251//////////////////////////////////////////////////////////////
252int _nic_cma_receive( unsigned int  nic_channel,
253                      unsigned int  cma_channel,
254                      nic_chbuf_t*  kernel_chbuf )
255                             
256{
257    unsigned int nic_chbuf_lsb;     // 32 LSB bits of the NIC chbuf physical address
258    unsigned int nic_chbuf_msb;     // 16 MSB bits of the NIC chbuf physical address
259    unsigned int mem_chbuf_lsb;     // 32 LSB bits of the kernel chbuf physical address
260    unsigned int mem_chbuf_msb;     // 16 MSB bits of the kernel chbuf physical address
261
262    unsigned int ppn;
263    unsigned int flags;
264
265    // checking parameters
266    if ( nic_channel >= NB_NIC_CHANNELS )
267    {
268        _puts("[GIET ERROR] in _nic_cma_start_receive() : nic_channel index too large\n");
269        return -1;
270    }
271    if ( cma_channel >= NB_CMA_CHANNELS )
272    {
273        _puts("[GIET ERROR] in _nic_cma_start_receive() : cma_channel index too large\n");
274        return -1;
275    }
276
277    // get the NIC_RX chbuf descriptor physical address
278    nic_chbuf_lsb = SEG_NIC_BASE + (nic_channel * NIC_CHANNEL_SPAN) + 0x1000;
279    nic_chbuf_msb = (X_IO << Y_WIDTH) + Y_IO;
280
281    // compute the kernel chbuf physical address
282    unsigned int ptab  = _get_context_slot(CTX_PTAB_ID);
283    unsigned int vaddr = (unsigned int)kernel_chbuf;
284    unsigned int ko    = _v2p_translate( (page_table_t*)ptab,
285                                          vaddr,
286                                          &ppn,
287                                          &flags );
288    if ( ko )
289    {
290        _puts("\n[GIET ERROR] in _nic_cma_start_receive() : kernel buffer unmapped\n");
291        return -1;
292    }
293
294    mem_chbuf_lsb = (ppn << 12) | (vaddr & 0x00000FFF);
295    mem_chbuf_msb = ppn >> 20;
296
297    // initializes CMA registers defining the source chbuf (NIC_RX)
298    _cma_set_register( cma_channel, CHBUF_SRC_DESC , nic_chbuf_lsb );
299    _cma_set_register( cma_channel, CHBUF_DST_EXT  , nic_chbuf_msb );
300    _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, 2 );
301
302    // initializes CMA registers defining the destination chbuf (kernel memory)
303    _cma_set_register( cma_channel, CHBUF_DST_DESC , mem_chbuf_lsb );
304    _cma_set_register( cma_channel, CHBUF_DST_EXT  , mem_chbuf_msb );
305    _cma_set_register( cma_channel, CHBUF_DST_NBUFS, GIET_CHBUF_NBUFS );
306
307    // set buffer size, polling period, and start
308    _cma_set_register( cma_channel, CHBUF_BUF_SIZE , 4096 );
309    _cma_set_register( cma_channel, CHBUF_PERIOD   , 300 );
310    _cma_set_register( cma_channel, CHBUF_RUN      , 1 );
311
312    return 0;
313}
314
315//////////////////////////////////////////////////////////
316int _nic_cma_send( unsigned int  nic_channel,
317                   unsigned int  cma_channel,
318                   nic_chbuf_t*  kernel_chbuf )
319{
320    unsigned int nic_chbuf_lsb;     // 32 LSB bits of the NIC chbuf physical address
321    unsigned int nic_chbuf_msb;     // 16 MSB bits of the NIC chbuf physical address
322    unsigned int mem_chbuf_lsb;     // 32 LSB bits of the kernel chbuf physical address
323    unsigned int mem_chbuf_msb;     // 16 MSB bits of the kernel chbuf physical address
324
325    unsigned int ppn;
326    unsigned int flags;
327
328    // checking parameters
329    if ( nic_channel >= NB_NIC_CHANNELS )
330    {
331        _puts("[GIET ERROR] in _nic_cma_start_send() : nic_channel index too large\n");
332        return -1;
333    }
334    if ( cma_channel >= NB_CMA_CHANNELS )
335    {
336        _puts("[GIET ERROR] in _nic_cma_start_send() : cma_channel index too large\n");
337        return -1;
338    }
339
340    // get the NIC_TX chbuf descriptor physical address
341    nic_chbuf_lsb = SEG_NIC_BASE + (nic_channel * NIC_CHANNEL_SPAN) + 0x1010;
342    nic_chbuf_msb = (X_IO << Y_WIDTH) + Y_IO;
343
344    // compute the kernel chbuf physical address
345    unsigned int ptab  = _get_context_slot(CTX_PTAB_ID);
346    unsigned int vaddr = (unsigned int)kernel_chbuf;
347    unsigned int ko    = _v2p_translate( (page_table_t*)ptab,
348                                          vaddr,
349                                          &ppn,
350                                          &flags );
351    if ( ko )
352    {
353        _puts("\n[GIET ERROR] in _nic_cma_start_send() : kernel buffer unmapped\n");
354        return -1;
355    }
356
357    mem_chbuf_lsb = (ppn << 12) | (vaddr & 0x00000FFF);
358    mem_chbuf_msb = ppn >> 20;
359
360    // initializes CMA registers defining the source chbuf (kernel memory)
361    _cma_set_register( cma_channel, CHBUF_SRC_DESC , mem_chbuf_lsb );
362    _cma_set_register( cma_channel, CHBUF_DST_EXT  , mem_chbuf_msb );
363    _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, GIET_CHBUF_NBUFS );
364
365    // initializes CMA registers defining the destination chbuf (NIC_TX)
366    _cma_set_register( cma_channel, CHBUF_DST_DESC , nic_chbuf_lsb );
367    _cma_set_register( cma_channel, CHBUF_DST_EXT  , nic_chbuf_msb );
368    _cma_set_register( cma_channel, CHBUF_DST_NBUFS, 2 );
369
370    // set buffer size, polling period, and start
371    _cma_set_register( cma_channel, CHBUF_BUF_SIZE , 4096 );
372    _cma_set_register( cma_channel, CHBUF_PERIOD   , 300 );
373    _cma_set_register( cma_channel, CHBUF_RUN      , 1 );
374
375    return 0;
376}
377
378////////////////////////////////////////////////////////////////////////////////////////////
379//            Interrupt Service Routines
380////////////////////////////////////////////////////////////////////////////////////////////
381
382////////////////////////////////////////
383void _nic_rx_isr( unsigned int irq_type,
384                  unsigned int irq_id,
385                  unsigned int channel )
386{
387    _puts("[NIC WARNING] RX buffers are full for NIC channel ");
388    _putd( channel );
389    _puts("\n");
390}
391
392////////////////////////////////////////
393void _nic_tx_isr( unsigned int irq_type,
394                  unsigned int irq_id,
395                  unsigned int channel )
396{
397    _puts("[NIC WARNING] TX buffers are full for NIC channel ");
398    _putd( channel );
399    _puts("\n");
400}
401
402// Local Variables:
403// tab-width: 4
404// c-basic-offset: 4
405// c-file-offsets:((innamespace . 0)(inline-open . 0))
406// indent-tabs-mode: nil
407// End:
408// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
409
Note: See TracBrowser for help on using the repository browser.