+ -
当前位置:首页 → 问答吧 → ioremap映射的问题

ioremap映射的问题

时间:2010-09-08

来源:互联网

本帖最后由 marcomo1986 于 2010-09-09 08:53 编辑

我写的驱动要对外设I/O资源进行操作,需要对物理地址进行映射,部分程序如下:

void *AC97C_VIR_BASE;
#define AC97C_PHY_BASE                0xfffa0000


#define AC97C_CAMR_VIR   AC97C_CAMR+AC97C_VIR_BASE
#define AC97C_CBMR_VIR   AC97C_CBMR+AC97C_VIR_BASE
#define AC97C_COTHR_VIR  AC97C_COTHR+AC97C_VIR_BASE

AC97C_VIR_BASE = ioremap( AC97C_PHY_BASE, 0x100 );

在程序里
size = ((AT91C_BASE_AC97C->AC97C_CAMR_VIR) & AT91C_AC97C_SIZE) >> 16;
size = ((AT91C_BASE_AC97C->AC97C_CBMR_VIR) & AT91C_AC97C_SIZE) >> 16;
这两句能编译通过,但是其他的涉及虚拟地址映射的部分都编译出错了
比如:
(AT91C_BASE_AC97C->AC97C_COTHR_VIR) = data;

(AT91C_BASE_AC97C->AC97C_COMR_VIR) |= AT91C_AC97C_RXRDY;

都提示:
error: invalid lvalue in assignment
这是为什么呢?请哪位高手指点小弟一下

作者: marcomo1986   发布时间: 2010-09-08

咋没回复的呢?小弟有点着急请哪位大哥帮忙看一下

作者: marcomo1986   发布时间: 2010-09-09

代码贴的太少了,大写的看起来都是宏,不知道是不是宏,宏不可以这样用的。
再者若是虚拟地址则应该*(addr)=value。

作者: EZWORD   发布时间: 2010-09-09

本帖最后由 marcomo1986 于 2010-09-09 09:16 编辑

EZWORD (vs复仇之魂):大写的都是宏,那我改怎么改呢
我贴出了部分程序您看一下
#define AC97C_PHY_BASE        0xfffa0000                //AC97C的物理地址
#define PIO_PHY_BASE         0xffff4000                        //PIO的物理地址
#define AIC_PHY_BASE            0xfffff000                        //AIC的物理地址
#define PMC_PHY_BASE            0xfffffc00                //PMC的物理地址

void *AC97C_VIR_BASE;       
void *PIO_VIR_BASE;
void *AIC_VIR_BASE;
void *PMC_VIR_BASE;


#define PIO_ASR_VIR     PIO_ASR+PIO_VIR_BASE
#define PIO_PDR_VIR     PIO_PDR+PIO_VIR_BASE

#define AC97C_CAMR_VIR   AC97C_CAMR+AC97C_VIR_BASE
#define AC97C_CBMR_VIR   AC97C_CBMR+AC97C_VIR_BASE
#define AC97C_COTHR_VIR  AC97C_COTHR+AC97C_VIR_BASE
#define AC97C_COMR_VIR   AC97C_COMR+AC97C_VIR_BASE
#define AC97C_IER_VIR    AC97C_IER+AC97C_VIR_BASE
#define AC97C_PTCR_VIR   AC97C_PTCR+AC97C_VIR_BASE
#define AC97C_TPR_VIR    AC97C_TPR+AC97C_VIR_BASE
#define AC97C_TCR_VIR    AC97C_TCR+AC97C_VIR_BASE
#define AC97C_TNPR_VIR   AC97C_TNPR+AC97C_VIR_BASE
#define AC97C_TNCR_VIR   AC97C_TNCR+AC97C_VIR_BASE
#define AC97C_RPR_VIR    AC97C_RPR+AC97C_VIR_BASE
#define AC97C_RCR_VIR    AC97C_RCR+AC97C_VIR_BASE
#define AC97C_RNPR_VIR   AC97C_RNPR+AC97C_VIR_BASE
#define AC97C_RNCR_VIR   AC97C_RNCR+AC97C_VIR_BASE
#define AC97C_ICA_VIR    AC97C_ICA+AC97C_VIR_BASE
#define AC97C_OCA_VIR    AC97C_OCA+AC97C_VIR_BASE
#define AC97C_COSR_VIR   AC97C_COSR+AC97C_VIR_BASE
#define AC97C_IDR_VIR    AC97C_IDR+AC97C_VIR_BASE
#define AC97C_CORHR_VIR  AC97C_CORHR+AC97C_VIR_BASE
#define AC97C_CASR_VIR   AC97C_CASR+AC97C_VIR_BASE
#define AC97C_SR_VIR     AC97C_SR+AC97C_VIR_BASE
#define AC97C_IMR_VIR    AC97C_IMR+AC97C_VIR_BASE
#define AC97C_MR_VIR     AC97C_MR+AC97C_VIR_BASE

#define AIC_IDCR_VIR     AIC_IDCR+AIC_VIR_BASE
#define AIC_SMR_VIR      AIC_SMR+AIC_VIR_BASE
#define AIC_SVR_VIR      AIC_SVR+AIC_VIR_BASE
#define AIC_ICCR_VIR     AIC_ICCR+AIC_VIR_BASE
#define AIC_IECR_VIR     AIC_IECR+AIC_VIR_BASE

#define PMC_PCER_VIR     PMC_PCER+PMC_VIR_BASE

static unsigned char GetSampleSize(unsigned char channel)

