350 likes | 582 Views
Introduction to LDD (Reading CMOS Clock & Type of DD). Dr A Sahu Dept of Comp Sc & Engg . IIT Guwahati. Outline. Kernel Module Writing/Registering to /proc FS Payload of kernel module Reading CMOS Data Real Time CMOS Clock Type of devices and drivers Character Block
E N D
Introduction to LDD(Reading CMOS Clock & Type of DD) Dr A Sahu Dept of Comp Sc & Engg. IIT Guwahati
Outline • Kernel Module • Writing/Registering to /proc FS • Payload of kernel module • Reading CMOS Data • Real Time CMOS Clock • Type of devices and drivers • Character • Block • Network/Stream
Advance Peripheral interfacing • Kernel and Device driver • Device Driver Types • CMOS • Reading CMOS Clock and printing at /proc
Linux Kernel Modules Linux allows us to write our own installable kernel modules and add them to a running system application module ret call call Operating System kernel ret syscall standard “runtime” libraries sysret user space kernel space
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 • We can write code to implement our own ‘pseudo’ files, located in ‘/proc’ directory • We do this by adding a ‘payload’ function to a Linux Kernel Module, and by including calls to special kernel-functions within our module-init and our module-exit routines • These special kernel-functions serve to ‘register’, and ‘unregister’, our payload
The ‘get_info()’ callback • When an application-program (like ‘mycat’) tries to read our pseudo-file, the kernel will call our ‘get_info()’ function, passing it four function arguments -- and will expect it to return an integer value: intget_info( char *buf, char **start, off_t off, int count ); pointer to a kernel buffer pointer (optional) to module’ own buffer current file-pointer offset 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 • The kernel provides a function you module can call to print formatted text into a buffer • It resembles a standard C library-function: intsprintf( 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 intlen = sprintf( buf, “count = %d \n”, count ); Example:
Register/unregister • Your module-initialization function should ‘register’ the module’s ‘get_info()’ function: create_proc_info_entry( modname, 0, NULL, get_info ); • Your cleanup should do an ‘unregister’: 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 directory file’s name
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 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 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 Alarm seconds Current minutes Alarm minutes Current hours Alarm hours Day-of-the-Week Date of the Month Current Month Current Year
Reading CMOS Clock entry intmy_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 intmy_get_info( char *buf, char **start, off_t off, int count ) { inti, len = 0; intmonth_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 • A device driver is a kernel module responsible for managing low-level I/O operations for a particular hardware device. • Block device drivers manage devices with physically addressable storage media, such as disks. • All other devices are considered character devices
Overall Architecture • VFS (Virtual File System) • Driver Types • Basic: • Character (ADC, Line printer) • Block (SCSI DISK) • Network • Special • Stream • Terminal
Overall Architecture (cont.) System Call Interface Socket VFS File System Network Protocol Buffer Cache Block Device Driver Character Device Driver Network Device Driver Hardware
Overall Architecture (cont.) • Operation Modes • polling • interrupt • DMA
Loadable Module Entry Points • All drivers are required to implement the loadable module entry points • init () // (load) • finialise () //unload • info () // Gather information of device • Drivers should allocate and initialize any global resources in init()and release their resources in finilise().
Character Driver • Device Properties • can’t be randomly accessed • can’t be buffered • usually are slow devices • Export Interface • file_operations • Data Flow in read/write
Character Device Drivers • Character device drivers normally perform I/O in a byte stream. • Examples of devices using character drivers include tape drives and serial ports. • Character device drivers can also provide additional interfaces not present in block drivers, • I/O control (ioctl) commands • memory mapping • device polling.
Block Driver • Block Devices that support a file system are known as block devices. • Drivers written for these devices are known as block device drivers. • Block device drivers take a file system request, in the form of a buffer structure, • And issue the I/O operations to the disk to transfer the specified block. • The main interface to the file system is the strategy routine
Block Driver • Device Properties • can be randomly accessed • accessed in units of blocks • to speed up access, buffer cache is used • Export Interface • file_operations • request_fn() • Data Flow in read/write
Block Driver (cont.) Processes Read/Write System Call Buffer Cache Invoke Request Function Call Scheduler Check buffer upto date Done
Character and Block Driver Entry Points • Drivers for character and block devices export a cb_ops structure • which defines the driver entry points for block device access and character device access. • Both types of drivers are required to support open and close.
Character and Block Driver Entry Points • Block drivers are required to support strategy, while character drivers can choose to implement whatever mix of • read, write, ioctl, mmap, or devmap • These entry points as appropriate for the type of device. • Character drivers can also support a polling interface through • ch_poll • as well as asynchronous I/O through areadand awrite.
STREAMS Drivers • STREAMS is a separate programming model for writing a character driver. • Devices that receive data asynchronously (such as terminal and network devices) are suited to a STREAMS implementation. • STREAMS device drivers must provide the loading and autoconfiguration support
Auto configuration Entry Points • Drivers are required to implement these Entry points for device autoconfiguration. • Attach • Detach, • Getinfo • Drivers might need to implement probe if the driver supports devices that are not self identifying, such as SCSI target devices
Network Driver • Export Interface • Data Flow in read/write
Network Driver (cont.) User Application Berkley Socket API INET Socket TCP UDP IP ARP ICMP Network Device Driver Transmit Data: Xmit Receive Data Int. Handler Network Device
Support Functions • I/O ports reservations • request_region() • Memory Allocations • kmalloc(), vmalloc(), get_free_page() • Interrupt Handler Registration • request_irq() • Data Transfer between User/Kernel • memcpy_fromfs()
Lab Excersize • Download mmake.cpp and cmos.c • Course Website, tested on Fedora 12 • Compile mmake.cpp using ‘make’ • Then compile cmos.cusing ‘make’ • Install ‘cmos.ko’ (and see printk-message) • See $cat /proc/cmos