网站公告列表

  没有公告

加入收藏
设为首页
联系站长
您现在的位置: 61IC中国电子在线 >> DSP >> 代码示例 >> TI DSP代码示例 >> C6000 >> 文章正文
  TMS320C64XX串口PCI(C)代码程序         ★★★ 【字体:
TMS320C64XX串口PCI(C)代码程序
作者:61IC    文章来源:本站原创    点击数:    更新时间:2007-1-16    

/*
 *  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)" */
/*
 *  ======== c64xx_pci.c ========
 *
 *  DSP/BIOS PCI IOM mini-driver for the c64xx DSPs
 *  Uses the  BIOS PCI Chip Support Library(CSL).
 */
#include <std.h>
#include <csl_pci.h>
#include <hwi.h>
#include <mem.h>
#include <que.h>

#include <iom.h>
#include <c64xx_pci.h>

 

/* PCI Interrupt mapped to HWI Vector 4 */
#define ISR_VECTOR_ID   4

#define GET_BYTE_COUNT(count) \
        (((count)<< 16) & C64XX_PCI_MASK_PCIMC_CNT)

#define CALLBACK(chan, packet, result) { (packet)->status = (result);\
            ((chan)->callback)((Ptr)(chan)->callbackArg, (packet));}

/* Channel variables */
typedef struct ChanObj {
    QUE_Handle          queue; /* priority queue */
    Uns                 writeCount; /* count for number of IOM_WRITE IOPs */
    IOM_Packet          *flushAbortIop; /* hold IOM_FLUSH/IOM_ABORT IOP */
    /* callback used to notify client when I/O complete */
    IOM_TiomCallback    callback;
    Ptr                 callbackArg;
} ChanObj, *ChanHandle;

/* Device object */
typedef struct PCIDeviceObj
{
    IOM_Packet                  *curPacket; /* current packet in process */
    QUE_Obj                     highPrioQue;
    QUE_Obj                     lowPrioQue;
    C64XX_PCI_TerrCallback      errCallback; /* async error callback */
    Uns                         evtMask; /* registered events ored together */
    C64XX_PCI_ErrInfo           *errInfo; /* detailed info for async error */
    Int                         openCount; /* count number of open channels */
} PCIDeviceObj, PCIDeviceHandle;

/* static device object */
static PCIDeviceObj device;

static Void doTransfer(C64XX_PCI_Request *request);
static Void isr();
#ifdef PCI_ERROR_ISR_IMPL
static Void pciErrorIsr();
#endif
static Void processQueue();
static Void removePackets(Ptr chanp, Int cmd);
static Void resetChannel(Ptr chanp);
static Void resetDevice();

/*
 * Forward declaration of mini driver interface functions. They are only
 * exposed via the IOM_Fxns function table to avoid namespace pollution.
 */
static Int      mdBindDev(Ptr *devp, Int devid, Ptr devParams);
static Int      mdControlChan(Ptr chanp, Uns command, Ptr arg);
static Int      mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
        Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg);
static Int      mdDeleteChan(Ptr chanp);
static Int      mdSubmitChan(Ptr chanp, IOM_Packet* pPacket);
static Int      mdUnBindDev(Ptr devp);

/*
 * Public mini driver interface table.
 */
IOM_Fxns C64XX_PCI_FXNS = {
    &mdBindDev,
    &mdUnBindDev,
    &mdControlChan,
    &mdCreateChan,
    &mdDeleteChan,
    &mdSubmitChan
};

/*
 *  ======== mdBindDev ========
 *  This function will init the queues, set up interrupt.
 *  it does not allocate memory, so return NULL. 
 */
