?? uartmd.c
字號:
/*
* 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.10.00.23 07-02-03 (ddk-b12)" */
/*
* ======== 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 4 /* 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 + -