ts-7000
[Top] [All Lists]

[ts-7000] Re: Cannot read PC104 from kernel space

To:
Subject: [ts-7000] Re: Cannot read PC104 from kernel space
From: "Frank Pagliughi" <>
Date: Thu, 29 Nov 2007 20:36:34 -0000
I was able to write a device driver for a proprietary PC/104
co-processor board for use with a TS-7260, but I could never get it to
work reliably with the standard speed for accessing the 104 bus. I had
similar problems to what you're reporting in that individual reads and
writes were sometime (often) incorrect.

Then I tried using the "fast" mode to access the board. This is a
non-standard extension of the TS-72xx boards that clocks the bus at a
faster rate (requiring a wait state setup in the EBI).  Then my driver
worked fine.  But this probably wouldn't work with off-the-self PC/104
peripheral boards.

I chalked it up to a problem with the default implementation of the
PC/104 support in the boards's CPLD, but never did resolve the issue.

- Frank

--- In  "elliotbuller" <> wrote:
>
> Is it possible I'm am accessing the PC104 memory at the wrong
> location? Does the kernel access 16bit mem-mapped pc104 at 0x21A00000?
> 
> -Elliot
> 
> --- In  "elliotbuller" <ebuller@> wrote:
> >
> > I'm having an issue reading data over the pc104 bus from a kernel
> > module. I am able to read just fine from a userspace app using mmap.
> > Please tell me what the difference is between the access I am doing in
> > userspace and kernel space. The externel hardware generates the
> > interrupt and I see it trap to the interrupt handler. At that point it
> > tries to do a read over the bus but it is not latching the data right.
> > I get random results as if I'm just reading random memory although I
> > do see the mem_r line strobe low. I know you can't use mmap in a
> > kernel module but from what I've read it sounded like the ISA memory
> > region could be accessed using __ioremap(). Any suggestions would be
> > great.
> > -Elliot
> > TS7300 - 2.4.26-ts11 #35
> > 
> > Here is my userspace app:
> > 
> > #include <unistd.h>
> > #include <sys/mman.h>
> > #include <stdio.h>
> > #include <fcntl.h>
> > #include <time.h>
> > #include "stdtypes.h"
> > #include "peekpoke.h"
> > 
> > /*
> > Other possible bases
> > 0x21810000
> > 0x21A00000
> > 0x21A10000
> > */
> > 
> > #define PC104_BASE 0x21A00000L
> > 
> > int passed=0, failed=0, reads=0;
> > uint16 expected=0x0;
> > int t_delay = 0;
> > clock_t begin, end;
> > 
> > delay( volatile int x )
> > {
> >         volatile int k=0;
> >         while( k < x ) k++;
> > }
> > int main(int argc, char **argv){
> >         uint16 reading;
> >         volatile uint16 *start;
> >         long seconds;
> >         uint32 count = 0;
> >         int fd = open("/dev/mem", O_RDWR|O_SYNC);
> >         start = mmap(0, getpagesize(), PROT_READ|PROT_WRITE,
MAP_SHARED,
> > 
> >           reading =  PEEK16((long)start);
> >           expected = reading + 1;
> > 
> >           while(count < 10000000)
> >           {
> >                 reading =  PEEK16((long)start);
> >                 if(reading == expected)
> >                 {
> >                   passed++;
> >                   expected++;
> >                 }
> >                 else
> >                 {
> >                   failed++;
> >                   expected=reading+1;
> >                 }
> >                 count++;
> >           }
> >           printf("%d READS\n---------\nPASSED: %d   FAILED: %d\n",
> > count, passed, failed);
> >         
> >         close(fd);
> >         return 0;
> > }
> > 
> > /***********************************/
> > 
> > Here is my kernel module:
> > // Linux Device Driver Template/Skeleton
> > // Kernel Module
> > 
> > #include <linux/module.h>
> > #include <linux/errno.h>
> > #include <linux/fs.h>
> > #include <linux/mm.h>
> > #include <linux/interrupt.h>
> > #include <linux/sched.h>
> > #include <linux/init.h>
> > #include <linux/ioport.h>
> > 
> > #include <asm/uaccess.h>
> > #include <asm/io.h>
> > #include "peekpoke.h"
> > 
> > #define PC104_MAJOR              63
> > #define PC104_NAME               "PC104"
> > #define PC104_INTERRUPT          22        // Corresponds to IRQ5
> > #define PC104_BASE               0x21A00000L
> > #define PC104_MEM_SIZE           4
> > 
> > 
> > MODULE_AUTHOR("Elliot Buller: Colorado State 2007");
> > MODULE_LICENSE("GPL");
> > MODULE_DESCRIPTION("PC104 Data Acquisition Card Driver");
> > 
> > extern void disable_irq (unsigned int irq);
> > static unsigned int counter = 0;
> > static int interruptcount = 0;
> > static volatile uint16_t *base;
> > static char string[150];
> > DECLARE_WAIT_QUEUE_HEAD(pc104_wait);
> > static int data_not_ready = 1;
> > 
> > static int pc104_open (struct inode *inode, struct file *file) {
> >   printk("pc104_open\n");
> >   return 0;
> > }
> > 
> > static int pc104_release (struct inode *inode, struct file *file) {
> >     printk("pc104_release\n");
> >     return 0;
> > }
> > 
> > static ssize_t pc104_read (struct file *file, char *buf,
> >                        size_t count, loff_t *ppos) {
> >   int len, err;
> >   
> >   // check if we have data - if not, sleep
> >   // wake up in interrupt_handler
> >   while (data_not_ready) {
> >     interruptible_sleep_on(&pc104_wait);
> >   }
> >   data_not_ready = 1;
> > 
> >   /* Add read code here */
> >   return len;
> > }
> > 
> > // write function called when to /dev/skeleton is written
> > static ssize_t pc104_write (struct file *file, const char *buf,
> >                         size_t count, loff_t *ppos) {
> >   int err;
> >   err = copy_from_user(string,buf,count);
> >   if (err != 0)
> >     return -EFAULT;
> >   counter += count;
> >   return count;
> > }
> > 
> > 
> > // interrupt handler
> > static int interrupt_handler(void)
> > {
> >   
> >   interruptcount++;
> >   printk(">>> PC104 BUS INT: interruptcount=%d\n", interruptcount);  
> >  
> >   printk("PC104 Samples: 0x%04X\n", PEEK16(base));
> > 
> >   /* Data ready. Wake up userspace process */
> >   data_not_ready = 0;
> >   wake_up_interruptible(&pc104_wait);
> >   
> >   return IRQ_HANDLED;
> > }
> > 
> > // define which file operations are supported
> > struct file_operations pc104_fops = {
> >     .owner  =       THIS_MODULE,
> >     .llseek =       NULL,
> >     .read   =       pc104_read,
> >     .write  =       pc104_write,
> >     .readdir =      NULL,
> >     .poll =         NULL,
> >     .ioctl  =       NULL,
> >     .mmap  =        NULL,
> >     .open =         pc104_open,
> >     .flush  =       NULL,
> >     .release =      pc104_release,
> >     .fsync  =       NULL,
> >     .fasync =       NULL,
> >     .lock  =        NULL,
> >     .readv  =       NULL,
> >     .writev =       NULL,
> > };
> > 
> > // initialize module (and interrupt)
> > static int pc104_init_module (void) {
> >   int i;
> >   int ret;
> >   printk("<1>Initializing PC104 module\n");
> >   
> >   i = register_chrdev (PC104_MAJOR, PC104_NAME, &pc104_fops);
> >   if (i != 0) return - EIO;
> >   
> >   // INIT INTERRUPT
> >   ret = request_irq(PC104_INTERRUPT, &interrupt_handler,
> >                 SA_INTERRUPT, "pc104_driver", NULL);
> >   
> >   /* Check to see if ISA memory in use */
> >   if (check_mem_region(PC104_BASE, PC104_MEM_SIZE)) {
> >     printk("pc104: memory already in use\n");
> >     return -EBUSY;
> >   }
> >   
> >   /* Request memory space */
> >   request_mem_region(PC104_BASE, PC104_MEM_SIZE, PC104_NAME);
> >   
> >   /* Warning: Cannot use ioremap as it adds offset */
> >   base = (volatile uint16_t*)__ioremap(PC104_BASE, PC104_MEM_SIZE, 0);
> >   if(base == NULL)
> >   {
> >     printk("Error mapping memory!\n");
> >     return -EBUSY;
> >   }
> >   
> >   printk("Memory mapped: 0x%08X\n", base);
> >   return 0;
> > }
> > 
> > 
> > // close and cleanup module
> > static void pc104_cleanup_module (void) {
> >   printk("<1>Cleaning up PC104 module\n");
> >   
> >   iounmap((void*)base);
> >   release_mem_region(base, PC104_MEM_SIZE);
> >   unregister_chrdev (PC104_MAJOR, PC104_NAME);
> >   disable_irq(PC104_INTERRUPT);
> >   free_irq(PC104_INTERRUPT, NULL);
> >   
> > }
> > 
> > module_init(pc104_init_module);
> > module_exit(pc104_cleanup_module);
> >
>




 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/ts-7000/

<*> Your email settings:
    Individual Email | Traditional

<*> To change settings online go to:
    http://groups.yahoo.com/group/ts-7000/join
    (Yahoo! ID required)

<*> To change settings via email:
     
    

<*> To unsubscribe from this group, send an email to:
    

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/
 

<Prev in Thread] Current Thread [Next in Thread>
Admin

Disclaimer: Neither Andrew Taylor nor the University of NSW School of Computer and Engineering take any responsibility for the contents of this archive. It is purely a compilation of material sent by many people to the birding-aus mailing list. It has not been checked for accuracy nor its content verified in any way. If you wish to get material removed from the archive or have other queries about the archive e-mail Andrew Taylor at this address: andrewt@cse.unsw.EDU.AU