Introduction to LDD�(Reading CMOS Clock & Type of DD)
Dr A Sahu
Dept of Comp Sc & Engg.
IIT Guwahati
Outline
Advance Peripheral interfacing
Linux Kernel Modules
application
standard
“runtime”
libraries
call
ret
user space
kernel space
Operating System
kernel
syscall
sysret
module
Linux allows us to write our own
installable kernel modules
and add them to a running system
call
ret
Kernel module written in C
#include <linux/module.h> // for printk()
int init( void ){
printk( "\n Kello, everybody! \n\n" );
return 0;
}
void exit( void ){
printk( "\n Goodbye now... \n\n" );
}
MODULE_LICENSE("GPL");
module_init(init);
module_exit(exit);
Creating our own ‘/proc’ files
The ‘get_info()’ callback
int get_info( char *buf, char **start, off_t off, int count );
pointer to a kernel buffer
current file-pointer offset
pointer (optional) to module’ own buffer
size of space available in the kernel’s buffer
function should return the number of bytes it has written into its buffer
The ‘sprintf()’ function
int sprintf( char *dstn, const char *fmt, <arguments> );
pointer to destination
formatting specification string
list of the argument-values to format
will return the number of characters that were printed to the destination-buffer
int len = sprintf( buf, “count = %d \n”, count );
Example:
Register/unregister
create_proc_info_entry( modname, 0, NULL, get_info );
remove_proc_entry( modname, NULL );
the name for your proc file
the file-access attributes (0=default)
directory where file will reside (NULL=default)
function-pointer to your module’s ‘callback’ routine
file’s name
directory
Reading CMOS Clock entry
#include <linux/module.h> // for init_module()
#include <linux/proc_fs.h> // for create_proc_info_entry()
#include <asm/io.h> // for inb(), outb()
char modname[] = "cmos";
unsigned char cmos[10];
char *day[] = { "", "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN" };
char *month[] = { "", "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
"JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
Ten clock/calendar bytes
Current seconds
Alarm seconds
Current minutes
Alarm minutes
Current hours
Alarm hours
Day-of-the-Week
Date of the Month
Current Month
Current Year
0x0
0x1
0x2
0x3
0x4
0x5
0x6
0x7
0x8
0x9
Range is 0..59
Range is 0..59
Range is 0..59
Range is 0..59
Range is 0..23 or 1..12
Range is 0..23 or 1..12
Range is 1..7 (Sunday=7)
Range is 1..31
Range is 1..12 (January=1)
Range is 0..99
Reading CMOS Clock entry
int my_get_info( char *buf, char **start, off_t off, int count ) {
…….
// show the current time and date
len += sprintf( buf+len, "CMOS Real-Time Clock:\
%02X:%02X:%02X on ", mos[4], cmos[2],cmos[0]); // cur h,m,s
len += sprintf( buf+len, " %s, ", day[ cmos[6] ] ); // day-name
len += sprintf( buf+len, "%02X", cmos[7] ); // day-number
// convert 'cmos[ 8 ]' from BCD-format to integer-format
month_index = ((cmos[ 8 ] & 0xF0)>>4)*10 + (cmos[ 8 ] & 0x0F);
len += sprintf( buf+len, " %s", month[ month_index ] ); // month-name
len += sprintf( buf+len, " 20%02X\n ", cmos[9] ); // year-number
return len;
}
Reading CMOS Clock entry: get_info
int my_get_info( char *buf, char **start, off_t off, int count ) {
int i, len = 0; int month_index;
// input and store the first ten CMOS entries
for (i = 0; i < 10; i++) {
outb( i, 0x70 );
cmos[i] = inb( 0x71 );
}
…………………..
Here’s “C” code to read the N-th location:
{
int datum; // storage for a CMOS data-value
outb( N, 0x70 ); // select cell number N for access
datum = inb( 0x71 ); // input value from selected location
}
Reading CMOS Clock entry
static int __init my_init( void ){
printk( "<1>\nInstalling \'%s\' module\n", modname );
create_proc_read_entry( modname, 0, NULL, my_get_info, NULL );
return 0; //SUCCESS
}
static void __exit my_exit(void ) {
remove_proc_entry( modname, NULL );
printk( "<1>Removing \'%s\' module\n", modname );
}
module_init( my_init );
module_exit( my_exit );
MODULE_LICENSE("GPL");
Device Driver
Overall Architecture
Overall Architecture (cont.)
System Call Interface
VFS
File System
Buffer
Cache
Block
Device Driver
Character
Device Driver
Network
Device Driver
Network
Protocol
Socket
Hardware
Overall Architecture (cont.)
Loadable Module Entry Points
Character Driver
Character Device Drivers
Character Driver Functions
Function | Meanings |
Lseek | to change the current read/write position in a file |
Read | to retrieve data from the device |
Write | Sends data to the devic |
Readdir | NULL for device files; reading dirs & only useful to FS. |
Poll | back end of two system calls, poll and select, used to inquire a device is readable or writable or in some special state |
Ioctl | to issue device-specific commands |
Mmap | to request a mapping of device mem to a process's address space |
Open | first operation performed on the device file |
Flush | .. |
Lock | .. |
Release | .. |
Fsync | .. |
Fasync | .. |
Block Driver
Block Driver
Block Driver (cont.)
Processes
Read/Write System Call
Buffer Cache
Invoke Request Function
Check buffer upto date
Done
Call
Scheduler
Character and Block Driver Entry Points
Character and Block Driver Entry Points
STREAMS Drivers
Auto configuration Entry Points
Network Driver
Network Driver (cont.)
User Application
Berkley Socket API
INET Socket
TCP
UDP
IP
ARP
ICMP
Network Device Driver
Network Device
Transmit Data: Xmit
Receive Data
Int. Handler
Support Functions
Lab Excersize
Thanks