o.k., here is the story:

we are developping a uwb (ultra wide band) network chip.
this should be a wireless 100-500 Mbps with Qos communication chip. ( bluetooth and WiFi, beware ;-)


the prototype i am working on has it's registers and rams mapped as memory on a PCI card.

i tried using /dev/mem to access it, but it didn't work.
so i  tried looking at examples and builded my own driver.

i am succesfull at accessing my card as a file. (/dev/uwb/0)
i was not successful at accessing it as mmapped (i can mmap it, write/read to/from it, but it does not do the real writing/reading to/from the card, and i get no errors either).


the only issue, is that when i do a read or write, even that the length of the copy_from_user or copy_to_user is 4 bytes long, it seems to read/write more than that
so if i access (read) adress 0xa00004, i get the register at 0xa00000 also read. (probably being cached)


arch is x86 (Pentium III)

any idea ?

cheers,
erez.


btw, here are the main code:



static ssize_t uwb_dev_read (struct file *filp, char *buf, size_t count, loff_t * offp) { unsigned int num=(unsigned int)filp->private_data-1; unsigned long p=*offp; ssize_t ret = 0; int size;

//printk(KERN_INFO UWB "read: addr=%d, len=%d\n",(int)p,(int)count);
//printk(KERN_INFO UWB "num=%d, num_boards=%d\n",(int)num,(int)num_boards);
if (num>num_boards) return -EFAULT;
if (p>(unsigned int)mem_size) return -EFAULT;
size=MIN(count,(unsigned int)mem_size-p);
size=MIN(size,4);
//printk(KERN_INFO UWB "read addres 0x%lx..0x%lx ... ",p,p+size-1);
//printk(KERN_INFO UWB "coping to user space\n");
if (copy_to_user (buf, uwb_mem[num]+p, size))
return -EFAULT;
ret=size;
//printk(KERN_INFO UWB "done read\n");
//printk("%d bytes read \n",ret);
*offp+=ret;
return ret;
}



static ssize_t uwb_dev_write(struct file *filp, const char *buf, size_t count, loff_t * offp)
{
unsigned int num=(unsigned int)filp->private_data-1;
unsigned long p=*offp;
ssize_t ret = 0;
int size;


       if (num>num_boards) return -EFAULT;
       if (p>(unsigned int)mem_size) return -EFAULT;
       size=MIN(count,(unsigned int)mem_size-p);
       size=MIN(size,4);
       if (copy_from_user (uwb_mem[num]+p, buf, size))
                     return -EFAULT;
       ret=size;

       *offp+=ret;
       return ret;
}



static int uwb_dev_mmap(struct file * filp, struct vm_area_struct * vma)
{
       unsigned int num=(unsigned int)filp->private_data-1;
       //unsigned int num=0;
       //unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
       ssize_t ret = 0;
       unsigned long prot = pgprot_val(vma->vm_page_prot);
       if (boot_cpu_data.x86 > 3)
               prot |= _PAGE_PCD | _PAGE_PWT;
       vma->vm_page_prot = __pgprot(prot);

       /*
        * Accessing memory above the top the kernel knows about or
        * through a file pointer that was marked O_SYNC will be
        * done non-cached.
        */
       //if (noncached_address(offset) || (file->f_flags & O_SYNC))
        //       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);


/* Don't try to swap out physical pages.. */ vma->vm_flags |= VM_RESERVED;

       /*
        * Don't dump addresses that are not real memory to a core file.
        */
        /*
       if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
               vma->vm_flags |= VM_IO;
               */
       vma->vm_flags |= VM_IO;

if (vma->vm_end-vma->vm_start > mem_size[num]) ret= -EAGAIN;
else
if (remap_page_range(vma->vm_start, (unsigned long) uwb_mem[num],
vma->vm_end-vma->vm_start,
vma->vm_page_prot))
ret= -EAGAIN;
printk ("uwb: mmap, physical_ptr=0x%8X, size=0x%X, uwb num=%d, vm_ptr=0x%08X, ret=%d\n",(unsigned int) uwb_mem[num],(unsigned int)(vma->vm_end-vma->vm_start),(int)num,(unsigned int)vma->vm_start,(unsigned int)ret);
return ret;
}




