(no subject)

 Hello,
 I have a problem when using DMA on a National Instruments PCI-6025e.
 I try to run an ao_waveform example but I don't get a result and I think at
 this point the DMA driver doesn't work correctly (I don't get these problems if
I don't use DMA).
 
 For testing DMA access , I  write a little-device module using mite.c from
Comedi driver ( see newMite.c code below).
 
 It sounds like the MITE might not be working correctly. All DMAs registers
 readings return 2 (see dmesg results below )
 
 I think this would cause all calls to  fail.
 
 At the moment, I don't get access to the mMITE/DMA docs.
 
 What can be wrong? Your help would deeply be appreciated.
 
 Thanks,

Rémi Hamelin.

-bash-2.05b# insmod mite.o
-bash-2.05b# dmesg
Available NI device IDs: 0x2a80
MITE:0xe8052000 mapped to e005b000 DAQ:0xe8051000 mapped to e005d000
mite_dump_regs ch1
mite address is  =0xe005b000
mite status[CHOR]at 0xe005b600 =0x00000002
mite status[CHCR]at 0xe005b604 =0x00000002
mite status[TCR] at 0xe005b608 =0x00000002
mite status[MCR] at 0xe005b60c =0x00000002
mite status[MAR] at 0xe005b610 =0x00000002
mite status[DCR] at 0xe005b614 =0x00000002
mite status[DAR] at 0xe005b618 =0x00000002
mite status[LKCR]at 0xe005b61c =0x00000002
mite status[LKAR]at 0xe005b620 =0x00000002
mite status[CHSR]at 0xe005b63c =0x00000002
mite status[FCR] at 0xe005b640 =0x00000002

mite_prep_dma ch1
exit mite_prep_dma
mite_dump_regs ch1
mite address is  =0xe005b000
mite status[CHOR]at 0xe005b600 =0x00000002
mite status[CHCR]at 0xe005b604 =0x00000002
mite status[TCR] at 0xe005b608 =0x00000002
mite status[MCR] at 0xe005b60c =0x00000002
mite status[MAR] at 0xe005b610 =0x00000002
mite status[DCR] at 0xe005b614 =0x00000002
mite status[DAR] at 0xe005b618 =0x00000002
mite status[LKCR]at 0xe005b61c =0x00000002
mite status[LKAR]at 0xe005b620 =0x00000002
mite status[CHSR]at 0xe005b63c =0x00000002
mite status[FCR] at 0xe005b640 =0x00000002

-bash-2.05b#-bash-2.05b# cat newMite.c
/*
    module/mite.c
    Hardware driver for NI Mite PCI interface chip

    COMEDI - Linux Control and Measurement Device Interface
    Copyright (C) 1997-2002 David A. Schleef <ds_at_schleef.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/


#include <linux/version.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>

#include "mite.h"

#define PCI_MITE_SIZE           4096
#define PCI_DAQ_SIZE            4096


MODULE_LICENSE("GPL");


struct mite_struct *mite_devices = NULL;

#define TOP_OF_PAGE(x) ((x)|(~(PAGE_MASK)))


void mite_init(void)
{
        struct pci_dev *pcidev;
        struct mite_struct *mite;

        pci_for_each_dev(pcidev){
                if(pcidev->vendor==PCI_VENDOR_ID_NATINST){
                        mite=kmalloc(sizeof(*mite),GFP_KERNEL);
                        if(!mite){
                                printk("mite: allocation failed\n");
                                return;
                        }
                        memset(mite,0,sizeof(*mite));

                        mite->pcidev=pcidev;

                        mite->next=mite_devices;
                        mite_devices=mite;
                }
        }
}


int mite_setup(struct mite_struct *mite)
{
        unsigned long                   offset, start, length;
        u32                             addr;
        int i;

        if(pci_enable_device(mite->pcidev)){
                printk("error enabling mite\n");
                return -EIO;
        }
        pci_set_master(mite->pcidev);
        if( pci_request_regions( mite->pcidev, "mite" ) ) {
                printk("failed to request mite io regions\n");
                return -EIO;
        };

        addr = pci_resource_start(mite->pcidev, 0);
        mite->mite_phys_addr = addr;
        offset = mite->mite_phys_addr & ~PAGE_MASK;
        start = mite->mite_phys_addr & PAGE_MASK;
        length = PCI_MITE_SIZE + offset;
        mite->mite_io_addr = ioremap(start, length) + offset;
        printk("MITE:0x%08lx mapped to %p
",mite->mite_phys_addr,mite->mite_io_addr);

        addr=pci_resource_start(mite->pcidev, 1);
        mite->daq_phys_addr=addr;
        offset = mite->daq_phys_addr & ~PAGE_MASK;
        start = mite->daq_phys_addr & PAGE_MASK;
        length = PCI_DAQ_SIZE + offset;
        mite->daq_io_addr = ioremap(start, length) + offset;
        printk("DAQ:0x%08lx mapped to
%p\n",mite->daq_phys_addr,mite->daq_io_addr);

        /* XXX don't know what the 0xc0 and 0x80 mean */
        /* It must be here for the driver to work though */
        writel(mite->daq_phys_addr | 0x80 , mite->mite_io_addr + 0xc0 );

        for( i = 0; i < NUM_MITE_DMA_CHANNELS; i++ ) {

                writel(CHOR_DMARESET, mite->mite_io_addr + MITE_CHOR +
CHAN_OFFSET(i));
                /* disable interrupts */
                writel(0,mite->mite_io_addr + MITE_CHCR + CHAN_OFFSET(i));
        }
        mite->used = 1;

        return 0;
}