static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams)
{
    Int intrId;
    C64XX_PCI_DevParams *pciDevParams = (C64XX_PCI_DevParams *)devParams;
    HWI_Attrs hwiAttrs;

    QUE_new(&device.highPrioQue);
    QUE_new(&device.lowPrioQue);
   
    device.curPacket = NULL;
    device.openCount = 0;
   
    if (pciDevParams != NULL) {
        /* Check the version number */
        if (pciDevParams->versionId != C64XX_PCI_VERSION_1){
           /* Unsupported version */
           return(IOM_EBADARGS);
        }
        if (pciDevParams->pciIntrId > 0) {
           intrId = pciDevParams->pciIntrId;
        }
        else {
           intrId = ISR_VECTOR_ID;
        }
       
        hwiAttrs.intrMask = pciDevParams->intrMask;

        if (pciDevParams->errCallback != NULL) {
            device.errCallback = pciDevParams->errCallback->errFxn;
            device.evtMask = pciDevParams->errCallback->evtMask;
            device.errInfo = pciDevParams->errCallback->errInfo;
        }
        else {
            device.errCallback = NULL;
        }

#ifdef PCI_ERROR_ISR_IMPL
        /*
         *  pciErrIntrId plug in depend on board hardware design.
         *  ERR_ISR_VECTOR_ID: TBD.
         */
       
        Int pciErrIntrId;
        if (pciDevParams->pciErrIntrId > 0) {
            pciErrIntrId = pciDevParams->pciErrIntrId;
        }
        else {
            pciErrIntrId = ERR_ISR_VECTOR_ID;
        }
#endif
    }
    else {
        intrId = ISR_VECTOR_ID;
        hwiAttrs.intrMask = C64XX_PCI_INTR_MASK_DEFAULT;
        device.errCallback = NULL;
    }
   
    hwiAttrs.ccMask = IRQ_CCMASK_NONE; /* the default value */
    hwiAttrs.arg = NULL;

    /* plug in normal pci isr routine */
    IRQ_map(IRQ_EVT_DSPINT, intrId);
    /* dmachan parameter set to -1 since 6416 has EDMA instead of DMA */ 
    HWI_dispatchPlug(intrId, (Fxn)isr, -1, &hwiAttrs);

#ifdef PCI_ERROR_ISR_IMPL
    /* plug in error pci isr routine if registered. IRQ_EVT_XXX: TBD. 
     * need to enable two bits in PCI Command Register: TBD
     *          bit6 - parity error reporting enable bit
     *          bit8 - system error reporting ebable bit
     */
    IRQ_map(IRQ_EVT_XXX, pciErrIntrId);
    HWI_dispatchPlug(pciErrIntrId, (Fxn)pciErrIsr, -1, NULL);
    IRQ_enable(IRQ_EVT_XXX);
#endif

    return (IOM_COMPLETED);
   
}

/*
 *  ======== mdControlChan ========
 *  This function could be implemented by using function table, avoid complier
 *  link each function and also avoid using "switch" call.
 *  return status 
 */
