📄 c64xx_pci.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.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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -