Tuesday, October 25, 2011

VIM - ETAGS/CSCOPE

VIM - ETAGS/CSCOPE
CTRL + \ + s [To go to a symbol]
CTRL + t  [To jump back]

CTRL + Spacebar + s [split horizontally]
CTRL + w + w [Browse windows]
CTRL + w + c [Close a window]
CTRL + w + o [Make the current window only one]
CTRL + w + s [Horizontal split]
CTRL + w + v [Vertical split]
CTRL + Spacebar CTRL + Spacebar + s [Split vertically]


Cscope database for linux kernel
LNX=/home/vinod/files/beagle/linux-3.0.4
    find  $LNX                                                                \
    -path "$LNX/arch/*" ! -path "$LNX/arch/arm*" -prune -o               \
    -path "$LNX/tmp*" -prune -o                                           \
    -path "$LNX/Documentation*" -prune -o                                 \
    -path "$LNX/scripts*" -prune -o                                       \
        -name "*.[chxsS]" -print >/home/vinod/files/beagle/linux-3.0.4/cscope.files

cscope -b -q -k -v


Friday, October 21, 2011

Create Mask


/* Create a mask with m set bits followed by n unset bits */

#include <stdio.h>


unsigned int createmask(unsigned int m, unsigned int n)
{
    return (~(~0 << m) << n);
}

char *basecalc(unsigned int num, unsigned int base)
{
    static char buff[32];
    char *s = &buff[31];
    *s = '\0';
    int cnt = 0,i;
    while(num)
    {
        *(--s) = "0123456789ABCDEF"[num%base];
        num /= base;
        cnt++;
        if(cnt > 7) break;
    }
    for(i=cnt; i<=7;i++)
        *(--s) = '0';
    return s;
}

int main()
{
    unsigned int m,n,r;
    printf("Enter the required set bits: ");
    scanf("%d",&m);
    printf("Enter the required unset bits: ");
    scanf("%d",&n);
    r = createmask(m,n);
    printf("The created mask: %s\n",basecalc(r,2));
    return 0;
}

Test 1:
Enter the required set bits  : 5
Enter the required unset bits: 3
The created mask             : 11111000

Test 2:
Enter the required set bits  : 2
Enter the required unset bits: 5
The created mask             : 01100000


Register, Mask and Value


#include <stdio.h>


char *basecalc(unsigned int num, unsigned int base)
{
    static char buff[32];
    char *s = &buff[31];
    int cnt = 0,i;
    *s = '\0';
    while(num)
    {
        *(--s) = "0123456789ABCDEF"[num%base];
        num /= base;
        cnt++;
        if(cnt>7) break;
    }
    for(i=cnt;i<=7;i++)
        *(--s) = '0';
    return s;
   
}

int fbs(int mask)
{
    unsigned int pos = 0;
    if(!mask) return 0;
    while(!(mask &1))
    {
        mask >>= 1;
        pos++;
    }
    return (pos);
}

int setmask (int num, int mask, int value)
{
    /*This multiplies value by the lowest set bit in MASK.
      The multiplier is known to be a constant power of 2 at compile time,
      so this will be compiled as a simple left shift by any remotely sane compiler.
     */
    //value *= ( mask & ~(mask << 1));
    //return (num &= (value | ~mask) );
    return ( num &= ((value*(mask & ~(mask<<1)))|~mask )  );
}

int main()
{
    int num, mask, value,res;

    printf("Enter the num: ");
    scanf("%d",&num);      
    printf("Enter the mask: ");
    scanf("%d",&mask);
    printf("Enter the value: ");
    scanf("%d",&value);

    /* ------------------------ */
    printf("Num  : %s\n",basecalc(num,2));
    printf("Mask : %s\n",basecalc(mask,2));
    printf("Value: %s\n",basecalc(value,2));
    /* ------------------------ */

    res = setmask(num,mask,value);
    printf("The set value: %s\n",basecalc(res,2));
    return 0;
}