static Int mdControlChan(Ptr chanp, Uns command, Ptr arg)
{
    C64XX_PCI_EEPROMData *promData = (C64XX_PCI_EEPROMData *)arg;
    Uns                   result;
    Uns                   imask;
   
#ifdef TEST_ERROR_HANDLER
    Bool report;
    C64XX_PCI_Request *req;
    IOM_Packet *packet;
    Uns error;
    Uns event;
#endif
   
    switch (command) {
        /* EEPROM call. */
        case C64XX_PCI_EEPROM_ERASE:
            promData->eeData = PCI_eepromErase((Uns)promData->eeAddr);
            return (IOM_COMPLETED);
        case C64XX_PCI_EEPROM_ERASE_ALL:
            promData->eeData = PCI_eepromEraseAll();
            return (IOM_COMPLETED);
        case C64XX_PCI_EEPROM_IS_AUTO_CFG:
            promData->eeData = PCI_eepromIsAutoCfg();
            return (IOM_COMPLETED);
        case C64XX_PCI_EEPROM_READ:
            promData->eeData = PCI_eepromRead((Uns)promData->eeAddr);
            return (IOM_COMPLETED);
        case C64XX_PCI_EEPROM_SIZE:
            promData->eeData = PCI_eepromSize();
            return (IOM_COMPLETED);
        case C64XX_PCI_EEPROM_TEST:
            promData->eeData = PCI_eepromTest();
            return (IOM_COMPLETED);
        case C64XX_PCI_EEPROM_WRITE:
            result = PCI_eepromWrite((Uns)promData->eeAddr, promData->eeData);
            promData->eeData = result;
            return (IOM_COMPLETED);
        case C64XX_PCI_EEPROM_WRITE_ALL:
            result = PCI_eepromWriteAll(promData->eeData);
            promData->eeData = result;
            return (IOM_COMPLETED);

        /* Host interrupt call */
        case C64XX_PCI_DSP_INT_REQ_SET:
            PCI_dspIntReqSet();
            return (IOM_COMPLETED);
        case C64XX_PCI_DSP_INT_REQ_CLEAR:
            PCI_dspIntReqClear();
            return (IOM_COMPLETED);

        /* reset calls */
        case C64XX_PCI_RESET_CHANNEL:
            resetChannel(chanp);
            return (IOM_COMPLETED);     
        case C64XX_PCI_RESET_ALL_CHANNELS:
            resetDevice();
            return (IOM_COMPLETED);           
#ifdef TEST_ERROR_HANDLER
        case C64XX_PCI_TEST_ERROR_HANDLER:
    error = 0;
    report = FALSE;
    event = *((Uns *)arg);
    imask = HWI_disable();
    if (device.errCallback == NULL) {
        HWI_restore(imask);
        return (IOM_COMPLETED);       
    }
    if ((event == C64XX_PCI_EVT_PARITY_ERR) &&
            (device.evtMask & C64XX_PCI_EVT_PARITY_ERR)) {
        error = error | C64XX_PCI_EVT_PARITY_ERR;
        report = TRUE;
    }
    else if ((event == C64XX_PCI_EVT_SYSTEM_ERR) &&
            (device.evtMask & C64XX_PCI_EVT_SYSTEM_ERR)) {
        error = error | C64XX_PCI_EVT_SYSTEM_ERR;
        report = TRUE;
    }

    if (!report) {
        HWI_restore(imask);
        return (IOM_COMPLETED);
    }

    if (device.curPacket != NULL) {
        packet = device.curPacket;
        req = (C64XX_PCI_Request *)packet->addr;
        device.errInfo->inprogressDstAddr = req->dstAddr;
        device.errInfo->inprogressSrcAddr = req->srcAddr;
        /* device.errInfo->statusReg = PCI_STATUS_REGISTER; */
    }
    else {
        device.errInfo->inprogressDstAddr = NULL;
        device.errInfo->inprogressSrcAddr = NULL;
        /* device.errInfo->statusReg = PCI_STATUS_REGISTER; */
    }

    (device.errCallback)(error, (Ptr)device.errInfo);
    HWI_restore(imask);
    return (IOM_COMPLETED);
#endif
        default:
            break;
    }
   
    return (IOM_ENOTIMPL);     
}


/*
 *  ======== mdCreateChan ========
 *  This function allocates memory for channel object and initializes it.
 *  return IOM_COMPLETED if success return IOM_EALLOC if fails
 */
static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
        Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg)
{
    ChanHandle          chan;  
    C64XX_PCI_Attrs     *pciAttrs = (C64XX_PCI_Attrs *)chanParams;
    Uns                 imask;
   
    chan = MEM_alloc(0, sizeof(ChanObj), 0);
    if ( chan == MEM_ILLEGAL ) {
        return (IOM_EALLOC);
    }
 
    if (mode != IOM_INOUT) {
        return (IOM_EBADMODE);
    }

    /* Initialize the channel structure */
    if ( pciAttrs != NULL &&
            pciAttrs->queuePriority == C64XX_PCI_QUEUE_PRIORITY_HIGH) {
        chan->queue = &device.highPrioQue;
    }
    else {
        chan->queue = &device.lowPrioQue;   
    }
   
    chan->writeCount = 0;
    chan->flushAbortIop = NULL;
    chan->callback = cbFxn;
    chan->callbackArg = cbArg;
        
    imask = HWI_disable();
    if (device.openCount == 0) {
        /* enable PCI events */
        PCI_intEnable(PCI_EVT_PCIMASTER);
        PCI_intEnable(PCI_EVT_PCITARGET);
        PCI_intEnable(PCI_EVT_MASTEROK);

        IRQ_enable(IRQ_EVT_DSPINT);
    }
    device.openCount++;
    HWI_restore(imask);

    *chanp = chan;

    return (IOM_COMPLETED);
}

