- From: <rhamelin_at_lycee-ledantec.ac-rennes.fr>
- Date: Mon, 3 May 2004 15:42:15 +0200
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