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

📄 c64xx_pci.c

📁 6000系列的dsp的mini-pci驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
 */
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); 
}

⌨️ 快捷键说明

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