/*
 *  ======== mdDeleteChan ========
 *  frees memory
 *  return status
 */
static Int mdDeleteChan(Ptr chanp)
{
    ChanHandle  chan = (ChanHandle)chanp;
    Uns                 imask;

    MEM_free(0, chan, sizeof(ChanObj));

    imask = HWI_disable();
    device.openCount--;
    if (device.openCount == 0) {
        /* disable PCI events */
        PCI_intDisable(PCI_EVT_PCIMASTER);
        PCI_intDisable(PCI_EVT_PCITARGET);
        PCI_intDisable(PCI_EVT_MASTEROK);

        IRQ_disable(IRQ_EVT_DSPINT);
    }
    HWI_restore(imask);

    return (IOM_COMPLETED);
}

/*
 *  ======== mdSubmitChan ========
 *  return submit status
 */
static Int mdSubmitChan(Ptr chanp, IOM_Packet *pPacket)
{
    ChanHandle          chan = (ChanHandle)chanp;
    IOM_Packet*         packet = pPacket;
    Uns                 imask;
    C64XX_PCI_Request  *req;   
    C64XX_PCI_Request  *curReq;

    req = (C64XX_PCI_Request *)packet->addr;
    req->reserved = chan;
   
    /* IOM_READ or IOM_WRITE command handle in the same way */
    if (packet->cmd == IOM_READ || packet->cmd == IOM_WRITE) {

        imask = HWI_disable();
        QUE_enqueue(chan->queue, packet);

        if (device.curPacket == NULL) {
#ifndef TEST_RESET
            processQueue();
#endif
        }
        HWI_restore(imask);
        return (IOM_PENDING);
    }

    if (packet->cmd == IOM_FLUSH || packet->cmd == IOM_ABORT) {
       
        imask = HWI_disable();
        chan->flushAbortIop = packet;

        /* check the channel of pending packet */
        if (device.curPacket != NULL) {
                curReq = (C64XX_PCI_Request *)device.curPacket->addr;

            /* The pending packet is this channel. Let isr handles it */
            if ((ChanHandle)curReq->reserved == chan) {
                HWI_restore(imask);        
                return (IOM_PENDING);
            }
        }        
       
        /* the pending packet is not FLUSH/ABORT channel */
        removePackets(chan, packet->cmd);

        /* FLUSH/ABORT done */
        if (chan->writeCount == 0) {
            chan->flushAbortIop = NULL;
            HWI_restore(imask);
            return (IOM_COMPLETED);
        }                  

        HWI_restore(imask);        
        return (IOM_PENDING);
    }  
    return (IOM_EBADIO);
}

/*
 *  ======== mdUnBindDev ========
 *  return status
 */

static Int mdUnBindDev(Ptr devp)
{
    /* empty for now */
    return (IOM_COMPLETED);
}

/*
 *  ======== C64XX_PCI_init ========
 */
Void C64XX_PCI_init(Void)
{
    /* empty for now */
}


/*
 *  ======== isr ========
 *  interrupt service routine is runtime pluged in
 */
