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

📄 dccdrv.c

📁 AT91所有开发板的资料 AT91所有开发板的资料
💻 C
字号:
/* -*-C-*- * * $Revision: 1.1 $ *   $Author: rivimey $ *     $Date: 1999/03/11 11:53:54 $ * * Copyright (c) 1996 Advanced RISC Machines Limited. * All Rights Reserved. * *   Project: ANGEL *     Title: Devide driver for the Thumb Direct Comms Channel */#include "devdriv.h"            /* device driver support */#include "logging.h"            /* LogInfo() */#include "support.h"            /* __rt_[en/dis]ableIRQ() */#include "serlock.h"            /* serialisation, etc. */#include "params.h"             /* parameter structures and utilities */#include "serring.h"            /* interface to high-level driver */#include "dccdrv.h"/* General purpose constants, macros, enums, typedefs *//* none *//* * forward declarations of necessary functions */#if !defined(RAW_DCC) || (RAW_DCC == 0)  /* Angel/shared */static void dcc_flow_control(char fc_char, void *cb_data);#endifstatic DevError dcc_Control(DeviceID devid, DeviceControl op, void *arg);static void dcc_ControlTx(DeviceID devid);static void dcc_ControlRx(DeviceID devid);static void dcc_KickStartFn(DeviceID devid);/* in dccsup.s */extern unsigned int dcc_GetFlags(void);extern unsigned int dcc_GetWord(void);extern void dcc_PutWord(unsigned int);/* the state shared between the IRQ handler and the deferred processor */static RingBuffer dcc_rx_ring;static RingBuffer dcc_tx_ring;#if !defined(RAW_DCC) || (RAW_DCC == 0)  /* Angel/shared *//* the configuration needed by the TX and RX engines */#define DCC_FC_SET  ((1 << serial_XON) | (1 << serial_XOFF))#define DCC_CTL_SET ((1 << serial_STX) | (1 << serial_ETX) |\                        (1 << serial_ESC))#define DCC_ESC_SET (DCC_FC_SET | DCC_CTL_SET)static const struct re_config engine_config ={    serial_STX, serial_ETX, serial_ESC,  /* self-explanatory?               */    DCC_FC_SET,                 /* set of flow-control characters  */    DCC_ESC_SET,                /* set of characters to be escaped */    dcc_flow_control, (void *)DI_DCC,  /* what to do with FC chars */    angel_DD_RxEng_BufferAlloc, (void *)DI_DCC  /* how to get a buffer */};/* the state of the rx engine */static struct re_state rx_engine_state;/* the state of the tx engine */static struct te_state tx_engine_state;/* packet for actual rx in progress */static struct data_packet rx_packet;/* the current write packet */static struct data_packet tx_packet;/* collected TX and RX engine state */static RxTxState dcc_rx_tx_state ={    &engine_config,    &rx_engine_state,    &tx_engine_state,    &rx_packet,    &tx_packet,    1 /* rx_flow */};#else /* raw */static RawState dcc_raw_state;static DevError dcc_RawWrite(DeviceID devid, p_Buffer buff, unsigned length);static DevError dcc_RawRead(DeviceID devid, p_Buffer buff, unsigned length);#endif /* ... else raw ... *//* * The control functions and interface */static const SerialControl dcc_ctrl ={#if !defined(RAW_DCC) || (RAW_DCC == 0)    &dcc_rx_tx_state,    NULL,    serpkt_int_tx_processing,    serpkt_int_rx_processing,#else    NULL,    &dcc_raw_state,    serraw_int_tx_processing,    serraw_int_rx_processing,#endif    0,                          /* only one DCC device, ident not used */    &dcc_tx_ring,    &dcc_rx_ring,    dcc_ControlTx,    dcc_ControlRx,    dcc_Control,    dcc_KickStartFn};/* Publically-accessible globals *//* * The device table entry for this device */const struct angel_DeviceEntry angel_DccDevice ={#if !defined(RAW_DCC) || (RAW_DCC == 0)    DT_ANGEL,    {        serpkt_AsyncWrite,        serpkt_RegisterRead    },    serpkt_Control,#else    DT_RAW,    {            /*             * We need our own veneer before the serraw versions, to             * ensure transfers are multiples of four bytes.             *             * Nasty but necessary casts, as can only statically initialise             * the first member of a union             */        (angel_DeviceWriteFn) dcc_RawWrite,        (angel_DeviceRegisterReadFn) dcc_RawRead    },    serraw_Control,#endif    &dcc_ctrl,    {        0, NULL    },    {        0, NULL    }};/* Private globals *//* status of DCC registers */static unsigned int dccflags = 0;static unsigned int ringBufGetWord(RingBuffer * ring){    int c;    unsigned int res = 0;    for (c = 0; c < 32; c += 8)    {        if (ring->count != 0)            res |= (ringBufGetChar(ring) << c);    }    return res;}#pragma no_check_stack/* *  Function: dcc_KickStartFn *   Purpose: Kick-start tx by sending first character * *    Params: *       Input: devid   device ID of the driver * *   Returns: Nothing */static void dcc_KickStartFn(DeviceID devid){    RingBuffer *ring = &dcc_tx_ring;    IGNORE(devid);    dccflags = dcc_GetFlags();    if ( /* dcc_CanWrite() */ ((dccflags & 0x2) == 0))    {        unsigned int dcw = ringBufGetWord(ring);        LogInfo(LOG_DCCDRV, ("\nkickstarting } 0x%8x, ", dcw));        dcc_PutWord(dcw);    }}DevError dcc_PollWrite(DeviceID devid){    volatile unsigned int *const status = angel_DeviceStatus + devid;    RingBuffer *ring = &dcc_tx_ring;    if ((ringBufCount(ring) >= 4) ||        ((ringBufCount(ring) > 0) && ((*status) & SER_TX_EOD)))    {        dccflags = dcc_GetFlags();        if ((dccflags & 0x2) == 0)        {            unsigned int dcw;            bool do_tx_processing = FALSE;            dcw = ringBufGetWord(ring);            LogInfo(LOG_WIRE, ("> 0x%x, ", dcw));            dcc_PutWord(dcw);            /*             * if we have reached to low-water mark in the             * ring buffer then it is time to ask for a refill,             * as long as there is more of the packet to come             */            if ((ring->count < RING_LOW_WATER_MARK)                && !((*status) & SER_TX_EOD))                do_tx_processing = TRUE;            /*             * is it time to give up yet?             */            if (ringBufEmpty(ring))            {                /*                 * if the end of the packet has been sent,                 * then queue deferred processing of this fact                 */                if ((*status) & SER_TX_EOD)                {                    do_tx_processing = TRUE;                    /* disable Tx if necessary */                    (*status) &= ~SER_TX_DATA;                }            }            if (do_tx_processing)                SerCtrl(devid)->tx_processing((void *)devid);        }        else        {            /* waiting for previous tx word to complete */            return DE_OKAY;        }    }    return DE_OKAY;}DevError dcc_PollRead(DeviceID devid){    RingBuffer *ring = &dcc_rx_ring;    dccflags = dcc_GetFlags();    /*  if (dcc_CanRead()) { */    if (dccflags & 0x1)    {        bool etx = FALSE;        int c;        unsigned int new_word;        RawState *const raw_state = dcc_ctrl.raw_state;        new_word = dcc_GetWord();        /* dcc is word based, we need to process byte-wise though */        for (c = 0; c < 32; c += 8)        {            char new_ch = (new_word >> c) & 0xFF;            LogInfo(LOG_WIRE, ("< 0x%2x, ", new_ch));            ringBufPutChar(ring, new_ch);            if (raw_state != NULL && raw_state->rx_to_go > 0)                --(raw_state->rx_to_go);            else if (new_ch == serial_ETX)                etx = TRUE;        }        LogInfo(LOG_WIRE, ("\n"));        if ((raw_state == NULL && etx)            || (raw_state != NULL && raw_state->rx_to_go == 0                && raw_state->rx_data != NULL)            || (ringBufCount(ring) >= RING_HIGH_WATER_MARK))        {            SerCtrl(devid)->rx_processing((void *)devid);        }    }    return DE_OKAY;}/* *  Function: dcc_init *   Purpose: Initialise the dcc port * *    Params: *       Input: devid   device ID of the driver * *   Returns: status from device reset */static DevError dcc_init(const DeviceID devid){    DevError err;    volatile unsigned int *const status = angel_DeviceStatus + devid;    LogInfo(LOG_DCCDRV, ("dcc_init\n"));    /* do one-time start-up initialisation */    /* reset private flags (LEAVE lowest 8 bits alone) */    (*status) &= 0xFF;    /* do a reset, via the framework */    Angel_ExitToUSR();          /* because DeviceControl requires it */#if defined(MINIMAL_ANGEL) && MINIMAL_ANGEL != 0    err = Angel_RawDeviceControl(devid, DC_RESET, NULL);#else    err = angel_DeviceControl(devid, DC_RESET, NULL);#endif    Angel_EnterSVC();    return err;}/* *  Function: dcc_reset *   Purpose: Reset the dcc port * *    Params: *       Input: devid   device ID of the driver *  * *   Returns: DE_OKAY */static DevError dcc_reset(DeviceID devid){    IGNORE(devid);    LogInfo(LOG_DCCDRV, ("dcc_reset\n"));    return DE_OKAY;}static DevError dcc_Control(DeviceID devid, DeviceControl op, void *arg){    DevError ret_code;    IGNORE(arg);    IGNORE(devid);    LogInfo(LOG_DCCDRV, ("dcc_Control: op %d arg %x\n", op, arg));    /* we only implement the standard ones here */    switch (op)    {        case DC_RESET:            ret_code = dcc_reset(devid);            break;        case DC_INIT:            ret_code = dcc_init(devid);            break;        default:            LogInfo(LOG_DCCDRV, ("dcc_Control defualt case taken - op=0x%x\n", op));            ret_code = DE_BAD_OP;            break;    }    return ret_code;}#if !defined(RAW_DCC) || (RAW_DCC == 0)  /* Angel/shared */static void dcc_flow_control(char fc_char, void *cb_data){    IGNORE(fc_char);    IGNORE(cb_data);    LogInfo(LOG_DCCDRV, ("dcc_flowcontrol\n"));    /* shouldn't have any flow control on this device */    return;}#endif/* dummies - no Interrupt control required, fully polled device */static void dcc_ControlTx(DeviceID devid){    IGNORE(devid);}static void dcc_ControlRx(DeviceID devid){    IGNORE(devid);}#if defined(RAW_DCC) && (RAW_DCC > 0)  /* raw */static DevError dcc_RawWrite(DeviceID devid, p_Buffer buff, unsigned length){    if ((length % 4) != 0)        return DE_INVAL;    else        return serraw_Write(devid, buff, length);}static DevError dcc_RawRead(DeviceID devid, p_Buffer buff, unsigned length){    if ((length % 4) != 0)        return DE_INVAL;    else        return serraw_Read(devid, buff, length);}#endif /* raw *//* EOF dccdrv.c */

⌨️ 快捷键说明

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