void mite_cleanup(void)
{
        struct mite_struct *mite,*next;

        for(mite=mite_devices;mite;mite=next){
                next=mite->next;
                kfree(mite);
        }
}

void mite_unsetup(struct mite_struct *mite)
{
        //unsigned long offset, start, length;

        if(!mite)return;

        if(mite->mite_io_addr){
                iounmap(mite->mite_io_addr);
                mite->mite_io_addr=NULL;
        }
        if(mite->daq_io_addr){
                iounmap(mite->daq_io_addr);
                mite->daq_io_addr=NULL;
        }
        if( mite->used )
                pci_release_regions( mite->pcidev );

        mite->used = 0;
}


void mite_list_devices(void)
{
        struct mite_struct *mite,*next;

        printk("Available NI device IDs:");
        if(mite_devices)for(mite=mite_devices;mite;mite=next){
                next=mite->next;
                printk(" 0x%04x",mite_device_id(mite));
                if(mite->used)printk("(used)");
        }
        printk("\n");

}

void mite_dma_arm( struct mite_struct *mite, unsigned int channel )
{
        int chor;

        MDPRINTK("mite_dma_arm ch%i\n", channel);
        /* arm */
        chor = CHOR_START;
        writel(chor, mite->mite_io_addr + CHAN_OFFSET(channel) + MITE_CHOR);

        mite_dma_tcr(mite, channel);
}




