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