ts-7000
[Top] [All Lists]

[ts-7000] Re: TS-ADC16

To:
Subject: [ts-7000] Re: TS-ADC16
From: "dan" <>
Date: Thu, 09 Apr 2009 15:40:50 -0000
Hello,

Below the driver source and header file.
to make it work:

1. compile it
2. enable PC104 bus
3. load driver
4. create filesystem node acording to major/minor number
5. build an user land application to send basic IOCTLs to the board(also check 
board ID)

For sure the driver can be improved and I would be happy with any 
sugestions/fixes for it.
In case of trouble I'll try to respond to your 

I don't have any better ideea to post it, than listing below the files:
adc_drv.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <asm/uaccess.h>
//#include <asm/arch/regmap.h>
#include <linux/proc_fs.h>
#include <asm/io.h>
#include "/usr/src/linux/include/linux/ioport.h"
#include </usr/src/linux/include/linux/ioport.h>
#include <linux/interrupt.h>

#include "adc_drv.h"

MODULE_DESCRIPTION("ADC character dev");
MODULE_AUTHOR("Dan Lupu");
MODULE_LICENSE("GPL");

#define LOG_LEVEL       KERN_DEBUG

struct my_adc_data {
    struct cdev cdev;
    /* my data starts here */
        int size;
        int* buffer;            // buffer to store FIFO data
        volatile char* ptr;     /* board addr from k*/
        unsigned int irq7Show;  
};

irqreturn_t adc_irqHnd(int irq_no, void *dev_id)
{
    struct my_adc_data *my_data = (struct my_adc_data *) dev_id;
 
        printk("ADC IRQ Hnd called\n");

        if(irq_no==0x07)
        {
         my_data->irq7Show = my_data->irq7Show + 1;     
         return IRQ_HANDLED;
        }       

    return IRQ_NONE;
}

struct my_adc_data my_adc;

static int my_open(struct inode *inode, struct file *file);
static int my_read(struct file *file, char __user *user_buffer, 
                                size_t size, loff_t *offset);

static int my_write (struct file *file, const char __user * user_buffer,
                      size_t size, loff_t *offset);
static int adc_ioctl (struct inode *inode,struct file *file,unsigned int cmd, 
unsigned long arg);
static int my_release (struct inode *inode, struct file *file);


struct file_operations my_fops = {
    .owner = THIS_MODULE,
    .open = my_open,
    .read = my_read,
    .write = my_write,
    .release = my_release,
    .ioctl = adc_ioctl
};


static int my_init(void)
{
        int err;
        //printk(LOG_LEVEL "Init ADC module\n");
        // offset adaugat isa_regbase.  
        my_adc.size=0;  
        my_adc.ptr = NULL;      
        my_adc.irq7Show=0;
        err = register_chrdev_region(MKDEV(MY_MAJOR, MY_MINOR),1,MODULE_NAME);

        if (err != 0) {
                /* report error */
                return err;
        }
   
        /* initialize my_dev fields */
        cdev_init(&my_adc.cdev, &my_fops);
        cdev_add(&my_adc.cdev, MKDEV(MY_MAJOR, MY_MINOR), 1);

        //printk(LOG_LEVEL "Open ADC device\n");

        if(check_mem_region(ADC_BASE,8))
        {
         printk("ADC_BASE space in use!");
         return -EBUSY; 
        }

        request_mem_region(ADC_BASE,0x1E,"adc_drv");
        my_adc.ptr=__ioremap(ADC_BASE,0x1E,0);  

        if(my_adc.ptr == NULL)
        {
         printk("no IOREMAP success!\n");
        }
        // board ID     
        if(0x3e!=readb(my_adc.ptr))
        { 
         printk("no ID from board 1"); 
         if(0x3e!=inb(my_adc.ptr))
         { 
          printk("no ID from board 2"); 
          return -EBUSY;
         }
        }

        // request IRQs 
        if ((err = request_irq(MY_IRQ1, adc_irqHnd, IRQF_SAMPLE_RANDOM | 
IRQF_SHARED,
                       "adc", &my_adc))) {
            /* handle error*/
             printk("alocate IRQ7 not possible"); 
            return err;
        }

        //allocate mem for ADC FIFO
        my_adc.buffer=kmalloc(BUFFER_SIZE * sizeof(unsigned int),GFP_KERNEL);

        return 0;
}

static void my_exit(void)
{
        //printk(LOG_LEVEL "Exit\n");

        release_mem_region(ADC_BASE,0x1E);
        __iounmap(my_adc.ptr);  

        free_irq(MY_IRQ1, &my_adc);
    
        cdev_del(&my_adc.cdev);
        kfree(my_adc.buffer);

        unregister_chrdev_region(MKDEV(MY_MAJOR, MY_MINOR), 1);
}

