Sei sulla pagina 1di 8

8/5/13

Write For Us Submit Tips

Device Drivers, Part 7: Generic Hardware Access in Linux - LINUX For You
Subscribe to Print Edition Search

HOME

REVIEWS

HOW-TOS

CODING

INTERVIEWS

FEATURES

OVERVIEW

BLOGS

SERIES

IT ADMIN

Device Drivers, Part 7: Generic Hardware Access in Linux


By Anil Kumar Pugalia on June 1, 2011 in Coding, Developers 23 Comments and 0 Reactions

Search for:

Search

This article, which is part of the series on Linux device drivers, talks about accessing hardware in Linux.
Shweta was all jubilant about her character driver achievements, as she entered the Linux device drivers laboratory on the second floor of her college. Many of her classmates had already read her blog and commented on her expertise. And today was a chance to show off at another level. Till now, it was all software but todays lab was on accessing hardware in Linux. In the lab, students are expected to learn by experiment how to access different kinds of hardware in Linux, on various architectures, over multiple lab sessions. Members of the lab staff are usually reluctant to let students work on the hardware straight away without any experience so they had prepared some presentations for the students (available here).

Get Connected RSS Feed Twitter

Generic hardware interfacing


As every one settled down in the laboratory, lab expert Priti started with an introduction to hardware interfacing in Linux. Skipping the theoretical details, the first interesting slide was about generic architecture-transparent hardware interfacing (see Figure 1).

LINUX For You on

Follow

+2,474

Figure 1: Hardw are mapping

The basic assumption is that the architecture is 32-bit. For others, the memory map would change accordingly. For a 32-bit address bus, the address/memory map ranges from 0 (0 x 0 0 0 0 0 0 0 0 ) to 232 1 (0 x F F F F F F F F ). An architecture-independent layout of this memory map would be like whats shown in Figure 1 memory (RAM) and device regions (registers and

www.linuxforu.com/2011/06/generic-hardware-access-in-linux/

1/8

8/5/13

Device Drivers, Part 7: Generic Hardware Access in Linux - LINUX For You
Find us on Facebook

memories of devices) mapped in an interleaved fashion. These addresses actually are architecture-dependent. For example, in an x86 architecture, the initial 3 GB (0 x 0 0 0 0 0 0 0 0to 0 x B F F F F F F F ) is typically for RAM, and the later 1GB (0 x C 0 0 0 0 0 0 0to 0 x F F F F F F F F ) for device maps. However, if the RAM is less, say 2GB, device maps could start from 2GB (0 x 8 0 0 0 0 0 0 0 ). Run c a t/ p r o c / i o m e mto list the memory map on your system. Run c a t/ p r o c / m e m i n f oto get the approximate RAM size on your system. Refer to Figure 2 for a snapshot.

Open Source For You


Like 251,503 people like Open Source For You.

F acebook social plugin

Popular

Comments

Tag cloud

May 6, 2013 5 Comments Priyanka Sarkar

PHP Development: A Smart Career Move


June 20, 2013 3 Comments Priyanka Sarkar

What it Takes to be an Open Source Expert


June 20, 2013 2 Comments sophie-samuel

New and amazing features of Linux


May 6, 2013 1 Comments Deepti Sharma

A Simple guide to building your own Linux Kernel


May 6, 2013 1 Comments Prashant Phatak

Cyber Attacks Explained: Cryptographic Attacks

Figure 2: Physical and bus addresses on an x86 system

Irrespective of the actual values, the addresses referring to RAM are termed as physical addresses, and those referring to device maps as bus addresses, since these devices are always mapped through some architecture-specific bus for example, the PCI bus in the x86 architecture, the AMBA bus in ARM architectures, the SuperHyway bus in SuperH architectures, etc. All the architecture-dependent values of these physical and bus addresses are either dynamically configurable, or are to be obtained from the data-sheets (i.e., hardware manuals) of the corresponding architecture processors/controllers. The interesting part is that in Linux, none of these are directly accessible, but are to be mapped to virtual addresses and then accessed through them thus making the RAM and device accesses generic enough. The corresponding APIs (prototyped in < a s m / i o . h > ) for mapping and unmapping the device bus addresses to virtual addresses are:
v o i d* i o r e m a p ( u n s i g n e dl o n gd e v i c e _ b u s _ a d d r e s s ,u n s i g n e dl o n gd e v i c e _ r e g i o n _ s i z e ) ; v o i di o u n m a p ( v o i d* v i r t _ a d d r ) ;

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 write into, by adding their offsets to the virtual address returned by i o r e m a p ( ) . For that, the following are the APIs (also prototyped in
< a s m / i o . h > ):
u n s i g n e di n ti o r e a d 8 ( v o i d* v i r t _ a d d r ) ; u n s i g n e di n ti o r e a d 1 6 ( v o i d* v i r t _ a d d r ) ; u n s i g n e di n ti o r e a d 3 2 ( v o i d* v i r t _ a d d r ) ; u n s i g n e di n ti o w r i t e 8 ( u 8v a l u e ,v o i d* v i r t _ a d d r ) ; u n s i g n e di n ti o w r i t e 1 6 ( u 1 6v a l u e ,v o i d* v i r t _ a d d r ) ; u n s i g n e di n ti o w r i t e 3 2 ( u 3 2v a l u e ,v o i d* v i r t _ a d d r ) ;

