Hello,

I'm quite new to (embedded-kernel level) linux even though I have a
lot of experience otherwise with embedded systems, RTOSes.
I was asked to help and develop a DMA driver which would enable a
clean access between the MPC8245 and a PCI area (SDRAM), where other
processor would read the data. The driver would be written at kernel
level.
Since I plunged into this feature I wasn't aware how complex all the
memory aspect is.
While I seem to understand the module interface, the memory accesses
are far less obvious to me.
There are 2 modes of operation for this particular DMA (chaining and
direct). The code reflects that. I tried both and it doesn't work.
In the init command I could call the "ch_"/none versions for
chaining/direct modes.
The only thing I managed to make work is to write to 0xfdcc0000 (over
PCI) (I guess it comes from 4G - 48M memory map). Whether this helps
me to actually write the driver, I don't know.
How do I access a register in the EUMB region? Is it using ioremap? or
_nocache?
Is that a logical/phys memory?
What do I save in the source adress/dest address? What format? Bus
address? Virtual?
Should I use writeb(w,l), readb(w,l)? Or just go and access the
registers?

Really appreciate any help.

Following are some code lines:
#define MPC8240_EUMBAR 0xf8000000-0x100000
#define DMA_SPACE(x) MPC8240_EUMBAR+0x1000+0x100*((x)+1)
#define I2C_SPACE MPC8240_EUMBAR+0x3000
#define U32 unsigned int
#define U8 unsigned char
#define MEMORY_SIZE 13*1024*1024

typedef struct txdes {
volatile U32 sa;
volatile U32 hsa;
volatile U32 da;
volatile U32 hda;
volatile U32 next;
volatile U32 hnext;
volatile U32 count;
volatile U32 res;
} TXD;

typedef struct dmas{
volatile U32 dmr;
volatile U32 dsr;
volatile U32 cdar;
volatile U32 hcdar;
volatile U32 sar;
volatile U32 hsar;
volatile U32 dar;
volatile U32 hdar;
volatile U32 bcr;
volatile U32 ndar;
} DMAS;

volatile DMAS* dma_t;
volatile DMAS* dma_r;
volatile TXD* txd[2];
volatile TXD* rxd[2];
char hllo[8] = "Hello";
char rrr[8];

static ch_dma_init()
{
int i;
U32 temp;
dma_t = (DMAS*) ioremap_nocache(DMA_SPACE(0),1024*1024);
txd[0] = kmalloc(1024,GFP_KERNEL);
temp = kmalloc(1024,GFP_KERNEL);
temp += 0x40;
temp &= 0xffffffe0;
txd[0] = (TXD*)temp;
printk("desc0:%x %x\n",txd[0],virt_to_bus(&txd[0]));
temp = kmalloc(1024,GFP_KERNEL);
temp += 0x40;
temp &= 0xffffffe0;
txd[1] = (TXD*)temp;
printk("desc1:%x %x\n",txd[1],virt_to_bus(hllo));
for (i=0;i<2;i++)
{
txd[i]->sa = virt_to_bus(hllo);
//txd[i]->da = virt_to_bus(rrr);
txd[i]->da = 0xfdcc0008;
txd[i]->count = 4;
if (i==1)
{
txd[i]->next = 3;
}else
{
txd[i]->next = virt_to_bus(&txd[1]) | 2;
}
}
writel(virt_to_bus(&txd[0]),&dma_t->cdar);
printk("prim %x %x %x %x %x %x\n",
(((U32)readl(&dma_t->dmr))),(((U32)readl(&dma_t->dsr))),
(((U32)readl(&dma_t->cdar))),(((U32)readl(&dma_t->sar))),
(((U32)readl(&dma_t->dar))),(((U32)readl(&dma_t->bcr))));

}

