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

📄 uartmd.c

📁 DSP/BIOS Driver Developer Kit 1.11 The DSP/BIOS Driver Developer Kit (DDK) provides a selection of
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *  Copyright 2003 by Texas Instruments Incorporated.
 *  All rights reserved. Property of Texas Instruments Incorporated.
 *  Restricted rights to use, duplicate or disclose this code are
 *  granted through contract.
 *  
 */
/* "@(#) DDK 1.11.00.00 11-04-03 (ddk-b13)" */
/*
 *  ======== uartmd.c ========
 */

#include <std.h>
#include <stdlib.h>
#include <string.h>

#include <atm.h>
#include <hwi.h>
#include <iom.h>
#include <que.h>

#include <uartmd.h>
#include <uarthw.h>
#include <circ.h>

#define INPUT           0
#define OUTPUT          1
#define NUMCHANS        2

/*
 * SUPPORTPACKEDCHARS is used for devices that are not byte-addressable
 * where you want to use the UART to transfer full 16-bits of data.  A
 * character is 16-bits on the 54x and 55x.  SUPPORTPACKEDCHARS and the
 * UARTMD_DevParams.packedChars flag are used to specify that full 16-bits
 * of word should be output.  This is useful when using UART to transfer
 * data (not ASCII). UARTs typically support only 8-bit transfers so we
 * need to do 2 transfers per 16-bit word.
 */
#if defined(_54_) || defined(_55_)
#define SUPPORTPACKEDCHARS      1
#else
#define SUPPORTPACKEDCHARS      0
#endif

/*
 * There is one UartChanObj per direction.  This mini-driver must be
 * opened for input and output separately (does not support IOM_INOUT).
 */
typedef struct UartChanObj {
    Uns                 inUse;          /* TRUE if channel is in use */
    Int                 mode;           /* INPUT or OUTPUT */

    struct UartPortObj  *port;          /* to support multiple UART ports */
    
    IOM_Packet          *dataPacket;    /* current active I/O packet */
    Char                *bufptr;        /* pointer within current buf */
    Uns                 bufcnt;         /* size of remaining I/O job */

    QUE_Obj             pendList;       /* IOM_Packets pending I/O go here */

    CIRC_Obj            circ;           /* circular buffer */

    IOM_TiomCallback    cbFxn;          /* to notify client when I/O complete */
    Ptr                 cbArg;          /* argument for cbFxn() */

#if SUPPORTPACKEDCHARS
    Bool                packedChars;    /* TRUE => output all 16 bits */
    Bool                halfWay;        /* TRUE if we're between 1/2 words */
    Char                halfWord;       /* holds 1/2 word */
#endif
 
} UartChanObj, *UartChanHandle;

/*
 * There is one UartPortObj per UART.
 * This mini-driver supports 'NUMPORTS' UART.
 */
typedef struct UartPortObj {
    UARTHW_Handle               hUart;
    UARTMD_TnotifyHandler       notifyFunc;
    Uns                         evtMask;
    UartChanObj                 chans[NUMCHANS];
} UartPortObj, *UartPortHandle;

/*
 * Forward declaration of IOM mini driver interface functions.  These
 * are only exposed via the IOM function table to avoid namespace pollution.
 */
static Int mdBindDev(Ptr *devp, Int devid, Ptr bindParams);
static Int mdControlChan(Ptr chanp, Uns cmd, Ptr arg);
static Int mdCreateChan(Ptr *mdChan, Ptr drvhandle, String name, Int mode, \
        Ptr optArgs, IOM_TiomCallback cbFxn, Ptr cbArg);
static Int mdDeleteChan(Ptr chanp);
static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet);


/*
 * Control functions.  These functions are called by mdControl() for
 * assorted control commmands.
 */
static Int  controlNotify(UartChanHandle chan, UARTMD_NotifyStruct* notify);


/*
 * Submit functions.  These functions are called by mdSubmitChan() for
 * assorted submit commands.
 */
static Int  submitAbort(UartChanHandle chan, IOM_Packet *packet);
static Int  submitFlush(UartChanHandle chan, IOM_Packet *packet);
static Int  submitRead(UartChanHandle chan, IOM_Packet *packet);
static Int  submitWrite(UartChanHandle chan, IOM_Packet *packet);


/* 
 * Callback functions.  These functions are called by the low-level UARTHW
 * ISR for different event types.
 */
