| 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 <tty0.h> | 
|---|
| 13 | #include <ctx_handler.h> | 
|---|
| 14 | #include <vmem.h> | 
|---|
| 15 |  | 
|---|
| 16 | #if !defined(GIET_USE_IOMMU)  | 
|---|
| 17 | # error: You must define GIET_USE_IOMMU in the giet_config.h file | 
|---|
| 18 | #endif | 
|---|
| 19 |  | 
|---|
| 20 | #if !defined(SEG_NIC_BASE) | 
|---|
| 21 | # error: You must define SEG_NIC_BASE in the hard_config.h file  | 
|---|
| 22 | #endif | 
|---|
| 23 |  | 
|---|
| 24 | #if !defined(NB_NIC_CHANNELS) | 
|---|
| 25 | # error: You must define NB_NIC_CHANNELS in the hard_config.h file  | 
|---|
| 26 | #endif | 
|---|
| 27 |  | 
|---|
| 28 | #if !defined(X_IO) | 
|---|
| 29 | # error: You must define X_IO in the hard_config.h file | 
|---|
| 30 | #endif | 
|---|
| 31 |  | 
|---|
| 32 | #if !defined(Y_IO) | 
|---|
| 33 | # error: You must define Y_IO in the hard_config.h file | 
|---|
| 34 | #endif | 
|---|
| 35 |  | 
|---|
| 36 | #if ( NB_NIC_CHANNELS > 8 ) | 
|---|
| 37 | # error: NB_NIC_CHANNELS cannot be larger than 8 | 
|---|
| 38 | #endif | 
|---|
| 39 |  | 
|---|
| 40 | #if !defined(NB_CMA_CHANNELS) | 
|---|
| 41 | # error: You must define NB_CMA_CHANNELS in the hard_config.h file  | 
|---|
| 42 | #endif | 
|---|
| 43 |  | 
|---|
| 44 | #if ( NB_CMA_CHANNELS > 8 ) | 
|---|
| 45 | # error: NB_CMA_CHANNELS cannot be larger than 8 | 
|---|
| 46 | #endif | 
|---|
| 47 |  | 
|---|
| 48 | #if !defined( USE_IOB ) | 
|---|
| 49 | # error: You must define USE_IOB in the hard_config.h file | 
|---|
| 50 | #endif | 
|---|
| 51 |  | 
|---|
| 52 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 53 | // This low_level function returns the value contained in a channel register.  | 
|---|
| 54 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 55 | unsigned int _nic_get_channel_register( unsigned int channel, | 
|---|
| 56 |                                         unsigned int index ) | 
|---|
| 57 | { | 
|---|
| 58 |     unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE +  | 
|---|
| 59 |                            NIC_CHANNEL_SPAN * channel + 0x1000 + index; | 
|---|
| 60 |     return _io_extended_read( vaddr ); | 
|---|
| 61 | } | 
|---|
| 62 |  | 
|---|
| 63 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 64 | // This low-level function set a new value in a channel register. | 
|---|
| 65 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 66 | void _nic_set_channel_register( unsigned int channel, | 
|---|
| 67 |                                 unsigned int index, | 
|---|
| 68 |                                 unsigned int value )  | 
|---|
| 69 | { | 
|---|
| 70 |     unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE +  | 
|---|
| 71 |                            NIC_CHANNEL_SPAN * channel + 0x1000 + index; | 
|---|
| 72 |     _io_extended_write( vaddr, value ); | 
|---|
| 73 | } | 
|---|
| 74 |  | 
|---|
| 75 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 76 | // This low_level function returns the value contained in a global register.  | 
|---|
| 77 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 78 | unsigned int _nic_get_global_register( unsigned int index ) | 
|---|
| 79 | { | 
|---|
| 80 |     unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE +  | 
|---|
| 81 |                            NIC_CHANNEL_SPAN * 8 + index; | 
|---|
| 82 |     return _io_extended_read( vaddr ); | 
|---|
| 83 | } | 
|---|
| 84 |  | 
|---|
| 85 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 86 | // This low-level function set a new value in a global register. | 
|---|
| 87 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| 88 | void _nic_set_global_register( unsigned int index, | 
|---|
| 89 |                                unsigned int value )  | 
|---|
| 90 | { | 
|---|
| 91 |     unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE +  | 
|---|
| 92 |                            NIC_CHANNEL_SPAN * 8 + index; | 
|---|
| 93 |     _io_extended_write( vaddr, value ); | 
|---|
| 94 | } | 
|---|
| 95 |  | 
|---|
| 96 | //////////////////////////////////////////// | 
|---|
| 97 | int _nic_global_init( unsigned int bc_enable, | 
|---|
| 98 |                       unsigned int bypass_enable, | 
|---|
| 99 |                       unsigned int tdm_enable, | 
|---|
| 100 |                       unsigned int tdm_period ) | 
|---|
| 101 | { | 
|---|
| 102 |     _nic_set_global_register( NIC_G_BC_ENABLE    , bc_enable ); | 
|---|
| 103 |     _nic_set_global_register( NIC_G_BYPASS_ENABLE, bypass_enable ); | 
|---|
| 104 |     _nic_set_global_register( NIC_G_TDM_ENABLE   , tdm_enable ); | 
|---|
| 105 |     _nic_set_global_register( NIC_G_TDM_PERIOD   , tdm_period ); | 
|---|
| 106 |     _nic_set_global_register( NIC_G_VIS          , 0 );     // channels activated later | 
|---|
| 107 |     _nic_set_global_register( NIC_G_ON           , 1 );    | 
|---|
| 108 |  | 
|---|
| 109 |     return 0; | 
|---|
| 110 | } | 
|---|
| 111 |  | 
|---|
| 112 | //////////////////////////////////////////// | 
|---|
| 113 | int _nic_channel_start( unsigned int channel, | 
|---|
| 114 |                         unsigned int is_rx, | 
|---|
| 115 |                         unsigned int mac4, | 
|---|
| 116 |                         unsigned int mac2 ) | 
|---|
| 117 | { | 
|---|
| 118 |     unsigned int vis = _nic_get_global_register( NIC_G_VIS ); | 
|---|
| 119 |     vis |= (0x1 << channel ); | 
|---|
| 120 |  | 
|---|
| 121 |     _nic_set_global_register( NIC_G_MAC_4 + channel, mac4 ); | 
|---|
| 122 |     _nic_set_global_register( NIC_G_MAC_2 + channel, mac2 ); | 
|---|
| 123 |     _nic_set_global_register( NIC_G_VIS            , vis ); | 
|---|
| 124 |      | 
|---|
| 125 |     unsigned int base     = SEG_NIC_BASE; | 
|---|
| 126 |     unsigned int extend   = (X_IO << Y_WIDTH) + Y_IO; | 
|---|
| 127 |  | 
|---|
| 128 |     unsigned int buf_0_addr; | 
|---|
| 129 |     unsigned int buf_1_addr; | 
|---|
| 130 |     unsigned int sts_0_addr; | 
|---|
| 131 |     unsigned int sts_1_addr; | 
|---|
| 132 |  | 
|---|
| 133 |     unsigned int desc_lo_0; | 
|---|
| 134 |     unsigned int desc_lo_1; | 
|---|
| 135 |     unsigned int desc_hi_0; | 
|---|
| 136 |     unsigned int desc_hi_1; | 
|---|
| 137 |  | 
|---|
| 138 |     if ( is_rx ) | 
|---|
| 139 |     { | 
|---|
| 140 |         buf_0_addr = base; | 
|---|
| 141 |         buf_1_addr = base + 0x1000; | 
|---|
| 142 |         sts_0_addr = base + 0x4000; | 
|---|
| 143 |         sts_1_addr = base + 0x4040; | 
|---|
| 144 |  | 
|---|
| 145 |         desc_lo_0 = (sts_0_addr >> 6) + ((buf_0_addr & 0xFC0) << 20); | 
|---|
| 146 |         desc_lo_1 = (sts_1_addr >> 6) + ((buf_1_addr & 0xFC0) << 20); | 
|---|
| 147 |         desc_hi_0 = ((buf_0_addr & 0xFFFFF000) >> 12) + ((extend & 0xFFF) << 20); | 
|---|
| 148 |         desc_hi_1 = ((buf_1_addr & 0xFFFFF000) >> 12) + ((extend & 0xFFF) << 20); | 
|---|
| 149 |  | 
|---|
| 150 |         _nic_set_channel_register( channel, NIC_RX_DESC_LO_0, desc_lo_0     ); | 
|---|
| 151 |         _nic_set_channel_register( channel, NIC_RX_DESC_LO_1, desc_lo_1     ); | 
|---|
| 152 |         _nic_set_channel_register( channel, NIC_RX_DESC_HI_0, desc_hi_0     ); | 
|---|
| 153 |         _nic_set_channel_register( channel, NIC_RX_DESC_HI_1, desc_hi_1     ); | 
|---|
| 154 |         _nic_set_channel_register( channel, NIC_RX_RUN      , 1             ); | 
|---|
| 155 |     } | 
|---|
| 156 |     else | 
|---|
| 157 |     { | 
|---|
| 158 |         buf_0_addr = base + 0x2000; | 
|---|
| 159 |         buf_1_addr = base + 0x3000; | 
|---|
| 160 |         sts_0_addr = base + 0x4080; | 
|---|
| 161 |         sts_1_addr = base + 0x40c0; | 
|---|
| 162 |  | 
|---|
| 163 |         desc_lo_0 = (sts_0_addr >> 6) + ((buf_0_addr & 0xFC0) << 20); | 
|---|
| 164 |         desc_lo_1 = (sts_1_addr >> 6) + ((buf_1_addr & 0xFC0) << 20); | 
|---|
| 165 |         desc_hi_0 = ((buf_0_addr & 0xFFFFF000) >> 12) + ((extend & 0xFFF) << 20); | 
|---|
| 166 |         desc_hi_1 = ((buf_1_addr & 0xFFFFF000) >> 12) + ((extend & 0xFFF) << 20); | 
|---|
| 167 |  | 
|---|
| 168 |         _nic_set_channel_register( channel, NIC_TX_DESC_LO_0, desc_lo_0     ); | 
|---|
| 169 |         _nic_set_channel_register( channel, NIC_TX_DESC_LO_1, desc_lo_1     ); | 
|---|
| 170 |         _nic_set_channel_register( channel, NIC_TX_DESC_HI_0, desc_hi_0     ); | 
|---|
| 171 |         _nic_set_channel_register( channel, NIC_TX_DESC_HI_1, desc_hi_1     ); | 
|---|
| 172 |         _nic_set_channel_register( channel, NIC_TX_RUN      , 1             ); | 
|---|
| 173 |     } | 
|---|
| 174 |  | 
|---|
| 175 |     return 0; | 
|---|
| 176 | } | 
|---|
| 177 |  | 
|---|
| 178 | //////////////////////////////////////////// | 
|---|
| 179 | int _nic_channel_stop( unsigned int channel, | 
|---|
| 180 |                        unsigned int is_rx ) | 
|---|
| 181 | { | 
|---|
| 182 |     if ( is_rx )  _nic_set_channel_register( channel, NIC_RX_RUN, 0 ); | 
|---|
| 183 |     else          _nic_set_channel_register( channel, NIC_TX_RUN, 0 ); | 
|---|
| 184 |  | 
|---|
| 185 |     return 0;    | 
|---|
| 186 | } | 
|---|
| 187 |  | 
|---|
| 188 |  | 
|---|
| 189 |  | 
|---|
| 190 | //////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 191 | //            Interrupt Service Routines | 
|---|
| 192 | //////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 193 |  | 
|---|
| 194 | //////////////////////////////////////// | 
|---|
| 195 | void _nic_rx_isr( unsigned int irq_type, | 
|---|
| 196 |                   unsigned int irq_id, | 
|---|
| 197 |                   unsigned int channel ) | 
|---|
| 198 | { | 
|---|
| 199 |     _puts("[NIC WARNING] RX buffers are full for NIC channel "); | 
|---|
| 200 |     _putd( channel ); | 
|---|
| 201 |     _puts("\n"); | 
|---|
| 202 | } | 
|---|
| 203 |  | 
|---|
| 204 | //////////////////////////////////////// | 
|---|
| 205 | void _nic_tx_isr( unsigned int irq_type, | 
|---|
| 206 |                   unsigned int irq_id, | 
|---|
| 207 |                   unsigned int channel ) | 
|---|
| 208 | { | 
|---|
| 209 |     _puts("[NIC WARNING] TX buffers are full for NIC channel "); | 
|---|
| 210 |     _putd( channel ); | 
|---|
| 211 |     _puts("\n"); | 
|---|
| 212 | } | 
|---|
| 213 |  | 
|---|
| 214 | // Local Variables: | 
|---|
| 215 | // tab-width: 4 | 
|---|
| 216 | // c-basic-offset: 4 | 
|---|
| 217 | // c-file-offsets:((innamespace . 0)(inline-open . 0)) | 
|---|
| 218 | // indent-tabs-mode: nil | 
|---|
| 219 | // End: | 
|---|
| 220 | // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4 | 
|---|
| 221 |  | 
|---|