Accessing the video RAM of DOS days


After this first set of information, students were directed for the live experiments. The suggested initial experiment was with the video RAM of DOS days, to understand the usage of the above APIs. Shweta got onto the system and went through / p r o c / i o m e m(as in Figure 2) and got the video RAM address, ranging from 0 x 0 0 0 A 0 0 0 0to 0 x 0 0 0 B F F F F . She added the above APIs, with appropriate parameters, into the constructor and destructor of her existing null driver, to convert it into a vram driver. Then she added the user access to the video RAM through read and write calls of the vram driver; heres her new file v i d e o _ r a m . c :
1 # i n c l u d e< l i n u x / m o d u l e . h >

www.linuxforu.com/2011/06/generic-hardware-access-in-linux/

2/8

8/5/13
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 3 8 3 9 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5 8 5 9 6 0 6 1 6 2 6 3 6 4 6 5 6 6 6 7 6 8 6 9 7 0 7 1 7 2 7 3 7 4 7 5 7 6 7 7 7 8 7 9 8 0 8 1 8 2 8 3 8 4 8 5 8 6 8 7 8 8 8 9 9 0 9 1 9 2 9 3 9 4 9 5 9 6 9 7 9 8 9 9 1 0 0 1 0 1 1 0 2 1 0 3 1 0 4 1 0 5 1 0 6 1 0 7 1 0 8 1 0 9 1 1 0 # 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 / k e r n e l . 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 / k d e v _ t . h > # i n c l u d e< l i n u x / f s . h > # i n c l u d e< l i n u x / d e v i c e . h > # i n c l u d e< l i n u x / c d e v . h > # i n c l u d e< l i n u x / u a c c e s s . h > # i n c l u d e< a s m / i o . h > # d e f i n eV R A M _ B A S E0 x 0 0 0 A 0 0 0 0 # d e f i n eV R A M _ S I Z E0 x 0 0 0 2 0 0 0 0 s t a t i cv o i d_ _ i o m e m* v r a m ; s t a t i cd e v _ tf i r s t ; s t a t i cs t r u c tc d e vc _ d e v ; s t a t i cs t r u c tc l a s s* c l ;

Device Drivers, Part 7: Generic Hardware Access in Linux - LINUX For You

s t a t i ci n tm y _ o p e n ( s t r u c ti n o d e* i ,s t r u c tf i l e* f ) { r e t u r n0 ; } s t a t i ci n tm y _ c l o s e ( s t r u c ti n o d e* i ,s t r u c tf i l e* f ) { r e t u r n0 ; } s t a t i cs s i z e _ tm y _ r e a d ( s t r u c tf i l e* f ,c h a r_ _ u s e r* b u f ,s i z e _ tl e n ,l o f f _ t* o f f ) { i n ti ; u 8b y t e ; i f( * o f f> =V R A M _ S I Z E ) { r e t u r n0 ; } i f( * o f f+l e n>V R A M _ S I Z E ) { l e n=V R A M _ S I Z E-* o f f ; } f o r( i=0 ;i<l e n ;i + + ) { b y t e=i o r e a d 8 ( ( u 8* ) v r a m+* o f f+i ) ; i f( c o p y _ t o _ u s e r ( b u f+i ,& b y t e ,1 ) ) { r e t u r nE F A U L T ; } } * o f f+ =l e n ; r e t u r nl e n ; } s t a t i cs s i z e _ tm y _ w r i t e ( s t r u c tf i l e* f ,c o n s tc h a r_ _ u s e r* b u f ,s i z e _ tl e n ,l o f f _ t* o f f ) { i n ti ; u 8b y t e ; i f( * o f f> =V R A M _ S I Z E ) { r e t u r n0 ; } i f( * o f f+l e n>V R A M _ S I Z E ) { l e n=V R A M _ S I Z E-* o f f ; } f o r( i=0 ;i<l e n ;i + + ) { i f( c o p y _ f r o m _ u s e r ( & b y t e ,b u f+i ,1 ) ) { r e t u r nE F A U L T ; } i o w r i t e 8 ( b y t e ,( u 8* ) v r a m+* o f f+i ) ; } * o f f+ =l e n ; } r e t u r nl e n ;

