/////////////////////////////////////////////////////////////////////////////////// // File : nic_driver.c // Date : 23/05/2013 // Author : alain greiner // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #if !defined(GIET_USE_IOMMU) # error: You must define GIET_USE_IOMMU in the giet_config.h file #endif #if !defined(SEG_NIC_BASE) # error: You must define SEG_NIC_BASE in the hard_config.h file #endif #if !defined(NB_NIC_CHANNELS) # error: You must define NB_NIC_CHANNELS in the hard_config.h file #endif #if !defined(X_IO) # error: You must define X_IO in the hard_config.h file #endif #if !defined(Y_IO) # error: You must define Y_IO in the hard_config.h file #endif #if ( NB_NIC_CHANNELS > 8 ) # error: NB_NIC_CHANNELS cannot be larger than 8 #endif #if !defined(NB_CMA_CHANNELS) # error: You must define NB_CMA_CHANNELS in the hard_config.h file #endif #if ( NB_CMA_CHANNELS > 8 ) # error: NB_CMA_CHANNELS cannot be larger than 8 #endif #if !defined( USE_IOB ) # error: You must define USE_IOB in the hard_config.h file #endif /////////////////////////////////////////////////////////////////////////////// // This low_level function returns the value contained in a channel register. /////////////////////////////////////////////////////////////////////////////// unsigned int _nic_get_channel_register( unsigned int channel, unsigned int index ) { unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE + NIC_CHANNEL_SPAN * channel + 0x1000 + index; return _io_extended_read( vaddr ); } /////////////////////////////////////////////////////////////////////////////// // This low-level function set a new value in a channel register. /////////////////////////////////////////////////////////////////////////////// void _nic_set_channel_register( unsigned int channel, unsigned int index, unsigned int value ) { unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE + NIC_CHANNEL_SPAN * channel + 0x1000 + index; _io_extended_write( vaddr, value ); } /////////////////////////////////////////////////////////////////////////////// // This low_level function returns the value contained in a global register. /////////////////////////////////////////////////////////////////////////////// unsigned int _nic_get_global_register( unsigned int index ) { unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE + NIC_CHANNEL_SPAN * 8 + index; return _io_extended_read( vaddr ); } /////////////////////////////////////////////////////////////////////////////// // This low-level function set a new value in a global register. /////////////////////////////////////////////////////////////////////////////// void _nic_set_global_register( unsigned int index, unsigned int value ) { unsigned int* vaddr = (unsigned int*)SEG_NIC_BASE + NIC_CHANNEL_SPAN * 8 + index; _io_extended_write( vaddr, value ); } //////////////////////////////////////////// int _nic_global_init( unsigned int bc_enable, unsigned int bypass_enable, unsigned int tdm_enable, unsigned int tdm_period ) { _nic_set_global_register( NIC_G_BC_ENABLE , bc_enable ); _nic_set_global_register( NIC_G_BYPASS_ENABLE, bypass_enable ); _nic_set_global_register( NIC_G_TDM_ENABLE , tdm_enable ); _nic_set_global_register( NIC_G_TDM_PERIOD , tdm_period ); _nic_set_global_register( NIC_G_VIS , 0 ); // channels activated later _nic_set_global_register( NIC_G_ON , 1 ); return 0; } //////////////////////////////////////////// int _nic_channel_start( unsigned int channel, unsigned int is_rx, unsigned int mac4, unsigned int mac2 ) { unsigned int vis = _nic_get_global_register( NIC_G_VIS ); vis |= (0x1 << channel ); _nic_set_global_register( NIC_G_MAC_4 + channel, mac4 ); _nic_set_global_register( NIC_G_MAC_2 + channel, mac2 ); _nic_set_global_register( NIC_G_VIS , vis ); unsigned int base = SEG_NIC_BASE; unsigned int extend = (X_IO << Y_WIDTH) + Y_IO; if ( is_rx ) { _nic_set_channel_register( channel, NIC_RX_DESC_LO_0, base ); _nic_set_channel_register( channel, NIC_RX_DESC_LO_1, base + 0x1000 ); _nic_set_channel_register( channel, NIC_RX_DESC_HI_0, extend ); _nic_set_channel_register( channel, NIC_RX_DESC_HI_1, extend ); _nic_set_channel_register( channel, NIC_RX_RUN , 1 ); } else { _nic_set_channel_register( channel, NIC_TX_DESC_LO_0, base + 0x2000 ); _nic_set_channel_register( channel, NIC_TX_DESC_LO_1, base + 0x3000 ); _nic_set_channel_register( channel, NIC_TX_DESC_HI_0, extend ); _nic_set_channel_register( channel, NIC_TX_DESC_HI_1, extend ); _nic_set_channel_register( channel, NIC_TX_RUN , 1 ); } return 0; } //////////////////////////////////////////// int _nic_channel_stop( unsigned int channel, unsigned int is_rx ) { if ( is_rx ) _nic_set_channel_register( channel, NIC_RX_RUN, 0 ); else _nic_set_channel_register( channel, NIC_TX_RUN, 0 ); return 0; } //////////////////////////////////////////////////////////////////////////////////////////// // Interrupt Service Routines //////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// void _nic_rx_isr( unsigned int irq_type, unsigned int irq_id, unsigned int channel ) { _puts("[NIC WARNING] RX buffers are full for NIC channel "); _putd( channel ); _puts("\n"); } //////////////////////////////////////// void _nic_tx_isr( unsigned int irq_type, unsigned int irq_id, unsigned int channel ) { _puts("[NIC WARNING] TX buffers are full for NIC channel "); _putd( channel ); _puts("\n"); } // Local Variables: // tab-width: 4 // c-basic-offset: 4 // c-file-offsets:((innamespace . 0)(inline-open . 0)) // indent-tabs-mode: nil // End: // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4