static Void isr(Void)
{
    ChanHandle          chan;
    IOM_Packet          *oldPacket;
    C64XX_PCI_Request   *oldReq;        
    Int                 status = IOM_EBADIO;
   
    if (PCI_FGET(PCIIS, MASTEROK)) {
        /* pci master transfer complete */      
        PCI_FSET(PCIIS, MASTEROK, 1);
        status = IOM_COMPLETED;
       
    }
    else if (PCI_FGET(PCIIS, PCIMASTER)) {
        /* pci master abort */
        PCI_FSET(PCIIS, PCIMASTER, 1);
       
    }
    else if (PCI_FGET(PCIIS, PCITARGET)) {
        /* pci target abort */
        PCI_FSET(PCIIS, PCITARGET, 1);
       
    }
    else {
        /* not registered interrupt, clear intr here */
        PCI_RSET(PCIIS, 0x00000FFF);
        /* error handling TBD */
        return;
    }

    if (device.curPacket != NULL) {
        oldPacket = device.curPacket;
        oldReq = (C64XX_PCI_Request *)oldPacket->addr;
        chan = (ChanHandle)oldReq->reserved;
        
        device.curPacket = NULL;

        if (chan->flushAbortIop == NULL) {
            /* normal. process next request in the queues */
            processQueue();
           
            /* callback */
            CALLBACK(chan,oldPacket,status);  
            return;
        }
       
        /* flush or abort cmd */
        /* first do callback */
        CALLBACK(chan,oldPacket,status);
                    
        if (chan->writeCount) {
           chan->writeCount--;             
        }
        else {
           removePackets(chan, chan->flushAbortIop->cmd);
        }
           
        /* process next request in the queues */
        processQueue();   

        /* if all write IOPs are done, call the callback for the FLUSH IOP */
        if (chan->writeCount == 0) {
           CALLBACK(chan,chan->flushAbortIop,IOM_COMPLETED);
           chan->flushAbortIop = NULL;  
        }
        return;
    }

    /* process next request in the queues */
    processQueue();
}

/*
 *  ======== pciErrorIsr ========
 *  interrupt service routine is runtime pluged in for asynchronous error TBD
 */
#ifdef PCI_ERROR_ISR_IMPL
static Void pciErrorIsr(Void)
{
    /* How to check PCI status register to identify the error source --
    parity/system: TBD (on C6416, not accessable) use 'event' here to
    represent the status register related content */
   
    Bool report = FALSE;
    Uns error = 0;
    C64XX_PCI_Request *req;
    IOM_Packet *packet;

    if (device.errCallback == NULL) {
        return;
    }
    if ((event == C64XX_PCI_EVT_PARITY_ERR) &&
            (device.evtMask & C64XX_PCI_EVT_PARITY_ERR)) {
        error = error | C64XX_PCI_EVT_PARITY_ERR;
        report = TRUE;
    }
    else if ((event == C64XX_PCI_EVT_SYSTEM_ERR) &&
            (device.evtMask & C64XX_PCI_EVT_SYSTEM_ERR)) {
        error = error | C64XX_PCI_EVT_SYSTEM_ERR;
        report = TRUE;
    }

    if (!report) {
        return;
    }

    if (device.curPacket != NULL) {
        packet = device.curPacket;
        req = (C64XX_PCI_Request *)packet->addr;
        device.errInfo->inprogressDstAddr = req->dstAddr;
        device.errInfo->inprogressSrcAddr = req->srcAddr;
        device.errInfo->statusReg = PCI_STATUS_REGISTER;
    }
    else {
        device.errInfo->inprogressDstAddr = NULL;
        device.errInfo->inprogressSrcAddr = NULL;
        device.errInfo->statusReg = PCI_STATUS_REGISTER;
    }

    (device.errCallback)(error, (Ptr)device.errorInfo);
    
}
#endif


/*
 *  ======== doTransfer ========
 */
static Void doTransfer(C64XX_PCI_Request *request)
{
    C64XX_PCI_Request   *req = request;
    PCI_ConfigXfr       config;
    Uns                 xfrMode;
        
    xfrMode = C64XX_PCI_GETXFERMODE(request->options);
       
    if (xfrMode == PCI_WRITE) {
        config.dspma = (Uns)req->srcAddr;
        config.pcima = (Uns)req->dstAddr;
        config.pcimc = GET_BYTE_COUNT(req->byteCnt);
                                 
    }
    else if (xfrMode ==  PCI_READ_PREF || xfrMode ==  PCI_READ_NOPREF) {
        config.dspma = (Uns)req->dstAddr;
        config.pcima = (Uns)req->srcAddr;
        config.pcimc = GET_BYTE_COUNT(req->byteCnt);                   
    }
       
    PCI_xfrConfig(&config);
    PCI_xfrStart(xfrMode);     
}


/*
 *  ======== processQueue ========
 */
static Void processQueue()
{
    QUE_Handle          que;
    C64XX_PCI_Request   *req;

    que = &device.highPrioQue;
    /* process next packet in queue */ 
    if (QUE_empty(que)) {
        que = &device.lowPrioQue;
        if (QUE_empty(que)) {
            return;
        }
    }
    device.curPacket = QUE_dequeue(que);
    req = (C64XX_PCI_Request *)device.curPacket->addr;
    doTransfer(req);                    
}