TEST 1
Enter the num  : 25
Enter the mask : 24
Enter the value: 1
Num            : 00011001
Mask           : 00011000
Value          : 00000001
The set value  : 00001001

TEST 2
Enter the num  : 153
Enter the mask : 24
Enter the value: 2
Num            : 10011001
Mask           : 00011000
Value          : 00000010
The set value  : 10010001

Monday, October 3, 2011

Video RAM driver


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

#include <linux/kdev_t.h>
#include <linux/types.h>
#include <linux/fs.h>

#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/device.h>
#include <linux/cdev.h>


#define VRAM_BASE 0x000A0000
#define VRAM_SIZE 0x00020000

static void __iomem *vram;
static dev_t first;
static struct cdev c_dev;
static struct class *cl;


static int my_open(struct inode *i, struct file *f)
{return 0;}

static int my_close(struct inode *i, struct file *f)
{return 0;}

static ssize_t my_read(struct file *f, char __user *buf,size_t len,loff_t *off)
{
    int i;
    unsigned char byte;

    if(*off >= VRAM_SIZE)
    {
         return 0;          
    }
   
    if(*off + len > VRAM_SIZE)
    {
        len = VRAM_SIZE - *off;
    }
   
    for(i=0; i
    {
        byte = ioread8((unsigned char *)vram + *off + i);
        if(copy_to_user(buf+i,&byte,1))
            return -EFAULT;
    }
    *off +=len;
    return len;
}

static ssize_t my_write(struct file *f,const char __user *buf, size_t len, loff_t *off)
{
    int i;
    unsigned char byte;

    if(*off >= VRAM_SIZE)
        return 0;

    if(*off + len > VRAM_SIZE)
        len = VRAM_SIZE - *off;

    for(i=0; i
    {
        if(copy_from_user(&byte,buf+i,1))
            return -EFAULT;
        iowrite8(byte,(unsigned char *)vram + *off +i);
    }
    *off += len;   
    return len;
}

static struct file_operations vram_fops =
{
    .owner = THIS_MODULE,
    .open = my_open,
    .release = my_close,
    .read = my_read,
    .write = my_write
};

static int __init vram_init(void)
{
    printk(KERN_INFO "VRAM init started...");
    if( (vram = ioremap(VRAM_BASE,VRAM_SIZE)) == NULL)
    {
        printk(KERN_ERR "Mapping video ram failed\n");
        return -1;
    }
    printk(KERN_INFO "Video RAM mapping OK");

    if(alloc_chrdev_region(&first,0,1,"vram") < 0)
        return -1;

    if( (cl = class_create(THIS_MODULE,"chrdrv")) == NULL)
    {
        unregister_chrdev_region(first,1);
        return -1;
    }       

    if(device_create(cl,NULL,first,NULL,"vram") == NULL)
    {
        class_destroy(cl);
        unregister_chrdev_region(first,1);
        return -1;
    }
   
    cdev_init(&c_dev,&vram_fops);
    if(cdev_add(&c_dev,first,1) == -1)
    {
        device_destroy(cl,first);
        class_destroy(cl);
        unregister_chrdev_region(first,1);
        return -1;
    }

    printk(KERN_INFO "Successful vram driver init...");
    return 0;
}

static void __exit vram_exit(void)
{
    cdev_del(&c_dev);
    device_destroy(cl,first);
    class_destroy(cl);
    unregister_chrdev_region(first,1);
    iounmap(vram);
    printk(KERN_INFO "Alvida: vram driver unregistered");
}

module_init(vram_init);
module_exit(vram_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("VINOD");
MODULE_DESCRIPTION("VRAM driver");

COMMANDS:

WRITE: echo -n "0123456789" > /dev/vram
READ: od -t x1 -v /dev/vram 


cat /proc/iomem
cat /proc/meminfo

Simple Character Driver


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

#include <linux/kdev_t.h>
#include <linux/types.h>
#include <linux/fs.h>

#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>

static dev_t first;
static struct cdev c_dev;
static struct class *cl;
static char c;

static int my_open(struct inode *i, struct file *f)
{
    printk(KERN_INFO "DRIVER: open()");
    return 0;
}

static int my_close(struct inode *i, struct file *f)
{
    printk(KERN_INFO "DRIVER: close()");
    return 0;
}

static ssize_t my_read(struct file *f,char __user *buf, size_t len, loff_t *off)
{
    printk(KERN_INFO "DRIVER: read()");
    if(copy_to_user(buf,&c,1) != 0)
        return -EFAULT;
    else
        return 1;
}

static ssize_t my_write(struct file *f, const char __user *buf, size_t len, loff_t *off)
{
    printk(KERN_INFO "DRIVER: write()");
    if(copy_from_user(&c, buf+len-1,1) != 0)
        return -EFAULT;
    else
        return len;
}

static struct file_operations my_fops =
{
    .owner    = THIS_MODULE,
    .open     = my_open,
    .release  = my_close,
    .read     = my_read,
    .write    = my_write
};

static int __init dd_init(void)
{
    printk(KERN_INFO "Namaskar: dd initialization");
   
    if(alloc_chrdev_region(&first, 0, 1, "VINZU") < 0)
    {
        return -1;
    } 

    if( (cl = class_create(THIS_MODULE,"chrdrv")) == NULL)
    {
        unregister_chrdev_region(first,1);
        return -1;
    }  

    if(device_create(cl,NULL,first,NULL,"mynull") == NULL)
    {
        class_destroy(cl);
        unregister_chrdev_region(first,1);
        return -1;
    }

    cdev_init(&c_dev,&my_fops);
    if(cdev_add(&c_dev,first,1) == -1)
    {
        device_destroy(cl,first);
        class_destroy(cl);
        unregister_chrdev_region(first,1);
        return -1;
    }

    printk(KERN_INFO "dd registerd successfully...");
    return 0;
}

static void __exit dd_exit(void)
{
    cdev_del(&c_dev);
    device_destroy(cl,first);
    class_destroy(cl);
    unregister_chrdev_region(first,1);
    printk(KERN_INFO "Alvida: dd unregisterd");
}

module_init(dd_init);
module_exit(dd_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("VINOD");
MODULE_DESCRIPTION("Simple character driver");



|COMMANDS FOR TESTING:



cat /proc/devices - VINZU
ls /sys/class - chardrv
ls -l /dev - mynull

echo -n "hello" > /dev/mynull
dmesg | tail -10
cat /dev/mynull
ctrl + c
dmesg | tail -10




how to write to a physical address in Linux?


 Usually you do this in several steps in a device driver:

1. Call request_mem_region() to request virtual memory region;
2. Call ioremap() to map physical address to virtual address;
3. Read/write mapped virtual address by using iowriteXX() /
ioreadXX(), etc. Here XX can be 8, 16, or 32 for example, represents
bit width.
4. Call iounmap() and release_mem_region() to release memory mapping;
[ NOTE: phys_to_virt() only works with directly mapped physical address. Using phys_to_virt() is the best idea, anyway.]


To make access generic
The addresses referring to RAM are termed as physical addresses,and those referring to device maps are bus addresses.In Linux, none of these are directly accessible, but are to mapped to virtual addresses and then accesses through them. This is to make RAM and device access generic.


void *ioremap (unsigned long device_bus_address, unsigned long device_region_size);
void iounmap (void *virt_addr);

Once mapped to virtual addresses, it depends on the device datasheet as to which set of device registers and/or device memory to read from or wirte into, by adding their offsets to the virtual address returned by ioremap().
unsigned int ioread8(void *virt_addr);
unsigned int ioread16(void *virt_addr);
unsigned int ioread32(void *virt_addr);

unsigned int iowrite8(u8 value, void *virt_addr);
unsigned int iowrite16(u16 value, void *virt_addr);
unsigned int iowrite32(u32 value, void *virt_addr);