s t a t i cs t r u c tf i l e _ o p e r a t i o n sv r a m _ f o p s= { . o w n e r=T H I S _ M O D U L E , . o p e n=m y _ o p e n , . r e l e a s e=m y _ c l o s e , . r e a d=m y _ r e a d , . w r i t e=m y _ w r i t e } ; s t a t i ci n t_ _ i n i tv r a m _ i n i t ( v o i d )/ *C o n s t r u c t o r* / { i f( ( v r a m=i o r e m a p ( V R A M _ B A S E ,V R A M _ S I Z E ) )= =N U L L ) { p r i n t k ( K E R N _ E R R" M a p p i n gv i d e oR A Mf a i l e d \ n " ) ; r e t u r n1 ; } i f( a l l o c _ c h r d e v _ r e g i o n ( & f i r s t ,0 ,1 ," v r a m " )<0 ) { r e t u r n1 ; } i f( ( c l=c l a s s _ c r e a t e ( T H I S _ M O D U L E ," c h a r d r v " ) )= =N U L L ) { u n r e g i s t e r _ c h r d e v _ r e g i o n ( f i r s t ,1 ) ; r e t u r n1 ; } i f( d e v i c e _ c r e a t e ( c l ,N U L L ,f i r s t ,N U L L ," v r a m " )= =N U L L ) { c l a s s _ d e s t r o y ( c l ) ; u n r e g i s t e r _ c h r d e v _ r e g i o n ( f i r s t ,1 ) ; r e t u r n1 ; }

www.linuxforu.com/2011/06/generic-hardware-access-in-linux/

3/8

8/5/13
1 1 1 1 1 2 1 1 3 1 1 4 1 1 5 1 1 6 1 1 7 1 1 8 1 1 9 1 2 0 1 2 1 1 2 2 1 2 3 1 2 4 1 2 5 1 2 6 1 2 7 1 2 8 1 2 9 1 3 0 1 3 1 1 3 2 1 3 3 1 3 4 1 3 5 1 3 6

Device Drivers, Part 7: Generic Hardware Access in Linux - LINUX For You
c d e v _ i n i t ( & c _ d e v ,& v r a m _ f o p s ) ; i f( c d e v _ a d d ( & c _ d e v ,f i r s t ,1 )= =1 ) { d e v i c e _ d e s t r o y ( c l ,f i r s t ) ; c l a s s _ d e s t r o y ( c l ) ; u n r e g i s t e r _ c h r d e v _ r e g i o n ( f i r s t ,1 ) ; r e t u r n1 ; } r e t u r n0 ;

s t a t i cv o i d_ _ e x i tv r a m _ e x i t ( v o i d )/ *D e s t r u c t o r* / { c d e v _ d e l ( & c _ d e v ) ; d e v i c e _ d e s t r o y ( c l ,f i r s t ) ; c l a s s _ d e s t r o y ( c l ) ; u n r e g i s t e r _ c h r d e v _ r e g i o n ( f i r s t ,1 ) ; i o u n m a p ( v r a m ) ; } m o d u l e _ i n i t ( v r a m _ i n i t ) ; m o d u l e _ e x i t ( v r a m _ e x i t ) ; M O D U L E _ L I C E N S E ( " G P L " ) ; M O D U L E _ A U T H O R ( " A n i lK u m a rP u g a l i a< e m a i l _ a t _ s a r i k a p u g s _ d o t _ c o m > " ) ; M O D U L E _ D E S C R I P T I O N ( " V i d e oR A MD r i v e r " ) ;

Summing up
Shweta then repeated the usual steps: 1. Build the vram driver (v i d e o _ r a m . k ofile) by running m a k ewith a changed M a k e f i l e . 2. Load the driver using i n s m o dv i d e o _ r a m . k o . 3. Write into / d e v / v r a m , say, using e c h on" 0 1 2 3 4 5 6 7 8 9 ">/ d e v / v r a m . 4. Read the / d e v / v r a mcontents using o dtx 1v/ d e v / v r a m|l e s s . (The usual c a t / d e v / v r a mcan also be used, but that would give all the binary content. o dtx 1shows it as hexadecimal. For more details, run m a no d .) 5. Unload the driver using r m m o dv i d e o _ r a m . With half an hour still left for the end of the practical class, Shweta decided to walk around and possibly help somebody else with their experiments.

Related Posts:
Device Drivers, Part 5: Character Device Files Creation & Operations Device Drivers, Part 6: Decoding Character Device File Operations Device Drivers, Part 8: Accessing x86-Specific I/O-Mapped Hardware Device Drivers, Part 4: Linux Character Drivers Device Drivers, Part 9: I/O Control in Linux
Tags: architectures, ARM architecture, device drivers, DOS, drivers, generic architecture, hardware interfacing, LFY June 2011, linux device drivers, Linux Device Drivers Series, RAM, registers, video RAM, Video RAM Drivers, VRAM, x86 architecture

Article written by:


Anil Kumar Pugalia
The author is a freelance trainer in Linux internals, Linux device drivers, embedded Linux and related topics. Prior to this, he had worked at Intel and Nvidia. He has been exploring Linux since 1994. A gold medallist from the Indian Institute of Science, Linux and knowledge-sharing are two of his many passions. Connect with him: Website - Twitter - Facebook - Google+

Previous Post

Next Post

Sed Explained, Part 2: Data Structures and Operators

Code Profiling in Linux Using Gprof

23 comments Leave a message...


Newest Community s ant os h y adav

Share

3 months ago

hello everyone!
www.linuxforu.com/2011/06/generic-hardware-access-in-linux/ 4/8

8/5/13

Device Drivers, Part 7: Generic Hardware Access in Linux - LINUX For You

i am trying to do gpio access and encounter segmentation fault. so to overcome it i will have to map the physical address to logical and for that i made use of ioremap(). but while i am using it the kernel is unable to locate the 'asm/io.h' header file so what should i do to include the header so that it may work.
Reply Share
santosh yadav 2 months ago

anil_pugalia

I assume that you have set up the kernel headers path appropriately. If not, do it. If yes, have you configured the kernel? Which architecture is it for?
Reply s rik ant h

Share

3 months ago

static void __iomem *vram; what is __iomem ? I understood that vram is void pointer, but __iomem signifies what?
Reply Share
srikanth 2 months ago

anil_pugalia

When tagged with __iomem, it enables that pointer for compiler checks &/or optimizations, relevant for I/O mapped memory.
Reply linux _bot

Share

7 months ago

how is VRAM_SIZE = 0x00020000 is calculated, when subtracted from 0x000BFFFF - 0x000A0000 = 1ffff
Reply Share
linux_bot 6 months ago

anil_pugalia

You need to add 1 to the result of subtraction. Why? Here's the logic: If an address starts from A0000 and ends at A0001, then they are 2 addresses and hence the size is 2; and we calculate as follows (A0001 - A0000) + 1 = 2.
2 S A THE E S A RA N Reply

Share

7 months ago

Hi Anil, So whatever we write to this device driver is written to memory of the device [bus address], so how would the visual display unit interprets it and shows in the screen ? One more thing is, I could not understand the data when I read from video driver. I wrote , "0123456789" to driver and I read from driver using the command, xxd. Output goes like this, 0000000: 0100 0000 3435 3637 3839 0000 0000 0000 ....456789...... How could I interpret the pattern "0123456789" from above read input ? Thanks, Satheesaran
Reply Share
SATHEESARAN 7 months ago

anil_pugalia

As this video RAM is no longer used, you may not see any characters on the screen. About the output, centre is the ASCII values in hex, and right is the characters.
Reply plr

Share

11 months ago

Hi Anil , I had a doubt regarding the read function . ssize_t my_read(struct file *f, char __user *buf, size_t len, loff_t *off) here len tells the number of bytes to be read . www.linuxforu.com/2011/06/generic-hardware-access-in-linux/
5/8

8/5/13

Device Drivers, Part 7: Generic Hardware Access in Linux - LINUX For You

here len tells the number of bytes to be read . and what is loff_t *off field meant for ? I thot it is the offset from which the byte has to be read . But if (*off >= VRAM_SIZE) { return 0; } gives a different meaning . here it refers to number of bytes to be read if Im not wrong... Please clarify regarding this... I kno its a very small thing but Im stuck right at this point...
Reply plr Share

plr 11 months ago

hi sir, I understood it myself... Here off is the offset from the base address . (off > base address) means its going beyond the mapping for vram ....
Reply Share
plr 8 months ago

anil_pugalia

Yes, you understood correct - (off_from_base_address >= VRAM_SIZE) will go beyond the VRAM mapping.
Reply s andeep

Share

11 months ago

excellent work sir please try to upload the same with linux internals also
Reply Share
sandeep 11 months ago

A nil P ugalia Reply B uk

Thanks. And what do you mean by upload same with linux internals?
Share

a year ago

Great tutorials but it would be better if you could give the output screen after od -t x1 -v /dev/vram | less command. am not sure if i did any mistake because there isn' t much difference between writing echo 0123456789 and echo 55
Reply Share
Buk a year ago

A nil P ugalia

If there is no change - that's very much possible, if the underlying system doesn't have that Video RAM physically, present.
Reply mrr

Share

a year ago

Worth to mention that if you couldn't find "Video RAM" in /proc/iomem, try to run `lspci v` and find video device info: bash# lspci -v 00:02.0 VGA compatible controller: Cirrus Logic GD 5446 Subsystem: Qumranet, Inc. Device 1100 Flags: fast devsel Memory at e0000000 (32-bit, prefetchable) [size=32M] Memory at e2000000 (32-bit, non-prefetchable) [size=4K] Expansion ROM at e2010000 [disabled] [size=64K] Kernel modules: cirrusfb and with device number '00:02.0' you can find it now in /proc/iomem: bash# grep 00:02.0 /proc/iomem e0000000-e1ffffff : 0000:00:02.0 e2000000-e2000fff : 0000:00:02.0 e2010000-e201ffff : 0000:00:02.0 Memory at 0xe0000000 is good enough for the article example.
Reply Share
mrr a year ago

anil_pugalia

www.linuxforu.com/2011/06/generic-hardware-access-in-linux/

6/8

8/5/13
anil_pugalia

Device Drivers, Part 7: Generic Hardware Access in Linux - LINUX For You
mrr a year ago

What you pointed out is correct. But we do not want to play & goof up with the ram of the currently being used video card. And that's why, looking for the unused video ram from the "DOS days", which is at the location as mentioned in the article.
Reply Haris Ibrahim K . V .

Share
a year ago

I believe the meaning of the output of "od -t x1 -v /dev/vram | less" should be explained so as to how it relates with the "0123456789" that we wrote into our driver.
Reply Share
Haris Ibrahim K. V. a year ago

Lok es h W alas eP at il

Yes, even I m not understanding what the o/p should be. Pls someone explain it !! :)
Reply Share
Lokesh WalasePatil a year ago

anil_pugalia

Easier way for understanding the same would be to try xxd. Just do the following: xxd /dev/vram | less What exactly we are doing with all these, is reading & display the vide ram content, in more readable ways, like in hex, in ASCII, etc
Reply y uva

Share

2 years ago

Hi Anil , I am reading your article from the beginning . I am happy with your sharing. Your article is really good . I have some queries please clarify. From the following link i came to know that there are three ways for addressing memory . http://tldp.org/LDP/khg/HyperN... I want to understand what is "virtual address" and "bus address" clearly . Regards, A.Yuvaraj
Reply Share
yuva a year ago

Haris Ibrahim K . V .

Hi Yuva, I'm a bit confused regarding the 'bus address' terminology. There are 'address buses' that carry addresses between different devices. Basically a 16-bit system having 16 parallel wires to carry this. I believe this tech has been improved by multiplexing the addresses and hence using lesser number of wires in parallel. Where as 'virtual address' refers to the address space the processes have within the virtual memory. The concept of virtual memory can be viewed as 'enlarging the capacity of RAM'. So the part of the processes that are needed for execution are in the RAM while those parts that are not currently needed will be in their corresponding virtual addresses ready to be mapped onto the RAM. My answer is not accurate and can be wrong too. Please discuss and let us reach at the correct answer.
Reply Share
Haris Ibrahim K. V. a year ago

anil_pugalia

Bus Addresses are the addresses coming on the bus - e.g. on PCI Bus for x86 architecture. They are the real hardware addresses. Virtual addresses are only conceptual. They only exist in the page tables used by the MMU for ultimately getting translated into hardware addresses, which could be bus addresses or physical RAM addresses.
1 Reply Share

www.linuxforu.com/2011/06/generic-hardware-access-in-linux/

7/8

8/5/13

Reply

Device Drivers, Part 7: Generic Hardware Access in Linux - LINUX For You
Share

C o m m e n t fe e d

Su b s cri b e vi a e m a i l

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

For You & Me Developers Sysadmins Open Gurus CXOs Columns

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/06/generic-hardware-access-in-linux/

8/8

Potrebbero piacerti anche