/////////////////////////////////////////////////////////////////////////////////// // File : nic_driver.c // Date : 23/05/2013 // Author : alain greiner // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// #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 #if !defined( GIET_NIC_CHBUF_NBUFS ) # error: You must define GIET_NIC_CHBUF_NBUFS in the giet_config.h file #endif #if !defined( GIET_NIC_CHBUF_SIZE ) # error: You must define GIET_NIC_CHBUF_SIZE in the giet_config.h file #endif #if !defined( GIET_NIC_CHBUF_TIMEOUT ) # error: You must define GIET_NIC_CHBUF_TIMEOUT in the giet_config.h file #endif #define in_unckdata __attribute__((section (".unckdata"))) /////////////////////////////////////////////////////////////////////////////// // 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 + 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 + 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 * NB_NIC_CHANNELS + 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 * NB_NIC_CHANNELS + index; _io_extended_write( vaddr, value ); } //////////////////////////////////////////// int _nic_global_init( unsigned int channels, unsigned int vis, unsigned int bc_enable, unsigned int bypass_enable ) { _nic_set_global_register( NIC_G_VIS , vis ); _nic_set_global_register( NIC_G_NB_CHAN , channels ); _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_ON , 1 ); return 0; } //////////////////////////////////////////// int _nic_channel_start( unsigned int channel, unsigned int is_rx, unsigned int mac4, unsigned int mac2 ) { 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 + 4096, base ); _nic_set_channel_register( channel, NIC_RX_DESC_LO_1 + 4096, 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 + 4096, base + 0x2000 ); _nic_set_channel_register( channel, NIC_TX_DESC_LO_1 + 4096, 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 ); } _nic_set_channel_register( channel, NIC_MAC_4 , mac4 ); _nic_set_channel_register( channel, NIC_MAC_2 , mac2 ); 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