void mite_prep_dma( struct mite_struct *mite, unsigned int channel,
        unsigned int num_device_bits, unsigned int num_memory_bits )
{
        unsigned int chor,chcr,mcr,dcr,lkcr;
        struct mite_channel *mite_chan = &mite->channels[ channel ];

        MDPRINTK("mite_prep_dma ch%i\n", channel );

        /* reset DMA and FIFO */
        chor = CHOR_DMARESET | CHOR_FRESET;
        writel(chor, mite->mite_io_addr + MITE_CHOR + CHAN_OFFSET(channel));

        /* short link chaining mode */
        chcr = CHCR_SET_DMA_IE| CHCR_LINKSHORT | CHCR_SET_DONE_IE;
        /*
         * Link Complete Interrupt: interrupt every time a link
         * in MITE_RING is completed. This can generate a lot of
         * extra interrupts, but right now we update the values
         * of buf_int_ptr and buf_int_count at each interrupt.  A
         * better method is to poll the MITE before each user
         * "read()" to calculate the number of bytes available.
         * mite_bytes_transferred(), mite_bytes_read(), and
         * mite_bytes_in_transit() are provided to get the number
         * of bytes transferred by the mite so far.
         */
        chcr |= CHCR_SET_LC_IE;

        if(mite_chan->dir == 0) { 
                chcr |= CHCR_DEV_TO_MEM;
        }
        writel(chcr, mite->mite_io_addr + MITE_CHCR + CHAN_OFFSET(channel));

        /* to/from memory */
        mcr = CR_RL64 | CR_ASEQxP1;
        switch( num_memory_bits ){
                case 8:
                        mcr |= CR_PSIZEBYTE;
                        break;
                case 16:
                        mcr |= CR_PSIZEHALF;
                        break;
                case 32:
                        mcr |= CR_PSIZEWORD;
                        break;
                default:
                        printk( "mite: bug! invalid mem bit width for dma
transfer\n" );
                        break;
        }
        writel(mcr, mite->mite_io_addr + MITE_MCR + CHAN_OFFSET(channel));

        /* from/to device */
        dcr = CR_RL64 |  CR_ASEQx(1);
        dcr |= CR_PORTIO | CR_AMDEVICE | CR_REQS(0x4 + channel);
        switch( num_device_bits ){
                case 8:
                        dcr |= CR_PSIZEBYTE;
                        break;
                case 16:
                        dcr |= CR_PSIZEHALF;
                        break;
                case 32:
                        dcr |= CR_PSIZEWORD;
                        break;
                default:
                        printk( "mite: bug! invalid dev bit width for dma
transfer\n" );
                        break;
        }
        writel(dcr, mite->mite_io_addr + MITE_DCR + CHAN_OFFSET(channel));

        /* reset the DAR */
        writel(0, mite->mite_io_addr + MITE_DAR + CHAN_OFFSET(channel));

        /* the link is 32bits */
        lkcr = CR_RL64 | CR_ASEQUP | CR_PSIZEWORD;
        writel(lkcr, mite->mite_io_addr + MITE_LKCR + CHAN_OFFSET(channel));

        /* starting address for link chaining */
        writel(virt_to_bus(mite_chan->ring),
                mite->mite_io_addr + MITE_LKAR + CHAN_OFFSET(channel));

        MDPRINTK("exit mite_prep_dma\n");
}


int mite_dma_tcr(struct mite_struct *mite, unsigned int channel)
{
        int tcr;
        int lkar;

        lkar=readl(mite->mite_io_addr + CHAN_OFFSET(channel) + MITE_LKAR);
        tcr=readl(mite->mite_io_addr + CHAN_OFFSET(channel) + MITE_TCR);
        MDPRINTK("mite_dma_tcr ch%i, lkar=0x%08x tcr=%d\n", channel, lkar, tcr);

        return tcr;
}

void mite_dma_disarm(struct mite_struct *mite, unsigned int channel)
{
        int chor;

        /* disarm */
        chor = CHOR_ABORT;
        writel(chor, mite->mite_io_addr + CHAN_OFFSET(channel) + MITE_CHOR);
}





void mite_dump_regs(struct mite_struct *mite, int channel)
{
        unsigned long mite_io_addr = (unsigned long) mite->mite_io_addr;
        unsigned long addr=0;
        unsigned long temp=0;

        printk("mite_dump_regs ch%i\n", channel);
        printk("mite address is  =0x%08lx\n",mite_io_addr);

        addr = mite_io_addr+MITE_CHOR+CHAN_OFFSET(channel);
        printk("mite status[CHOR]at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));
        addr = mite_io_addr+MITE_CHCR+CHAN_OFFSET(channel);
        printk("mite status[CHCR]at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));
        addr = mite_io_addr+MITE_TCR+CHAN_OFFSET(channel);
        printk("mite status[TCR] at 0x%08lx =0x%08x\n",addr, readl(addr));
        addr = mite_io_addr+MITE_MCR+CHAN_OFFSET(channel);
        printk("mite status[MCR] at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));
        addr = mite_io_addr+MITE_MAR+CHAN_OFFSET(channel);
        printk("mite status[MAR] at 0x%08lx =0x%08x\n",addr, readl(addr));
        addr = mite_io_addr+MITE_DCR+CHAN_OFFSET(channel);
        printk("mite status[DCR] at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));
        addr = mite_io_addr+MITE_DAR+CHAN_OFFSET(channel);
        printk("mite status[DAR] at 0x%08lx =0x%08x\n",addr, readl(addr));
        addr = mite_io_addr+MITE_LKCR+CHAN_OFFSET(channel);
        printk("mite status[LKCR]at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));
        addr = mite_io_addr+MITE_LKAR+CHAN_OFFSET(channel);
        printk("mite status[LKAR]at 0x%08lx =0x%08x\n",addr, readl(addr));
        addr = mite_io_addr+MITE_CHSR+CHAN_OFFSET(channel);
        printk("mite status[CHSR]at 0x%08lx =0x%08lx\n",addr, temp=readl(addr));
        addr = mite_io_addr+MITE_FCR+CHAN_OFFSET(channel);
        printk("mite status[FCR] at 0x%08lx =0x%08x\n\n",addr, readl(addr));
}


int init_module(void)
{
        mite_init();
        mite_list_devices();
        mite_setup(mite_devices);
        mite_dump_regs(mite_devices,1);
        mite_prep_dma(mite_devices,1,16,32);
        mite_dump_regs(mite_devices,1);
        return 0;
}

void cleanup_module(void)
{
        mite_unsetup(mite_devices);
        mite_cleanup();
}


 

Received on 2004-05-03Z12:42:15