static Void cbLineStatus(UartPortHandle port, Int lsrVal);
static Void cbModemStatus(UartPortHandle port, Int msrVal);
static Void cbRxHandler(UartPortHandle port, Int rxVal);
static Void cbTxHandler(UartPortHandle port);


/*
 * Support functions.
 */
static Void getNextPacket(UartChanHandle chan);


/*
 * Public Mini Driver interface table.
 */
IOM_Fxns UARTMD_FXNS =
{
    &mdBindDev,
    IOM_UNBINDDEVNOTIMPL,
    &mdControlChan,
    &mdCreateChan,
    &mdDeleteChan,
    &mdSubmitChan,
};

/*
 * These functions are called by the UARTHW code.
 */
static UARTHW_Tcallback cbFxns[4] = { 
    (UARTHW_Tcallback)cbModemStatus, 
    (UARTHW_Tcallback)cbTxHandler,
    (UARTHW_Tcallback)cbRxHandler, 
    (UARTHW_Tcallback)cbLineStatus
};

/* This mini-driver supports 'NUMPORTS' UARTs. */
#ifdef _64_
#define NUMPORTS        2       /* 2 ports for dual UART on EVMDM642 board */
#else
#define NUMPORTS        1
#endif
static UartPortObj  ports[NUMPORTS];

/*
 *  ======== UARTMD_init ========
 *  UARTMD_init() initializes the data structures used by this mini-driver.
 */
Void UARTMD_init(Void)
{
    Int i, j;

    /* initialize all uartPortObj fields to '0' */
    memset(ports, 0, sizeof(ports));

    for (i=0; i < NUMPORTS; i++) {
        for (j=0; j < NUMCHANS; j++) {
            /* initialize port->chans */
            QUE_new(&ports[i].chans[j].pendList);
            CIRC_new(&ports[i].chans[j].circ);
            ports[i].chans[j].port = &ports[i];
        }
    }
}

/*
 *  ======== mdBindDev ========
 *  mdBindDev() is called by DEV_init() to bind and initialize the hardware. 
 */
static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams)
{
    UARTMD_DevParams *params = (UARTMD_DevParams *)devParams;
    UARTMD_DevParams defaultParams = UARTMD_DEVPARAMS_DEFAULT;
    UARTHW_Handle hUart;

    if ((Uns)devid > NUMPORTS-1) {
        return (IOM_EBADARGS);
    }

    if (params == NULL) {
        params = &defaultParams;
    }

    /* Check if the version number is supported */
    if (params->versionId != UARTMD_VERSION_1){
        /* Unsupported version */
        return(IOM_EBADARGS);
    }

#if SUPPORTPACKEDCHARS
    ports[devid].chans[INPUT].packedChars = params->packedChars;
    ports[devid].chans[OUTPUT].packedChars = params->packedChars;
#endif

    hUart = UARTHW_open(devid, params->uarthwParams, &ports[devid], cbFxns);

    if (hUart != NULL) {
        ports[devid].hUart = hUart;
        *devp = &ports[devid];
        return (IOM_COMPLETED);
    }
    else {
        return (IOM_EBADIO);
    }
}

/*
 *  ======== mdControlChan ========
 *  The Mini driver ctrl function. Catch all for adding device or vendor
 *  specific functionality to a mini driver.
 */
static Int mdControlChan(Ptr chanp, Uns cmd, Ptr arg)
{
    UartChanHandle chan = (UartChanHandle)chanp;
    UARTHW_Handle hUart = chan->port->hUart;
    Int status;

    if (cmd == UARTMD_REGISTER_NOTIFY) {
        status = controlNotify(chan, arg);
    } 
    else if (cmd == UARTMD_SETBREAK) {
        status = UARTHW_setBreak(hUart, ArgToInt(arg));
    } 
    else if (cmd == UARTMD_GETMODEMSTATUS) {
        status = UARTHW_getModemStatus(hUart, (char*)arg);
    } 
    else if (cmd == UARTMD_SETRTS) {
        status = UARTHW_setRTS(hUart, ArgToInt(arg));
    } 
    else if (cmd == UARTMD_SETDTR) {
        status = UARTHW_setDTR(hUart, ArgToInt(arg));
    } 
    else {
        status = IOM_ENOTIMPL;
    }
        
    return (status);    
}

