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:etc).
i am using copy_from_user and copy_to_user functions.The simplest way is to snarf a block of contiguous memory OUTside the
how do i make that physical memory non cached ?
kernel, export it and write to/read from it somehow (e.g. by mmap,
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]