⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 channels.c

📁 ARM入门的好帮手.包含了从简单到相对较复杂的程序.
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* adjust the pointer back to where it ought to be */    if (buffer != NULL)    {        buffer -= CB_CHAN_DATA_BYTE_POS;    }    /* pass it on to the buffer module */    Angel_BufferRelease(buffer);}/* * Function: angel_ChannelAllocDevBuffer *  Purpose: allocate a buffer that is at least req_size bytes long, *           alligned for use by the device driver. This routine is *           used to allocate buffers when receiving new packets. * *   Params: *              Input: req_size        the minimum size required *                     cb_data         ignored *             Output: - *             In/Out: - * *            Returns: pointer to allocated buffer, or *                     NULL if unable to allocate suitable buffer * *      Reads globals: - *   Modifies globals: - * * Other side effects: MUST ONLY be used by device drivers */static p_Buffer angel_ChannelAllocDevBuffer(unsigned req_size, void *cb_data){    p_Buffer ret_buffer;    IGNORE(cb_data);    /* commented out as the buffer code also has v. similar info calls: */    LogInfo(LOG_CHANNEL, ("angel_ChannelAllocDevBuffer: req_size %d\n", req_size));    /* make sure we get space for our overheads */    req_size += CB_CHAN_HEADER_BYTE_POS;    /*     * There must be at least 2 packets left here -- one we will allocate, and     * one which Angel can use to send a reply back (assuming that the in-buffer     * isn't freed before the out-buffer is allocated, which is common).     */    if (Angel_BuffersLeft() < 2)    {         LogWarning(LOG_CHANNEL, ("angel_ChannelAllocDevBuffer: Not enough buffers left!\n"));         return NULL;    }        ret_buffer = Angel_BufferAlloc(req_size);    /*     * Note this call can still fail, despite the check earlier!     */    if (ret_buffer != NULL)    {        /* null the link pointer */        *CB_LINK(ret_buffer) = NULL;        /* shift the returned value to the overall data area */        ret_buffer += CB_CHAN_HEADER_BYTE_POS;    }    /* LogInfo(LOG_CHANNEL, "angel_ChannelAllocDevBuffer: buffer 0x%x\n", ret_buffer); */    return ret_buffer;}/* * Function: write_unblock_callback *  Purpose: used to signal that a blocking write has completed, and that the *           write code can continue, returning to the caller. * *   Params: *              Input: chanid                the channel on which the write occurred. *                     callback_data         pointer to the status return (a ChanError) * *            Returns: none. * *      Reads globals: (via pointer) write_error *   Modifies globals: - * * Other side effects: MUST ONLY be used by device drivers */static void write_unblock_callback(ChannelID chanid, void *callback_data){    ChanError *write_error = (ChanError *) callback_data;    ASSERT(chanid < CI_NUM_CHANNELS, ("Channel ID %d invalid in callback\n", chanid));    ASSERT(chan_state[chanid].write_blocking == TRUE, ("Write not blocked in blocking callback!\n"));    ASSERT(write_error != NULL, ("Nowhere to write error code in callback\n"));    *write_error = CE_OKAY;    chan_state[chanid].write_blocking = FALSE;    LogInfo(LOG_CHANNEL, ( "write_unblock_callback: channel %d\n", chanid));}/* * Function: angel_ChannelSend *  Purpose: blocking send of a packet via a channel * * see channels.h for full description */ChanError angel_ChannelSend(DeviceID devid, ChannelID chanid,                  const p_Buffer data_pkt, unsigned data_len){    ChanError chan_error;    ChanError send_error = CE_PRIVATE;    ASSERT(chanid < CI_NUM_CHANNELS, ("Bad channel ID %d\n", chanid));    LogInfo(LOG_CHANNEL, ( "ChannelSend: send buffer 0x%x, len %d\n",                             data_pkt, data_len));        /* Check that a write is not already in progress */    Angel_EnterCriticalSection();    if (chan_state[chanid].write_blocking)    {        Angel_LeaveCriticalSection();        LogWarning(LOG_CHANNEL, ("ChannelSend: already busy on chan %d\n", chanid));        angel_ChannelReleaseBuffer(data_pkt);        return CE_BUSY;    }    chan_state[chanid].write_blocking = TRUE;    Angel_LeaveCriticalSection();    /* Start an async write */    chan_error = angel_ChannelSendAsync(devid, chanid, data_pkt, data_len,                                        write_unblock_callback,                                        (void *)&send_error);    if (chan_error != CE_OKAY)    {        chan_state[chanid].write_blocking = FALSE;        return chan_error;    }    /* now wait for the write to complete */    while (chan_state[chanid].write_blocking)    {        TRACE("csb");        Angel_Yield();    }    if (send_error)        LogWarning(LOG_CHANNEL, ( "ChannelSend: error code %d\n", send_error));    else        LogInfo(LOG_CHANNEL, ( "ChannelSend: packet 0x%x sent\n", data_pkt));    return send_error;}/* * Function: write_callback *  Purpose: used to clean up after a non-blocking write has completed. The channel *           state must be freed up and the buffer used to hold the packet freed up. * *   Params: *              Input: v_chan_pkt            pointer to the packet's data buffer *                     v_chan_len            the length of the buffer *                     v_status              the send status -- was the write completed *                     v_cb_data             callback data: in this case, the channel id * *            Returns: none. * *      Reads globals:  *   Modifies globals:  * * Other side effects:  */static void write_callback(void *v_chan_pkt, void *v_chan_len,               void *v_status, void *cb_data){    DevStatus status = (DevStatus) (int)v_status;    p_Buffer buffer = (p_Buffer) v_chan_pkt;    ChannelID chanid;    IGNORE(v_chan_len);    LogInfo(LOG_CHANNEL, ("write_callback: packet %p, len %d, status %d, channel %d\n",                          v_chan_pkt, (int)v_chan_len, status, (ChannelID) cb_data));    if (status == DS_DONE)    {        /* channel id is in callback data */        chanid = (ChannelID) cb_data;        ASSERT(chanid < CI_NUM_CHANNELS, ("Bad channel ID %d\n", chanid));        if (chan_state[chanid].writer != NULL)  /* could have been aborted */        {            /* do the callback */            chan_state[chanid].writer(chanid, chan_state[chanid].write_cb_data);            chan_state[chanid].writer = NULL;            chan_state[chanid].write_buff = NULL;        }    }    else    {        /*         * don't know which channel was being written, so must look it up in the channel         * state, then free it up         */        LogWarning(LOG_CHANNEL, ( "write_callback: device write error %d\n", status));        for(chanid = 0; chanid < CI_NUM_CHANNELS; chanid++)        {            if (chan_state[chanid].write_buff == buffer)            {                LogWarning(LOG_CHANNEL, ( "write_callback: releasing device for chan %d\n", chanid));                chan_state[chanid].writer = NULL;                chan_state[chanid].write_buff = NULL;                chan_state[chanid].write_blocking = FALSE;            }        }    }}/* * Function: angel_ChannelSendAsync *  Purpose: asynchronous send of a packet via a channel * * see channels.h for full description */ChanError angel_ChannelSendAsync(DeviceID devid,                       ChannelID chanid,                       const p_Buffer data_pkt,                       unsigned len,                       ChanTx_CB_Fn callback,                       void *callback_data){    DevError dev_error;    p_Buffer buffer;    /* adjust the device id, if required */    if (devid == CH_DEFAULT_DEV)    {        devid = active_device;    }    ASSERT(devid < DI_NUM_DEVICES, ("Bad device ID %d\n", devid));    ASSERT(chanid < CI_NUM_CHANNELS, ("Bad channel ID %d\n", chanid));    ASSERT(data_pkt != NULL, ("No data buffer\n"));    ASSERT(callback != NULL, ("No callback function\n"));    /* we can only service one request per channel in this version */    /* adjust buffer back to start, length to include header */    buffer = data_pkt - CB_CHAN_DATA_BYTE_POS;  /* includes link ptr  */    len += CF_DATA_BYTE_POS;    /* excludes link ptr - just header */        Angel_EnterCriticalSection();           /* start critical region */    if (chan_state[chanid].writer != NULL)    {        Angel_LeaveCriticalSection();        LogWarning(LOG_CHANNEL, ( "ChannelSendAsync: already busy on chan %d\n", chanid));        angel_ChannelReleaseBuffer(data_pkt);        return CE_BUSY;    }    INC(dev_state[devid].currentFrame);        /* record what we need to know later */    chan_state[chanid].writer = callback;    chan_state[chanid].write_cb_data = callback_data;    chan_state[chanid].write_buff = buffer;    Angel_LeaveCriticalSection();          /* end critical region */    buffer[CB_PACKET(CF_CHANNEL_BYTE_POS)] = chanid;    buffer[CB_PACKET(CF_PACKET_SEQ_BYTE_POS)] = dev_state[devid].currentFrame;    buffer[CB_PACKET(CF_ACK_SEQ_BYTE_POS)] = lastSEQ(dev_state[devid].frameExpected);    buffer[CB_PACKET(CF_FLAGS_BYTE_POS)] = CF_RELIABLE;        LogInfo(LOG_CHANNEL, ("ChannelSendAsync: packet packetseq %d ackseq %d\n",              buffer[CB_PACKET(CF_PACKET_SEQ_BYTE_POS)],              buffer[CB_PACKET(CF_ACK_SEQ_BYTE_POS)]));    /* store the buffer in the unacked list */    adp_add_pkt(devid, dev_state[devid].currentFrame, buffer, len);        do    {        /* attempt to queue transmission */        /* we use the channel id as callback data - simplifies write_callback */        dev_error = angel_DeviceWrite(devid, buffer + CB_CHAN_HEADER_BYTE_POS,                                      len, write_callback, (void *)chanid,                                      DC_DBUG);        if (dev_error == DE_BUSY)        {            Angel_Yield();        }    } while (dev_error == DE_BUSY);    if (dev_error == DE_OKAY)        return CE_OKAY;    else        return CE_DEV_ERROR;}static AdpErrs resend_packet_from(DeviceID devid, SequenceNR startpacket){    DevError chan_err = DE_OKAY;    ChannelID chanid;    short len;    ChanError send_error = CE_PRIVATE;    p_Buffer buf;    register struct DevState *dev = &dev_state[devid];    register short i, j = LISTEND;    SequenceNR thispacket = startpacket;        Angel_EnterCriticalSection();    while (chan_err == DE_OKAY &&           adp_between(startpacket, thispacket, nextSEQ(dev->currentFrame)))    {        /* search for the requested packet in the resend list */        for (i = dev->firstUsed; i != LISTEND; i = dev->unackedBufs[i].next)        {                    if (thispacket == dev->unackedBufs[i].packno)                break;        }                if (i == LISTEND)        {            LogError(LOG_CHANNEL, ("resend_packet: packet %d not available (from %d, max %d)\n",                                   thispacket, startpacket, dev->currentFrame));            break;        }                /* get the buffer details */        buf = dev_state[devid].unackedBufs[i].buf;        len = dev_state[devid].unackedBufs[i].len;                chanid = (ChannelID) * buf;                Angel_LeaveCriticalSection();                /*         * set the current frameExpected, not the value when this frame was         * originally sent         */        buf[CB_PACKET(CF_ACK_SEQ_BYTE_POS)] = lastSEQ(dev_state[devid].frameExpected);                LogWarning(LOG_CHANNEL, ( "resend_packet: writing pkt 0x%x seq %d, chan %d, len %d\n",                                  buf, thispacket, chanid, len));                Angel_EnterCriticalSection();           /* start critical region */                /* Check that a write is not already in progress; if so, wait... */        /* now wait for the write to complete */        while (chan_state[chanid].write_blocking && chan_state[chanid].writer != NULL)        {            Angel_Yield();        }        chan_state[chanid].write_blocking = TRUE;        chan_state[chanid].write_buff = buf;        chan_state[chanid].writer = write_unblock_callback;        chan_state[chanid].write_cb_data = (void *)&send_error;                Angel_LeaveCriticalSection();          /* end critical region */                LogInfo(LOG_CHANNEL, ( "resend msg: writing...\n"));        do        {                    chan_err = angel_DeviceWrite(devid, buf + CB_CHAN_HEADER_BYTE_POS, len,                                         write_callback, (void *)chanid, DC_DBUG);            if (chan_err == DE_BUSY);            {                Angel_Yield();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -