Professional Documents
Culture Documents
Device Drivers, Part 8: Accessing x86-Specific I/O-Mapped Hardware - LINUX For You
Subscribe to Print Edition Search
HOME
REVIEWS
HOW-TOS
CODING
INTERVIEWS
FEATURES
OVERVIEW
BLOGS
SERIES
IT ADMIN
Search for:
Search
This article, which is part of the series on Linux device drivers, continues the discussion on accessing hardware in Linux.
The second day in the Linux device drivers laboratory was expected to be quite different from the typical software-oriented class. Apart from accessing and programming architecture-specific I/O mapped hardware in x86, it had a lot to offer first-timers with regard to reading hardware device manuals (commonly called data sheets) and how to understand them to write device drivers. In contrast, the previous session about generic architecture-transparent hardware interfacing was about mapping and accessing memory-mapped devices in Linux without any device-specific details.
The basic question that may arise relates to which devices are I/O mapped and what the port addresses of these devices are. The answer is pretty simple. As per x86-standard, all these devices and their mappings are predefined. Figure 1 shows a snippet of these mappings through the kernel window / p r o c / i o p o r t s . The listing includes predefined DMA, the timer and RTC, apart from serial, parallel and PCI bus interfaces, to name a few.
www.linuxforu.com/2011/07/accessing-x86-specific-io-mapped-hardware-in-linux/
1/5
8/12/13
Device Drivers, Part 8: Accessing x86-Specific I/O-Mapped Hardware - LINUX For You
Popular Comments Tag cloud
www.linuxforu.com/2011/07/accessing-x86-specific-io-mapped-hardware-in-linux/
2/5
8/12/13
Device Drivers, Part 8: Accessing x86-Specific I/O-Mapped Hardware - LINUX For You
Each of the eight rows corresponds to the respective bit of the registers. Also, note that the register addresses start from 0 and goes up to 7. The interesting thing about this is that a data sheet always gives the register offsets, which then needs to be added to the base address of the device, to get the actual register addresses. Who decides the base address and where is it obtained from? Base addresses are typically board/platform specific, unless they are dynamically configurable like in the case of PCI devices. In this case, i.e., a serial device on x86, it is dictated by the x86 architectureand that precisely was the starting serial port address mentioned above0x3F8. Thus, the eight register offsets, 0 to 7, exactly map to the eight port addresses 0x3F8 to 0x3FF. So, these are the actual addresses to be read or written, for reading or writing the corresponding serial registers, to achieve the desired serial operations, as per the register descriptions. All the serial register offsets and the register bit masks are defined in the header
< l i n u x / s e r i a l _ r e g . h > . So, rather than hard-coding these values from the data sheet, the
corresponding macros could be used instead. All the following code uses these macros, along with the following:
# d e f i n eS E R I A L _ P O R T _ B A S E0 x 3 F 8
Operating on the device registers To summarise the decoding of the PC16550D UART data sheet, here are a few examples of how to do read and write operations of the serial registers and their bits. Reading and writing the Line Control Register (LCR):
u 8v a l ; v a l=i n b ( S E R I A L _ P O R T _ B A S E+U A R T _ L C R/ *3* / ) ; o u t b ( v a l ,S E R I A L _ P O R T _ B A S E+U A R T _ L C R/ *3* / ) ;
Setting and clearing the Divisor Latch Access Bit (DLAB) in LCR:
u 8v a l ; v a l=i n b ( S E R I A L _ P O R T _ B A S E+U A R T _ L C R/ *3* / ) ; / *S e t t i n gD L A B* / v a l| =U A R T _ L C R _ D L A B/ *0 x 8 0* / ; o u t b ( v a l ,S E R I A L _ P O R T _ B A S E+U A R T _ L C R/ *3* / ) ; / *C l e a r i n gD L A B* / v a l& =~ U A R T _ L C R _ D L A B/ *0 x 8 0* / ; o u t b ( v a l ,S E R I A L _ P O R T _ B A S E+U A R T _ L C R/ *3* / ) ;
www.linuxforu.com/2011/07/accessing-x86-specific-io-mapped-hardware-in-linux/
3/5
8/12/13
Device Drivers, Part 8: Accessing x86-Specific I/O-Mapped Hardware - LINUX For You
Blinking an LED
To get a real experience of low-level hardware access and Linux device drivers, the best way would be to play with the Linux device driver kit (LDDK) mentioned above. However, just for a feel of low-level hardware access, a blinking light emitting diode (LED) may be tried, as follows: Connect a light-emitting diode (LED) with a 330 ohm resistor in series across Pin 3 (Tx) and Pin 5 (Gnd) of the DB9 connector of your PC. Pull up and down the transmit (Tx) line with a 500 ms delay, by loading and unloading the b l i n k _ l e ddriver, using i n s m o db l i n k _ l e d . k oand r m m o db l i n k _ l e d , respectively. Driver file b l i n k _ l e d . k ocan be created from its source file b l i n k _ l e d . cby running m a k ewith the usual driver M a k e f i l e . Given below is the complete b l i n k _ l e d . c :
1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5 3 6 3 7 # i n c l u d e< l i n u x / m o d u l e . h > # i n c l u d e< l i n u x / v e r s i o n . h > # i n c l u d e< l i n u x / t y p e s . h > # i n c l u d e< l i n u x / d e l a y . h > # i n c l u d e< a s m / i o . h > # i n c l u d e< l i n u x / s e r i a l _ r e g . h > # d e f i n eS E R I A L _ P O R T _ B A S E0 x 3 F 8 i n t_ _ i n i ti n i t _ m o d u l e ( ) { i n ti ; u 8d a t a ; d a t a=i n b ( S E R I A L _ P O R T _ B A S E+U A R T _ L C R ) ; f o r( i=0 ;i<5 ;i + + ) { / *P u l l i n gt h eT xl i n el o w* / d a t a| =U A R T _ L C R _ S B C ; o u t b ( d a t a ,S E R I A L _ P O R T _ B A S E+U A R T _ L C R ) ; m s l e e p ( 5 0 0 ) ; / *D e f a u l t i n gt h eT xl i n eh i g h* / d a t a& =~ U A R T _ L C R _ S B C ; o u t b ( d a t a ,S E R I A L _ P O R T _ B A S E+U A R T _ L C R ) ; m s l e e p ( 5 0 0 ) ; } r e t u r n0 ;
Looking ahead
You might have wondered why Shweta is missing from this article? She bunked all the classes! Watch out for the next article to find out why.
Related Posts:
Device Drivers, Part 7: Generic Hardware Access in Linux Device Drivers, Part 4: Linux Character Drivers Device Drivers, Part 11: USB Drivers in Linux Device Drivers, Part 12: USB Drivers in Linux Continued Device Drivers, Part 10: Kernel-Space Debuggers in Linux
Tags: architectures, assembly machine, data sheets, device drivers, generic architecture, hardware device, LDDK, LED, LFY July 2011, linux device drivers, Linux Device Drivers Series, mappings, PC16550D, programming architecture, serial port, UART PC16550D, virtual address, x86
Previous Post
Next Post
www.linuxforu.com/2011/07/accessing-x86-specific-io-mapped-hardware-in-linux/
4/5
8/12/13
Device Drivers, Part 8: Accessing x86-Specific I/O-Mapped Hardware - LINUX For You
Get Started with Pygame, Part 2
Reviews
How-Tos
Coding
Interviews
Features
Overview
Blogs
Search
Popular tags
Linux , ubuntu, Java, MySQL, Google, python, Fedora, Android, PHP, C, html, w eb applications , India, Microsoft, unix , Window s , Red Hat, Oracle, Security , Apache, xml, LFY April 2012, FOSS, GNOME, http, JavaScript, LFY June 2011, open source, RAM, operating systems
All published articles are released under Creative Commons Attribution-NonCommercial 3.0 Unported License, unless otherw ise noted. LINUX For You is pow ered by WordPress, w hich gladly sits on top of a CentOS-based LEMP stack.
www.linuxforu.com/2011/07/accessing-x86-specific-io-mapped-hardware-in-linux/
5/5