static int direct_dma_init(void)
{
U8* scr;
char* ttt;
U8* hhh;
// scr = (U8*)(spPciSyscfg_c + g_virt_start_addr);
dev = pci_find_device(0x14e4,0x5615,dev);
if (dev == NULL)
{
printk("no logical\n");
}
ttt = kmalloc(6656,GFP_KERNEL|GFP_DMA);
//scr = ioremap(spPciSyscfg_c,1024*1024);
// scr = ioremap((unsigned
long)pci_resource_start(dev,0),1024*1024);
scr = 0xfdcc0000;
if (scr == NULL)
{
printk("cannot allocate\n");
}
// scr += spPciSyscfg_c;
printk("<1>pci:%x ttt:%x",scr,ttt);
dma_t = (DMAS*) ioremap(DMA_SPACE(0),1024*1024);
printk("udma_t:%x",dma_t);
//hhh = ioremap(I2C_SPACE,1024*1024);
hhh = ioremap(MPC8240_EUMBAR,1024*1024);
printk("vdma_t:%x",dma_t);
printk("hhh:%x hhh:%x %x %x %x %x %x %x %x",
readl(((U32*)(hhh+0x41030))),
readl(((U32*)(hhh+0x3004))),readl(((U32*)(hhh+0x41 020))),
(((U32)readl(&dma_t->dmr))),(((U32)readl(&dma_t->dsr))),
(((U32)readl(&dma_t->cdar))),(((U32)readl(&dma_t->sar))),
(((U32)readl(&dma_t->dar))),(((U32)readl(&dma_t->bcr))));
//dma_t = __va((DMAS*) DMA_SPACE(0));
printk("<1>dma_t:%x",dma_t);
// dma_r = (DMAS*) ioremap(DMA_SPACE(1),1024*1024);
//printk("<1>dma_r:%x",dma_r);
//poll dma channel DSR[CB]
//if (!DSR[CB]) return;
if (dma_t->dsr & 0x4) {
printk("nu pe aici0");
return;
}
//if (dma_r->dsr & 0x4) {
//printk("nu pe aici1");
// return;
// }
//SAR = hllo;
//dma_t->sar = virt_to_bus(hllo);
//dma_t->sar = (0xfdcc0000);
writel(virt_to_bus(hllo),&dma_t->sar);
//dma_t->sar = ( virt_to_bus(hllo));
//DAR = scr;
//dma_t->dar = __le32_to_cpu(0xfdcc0008);
writel(virt_to_bus(rrr),&dma_t->dar);
//dma_t->dar = __le32_to_cpu(virt_to_bus(rrr));
//BCR = strlen(hllo);
//dma_t->bcr = strlen(hllo) + 1;
//dma_t->bcr = __le32_to_cpu(3);
writel(3,&dma_t->bcr);
//CDAR[CTT](channel0) = 01 (local->PCI);
//dma_t->cdar =(0x2);
//dma_t->cdar =(0x0);
//dma_t->cdar =__le32_to_cpu(0x6);
writel(0,&dma_t->cdar);
//CDAR[CTT](channel1) = 10 (PCI->local);
// dma_r->cdar = 0x4;
//DMR[CTM](channelX) = 1; (direct mode)
//dma_t->dmr |= __le32_to_cpu(0x4);
writel(4,&dma_t->dmr);
//writeb(22,scr);
}

void dma_start_t(void)
{
//DMR[CS](x) = 0;
//dma_t->dmr &= __le32_to_cpu(~0x1);
writel((~0x1) | 0x4,&dma_t->dmr);
//DMR[CS](x) = 1;
//dma_t->dmr |= __le32_to_cpu(0x1);
writel(5, &dma_t->dmr);
}

void ch_dma_start_t(void)
{
U32 tt;
//DMR[CS](x) = 0;
//dma_t->dmr &= __le32_to_cpu(~0x1);
writel((~0x1),&dma_t->dmr);
//DMR[CS](x) = 1;
//dma_t->dmr |= __le32_to_cpu(0x1);
writel(1, &dma_t->dmr);
printk("astept");
tt = readl(&dma_t->dsr);
writel(tt,&dma_t->dsr);
printk("prim %x %x %x %x %x %x tt:%x\n",
(((U32)readl(&dma_t->dmr))),(((U32)readl(&dma_t->dsr))),
(((U32)readl(&dma_t->cdar))),(((U32)readl(&dma_t->sar))),
(((U32)readl(&dma_t->dar))),(((U32)readl(&dma_t->bcr))),tt);

}

int init_module(void)
{
int err,i;

ch_dma_init();
ch_dma_start_t();
/*
err = register_chrdev(MY_MAJOR,DEVICE_NAME,&Fops);
if (err) {
PRINTK ("Device failed with %d\n",err);
unregister_chrdev(MY_MAJOR,DEVICE_NAME);
return err;
}
PRINTK ("<1> Device %s inserted\n",DEVICE_NAME);
*/
printk("uuuu");
for(i=0;i<100000;i++)
{
if (rrr[0] == 'H') {printk("wwww");break;}
}
rrr[4] = '\0';
printk("%s.....",rrr);
return SUCCESS;
}


Virgil