static int my_open(struct inode *inode, struct file *file)
{
        struct my_adc_data *my_adc;
        //printk(LOG_LEVEL "Open DIO device\n");
        my_adc = container_of(inode->i_cdev, struct my_adc_data, cdev);
        file->private_data = my_adc;
        my_adc->size=0;
//      writeb(0x00,my_adc->ptr+DDR);
        return 0;
}

static int my_read(struct file *file, char __user *user_buffer, 
                                size_t size, loff_t *offset)
{
        struct my_adc_data *my_data =
             (struct my_adc_data*) file->private_data;
        size_t toberead;
        unsigned int ind;

        if(size >= BUFFER_SIZE)
                return 0;
        if(*offset >= BUFFER_SIZE)
                return 0;
        //printk(LOG_LEVEL "[my_read] Trying to read %d bytes\n", size);
        
        // first read in the buffer
        for(ind=0;ind<size;ind++){
         my_data->buffer[ind]=readw(my_data->ptr+ADCFIFO);
        }
        // toberead = (size < my_data->size - *offset) ? size : my_data->size - 
*offset;
        if(copy_to_user(user_buffer, my_data->buffer, size))
                return -EFAULT;
                
        return size;
}


static int my_write (struct file *file, const char __user * user_buffer,
                      size_t size, loff_t *offset)
{
//        struct my_adc_data *my_adc = (struct my_adc_data*) file->private_data;
        size_t tobewritten;

        return tobewritten;
}

static int adc_ioctl (struct inode *inode, struct file *file,
                      unsigned int cmd, unsigned long arg)
{
  unsigned int adccfg,adcstat,count,temp;
  unsigned int retval=0;
        struct my_adc_data *my_adc = (struct my_adc_data*) file->private_data;

        switch(cmd) {
        case ADC_BID_IOCTL:
                retval=ioread16(my_adc->ptr);
                break;
        case ADC_CFG_IOCTL:
                //printk(LOG_LEVEL "set ADCCFG %d\n",arg);
                iowrite16(0x167, my_adc->ptr+ADCCFG);
                //writeb(0x67, my_adc->ptr+ADCCFG+1);
                break;
        case ADC_GETCFG_IOCTL:
                //get by pointer.
                // cal this from user space 
ioctl(fd,ADC_GETCFG_IOCTL,&adccfg);uint adccfg;
                adccfg = ioread16( my_adc->ptr+ADCCFG);
                retval = put_user(adccfg, (int __user *)arg);
                //printk(LOG_LEVEL "get ADCCFG W %d\n",adccfg);
                //printk(LOG_LEVEL "get ADCCFG MSB %d\n",ioread8( my_adc->ptr + 
ADCCFG ));
                //printk(LOG_LEVEL "get ADCCFG LSB %d\n",ioread8( my_adc->ptr + 
ADCCFG+1 ));
                break;
        case ADC_DLYLSW_IOCTL:
                iowrite16(arg, my_adc->ptr + ADC_DLY_LSW);
                break;
        case ADC_DLYLSWR_IOCTL:
                temp =ioread16(my_adc->ptr + ADC_DLY_LSW);
                retval = __put_user(temp, (int __user *)arg);
                break;
        case ADC_DLYMSW_IOCTL:
                writew(arg, my_adc->ptr + ADC_DLY_MSW);
                break;
        case ADC_STAT_IOCTL:
                writew(arg, my_adc->ptr +  ADCSTAT);
                break;
        case ADC_GETSTAT_IOCTL:
                adcstat=readw(my_adc->ptr +  ADCSTAT);
                retval = __put_user(adcstat, (int __user *)arg);
                break;

        case ADC_DACCFG_IOCTL:
                //printk(LOG_LEVEL "[my_ioctl] [MY_IOCTL_PRINT] Hello ioctl 
DDRB SET\n");
                writew(arg, my_adc->ptr + DACCFG);
                break;

        case ADC_DACCMDR_IOCTL:
                //printk(LOG_LEVEL "[my_ioctl] [MY_IOCTL_PRINT] Hello ioctl 
DDRB SET\n");
                retval=readw(my_adc->ptr + DACCMD);
                break;
        case ADC_DACCMDRP_IOCTL:
                //printk(LOG_LEVEL "[my_ioctl] [MY_IOCTL_PRINT] Hello ioctl 
DDRB SET\n");
                temp=readw(my_adc->ptr + DACCMD);
                retval=__put_user(temp, (int __user *)arg);             
                break;
        case ADC_DACCMD_IOCTL:
                //printk(LOG_LEVEL "[my_ioctl] [MY_IOCTL_PRINT] Hello ioctl 