/*
 *  ======== removePackets ========
 */
static Void removePackets(Ptr chanp, Int cmd)
{          
    ChanHandle          chan = (ChanHandle)chanp;
    QUE_Elem            *next;
    QUE_Elem            *current;
    C64XX_PCI_Request  *curReq; 
    Int                 status;

    if (cmd != IOM_FLUSH && cmd != IOM_ABORT) {
        return;
    }
   
    current = QUE_head(chan->queue);
    curReq = (C64XX_PCI_Request *)((IOM_Packet *)current)->addr;
  
    while (chan->queue != current) {
        next = QUE_next(current);
         
        /* check the channel of the each IOM_Packet in the queue */
        /* find the match. The packet and remove channels are identical */
        if ((ChanHandle)curReq->reserved == chan) {
            /* for write flush wait for complete */
            if ( cmd == IOM_FLUSH &&
                    ((IOM_Packet *)current)->cmd == IOM_WRITE ) {
                chan->writeCount++;
            } else {
                /* for read flush or abort, do flush */
                if (cmd == IOM_FLUSH) {
                    status = IOM_FLUSHED;
                }
                else {
                    status = IOM_ABORTED;
                }
                QUE_remove(current);
                CALLBACK(chan, (IOM_Packet *)current, status);
            }
        }
         
        current = next;
        curReq = (C64XX_PCI_Request*)((IOM_Packet *)current)->addr;     
    } /* end while */
}

/*
 *  ======== resetChannel ========
 */
static Void resetChannel(Ptr chanp)
{
    ChanHandle          chan = (ChanHandle)chanp;
    C64XX_PCI_Request  *curReq;
    Uns                 imask;
   
    imask = HWI_disable();
    /* assume reset async ? */
    if (device.curPacket != NULL) {      
        curReq = (C64XX_PCI_Request *)((IOM_Packet *)device.curPacket)->addr;
        if ((ChanHandle)curReq->reserved == chan) {
            CALLBACK((ChanHandle)curReq->reserved,
                    (IOM_Packet *)device.curPacket, IOM_ABORTED);
            device.curPacket = NULL;
        }    
    }
   
    removePackets(chanp, IOM_ABORT);
    HWI_restore(imask);
}

/*
 *  ======== resetDevice ========
 */
static Void resetDevice()
{
    QUE_Elem            *next;
    QUE_Elem            *current;
    QUE_Handle          queue;
    C64XX_PCI_Request  *curReq;
    Int                 i; 
    Uns                 imask;
   
    imask = HWI_disable();
    /* assume reset async ? */
    if (device.curPacket != NULL) {      
        curReq = (C64XX_PCI_Request *)((IOM_Packet *)device.curPacket)->addr;
         CALLBACK((ChanHandle)curReq->reserved,
                    (IOM_Packet *)device.curPacket, IOM_ABORTED);
        device.curPacket = NULL;     
    }
   
    for (i = 0; i < 2; i++) {
        if (i == 0 ) {
            queue = &device.highPrioQue;     
        }
        else {
            queue = &device.lowPrioQue;
        }
        /* remove all the elements in the high/low priority queue */
        current = QUE_head(queue);
        curReq = (C64XX_PCI_Request *)((IOM_Packet *)current)->addr;
   
        while (queue != current) {
            next = QUE_next(current);
         
            QUE_remove(current);
            CALLBACK((ChanHandle)curReq->reserved,
                    (IOM_Packet *)current, IOM_ABORTED);
                
            current = next;
            curReq = (C64XX_PCI_Request*)((IOM_Packet *)current)->addr;
        } /* end while */       
    } /* end for */
   
    HWI_restore(imask);
}

               欢迎点击进入:TI德州中文网   (国内唯一针对TI应用的中文技术网站)    文章录入:admin    责任编辑:admin 
  • 上一篇文章: 没有了

  • 下一篇文章:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
    没有相关文章
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    站长:61IC 湘ICP备05002478号