{

    unsigned int size=0;

    // Check selected channel

    if (channel == AC97C_CHANNEL_CODEC) {

        return 2;
    }

    else if (channel == AC97C_CHANNEL_A) {

       size = ((AT91C_BASE_AC97C->AC97C_CAMR_VIR) & AT91C_AC97C_SIZE) >> 16;

    }

    else if (channel == AC97C_CHANNEL_B) {

        size = ((AT91C_BASE_AC97C->AC97C_CBMR_VIR) & AT91C_AC97C_SIZE) >> 16;

    }

    // Compute size in bytes given SIZE field

    if ((size & 2) != 0) {

        return 2;
    }

    else {

        return 4;

    }
}

///////////////////////////////////////////////////////////////////////////////////////
unsigned char AC97C_Transfer(

    unsigned char channel,
    unsigned char *pBuffer,
    unsigned int numSamples,
    Ac97Callback callback,
    void *pArg)

{

    unsigned int size;
    unsigned int data;
    Ac97Transfer *pTransfer;

    // Check that no transfer is pending on the channel
    pTransfer = &(ac97c.transfers[channel]);
    if (pTransfer->numSamples > 0)
   {

        trace_LOG(trace_WARNING, "-W- AC97C_Transfer: Channel %d is busy\n\r",channel);

        return AC97C_ERROR_BUSY;

    }

    // Fill transfer information

    PTransfer->pBuffer = pBuffer;
    pTransfer->numSamples = numSamples;
    pTransfer->callback = callback;
    pTransfer->pArg = pArg;

    // Transmit or receive over codec channel
    if (channel == AC97C_CODEC_TRANSFER) {

        // Send command

        data = *((unsigned int *) pTransfer->pBuffer);

        (AT91C_BASE_AC97C->AC97C_COTHR_VIR) = data;

//size = ((AT91C_BASE_AC97C->AC97C_CAMR_VIR) & AT91C_AC97C_SIZE) >> 16;
//size = ((AT91C_BASE_AC97C->AC97C_CBMR_VIR) & AT91C_AC97C_SIZE) >> 16;


        // Check if transfer is read or write

        if ((data & AT91C_AC97C_READ) != 0) {

            (AT91C_BASE_AC97C->AC97C_COMR_VIR) |= AT91C_AC97C_RXRDY;

        }

        else {
   
            pTransfer->pBuffer += sizeof(unsigned int);

            (AT91C_BASE_AC97C->AC97C_COMR_VIR) |= AT91C_AC97C_TXRDY;

        }

        // Enable interrupts

        (AT91C_BASE_AC97C->AC97C_IER_VIR) |= AT91C_AC97C_COEVT;

    }

    // Transmit over channel A

    else if (channel == AC97C_CHANNEL_A_TRANSMIT) {

        // Disable PDC

        (AT91C_BASE_AC97C->AC97C_PTCR_VIR) = AT91C_PDC_TXTDIS;

        // Fill PDC buffers

        //size = min(pTransfer->numSamples, MAX_PDC_COUNTER);
        size = pTransfer->numSamples;

        (AT91C_BASE_AC97C->AC97C_TPR_VIR) = (unsigned int) pTransfer->pBuffer;

        (AT91C_BASE_AC97C->AC97C_TCR_VIR) = size;

        pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);

        //size = min(pTransfer->numSamples - size, MAX_PDC_COUNTER);
        size = pTransfer->numSamples - size;

        if (size > 0) {



            (AT91C_BASE_AC97C->AC97C_TNPR_VIR) = (unsigned int) pTransfer->pBuffer;

            (AT91C_BASE_AC97C->AC97C_TNCR_VIR) = size;

            pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);

        }


        // Enable interrupts

        (AT91C_BASE_AC97C->AC97C_CAMR_VIR) |= AT91C_AC97C_PDCEN | AT91C_AC97C_ENDTX;

        (AT91C_BASE_AC97C->AC97C_IER_VIR)|= AT91C_AC97C_CAEVT;

        // Start transfer

        (AT91C_BASE_AC97C->AC97C_PTCR_VIR) = AT91C_PDC_TXTEN;

    }

    // Receive over channel A

    else if (channel == AC97C_CHANNEL_A_RECEIVE) {

        // Disable PDC

        (AT91C_BASE_AC97C->AC97C_PTCR_VIR) = AT91C_PDC_RXTDIS;

        // Fill PDC buffers

        //size = min(pTransfer->numSamples, MAX_PDC_COUNTER);
        size = pTransfer->numSamples;

        (AT91C_BASE_AC97C->AC97C_RPR_VIR) = (unsigned int) pTransfer->pBuffer;

        (AT91C_BASE_AC97C->AC97C_RCR_VIR) = size;

        pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);


        //size = min(pTransfer->numSamples - size, MAX_PDC_COUNTER);
        size = pTransfer->numSamples - size;

        if (size > 0) {


            (AT91C_BASE_AC97C->AC97C_RNPR_VIR) = (unsigned int) pTransfer->pBuffer;

            (AT91C_BASE_AC97C->AC97C_RNCR_VIR) = size;

            pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);

        }


        // Enable interrupts

        (AT91C_BASE_AC97C->AC97C_CAMR_VIR) |= AT91C_AC97C_PDCEN | AT91C_AC97C_ENDRX;

        (AT91C_BASE_AC97C->AC97C_IER_VIR) |= AT91C_AC97C_CAEVT;


        // Start transfer

        (AT91C_BASE_AC97C->AC97C_PTCR_VIR) = AT91C_PDC_RXTEN;

    }



    return 0;

}

作者: marcomo1986   发布时间: 2010-09-09