/*
 *  ======== mdCreateChan ========
 */
static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode, \
                         Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg)
{
    UartChanHandle      chan;
    UartPortHandle      port = (UartPortHandle)devp;
               
    if (mode == IOM_INPUT) {
        chan = &port->chans[INPUT];
        chan->mode = INPUT;
    }
    else if (mode == IOM_OUTPUT) {
        chan = &port->chans[OUTPUT];
        chan->mode = OUTPUT;
    }
    else {
        return (IOM_EBADMODE);
    }
        
    if (ATM_setu(&chan->inUse, TRUE)) {
        return (IOM_EINUSE);
    }

    /*
     * Save the callback function and argument.  cbFxn() is called every
     * time an I/O job completes.
     */
    chan->cbFxn = cbFxn;
    chan->cbArg = cbArg;

    /* chanp will be passed to subsequent mini-driver calls */
    *chanp = chan;
    
    return (IOM_COMPLETED);             
}

/*
 *  ======== mdDeleteChan ========
 *  Deletes an instance of the UART channel. 
 *  All I/O jobs must be completed prior to calling mdDelete().
 */
static Int mdDeleteChan(Ptr chanp)
{
    UartChanHandle chan = (UartChanHandle)chanp;
   
    chan->inUse = FALSE;
        
    return (IOM_COMPLETED);
}

/*
 *  ======== mdSubmitChan ========
 *  The main entry point to the mini driver for read / write operations.
 *  mdSubmitChan() also handles the flush and abort operations.
 */
static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet)
{
    Uns cmd = (packet->cmd);
    Int status;
    
    if (cmd == IOM_READ){
        status = submitRead(chanp, packet);
    }
    else if (cmd == IOM_WRITE){
        status = submitWrite(chanp, packet);
    }
    else if (cmd == IOM_ABORT){
        status = submitAbort(chanp, packet);
    }
    else if (cmd == IOM_FLUSH){
        status = submitFlush(chanp, packet);
    }
    else {
        status = IOM_ENOTIMPL; 
    }
  
    return (status);
}


/*
 *  -------- control functions --------
 */

/*
 *  ======== controlNotify ========
 *  The local routine to handle application call to set the
 *  notification callback and events for which it desires
 *  notifications.
 */
static Int controlNotify(UartChanHandle chan, UARTMD_NotifyStruct * notify)
{
    chan->port->evtMask = notify->evtMask;
    chan->port->notifyFunc = notify->notifyFunc;
  
    return (IOM_COMPLETED);
}


/*
 *  -------- submit functions --------
 */

/*
 *  ======== submitAbort ========
 *  The local routine to handle an IOM_ABORT command.
 */
static Int submitAbort(UartChanHandle chan, IOM_Packet *packet)
{
    IOM_Packet  *dataPacket;
    Uns         imask;
    CIRC_Handle circ = &chan->circ;

    /*
     * Atomically save dataPacket and set chan->dataPacket to NULL.
     * 'chan->dataPacket' is used to synchronize with the ISR.  If the
     * ISR sees chan->dataPacket == NULL, it will not attempt to
     * reload any packets from the pendList.
     */
    imask = HWI_disable();
    CIRC_reset(circ);
    dataPacket = chan->dataPacket;
    chan->dataPacket = NULL;            /* stop all active I/O */

#if SUPPORTPACKEDCHARS
    chan->halfWay = FALSE;
#endif
    
    HWI_restore(imask);

    /*
     * Return all packets in order with their status tagged as aborted.
     * Since chan->dataPacket was set to NULL above, we don't need to
     * worry about synchronizing with the ISR.
     */

    /*
     * Return active dataPacket first.
     */ 
    if (dataPacket != NULL) {
        dataPacket->status = IOM_ABORTED;
        chan->cbFxn(chan->cbArg, dataPacket);
    }

    /*
     * Now remove remaining packets from the pending list and call
     * the callback one at a time.  We use QUE_get() here for code size
     * savings, but we could use QUE_dequeue() since ISR will not
     * reference this queue.
     */
    dataPacket = QUE_get(&chan->pendList);
    while (dataPacket != (IOM_Packet *)&chan->pendList) {
        dataPacket->status = IOM_ABORTED;
        chan->cbFxn(chan->cbArg, dataPacket);

        dataPacket = QUE_get(&chan->pendList);
    }

⌨️ 快捷键说明

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