Logo Search packages:      
Sourcecode: libffado version File versions  Download package

bool IsoHandlerManager::registerStream ( Streaming::StreamProcessor stream  ) 

register an iso stream with the manager

Registers an StreamProcessor with the IsoHandlerManager.

If nescessary, an IsoHandler is created to handle this stream. Once an StreamProcessor is registered to the handler, it will be included in the ISO streaming cycle (i.e. receive/transmit of it will occur).

Parameters:
stream the stream to register
Returns:
true if registration succeeds
Todo:
: currently there is a one-to-one mapping between streams and handlers, this is not ok for multichannel receive

Definition at line 714 of file IsoHandlerManager.cpp.

References Streaming::StreamProcessor::getMaxPacketSize(), Streaming::StreamProcessor::getPacketsPerPeriod(), Streaming::StreamProcessor::getType(), Streaming::StreamProcessor::getTypeString(), Util::Configuration::getValueForSetting(), pruneHandlers(), IsoHandler::registerStream(), IsoHandler::setReceiveMode(), and IsoHandler::setVerboseLevel().

{
    debugOutput( DEBUG_LEVEL_VERBOSE, "Registering %s stream %p\n", stream->getTypeString(), stream);
    assert(stream);

    IsoHandler* h = NULL;

    // make sure the stream isn't already attached to a handler
    for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
      it != m_IsoHandlers.end();
      ++it )
    {
        if((*it)->isStreamRegistered(stream)) {
            debugError( "stream already registered!\n");
            return false;
        }
    }

    // clean up all handlers that aren't used
    pruneHandlers();

    // allocate a handler for this stream
    if (stream->getType()==StreamProcessor::ePT_Receive) {
        // grab the options from the parent
        Util::Configuration *config = m_service.getConfiguration();
        int receive_mode_setting = DEFAULT_ISO_RECEIVE_MODE;
        int bufferfill_mode_threshold = BUFFERFILL_MODE_THRESHOLD;
        int min_interrupts_per_period = MINIMUM_INTERRUPTS_PER_PERIOD;
        int max_nb_buffers_recv = MAX_RECV_NB_BUFFERS;
        int min_packetsize_recv = MIN_RECV_PACKET_SIZE;
        if(config) {
            config->getValueForSetting("ieee1394.isomanager.iso_receive_mode", receive_mode_setting);
            config->getValueForSetting("ieee1394.isomanager.bufferfill_mode_threshold", bufferfill_mode_threshold);
            config->getValueForSetting("ieee1394.isomanager.min_interrupts_per_period", min_interrupts_per_period);
            config->getValueForSetting("ieee1394.isomanager.max_nb_buffers_recv", max_nb_buffers_recv);
            config->getValueForSetting("ieee1394.isomanager.min_packetsize_recv", min_packetsize_recv);
        }

        // setup the optimal parameters for the raw1394 ISO buffering
        unsigned int packets_per_period = stream->getPacketsPerPeriod();
        // reserve space for the 1394 header too (might not be necessary)
        unsigned int max_packet_size = stream->getMaxPacketSize() + 8;
        unsigned int page_size = getpagesize();

        enum raw1394_iso_dma_recv_mode receive_mode;
        switch(receive_mode_setting) {
            case 0:
                if(packets_per_period < (unsigned)bufferfill_mode_threshold) {
                    debugOutput( DEBUG_LEVEL_VERBOSE, "Using packet-per-buffer mode (auto) [%d, %d]\n",
                                 packets_per_period, bufferfill_mode_threshold);
                    receive_mode = RAW1394_DMA_PACKET_PER_BUFFER;
                } else {
                    debugOutput( DEBUG_LEVEL_VERBOSE, "Using bufferfill mode (auto) [%d, %d]\n",
                                 packets_per_period, bufferfill_mode_threshold);
                    receive_mode = RAW1394_DMA_BUFFERFILL;
                }
                break;
            case 1: 
                debugOutput( DEBUG_LEVEL_VERBOSE, "Using packet-per-buffer mode (config)\n");
                receive_mode = RAW1394_DMA_PACKET_PER_BUFFER;
                break;
            case 2:
                debugOutput( DEBUG_LEVEL_VERBOSE, "Using bufferfill mode (config)\n");
                receive_mode = RAW1394_DMA_BUFFERFILL;
                break;
            default: debugWarning("Bogus receive mode setting in config: %d\n", receive_mode_setting);
        }

        // Ensure we don't request a packet size bigger than the
        // kernel-enforced maximum which is currently 1 page.
        // NOTE: PP: this is not really true AFAICT
        if (max_packet_size > page_size) {
            debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
            return false;
        }
        if (max_packet_size < (unsigned)min_packetsize_recv) {
            debugError("min packet size (%u) < MIN_RECV_PACKET_SIZE (%u), using min value\n",
                       max_packet_size, min_packetsize_recv);
            max_packet_size = min_packetsize_recv;
        }

        // the interrupt/wakeup interval prediction of raw1394 is a mess...
        int irq_interval = (packets_per_period-1) / min_interrupts_per_period;
        if(irq_interval <= 0) irq_interval=1;

        // the receive buffer size doesn't matter for the latency,
        // it does seem to be confined to a certain region for correct
        // operation. However it is not clear how many.
        int buffers = max_nb_buffers_recv;

        // ensure at least 2 hardware interrupts per ISO buffer wraparound
        if(irq_interval > buffers/2) {
            irq_interval = buffers/2;
        }

        // create the actual handler
        debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n");
        h = new IsoHandler(*this, IsoHandler::eHT_Receive,
                           buffers, max_packet_size, irq_interval);

        if(!h) {
            debugFatal("Could not create IsoRecvHandler\n");
            return false;
        }

        h->setReceiveMode(receive_mode);

    } else if (stream->getType()==StreamProcessor::ePT_Transmit) {
        // grab the options from the parent
        Util::Configuration *config = m_service.getConfiguration();
        int min_interrupts_per_period = MINIMUM_INTERRUPTS_PER_PERIOD;
        int max_nb_buffers_xmit = MAX_XMIT_NB_BUFFERS;
        int max_packetsize_xmit = MAX_XMIT_PACKET_SIZE;
        int min_packetsize_xmit = MIN_XMIT_PACKET_SIZE;
        if(config) {
            config->getValueForSetting("ieee1394.isomanager.min_interrupts_per_period", min_interrupts_per_period);
            config->getValueForSetting("ieee1394.isomanager.max_nb_buffers_xmit", max_nb_buffers_xmit);
            config->getValueForSetting("ieee1394.isomanager.max_packetsize_xmit", max_packetsize_xmit);
            config->getValueForSetting("ieee1394.isomanager.min_packetsize_xmit", min_packetsize_xmit);
        }

        // setup the optimal parameters for the raw1394 ISO buffering
        // reserve space for the 1394 header too (might not be necessary)
        unsigned int max_packet_size = stream->getMaxPacketSize() + 8;

        if (max_packet_size > (unsigned)max_packetsize_xmit) {
            debugError("max packet size (%u) > MAX_XMIT_PACKET_SIZE (%u)\n",
                       max_packet_size, max_packetsize_xmit);
            return false;
        }
        if (max_packet_size < (unsigned)min_packetsize_xmit) {
            debugError("min packet size (%u) < MIN_XMIT_PACKET_SIZE (%u), using min value\n",
                       max_packet_size, min_packetsize_xmit);
            max_packet_size = min_packetsize_xmit;
        }

        int buffers = max_nb_buffers_xmit;
        unsigned int packets_per_period = stream->getPacketsPerPeriod();

        int irq_interval = (packets_per_period-1) / min_interrupts_per_period;
        if(irq_interval <= 0) irq_interval=1;
        // ensure at least 2 hardware interrupts per ISO buffer wraparound
        if(irq_interval > buffers/2) {
            irq_interval = buffers/2;
        }

        debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoXmitHandler\n");

        // create the actual handler
        h = new IsoHandler(*this, IsoHandler::eHT_Transmit,
                           buffers, max_packet_size, irq_interval);

        if(!h) {
            debugFatal("Could not create IsoXmitHandler\n");
            return false;
        }

    } else {
        debugFatal("Bad stream type\n");
        return false;
    }

    h->setVerboseLevel(getDebugLevel());

    // register the stream with the handler
    if(!h->registerStream(stream)) {
        debugFatal("Could not register receive stream with handler\n");
        return false;
    }

    // register the handler with the manager
    if(!registerHandler(h)) {
        debugFatal("Could not register receive handler with manager\n");
        return false;
    }
    debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n", stream, h);

    m_StreamProcessors.push_back(stream);
    debugOutput( DEBUG_LEVEL_VERBOSE, " %zd streams, %zd handlers registered\n",
                                      m_StreamProcessors.size(), m_IsoHandlers.size());
    return true;
}


Generated by  Doxygen 1.6.0   Back to index