c55xx_dma_mcbsp.c
上传用户:dahaojd
上传日期:2008-01-29
资源大小:14357k
文件大小:12k
- /*
- * 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)" */
- /*
- * ======== c55xx_dma_mcbsp.c ========
- */
- #include <std.h>
- #include <atm.h>
- #include <hwi.h>
- #include <que.h>
- #include <csl.h>
- #include <csl_dma.h>
- #include <csl_irq.h>
- #include <csl_mcbsp.h>
- #include <iom.h>
- #include <c55xx_dma_mcbsp.h>
- #define NUMPORTS MCBSP_PORT_CNT
- #define NUMCHANS 2 /* IOM_INPUT and IOM_OUTPUT */
- #define INPUT 0
- #define OUTPUT 1
- /* Channel Object -- intialized by mdCreateChan() */
- typedef struct ChanObj {
- Uns inUse; /* TRUE => channel has been opened */
- Uns dmaId; /* DMA channel */
- void *devp; /* needed for McBSP access */
- DMA_Handle hDma; /* DMA handle */
- IOM_Packet *flushPacket; /* used for submit/IOM_FLUSH/output */
- IOM_Packet *dataPacket; /* current active I/O packet */
- QUE_Obj pendList; /* list of packets for I/O */
- IOM_TiomCallback cbFxn; /* used to notify client when I/O complete */
- Ptr cbArg;
- } ChanObj, *ChanHandle;
- #define CHANOBJINIT {
- FALSE, /* inUse */
- 0, /* dmaId */
- NULL, /* devp */
- NULL, /* hDma */
- NULL, /* flushPacket */
- NULL, /* dataPacket */
- { NULL, NULL }, /* pendList */
- NULL, /* cbFxn */
- NULL /* cbArg */
- }
- /* Device Object -- intialized by mdBindDev() */
- typedef struct PortObj {
- Uns inUse;
- MCBSP_Handle hMcbsp; /* McBSP handle */
- ChanObj chans[NUMCHANS];
- Uns rxIerMask[2];
- Uns txIerMask[2];
- } PortObj, *PortHandle;
- #define PORTOBJINIT {
- FALSE, /* inUse */
- NULL, /* hMcbsp */
- { /* chans */
- CHANOBJINIT,
- CHANOBJINIT
- },
- {
- NULL,
- NULL
- },
- {
- NULL,
- NULL
- }
- }
- #if NUMPORTS == 2
- static PortObj ports[NUMPORTS] = {
- PORTOBJINIT,
- PORTOBJINIT
- };
- #elif NUMPORTS == 3
- PortObj ports[NUMPORTS] = {
- PORTOBJINIT,
- PORTOBJINIT,
- PORTOBJINIT
- };
- #else
- #error Number of serials ports undefined!!
- #endif
- /*
- * Forward declaration of IOM interface functions.
- */
- static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams);
- static Int mdControlChan(Ptr chanp, Uns cmd, Ptr args);
- 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 *packet);
- /*
- * Public IOM interface table.
- */
- IOM_Fxns C55XX_DMA_MCBSP_FXNS = {
- mdBindDev,
- IOM_UNBINDDEVNOTIMPL,
- mdControlChan,
- mdCreateChan,
- mdDeleteChan,
- mdSubmitChan,
- };
- /*
- * local functions
- */
- static Void startDma(ChanHandle chan, IOM_Packet *packet);
- static Void dmaIsr(ChanHandle chan);
- static Void abortio(ChanHandle chan);
- /*
- * ======== mdBindDev ========
- */
- #pragma CODE_SECTION(mdBindDev, ".text:init")
- static Int mdBindDev(Ptr *devp, Int devid, Ptr devParams)
- {
- C55XX_DMA_MCBSP_DevParams *params =
- (C55XX_DMA_MCBSP_DevParams *)devParams;
- PortHandle port = (PortHandle)&ports[devid];
- if (ATM_setu(&port->inUse, TRUE)) {
- return (IOM_EBADIO);
- }
- /* this driver requires parameters, there are no valid defaults */
- if (params == NULL) {
- return (IOM_EBADARGS);
- }
- /* Check the version number */
- if (params->versionId != C55XX_DMA_MCBSP_VERSION_1){
- /* Unsupported Version */
- return(IOM_EBADARGS);
- }
- /* open the McBSP */
- port->hMcbsp = MCBSP_open(devid, MCBSP_OPEN_RESET);
-
- if (port->hMcbsp == INV) {
- return (IOM_EBADIO);
- }
- MCBSP_config(port->hMcbsp, params->mcbspCfg);
- port->chans[INPUT].dmaId = params->rxDmaId;
- port->chans[OUTPUT].dmaId = params->txDmaId;
- /* store the interrupt masks */
- port->rxIerMask[0] = params->rxIerMask[0];
- port->rxIerMask[1] = params->rxIerMask[1];
- port->txIerMask[0] = params->txIerMask[0];
- port->txIerMask[1] = params->txIerMask[1];
-
- *devp = port;
-
- return (IOM_COMPLETED);
- }
- /*
- * ======== mdControlChan ========
- */
- static Int mdControlChan(Ptr chanp, Uns cmd, Ptr args)
- {
- /*
- * If a channel timeouts(in IOM class driver) a calldown is made to
- * mdControlChan w/ cmd = IOM_CHAN_TIMED out. Timeout processing is
- * optionally implemented here. If not performed return status of
- * IOM_ENOTIMPL.
- */
- /*
- * Channel timed out. Perform needed channel cleanup.
- */
- if (cmd == IOM_CHAN_TIMEDOUT) {
- abortio(chanp);
- }
- else {
- return (IOM_ENOTIMPL); /* return IOM_ENOTIMPL for codes not handled */
- }
- return (IOM_COMPLETED);
- }
- /*
- * ======== mdCreateChan ========
- */
- static Int mdCreateChan(Ptr *chanp, Ptr devp, String name, Int mode,
- Ptr chanParams, IOM_TiomCallback cbFxn, Ptr cbArg)
- {
- PortHandle port = (PortHandle)devp;
- C55XX_DMA_MCBSP_ChanParams *params =
- (C55XX_DMA_MCBSP_ChanParams *)chanParams;
- HWI_Attrs attrs;
- ChanHandle chan;
- Int event;
- volatile Uns temp;
- chan = (mode == IOM_INPUT) ? &port->chans[INPUT] : &port->chans[OUTPUT];
- /* this driver requires channel parameters, no reasonable default */
- if (params == NULL) {
- return (IOM_EBADARGS);
- }
- /*
- * Check check if channel is already in use.
- * Use ATM_setu() for atomic test-and-set.
- */
- if (ATM_setu((Uns *)&chan->inUse, TRUE)) {
- return (IOM_EBADIO); /* ERROR! channel is already open! */
- }
- QUE_new(&chan->pendList);
- chan->devp = devp;
- chan->cbFxn = cbFxn;
- chan->cbArg = cbArg;
- /* open and configure DMA */
- chan->hDma = DMA_open(chan->dmaId, DMA_OPEN_RESET);
- if (chan->hDma == INV) {
- return (IOM_EBADIO);
- }
- DMA_config(chan->hDma, params->dmaCfg);
-
- event = DMA_getEventId(chan->hDma);
- /* plug interrupt vector */
- attrs.ier0mask = (mode == IOM_INPUT) ? port->rxIerMask[0] : port->txIerMask[0];
- attrs.ier1mask = (mode == IOM_INPUT) ? port->rxIerMask[1] : port->txIerMask[1];
- attrs.arg = (Arg)chan;
- HWI_dispatchPlug(event, (Fxn)dmaIsr, &attrs);
- /* enable DMA interrupt */
- IRQ_enable(event);
- *chanp = chan;
- return (IOM_COMPLETED); /* success */
- }
- /*
- * ======== mdDeleteChan ========
- * Mark the channel available and disable the appropriate interrupt.
- */
- static Int mdDeleteChan(Ptr chanp)
- {
- ChanHandle chan = (ChanHandle)chanp;
- /* disable DMA interrupt */
- IRQ_disable(DMA_getEventId(chan->hDma));
- /* close the DMA channel */
- DMA_close(chan->hDma);
- chan->inUse = FALSE;
- return (IOM_COMPLETED);
- }
- /*
- * ======== mdSubmitChan ========
- */
- static Int mdSubmitChan(Ptr chanp, IOM_Packet *packet)
- {
- ChanHandle chan = (ChanHandle)chanp;
- PortHandle port = (PortHandle)chan->devp;
- Uns imask;
- if (packet->cmd == IOM_FLUSH || packet->cmd == IOM_ABORT) {
- abortio(chan);
- packet->status = IOM_COMPLETED; /* flush/abort pkt completed */
- return (IOM_COMPLETED);
- }
- imask = HWI_disable();
- if (chan->dataPacket != NULL) {
- QUE_enqueue(&chan->pendList, packet);
- }
- else {
- chan->dataPacket = packet;
- startDma(chan, packet);
- if (packet->cmd == IOM_READ) {
- MCBSP_start(port->hMcbsp, MCBSP_RCV_START, 0);
- }
- else {
- MCBSP_start(port->hMcbsp, MCBSP_XMIT_START, 0);
- }
- }
- HWI_restore(imask);
- return (IOM_PENDING);
- }
- /*
- * ======== C55XX_DMA_MCBSP_init ========
- */
- #pragma CODE_SECTION(C55XX_DMA_MCBSP_init, ".text:init")
- Void C55XX_DMA_MCBSP_init(Void)
- {
- /* beware ... this is a global register! */
- /* Set DMA to continue transfer even during emulation stop */
- DMA_FSET(DMAGCR, FREE, 1);
- }
- /*
- * ======== startDma ========
- */
- static Void startDma(ChanHandle chan, IOM_Packet *packet)
- {
- /*
- * Program upper and lower addresses in appropriate DMA channel
- * and start transfer.
- * By default, the TMS320C55xx compiler assigns all data symbols word
- * addresses. The DMA however, expects all addresses to be byte
- * addresses. Therefore, we must shift the address by 2 in order to
- * change the word address to a byte address for the DMA transfer.
- */
- Uint16 dmaAddrU = (Uint16)( ((Uint32)packet->addr>>15) & 0xFFFF );
- Uint16 dmaAddrL = (Uint16)( ((Uint32)packet->addr<<1) & 0xFFFF );
- if (packet->cmd == IOM_READ) {
- DMA_RSETH(chan->hDma, DMACDSAL, dmaAddrL);
- DMA_RSETH(chan->hDma, DMACDSAU, dmaAddrU);
- DMA_RSETH(chan->hDma, DMACEN, packet->size);
- DMA_start(chan->hDma);
- }
- else {
- DMA_RSETH(chan->hDma, DMACSSAL, dmaAddrL);
- DMA_RSETH(chan->hDma, DMACSSAU, dmaAddrU);
- DMA_RSETH(chan->hDma, DMACEN, packet->size);
- DMA_start(chan->hDma);
- }
- }
- /*
- * ======== dmaIsr ========
- */
- Void dmaIsr(ChanHandle chan)
- {
- IOM_Packet *packet = chan->dataPacket;
- volatile Uns temp;
- if (packet == NULL) {
- /* return if spurious interrupt */
- return;
- }
-
- packet->status = IOM_COMPLETED;
- chan->dataPacket = QUE_get(&chan->pendList);
- if (chan->dataPacket == (IOM_Packet *)&chan->pendList) {
- chan->dataPacket = NULL;
- }
- else {
- startDma(chan, chan->dataPacket);
- }
-
- (*chan->cbFxn)(chan->cbArg, packet);
- }
- /*
- * ======== abortio ========
- * Aborts uncompleted i/o packet requests.
- */
- static Void abortio(ChanHandle chan)
- {
- IOM_Packet *tmpPacket;
- volatile Uns temp;
- DMA_stop(chan->hDma);
- HWI_disable();
- tmpPacket = chan->dataPacket;
- chan->dataPacket = NULL;
- HWI_enable();
- if (tmpPacket) {
- tmpPacket->status = IOM_ABORTED; /* abort current request */
- (*chan->cbFxn)(chan->cbArg, tmpPacket);
- tmpPacket = QUE_get(&chan->pendList);
- while (tmpPacket != (IOM_Packet *)&chan->pendList) {
- tmpPacket->status = IOM_ABORTED; /* abort queued requests */
- (*chan->cbFxn)(chan->cbArg, tmpPacket);
- tmpPacket = QUE_get(&chan->pendList);
- }
- }
- }