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/
|