DDRB SET\n");
                writew(arg, my_adc->ptr + DACCMD);
                break;
        case ADC_DACSTART_IOCTL:
                writeb((unsigned char)arg, my_adc->ptr + DACCMD+1);
                break;

        // count 0-3
        case ADC_COUNT0_IOCTL:
                count=readw(my_adc->ptr +  COUNT0);
                retval = __put_user(count, (int __user *)arg);
                break;
        case ADC_COUNT1_IOCTL:
                count=readw(my_adc->ptr +  COUNT1);
                retval = __put_user(count, (int __user *)arg);
                break;
        case ADC_COUNT2_IOCTL:
                count=readw( my_adc->ptr +  COUNT2);
                retval = __put_user(count, (int __user *)arg);
                break;
        case ADC_COUNT3_IOCTL:
                count=readw( my_adc->ptr +  COUNT3);
                retval = __put_user(count, (int __user *)arg);
                break;

        case ADC_DIGIO_IOCTL:
                writew(arg, my_adc->ptr +  DIGIO);
                break;


        }//switch
    
        return retval;
}


static int my_release (struct inode *inode, struct file *file)

{
        //printk(LOG_LEVEL "[my_release] Device released.\n");
        return 0;
}


module_init(my_init);
module_exit(my_exit);



adc_drv.h

#define MY_MAJOR                43 
#define MY_MINOR                0
#define MODULE_NAME             "adc"

#define ISAREGSBASE (0xE8000000)
#define ISABASE     (0xEE000000)
#define IOPOFFSET 0x120 // JP1-ON JP2-OFF
        
#define ADCCFG          0x02
#define ADC_DLY_MSW     0x04
#define ADC_DLY_LSW     0x06
#define ADCSTAT         0x08
#define ADCFIFO         0x0A
#define DACCFG          0x0C
#define DACCMD          0x0E
#define COUNT0          0x10
#define COUNT1          0x12
#define COUNT2          0x14
#define COUNT3          0x16
#define DIGIO           0x18


#define EXTRIG_BIT 0x09
#define SEDIF_BIT 0x08

        
// isa base + 0x120. JP1=on,JP2=off
#define ADC_BASE (0xEE000120)
#define BUFFER_SIZE             512
        
//#define BOARD_ID ((volatile char*)(my_data->ptr))
//#define RO1 ((volatile char*)(my_data->ptr+1))

#define BOARD_ID 0

#define ADC_DRV_IOC_MAGIC 141

#define ADC_CFG_IOCTL           _IOWR (ADC_DRV_IOC_MAGIC, 1, int)
#define ADC_DLYMSW_IOCTL        _IOW (ADC_DRV_IOC_MAGIC, 2, int)
#define ADC_DLYLSW_IOCTL        _IOW (ADC_DRV_IOC_MAGIC, 3, int)
#define ADC_STAT_IOCTL          _IOWR (ADC_DRV_IOC_MAGIC, 4, int)
#define ADC_FIFO_IOCTL          _IOR (ADC_DRV_IOC_MAGIC, 5, int)
#define ADC_DACCFG_IOCTL        _IOR (ADC_DRV_IOC_MAGIC, 6, int)
#define ADC_DACCMD_IOCTL        _IOW (ADC_DRV_IOC_MAGIC, 7, int)
#define ADC_COUNT0_IOCTL        _IOR (ADC_DRV_IOC_MAGIC, 8, int)
#define ADC_COUNT1_IOCTL        _IOR (ADC_DRV_IOC_MAGIC, 9, int)
#define ADC_COUNT2_IOCTL        _IOR (ADC_DRV_IOC_MAGIC, 10, int)
#define ADC_COUNT3_IOCTL        _IOR (ADC_DRV_IOC_MAGIC, 11, int)
#define ADC_DIGIO_IOCTL         _IOWR (ADC_DRV_IOC_MAGIC, 12, int)
#define ADC_BOARD_IOCTL         _IOR (ADC_DRV_IOC_MAGIC, 13, int)
#define ADC_GETCFG_IOCTL        _IOR (ADC_DRV_IOC_MAGIC, 14, int)
#define ADC_GETSTAT_IOCTL       _IOR (ADC_DRV_IOC_MAGIC, 15, int)
#define ADC_BID_IOCTL           _IOR (ADC_DRV_IOC_MAGIC, 16, int)
#define ADC_DACCMDR_IOCTL       _IOR (ADC_DRV_IOC_MAGIC, 17, int)
#define ADC_DACCMDRP_IOCTL      _IOR (ADC_DRV_IOC_MAGIC, 18, int)
#define ADC_DLYLSWR_IOCTL       _IOR (ADC_DRV_IOC_MAGIC, 19, int)
#define ADC_DACSTART_IOCTL      _IOW (ADC_DRV_IOC_MAGIC, 20, unsigned char)
#define MY_IRQ1 7








------------------------------------

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