/*
* uwb_init_one - look for and attempt to init a single UWB
*/
static int __init uwb_init_one (struct pci_dev *dev, int num)
{
       int rc;
       //u8 hw_status;

DPRINTK ("ENTER\n");


mem_size[num]=UWB_ADDR_END(dev)-UWB_ADDR(dev)+1; uwb_mem[num] = ioremap (UWB_ADDR(dev), mem_size[num]); if (uwb_mem[num] == NULL) { printk (KERN_ERR UWB "cannot ioremap UWB Memory\n"); DPRINTK ("EXIT, returning -EBUSY\n"); rc = -EBUSY; return rc; }

//printk(KERN_INFO UWB "found addr %lX..%lX\n",UWB_ADDR(dev),UWB_ADDR_END(dev));
DPRINTK ("EXIT, returning 0\n");
return 0;


}

static int __init uwb_init (void)
{
       int rc=0;
       struct pci_dev *pdev;
       int num=0;
       int i;
       char name[15];

DPRINTK ("ENTER\n");

// init_MUTEX (&uwb_open_sem);

       pci_for_each_dev(pdev) {
               if (pci_match_device (uwb_pci_tbl, pdev) != NULL)
               {
                  rc=uwb_init_one(pdev,num);
                  if (!rc) num++;
               }
       }

       if (!rc && !num)
       {
               DPRINTK ("EXIT, returning -ENODEV\n");
               return -ENODEV;
       }
       if (!num)
       {
               printk (KERN_ERR UWB "cannot initialize board \n");
               DPRINTK ("EXIT, returning %d\n", rc);
               return rc;
       }
       num_boards=num;
       printk ("uwb: %d board(s) found\n", num);
/*
       rc = misc_register (&uwb_miscdev);
       if (rc) {
               printk (KERN_ERR UWB "cannot register misc device\n");
               DPRINTK ("EXIT, returning %d\n", rc);
               return rc;
       }
*/

       if ((rc=devfs_register_chrdev (0, UWB_NAME, &uwb_chrdev_ops))<0) {
               printk ("uwb: unable to get major %d, rc=%d\n", major,rc);
               unmap_all();
               return -EIO;
       }
       major=rc;
       printk ("uwb: major=%d\n", major);

devdir=devfs_mk_dir (NULL, UWB_DIR , NULL);
if (NULL==devdir) {printk (KERN_INFO "unable to mkdir %s\n",UWB_DIR);};//return -EBUSY;};
for (i=0;i<num_boards;i++)
{
sprintf(name,"uwb%d",num);
handle[i]=devfs_register (devdir, "uwb", DEVFS_FL_NONE,
major, i,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,
&uwb_chrdev_ops, (int *)(i+1));
if (handle[i]==0) printk (KERN_INFO "unable to register card, do manually: mknod /dev/uwb/%d c %d %d\n",i,major,i);


}

printk (KERN_INFO "IFX Uwb Mac Board driver: %d boards installed\n",num);
DPRINTK ("EXIT, returning 0\n");
return 0;
}


/*
* uwb_init - shutdown UWB module
*/
static void __exit uwb_cleanup (void)
{
       int i;
       DPRINTK ("ENTER\n");

/*
misc_deregister (&uwb_miscdev);
*/
for (i=0;i<num_boards;i++) devfs_unregister(handle[i]);
devfs_unregister_chrdev(major, UWB_DIR);
unmap_all();
printk (KERN_INFO "IFX Uwb Mac Board driver: %d boards removed\n",num_boards);


       DPRINTK ("EXIT\n");
}



static int uwb_dev_open (struct inode *inode, struct file *filp)
{
       //printk (KERN_INFO "open device #%d\n",MINOR(inode->i_rdev));
       if (MINOR(inode->i_rdev) >= num_boards)
               return -ENXIO;

       filp->private_data=(void *)(1+MINOR(inode->i_rdev));
       MOD_INC_USE_COUNT;
       return 0;
}


static int uwb_dev_release (struct inode *inode, struct file *filp) { //printk (KERN_INFO "open\n"); MOD_DEC_USE_COUNT; return 0; }








Muli Ben-Yehuda wrote:


On Mon, Oct 20, 2003 at 09:46:48PM +0200, Official Flamer/Cabal NON-Leader wrote:


Quoth Erez Doron:



i am using copy_from_user and copy_to_user functions.
how do i make that physical memory non cached ?


The simplest way is to snarf a block of contiguous memory OUTside the
kernel, export it and write to/read from it somehow (e.g. by mmap,


etc).

Simplest, but it's also considered a fairly ugly hack :P
Erez, what are you trying to do, and on which arch? how to make
physical memory non cached is fairly architecture dependant, AFAIK.


Cheers, Muli




================================================================= To unsubscribe, send mail to [EMAIL PROTECTED] with the word "unsubscribe" in the message body, e.g., run the command echo unsubscribe | mail [EMAIL PROTECTED]



Reply via email to