<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>EmbLogic &#187; John McArthur</title>
	<atom:link href="https://www.emblogic.com/blog/author/varun/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.emblogic.com/blog</link>
	<description>Embedded System and ARM Training</description>
	<lastBuildDate>Tue, 03 Mar 2020 13:00:06 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.9.1</generator>
	<item>
		<title>broadcom wireless (wifi) driver installation process</title>
		<link>https://www.emblogic.com/blog/10/broadcom-wireless-wifi-driver-installation-process/</link>
		<comments>https://www.emblogic.com/blog/10/broadcom-wireless-wifi-driver-installation-process/#comments</comments>
		<pubDate>Sun, 07 Oct 2012 05:51:57 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=5483</guid>
		<description><![CDATA[For Broadcom BCM4301 BCM4303 BCM4306 BCM4309 BCM4311 BCM4312 BCM4318 Install b43-fwcutter. This is the software package that does the extraction of the firmware from the proprietary driver. Code: [root]#su - [root]yum install b43-fwcutter Determine which native driver is being used &#8230; <a href="https://www.emblogic.com/blog/10/broadcom-wireless-wifi-driver-installation-process/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>For Broadcom BCM4301 BCM4303 BCM4306 BCM4309<br />
BCM4311 BCM4312 BCM4318</p>
<p>Install b43-fwcutter. This is the software package that does the extraction of the firmware from the proprietary driver.<br />
Code:</p>
<p>[root]#su -<br />
[root]yum install b43-fwcutter</p>
<p>Determine which native driver is being used by the wireless card (b43 or b43legacy). The kernel is generally good about detecting a Broadcom wireless card and loading the correct driver module for it. The following terminal command will list the loaded kernel modules in alphabetical order. Look for b43 or b43legacy.<br />
Code:</p>
<p>[root]#lsmod | sort</p>
<p>Do this step only if you need to install version 4 firmware for the b43 driver module. Copy and execute the following command lines one after the other in a Fedora terminal.<br />
Code:</p>
<p>[root]#wget http://downloads.openwrt.org/sources/broadcom-wl-4.150.10.5.tar.bz2<br />
[root]#tar xjf broadcom-wl-4.150.10.5.tar.bz2<br />
[root]#cd broadcom-wl-4.150.10.5/driver<br />
[root]su<br />
[root]b43-fwcutter -w /lib/firmware wl_apsta_mimo.o</p>
<p>For Broadcom BCM4311 BCM4312 BCM4313 BCM4321<br />
BCM4322 BCM43224 BCM43225 BCM43227 BCM43228<br />
BCM4328 BCM43XG</p>
<p>1) Install the RPM Fusion repositories.<br />
To enable access to both the free and the nonfree repository use the following command:</p>
<p>For Fedora 15, 16 and 17:</p>
<p>[root]#su -c ‘yum localinstall _nogpgcheck http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-stable.noarch.rpm http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm‘</p>
<p>2)Do this step only if you need to install the kmod version of the driver for the i686 or x86_64 kernels.<br />
[root]#yum install kmod-wl</p>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/10/broadcom-wireless-wifi-driver-installation-process/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>SELinux</title>
		<link>https://www.emblogic.com/blog/09/selinux/</link>
		<comments>https://www.emblogic.com/blog/09/selinux/#comments</comments>
		<pubDate>Sat, 22 Sep 2012 10:09:44 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=5344</guid>
		<description><![CDATA[If SELinux is enabled, the policy defines what access to resources and operations on them (e.g. read, write) are allowed (i.e. SELinux stops all access unless allowed by policy). This is why SELinux is called a &#8216;mandatory access control&#8217; (MAC) &#8230; <a href="https://www.emblogic.com/blog/09/selinux/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>If SELinux is enabled, the policy defines what access to resources and operations on them (e.g. read, write) are allowed (i.e. SELinux stops all access unless allowed by policy). This is why SELinux is called a &#8216;mandatory access control&#8217; (MAC) system.<br />
The policy design, implementation and testing against a defined security policy or requirements is important, otherwise there could be &#8216;a false sense of security&#8217;.<br />
SELinux can confine an application within its own &#8216;domain&#8217; and allow it to have the minimum privileges required to do its job. Should the application require access to networks or other applications (or their data), then (as part of the security policy design), this access would need to be granted (so at least it is known what interactions are allowed and what are not &#8211; a good security goal).<br />
Should an application &#8216;do something&#8217; it is not allowed by policy (intentional or otherwise), then SELinux would stop these actions.<br />
Should an application &#8216;do something&#8217; it is allowed by policy, then SELinux may contain any damage that maybe done intentional or otherwise. For example if an application is allowed to delete all of its data files or database entries, and the bug, virus or malicious user gains these privileges then it would be able to do the same, however the good news is that if the policy &#8216;confined&#8217; the application and data, all your other data should still be there.<br />
User login sessions can be confined to their own domains. This allows clients they run to be given only the privileges they need (e.g. admin users, sales staff users, HR staff users etc.). This again will confine/limit any damage or leakage of data.<br />
Some applications (X-Windows for example) are difficult to confine as they are generally designed to have total access to all resources. SELinux can generally overcome these issues by providing sandboxing services.<br />
SELinux will not stop memory leaks or buffer over-runs (because its not designed to do this), however it may contain the damage that maybe done.<br />
SELinux will not stop all viruses/malware getting into the system (as there are many ways they could be introduced (including by legitimate users), however it should limit the damage or leaks they cause.<br />
SELinux will not stop kernel vulnerabilities, however it may limit their effects.<br />
It is very easy to add new rules to an SELinux policy using tools such as audit2allow(1) if a user has the relevant permissions, however be aware that this may start opening holes, so check what rules are really required.<br />
Finally, SELinux cannot stop anything allowed by the security policy, so good design is important.</p>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/09/selinux/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>MODULE_DEVICE_TABLE  Macro</title>
		<link>https://www.emblogic.com/blog/08/module_device_table-macro/</link>
		<comments>https://www.emblogic.com/blog/08/module_device_table-macro/#comments</comments>
		<pubDate>Mon, 13 Aug 2012 10:49:45 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=4698</guid>
		<description><![CDATA[This Macro is used by all USB and PCI drivers. This macro describes which devices each specific driver can support. At compilation time, the build process extracts this information out of the driver and builds a table. The table is &#8230; <a href="https://www.emblogic.com/blog/08/module_device_table-macro/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>This Macro is used by all USB and PCI drivers. This macro describes which devices each specific driver can support. At compilation time, the build process extracts this information out of the driver and builds a table. The table is called modules.pcimap and modules.usbmap for all PCI and USB devices, respectively, and exists in the directory /lib/modules/<em>kernel_version</em>/.</p>
<p>e.g.:-</p>
<p>static struct usb_device_id puzzle_id_table[]=<br />
{<br />
{       USB_DEVICE(VENDOR_ID,PRODUCT_ID)        },<br />
{0,},</p>
<p>};<br />
MODULE_DEVICE_TABLE(usb,puzzle_id_table);</p>
<p>This will add following lines to modules.usbmap</p>
<p># usb module         match_flags idVendor idProduct bcdDevice_lo bcdDevice_hi bDeviceClass bDeviceSubClass bDeviceProtocol bInterfaceClass bInterfaceSubClass bInterfaceProtocol driver_info<br />
lkm                  0&#215;0003      0&#215;0951   0&#215;1653    0&#215;0000       0&#215;0000       0&#215;00         0&#215;00            0&#215;00            0&#215;00            0&#215;00               0&#215;00               0&#215;0</p>
<p>The macro MODULE_DEVICE_TABLE automatically creates two variables. For the example: MODULE_DEVICE_TABLE (usb, puzzle_id_table); the variables __module_usb_device_size and __module_usb_device_table are created and placed into the read-only data section and the initialized data section of the module, respectively. The variable __module_usb_device_size contains the value of the size of the struct usb_id structure, and __module_usb_device_table points to the puzzle_id_table structure. The puzzle_id_table variable is an array of usb_id structures with a terminating NULL structure at the end of the list.</p>
<p>When the depmod program is run, as part of the kernel installation process, it goes through every module looking for the symbol __module_usb_device_size to be present in the compiled module. If it finds it, it copies the data pointed to by the __module_usb_device_table symbol into a structure, extracts all of the information and writes it out to the modules.usbmap file, which is located in the module root directory.</p>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/08/module_device_table-macro/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Symbols From Another External Module (Module.symvers)</title>
		<link>https://www.emblogic.com/blog/08/symbols-from-another-external-module-module-symvers/</link>
		<comments>https://www.emblogic.com/blog/08/symbols-from-another-external-module-module-symvers/#comments</comments>
		<pubDate>Sun, 12 Aug 2012 12:06:18 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=4526</guid>
		<description><![CDATA[Sometimes, an external module uses exported symbols from another external module. kbuild needs to have full knowledge of all symbols to avoid spitting out warnings about undefined symbols. Three solutions exist for this situation. NOTE: The method with a top-level &#8230; <a href="https://www.emblogic.com/blog/08/symbols-from-another-external-module-module-symvers/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Sometimes, an external module uses exported symbols from<br />
another external module. kbuild needs to have full knowledge of<br />
all symbols to avoid spitting out warnings about undefined<br />
symbols. Three solutions exist for this situation.<br />
NOTE: The method with a top-level kbuild file is recommended<br />
but may be impractical in certain situations.</p>
<p>Use a top-level kbuild file<br />
If you have two modules, foo.ko and bar.ko, where<br />
foo.ko needs symbols from bar.ko, you can use a<br />
common top-level kbuild file so both modules are<br />
compiled in the same build. Consider the following<br />
directory layout:</p>
<p>./foo/ &lt;= contains foo.ko<br />
./bar/ &lt;= contains bar.ko</p>
<p>The top-level kbuild file would then look like:</p>
<p>#./Kbuild (or ./Makefile):<br />
obj-y := foo/ bar/</p>
<p>And executing</p>
<p>$ make -C $KDIR M=$PWD</p>
<p>will then do the expected and compile both modules with<br />
full knowledge of symbols from either module.</p>
<p>Use an extra Module.symvers file<br />
When an external module is built, a Module.symvers file<br />
is generated containing all exported symbols which are<br />
not defined in the kernel. To get access to symbols</p>
<p>from bar.ko, copy the Module.symvers file from the<br />
compilation of bar.ko to the directory where foo.ko is<br />
built. During the module build, kbuild will read the<br />
Module.symvers file in the directory of the external<br />
module, and when the build is finished, a new<br />
Module.symvers file is created containing the sum of<br />
all symbols defined and not part of the kernel.</p>
<p>Use &#8220;make&#8221; variable KBUILD_EXTRA_SYMBOLS<br />
If it is impractical to copy Module.symvers from<br />
another module, you can assign a space separated list<br />
of files to KBUILD_EXTRA_SYMBOLS in your build file.<br />
These files will be loaded by modpost during the<br />
initialization of its symbol tables.</p>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/08/symbols-from-another-external-module-module-symvers/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Install gnome desktop environment from terminal</title>
		<link>https://www.emblogic.com/blog/08/install-gnome-desktop-environment-from-terminal/</link>
		<comments>https://www.emblogic.com/blog/08/install-gnome-desktop-environment-from-terminal/#comments</comments>
		<pubDate>Wed, 08 Aug 2012 04:50:47 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=4524</guid>
		<description><![CDATA[At terminal you just have to type single line [root@localhost ~]# yum groupinstall &#8220;GNOME Desktop Environment&#8221; and then you&#8217;ll be provided with a lots of packages to download . Say yes to it. ANd BRAVO&#8230; you just turned on the &#8230; <a href="https://www.emblogic.com/blog/08/install-gnome-desktop-environment-from-terminal/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>At terminal you just have to type single line<br />
[root@localhost ~]# yum groupinstall &#8220;GNOME Desktop Environment&#8221;</p>
<p>and then you&#8217;ll be provided with a lots of packages  to download . Say yes to it. ANd BRAVO&#8230; you just turned on the gnome environment features for your machine. Enjoy!!! </p>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/08/install-gnome-desktop-environment-from-terminal/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Static an Dynamic power dissipation</title>
		<link>https://www.emblogic.com/blog/07/static-an-dynamic-power-dissipation/</link>
		<comments>https://www.emblogic.com/blog/07/static-an-dynamic-power-dissipation/#comments</comments>
		<pubDate>Mon, 30 Jul 2012 06:25:51 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=4278</guid>
		<description><![CDATA[The amount of power that a chip dissipates per unit area is called its power density, and there are two types of power density that concern processor architects: dynamic power density and static power density. Dynamic Power Density Each transistor &#8230; <a href="https://www.emblogic.com/blog/07/static-an-dynamic-power-dissipation/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>The amount of power that a chip dissipates per unit area is called its power density, and there are two types of power density that concern processor architects: dynamic power density and static power density.</p>
<p><strong>Dynamic Power Density</strong></p>
<p>Each transistor on a chip dissipates a small amount of power when it is switched, and transistors that are switched rapidly dissipate more power than transistors that are switched slowly. The total amount of power dissipated per unit area due to switching of a chip&#8217;s transistors is called dynamic power density. There are two factors that work together to cause an increase in dynamic power density: clockspeed and transistor density.</p>
<p>Increasing a processor&#8217;s clockspeed involves switching its transistors more rapidly, and as I just mentioned, transistors that are switched more rapidly dissipate more power. Therefore, as a processor&#8217;s clockspeed rises, so does its dynamic power density, because each of those rapidly switching transistors contributes more to the device&#8217;s total power dissipation. You can also increase a chip&#8217;s dynamic power density by cramming more transistors into the same amount of surface area.<br />
In addition to clockspeed-related increases in dynamic power density, chip designers must also contend with the fact that even transistors that aren&#8217;t switching will still leak current during idle periods, much like how a faucet that is shut off can still leak water if the water pressure behind it is high enough. This leakage current causes an idle transistor to constantly dissipate a trace amount of power. The amount of power dissipated per unit area due to leakage current is called static power density.</p>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/07/static-an-dynamic-power-dissipation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Install KDE Plasma Workspaces</title>
		<link>https://www.emblogic.com/blog/05/install-kde-plasma-workspaces/</link>
		<comments>https://www.emblogic.com/blog/05/install-kde-plasma-workspaces/#comments</comments>
		<pubDate>Thu, 24 May 2012 09:26:45 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=2943</guid>
		<description><![CDATA[To install KDE Plasma Workspaces using the command line, execute the following as root: # yum install @kde-desktop]]></description>
				<content:encoded><![CDATA[<p>To install KDE Plasma Workspaces using the command line, execute the following as root:</p>
<p><strong># yum install @kde-desktop</strong></p>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/05/install-kde-plasma-workspaces/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Recover deleted files in Linux</title>
		<link>https://www.emblogic.com/blog/05/recover-deleted-files-in-linux/</link>
		<comments>https://www.emblogic.com/blog/05/recover-deleted-files-in-linux/#comments</comments>
		<pubDate>Tue, 15 May 2012 05:02:00 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=2825</guid>
		<description><![CDATA[&#160; Scalpel This is a filesystem-independent recovery tool for Linux and Mac OS, which you can also run on Windows by compiling it with MinGW. The latest version is 2.0. Install it in Fedora with # yum install scalpel. Next &#8230; <a href="https://www.emblogic.com/blog/05/recover-deleted-files-in-linux/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>&nbsp;</p>
<h2>Scalpel</h2>
<p>This is a filesystem-independent recovery tool for Linux and Mac OS, which you can also run on Windows by compiling it with <a href="http://www.mingw.org/" target="_blank">MinGW</a>. The latest version is 2.0. Install it in Fedora with <code></code></p>
<p><code># yum install scalpel</code>.</p>
<p>Next is some text editing — the configuration file is <code>/etc/scalpel/scalpel.conf</code>. You will find that everything has been commented out — uncomment the specific file format that you want to recover. For example, if I want to recover a deleted zip file, I will uncomment the <code>.zip</code> file section in <code>scalpel.conf</code>, as shown in Figure 1.</p>
<div><img src="http://cdn.linuxforu.com/wp-content/uploads/2011/09/Recover-del-fig01-590x114.jpg" alt="Figure 1: Scalpel.config file" width="590" height="114" />Figure 1: Scalpel.config file</p>
</div>
<p>Next, in a terminal, run:</p>
<div>
<div>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<div>
<div><code>#</code> <code>scalpel  [device</code><code>/directory/file</code> <code>name] -o [output directory]</code></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The output directory, in which you want to store recovered files, should be empty before running Scalpel; otherwise, you will get an error.</p>
<h2>Foremost</h2>
<p>Foremost is a console program to recover files based on their headers, footers, and internal data structures. This process is commonly referred to as data carving. Foremost can work on disk or partition image files, such as those generated by <code>dd</code>, Safeback, Encase, etc, or directly on a drive.</p>
<p>The headers and footers can be specified by a configuration file, or you can use command-line switches to specify built-in file types. Install in Ubuntu and its derivatives with the following command:</p>
<div>
<div>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<div>
<div><code># yum</code><code> </code><code>install</code> <code>foremost</code></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>There are a lot of options available. For example, to search for a deleted JPEG file, use:</p>
<div>
<div>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<div>
<div><code>#</code> <code>foremost -t jpg -i </code><code>/dev/sda1</code></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>The <code>-t</code> (“type”) option can be given as <code>-t all</code> to search for all file types. Multiple file types are comma-separated, like <code>-t jpg, pdf</code>. The (required) option <code>-i</code> is the base device/directory for the search. You can also specify an output directory with <code>-o</code>.</p>
<p>&nbsp;</p>
<p>Referrence :- http://www.linuxforu.com/2011/09/recover-deleted-files-in-linux/</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/05/recover-deleted-files-in-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MEMORY BARRIERS</title>
		<link>https://www.emblogic.com/blog/04/memory-barriers/</link>
		<comments>https://www.emblogic.com/blog/04/memory-barriers/#comments</comments>
		<pubDate>Wed, 11 Apr 2012 06:57:57 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=2379</guid>
		<description><![CDATA[Memory barriers are instructions to both the compiler and the CPU to impose a partial ordering between the memory access operations specified either side of the barrier. Older and less complex CPUs will perform memory accesses in exactly the order &#8230; <a href="https://www.emblogic.com/blog/04/memory-barriers/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<pre>Memory barriers are instructions to both the compiler and the CPU to 
impose a partial ordering between the memory access operations 
specified either side of the barrier.
Older and less complex CPUs will perform memory accesses in exactly 
the order specified, so if one is given the following piece of code:

	a = *A;
	*B = b;
	c = *C;
	d = *D;
	*E = e;

It can be guaranteed that it will complete the memory access for each
instruction before moving on to the next line, leading to a definite
sequence of operations on the bus:

	read *A, write *B, read *C, read *D, write *E.

However, with newer and more complex CPUs, this isn't always true 
because: 
 (*) they can rearrange the order of the memory accesses to promote 
     better use of the CPU buses and caches;

 (*) reads are synchronous and may need to be done immediately to 
     permit progress, whereas writes can often be deferred without
     a problem;

 (*) and they are able to combine reads and writes to improve 
     performance when talking to the SDRAM (modern SDRAM chips can 
     do batched accesses of adjacent locations, cutting down on
     transaction setup costs).

<strong>When a program runs on a single CPU, the hardware performs the </strong><strong>necessary bookkeeping 
 to ensure that programs execute as if all </strong><strong>memory operations were performed in the order 
specified by the </strong><strong>programmer (<em>program order</em>), hence memory barriers are not </strong><strong>necessary. 
However, when the memory is shared with multiple </strong><strong>devices, such as other CPUs in a 
multiprocessor system, or </strong><strong><a title="Memory-mapped I/O" href="http://en.wikipedia.org/wiki/Memory-mapped_I/O">memory mapped</a> peripherals, out-of-order access may affect 
program </strong><strong>behavior. For example, a second CPU may see memory changes made </strong><strong>by the 
first CPU in a sequence which differs from program order.</strong>

So what you might actually get from the above piece of code is:

	read *A, read *C+*D, write *E, write *B

Under normal operation, this is probably not going to be a problem;
however,there are two circumstances where it definitely _can_ be a
problem:

 (1) I/O

    Many I/O devices can be memory mapped, and so appear to the CPU 
    as if they're just memory locations. However, to control the 
    device, the driver has to make the right accesses in exactly the
    right order.
    Consider, for example, an ethernet chipset such as the AMD 
    PCnet32. It presents to the CPU an "address register" and a bunch
    of "data registers".The way it's accessed is to write the index 
    of the internal register you want to access to the address 
    register, and then read or write the appropriate data register 
    to access the chip's internal register:

	*ADR = ctl_reg_3;
	reg = *DATA;

    The problem with a clever CPU or a clever compiler is that the 
    write to the address register isn't guaranteed to happen before
    the access to the data register, if the CPU or the compiler 
    thinks it is more efficient to defer the address write:

	read *DATA, write *ADR

    then things will break.
    The way to deal with this is to insert an I/O memory barrier 
    between the two accesses:

	*ADR = ctl_reg_3;
	mb();
	reg = *DATA;

    In this case,<em><strong> the barrier makes a guarantee that all memory </strong></em><em><strong>accesses before the
  barrier will happen before all the memory </strong></em><em><strong>accesses after the barrier</strong></em>. It does <strong>not</strong>
    guarantee that all memory accesses before the barrier will be 
    complete by the time the barrier is complete.

 (2) Multiprocessor interaction

    When there's a system with more than one processor, these may be
    working on the same set of data, but attempting not to use locks
    as locks are quite expensive. This means that accesses that 
    affect both CPUs may have to be carefully ordered to prevent 
    error.

    Consider the R/W semaphore slow path. In that, a waiting process
    is queued on the semaphore, as noted by it having a record on 
    its stack linked to the semaphore's list:

	struct rw_semaphore {
		...
		struct list_head waiters;
	};

	struct rwsem_waiter {
		struct list_head list;
		struct task_struct *task;
	};

   To wake up the waiter, the up_read() or up_write() functions 
   have to read the pointer from this record to know as to where 
   the next waiter record is, clear the task pointer, call 
   wake_up_process() on the task, and release the task struct 
   reference held:
	READ waiter-&gt;list.next;
	READ waiter-&gt;task;
	WRITE waiter-&gt;task;
	CALL wakeup
	RELEASE task

  If any of these steps occur out of order, then the whole thing 
  may fail.
  Note that the waiter does not get the semaphore lock again - it 
  just waits for its task pointer to be cleared. Since the record 
  is on its stack, this means that if the task pointer is cleared 
  before the next pointer in the list is read, then another CPU 
  might start processing the waiter and it might clobber its stack
  before up*() functions have a chance to read the next pointer.

    CPU 0				  CPU 1
  =========================	      ===========================
					down_xxx()
					Queue waiter
					Sleep
    up_yyy()
    READ waiter-&gt;task;
    WRITE waiter-&gt;task;
    &lt;preempt&gt;
					Resume processing
					down_xxx() returns
					call foo()
					foo() clobbers *waiter
    &lt;/preempt&gt;
    READ waiter-&gt;list.next;
     --- OOPS ---

  This could be dealt with using a spinlock, but then the down_xxx()
  function has to get the spinlock again after it's been woken up, 
  which is a waste of resources. The way to deal with this is to 
  insert an SMP memory barrier: 
	READ waiter-&gt;list.next;
	READ waiter-&gt;task;
	smp_mb();
	WRITE waiter-&gt;task;
	CALL wakeup
	RELEASE task 

 In this case, the barrier makes a guarantee that all memory 
 accesses before the barrier will happen before all the memory 
 accesses after the barrier. It does <strong>not</strong> guarantee that all 
 memory accesses before the barrier will be complete by the time 
 the barrier is complete.
                         SMP memory barriers are normally no-ops on
 a UP system because the CPU orders overlapping accesses with 
respect to itself.
 
Referrece:-http://lwn.net/Articles/174655/

</pre>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/04/memory-barriers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Optimization in GCC</title>
		<link>https://www.emblogic.com/blog/04/optimization-in-gcc/</link>
		<comments>https://www.emblogic.com/blog/04/optimization-in-gcc/#comments</comments>
		<pubDate>Mon, 09 Apr 2012 10:01:46 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=2377</guid>
		<description><![CDATA[Levels of Optimization Let&#8217;s first look at how GCC categorizes optimizations and how a developer can control which are used and, sometimes more important, which are not. A large variety of optimizations are provided by GCC. Most are categorized into &#8230; <a href="https://www.emblogic.com/blog/04/optimization-in-gcc/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><strong>Levels of Optimization</strong></p>
<p>Let&#8217;s first look at how GCC categorizes optimizations and how a developer can control which are used and, sometimes more important, which are not. A large variety of optimizations are provided by GCC. Most are categorized into one of three levels, but some are provided at multiple levels. Some optimizations reduce the size of the resulting machine code, while others try to create code that is faster, potentially increasing its size. For completeness, the default optimization level is zero, which provides no optimization at all. This can be explicitly specified with option -O or -O0.<br />
<em><strong>Level 1 (-O1)</strong></em></p>
<p>The purpose of the first level of optimization is to produce an optimized image in a short amount of time. These optimizations typically don&#8217;t require significant amounts of compile time to complete. Level 1 also has two sometimes conflicting goals. These goals are to reduce the size of the compiled code while increasing its performance. The set of optimizations provided in -O1 support these goals, in most cases. These are shown in Table 1 in the column labeled -O1. The first level of optimization is enabled as:</p>
<p>gcc -O1 -o test test.c</p>
<p>Any optimization can be enabled outside of any level simply by specifying its name with the -f prefix, as:</p>
<p>gcc -fdefer-pop -o test test.c</p>
<p>We also could enable level 1 optimization and then disable any particular optimization using the -fno- prefix, like this:</p>
<p>gcc -O1 -fno-defer-pop -o test test.c</p>
<p>This command would enable the first level of optimization and then specifically disable the defer-pop optimization.<br />
<em><strong>Level 2 (-O2)</strong></em></p>
<p>The second level of optimization performs all other supported optimizations within the given architecture that do not involve a space-speed trade-off, a balance between the two objectives. For example, loop unrolling and function inlining, which have the effect of increasing code size while also potentially making the code faster, are not performed. The second level is enabled as:</p>
<p>gcc -O2 -o test test.c</p>
<p>The level -O2 optimizations include all of the -O1 optimizations, plus a large number of others.<br />
<em><strong>Level 2.5 (-Os)</strong></em></p>
<p>The special optimization level (-Os or size) enables all -O2 optimizations that do not increase code size; it puts the emphasis on size over speed. This includes all second-level optimizations, except for the alignment optimizations. The alignment optimizations skip space to align functions, loops, jumps and labels to an address that is a multiple of a power of two, in an architecture-dependent manner. Skipping to these boundaries can increase performance as well as the size of the resulting code and data spaces; therefore, these particular optimizations are disabled. The size optimization level is enabled as:</p>
<p>gcc -Os -o test test.c</p>
<p>In gcc 3.2.2, reorder-blocks is enabled at -Os, but in gcc 3.3.2 reorder-blocks is disabled.<br />
<em><strong>Level 3 (-O3)</strong></em></p>
<p>The third and highest level enables even more optimizations by putting emphasis on speed over size. This includes optimizations enabled at -O2 and rename-register. The optimization inline-functions also is enabled here, which can increase performance but also can drastically increase the size of the object, depending upon the functions that are inlined. The third level is enabled as:</p>
<p>gcc -O3 -o test test.c</p>
<p>Although -O3 can produce fast code, the increase in the size of the image can have adverse effects on its speed. For example, if the size of the image exceeds the size of the available instruction cache, severe performance penalties can be observed. Therefore, it may be better simply to compile at -O2 to increase the chances that the image fits in the instruction cache.</p>
<p>&nbsp;</p>
<p>Referrence:- http://www.linuxjournal.com/article/7269</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/04/optimization-in-gcc/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Anatomy of a Device Driver</title>
		<link>https://www.emblogic.com/blog/03/anatomy-of-a-device-driver/</link>
		<comments>https://www.emblogic.com/blog/03/anatomy-of-a-device-driver/#comments</comments>
		<pubDate>Tue, 13 Mar 2012 13:16:23 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=2123</guid>
		<description><![CDATA[A device driver has three sides: one side talks to the rest of the kernel, one talks to the hardware, and one talks to the user. In order to talk to the kernel, the driver registers with subsystems to respond &#8230; <a href="https://www.emblogic.com/blog/03/anatomy-of-a-device-driver/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>A device driver has three sides: one side talks to the rest of the kernel, one talks to the hardware, and one talks to the user.</p>
<p>In order to talk to the kernel, the driver registers with subsystems to respond to events. Such an event might be the opening of a file, a page fault, the plugging in of a new USB device, etc.</p>
<p>User Interface of a Device driver<br />
Since Linux follows the UNIX model, and in UNIX everything is a file, users talk with device drivers through device files. Device files are a mechanism, supplied by the kernel,<br />
precisely for this direct User-Driver interface.</p>
<p>Anatomy of scull device driver<br />
The user talks with scull through the /dev/scull device file.When the user opens /dev/scull, the kernel calls scull’s open routine. When the user closes /dev/scull, the kernel calls scull’s release routine<br />
Scull talks to the kernel through its initialization function . . . and through register_chrdev<br />
. . . and through hooking into the timer interrupt .</p>
<p>Driver Initialization Code<br />
static int __init scull_module _init ( void )<br />
{<br />
int ret ;<br />
pr_debug ( &#8221; Scull module init called \ n &#8221; ) ;<br />
i f ( ( ret = register_chrdev (SCULL_MAJOR_NUM, &#8221; scull &#8221; , &amp; scull _ fops printk(KERN_ERR &#8221; register_chrdev : %d \ n &#8221; , ret ) ;<br />
return ret ;<br />
}</p>
<p>Driver Initialization<br />
One function (init) is called on the driver’s initialization.<br />
One function (exit) is called when the driver is removed from the system.</p>
<p>Question: what happens if the driver is compiled into the kernel, rather than as a module?</p>
<p>The init function will register hooks that will get the driver’s code called when the appropriate event happens.<br />
Question: what if the init function doesn’t register any hooks?<br />
There are various hooks that can be registered: file<br />
operations, pci operations, USB operations, network operations &#8211; it all depends on what kind of device this is.</p>
<p>Registering Chardev Hooks<br />
struct file_operation scull_fops = {<br />
. owner = THIS_MODULE,<br />
. open = scull_open ,<br />
. release = scull _ release ,<br />
. read = scull _read ,<br />
. wr i t e = scull _write ,<br />
.mmap = scull_mmap ,<br />
. ioctl = scull _ ioctl<br />
} ;<br />
. . .<br />
i f ( ( ret = register_chrdev (SCULL_MAJOR_NUM, &#8221; scull &#8221; , &amp; scull _fops ) ) &lt; 0 )<br />
printk (KERN_ERR &#8221; register_chrdev : %d \ n &#8221; , ret ) ;</p>
<p>User Space Access to the Driver<br />
The driver registers a character device tied to a given major number, but how does the user create such a file?<br />
# mknod /dev/scull c 250 0</p>
<p>And how does the user open it?<br />
if ((kfd = open(&#8220;/dev/scull&#8221;, O_RDWR)) &lt; 0) {<br />
perror(&#8220;open /dev/scull&#8221;);<br />
exit(EXIT_FAILURE);<br />
}</p>
<p>File Operations<br />
. . . and then you start talking to the device. scull uses the following device file operations:<br />
open for  allocating resources.<br />
release for finishing releasing resources.<br />
write for seting the starting positions<br />
read for generating and then reading the next state .<br />
mmap for potentially faster but more complex direct access .</p>
<p>The open and release Routines<br />
open and release are where you perform any setup not done in initialization time and any cleanup not done in module unload time.</p>
<p>Scull_open<br />
scull’s open routine allocates the scull structure which holds all of the state</p>
<p>static int scull_open ( struct inode *inode , struct file *filp )<br />
{<br />
struct scull *k ;<br />
int ret ;<br />
ret = alloc_scull (&amp;k ) ;<br />
if ( ret )<br />
return ret ;<br />
filp-&gt;private_data = k ;<br />
return 0 ;<br />
}</p>
<p>scull_release<br />
scull’s release routine frees the resource allocated during open time.<br />
static int scull_release ( struct inode *inode , struct file *filp )<br />
{<br />
struct scull *k = filp-&gt;pr i vate_data ;<br />
&#8230;..<br />
&#8230;..</p>
<p>free_scull ( k ) ;<br />
return 0 ;<br />
}</p>
<p>Open and Release<br />
Beware of races if you have any global data . . . many a driver author stumble on this point.<br />
Note also that release can fail, but almost no onechecks errors from close(), so it’s better if it doesn’t . . .<br />
Question: what happens if the userspace program crashes while holding your device file open?</p>
<p>Use copy_from_user in case the user is passing a bad pointer.</p>
<p>Commentary on write<br />
Note that even for such a simple function, care must be exercised when dealing with untrusted users.Users are always untrusted.<br />
Always be prepared to handle errors!</p>
<p>memory mapping<br />
The read-write mechanism, involves an overhead of a system call and related context switching and of memory copying. mmap maps pages of a file into memory, thus enabling<br />
programs to directly access the memory directly and save the overhead, . . . but:<br />
fast synchronization between kernel space and user space is a pain (why do we need it?),<br />
and Linux read and write are really quite fast.</p>
<p>Referrence:-</p>
<p>Muli Ben-Yehuda IBM Haifa Research Labs and Haifux &#8211; Haifa Linux Club<br />
Understanding the Linux Kernel, by Bovet and Cesati<br />
Linux Device Drivers, 3rd edition, by Rubini et. al.<br />
Linux Kernel Development, 2nd edition, by Robert Love<br />
/usr/src/linux-xxx/</p>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/03/anatomy-of-a-device-driver/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Block driver : Disk On RAM</title>
		<link>https://www.emblogic.com/blog/02/block-driver-disk-on-ram/</link>
		<comments>https://www.emblogic.com/blog/02/block-driver-disk-on-ram/#comments</comments>
		<pubDate>Tue, 28 Feb 2012 15:44:39 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=2016</guid>
		<description><![CDATA[-&#62; Load the driver using insmod. This would create the block device files representing the disk on 512 KiB of RAM, with three primary and three logical partitions. &#8211;&#62; Check out the automatically created block device files (/dev/sd*). /dev/sdb is &#8230; <a href="https://www.emblogic.com/blog/02/block-driver-disk-on-ram/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>-&gt; Load the driver using insmod. This would create the block device files representing the disk on 512 KiB of RAM, with three primary and three logical partitions.<br />
&#8211;&gt; Check out the automatically created block device files (/dev/sd*). /dev/sdb is the entire disk, which is 512 KiB in size. sdb1, sdb2 and sdb3 are the primary partitions.<br />
&#8211;&gt; Read the entire disk (/dev/sdb) using the disk dump utility dd.<br />
&#8211;&gt; Zero out the first sector of the disk’s first partition (/dev/sdb1), again using dd.<br />
 &#8211;&gt; Write some text into the disk’s first partition (/dev/sdb1) using cat.<br />
&#8211;&gt; Display the initial contents of the first partition (/dev/sdb1) using the xxd utility.<br />
&#8211;&gt; Display the partition information for the disk using fdisk.<br />
&#8211;&gt; Quick-format the third primary partition (/dev/sdb3) as a vfat filesystem (like your pen drive), using mkfs.vfat<br />
&#8211;&gt; Mount the newly formatted partition using mount, say at /mnt<br />
&#8211;&gt; The disk usage utility df would now show this partition mounted at /mnt . You may go ahead and store files there, but remember that this is a disk on RAM, and so is non-persistent.<br />
Unload the driver using rmmod dor after unmounting the partition using umount /mnt. All data on the disk will be lost.</p>
<p>The block driver basics</p>
<p>Conceptually, the block drivers are very similar to character drivers, especially with regards to the following:</p>
<p>    Usage of device files<br />
    Major and minor numbers<br />
    Device file operations<br />
    Concept of device registration</p>
<p>So, if you already know character driver implementation, it would be easy to understand block drivers.</p>
<p>However, they are definitely not identical. The key differences are as follows:</p>
<p>    Abstraction for block-oriented versus byte-oriented devices.<br />
    Block drivers are designed to be used by I/O schedulers, for optimal performance. Compare that with character drivers that are to be used by VFS.<br />
    Block drivers are designed to be integrated with the Linux buffer cache mechanism for efficient data access. Character drivers are pass-through drivers, accessing the hardware directly.</p>
<p>And these cause the implementation differences. Let’s analyse the code .<br />
The first step is to register for an 8-bit (block) major number (which implicitly means registering for all 256 8-bit minor numbers associated with it). The function for that is as follows:<br />
int register_blkdev(unsigned int major, const char *name);</p>
<p>Here, major is the major number to be registered, and name is a registration label displayed under the kernel window /proc/devices. Interestingly, register_blkdev() tries to allocate and register a freely available major number, when 0 is passed for its first parameter major; on success, the allocated major number is returned. The corresponding de-registration function is as follows:<br />
void unregister_blkdev(unsigned int major, const char *name);</p>
<p>Both these are prototyped in .</p>
<p>The second step is to provide the device file operations, through the struct block_device_operations (prototyped in ) for the registered major number device files.</p>
<p>However, these operations are too few compared to the character device file operations, and mostly insignificant. To elaborate, there are no operations even to read and write, which is surprising. But as we already know that block drivers need to integrate with the I/O schedulers, the read-write implementation is achieved through something called request queues. So, along with providing the device file operations, the following need to be provided:</p>
<p>    The request queue for queuing the read/write requests<br />
    The spin lock associated with the request queue to protect its concurrent access<br />
    The request function to process the requests in the request queue</p>
<p>Also, there is no separate interface for block device file creations, so the following are also provided:</p>
<p>    The device file name prefix, commonly referred to as disk_name (sdb in the my driver)<br />
    The starting minor number for the device files, commonly referred to as first_minor.</p>
<p>Finally, two block-device-specific things are also provided, namely:</p>
<p>    The maximum number of partitions supported for this block device, by specifying the total minors.<br />
    The underlying device size in units of 512-byte sectors, for the logical block access abstraction.</p>
<p>All these are registered through the struct gendisk using the following function:<br />
void add_disk(struct gendisk *disk);</p>
<p>The corresponding delete function is as follows:<br />
void del_gendisk(struct gendisk *disk);</p>
<p>Prior to add_disk(), the various fields of struct gendisk need to initialised, either directly or using various macros/functions like set_capacity(). major, first_minor, fops, queue, disk_name are the minimal fields to be initialised directly. And even before the initialisation of these fields, the struct gendisk needs to be allocated, using the function given below:<br />
struct gendisk *alloc_disk(int minors);</p>
<p>Here, minors is the total number of partitions supported for this disk. And the corresponding inverse function would be:<br />
void put_disk(struct gendisk *disk);</p>
<p>All these are prototyped in .</p>
<p>Request queue and the request function</p>
<p>The request queue also needs to be initialised and set up into the struct gendisk, before add_disk(). The request queue is initialised by calling:<br />
struct request_queue *blk_init_queue(request_fn_proc *, spinlock_t *);</p>
<p>We provide the request-processing function and the initialised concurrency protection spin-lock as parameters. The corresponding queue clean-up function is given below:<br />
void blk_cleanup_queue(struct request_queue *);</p>
<p>The request (processing) function should be defined with the following prototype:<br />
void request_fn(struct request_queue *q);</p>
<p>It should be coded to fetch a request from its parameter q, for instance, by using the following:<br />
struct request *blk_fetch_request(struct request_queue *q);</p>
<p>Then it should either process it, or initiate processing. Whatever it does should be non-blocking, as this request function is called from a non-process context, and also after taking the queue’s spin-lock. Moreover, only functions not releasing or taking the queue’s spin-lock should be used within the request function.</p>
<p>A typical example of request processing, is given below:<br />
while ((req = blk_fetch_request(q)) != NULL) /* Fetching a request */<br />
{<br />
        /* Processing the request: the actual data transfer */<br />
        ret = rb_transfer(req); /* Our custom function */<br />
         /* Informing that the request has been processed with return of ret */<br />
        __blk_end_request_all(req, ret);<br />
}</p>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/02/block-driver-disk-on-ram/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The gendisk interface in Block driver</title>
		<link>https://www.emblogic.com/blog/02/the-gendisk-interface-in-block-driver/</link>
		<comments>https://www.emblogic.com/blog/02/the-gendisk-interface-in-block-driver/#comments</comments>
		<pubDate>Tue, 28 Feb 2012 05:12:49 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=2014</guid>
		<description><![CDATA[In 2.6 kernel the gendisk is at the core of the block subsystem; if you need to work with or find something out about a disk, struct gendisk probably has what you need. The best way of looking at the &#8230; <a href="https://www.emblogic.com/blog/02/the-gendisk-interface-in-block-driver/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>In 2.6 kernel the gendisk is at the core of the block subsystem; if you need to work with or find something out about a disk, struct gendisk probably has what you need.<br />
The best way of looking at the contents of a gendisk structure from a block driver&#8217;s point of view is to examine what that driver must do to set the structure up in the first place. If your driver makes a disk (or disk-like) device available to the system, it will have to provide an associated gendisk structure. The first step is to create the gendisk structure itself; the function you need is alloc_disk() .<br />
 struct gendisk *alloc_disk(int minors);<br />
The argument minors is the maximum number of minor numbers that this disk can have. Minor numbers correspond to partitions.If a single minor number is requested, the device cannot be partitioned at all.<br />
There are several fields of the gendisk structure which must be initialized by the block driver. They include:</p>
<p>int major;<br />
    The major number of this device; either a static major assigned to a specific driver, or one that was obtained dynamically from register_blkdev() </p>
<p>int first_minor;<br />
    The first minor device number corresponding to this disk. This number will be determined by how your driver divides up its minor number space. </p>
<p>char disk_name[32];<br />
    The name of this disk (i.e. hda). This name is used in places like /proc/partitions and in creating a sysfs directory for the device. </p>
<p>struct block_device_operations *fops;<br />
    The device operations (open, release, ioctl, media_changed, and revalidate_disk) for this device. Each disk has its own set of operations in 2.6. </p>
<p>struct request_queue *queue;<br />
    The request queue which will handle the list of pending operations for this disk. The queue must be created and initialized separately. </p>
<p>int flags;<br />
    A set of flags controlling the management of this device. They include GENHD_FL_REMOVABLE for removable devices, GENHD_FL_CD for CDROM devices, and GENHD_FL_DRIVERFS which certainly means something interesting, but which is not actually used anywhere. </p>
<p>void *private_data;<br />
    This field is reserved for the driver; the rest of the block subsystem will not touch it. Usually it holds a pointer to a driver-specific data structure describing this device. </p>
<p>The gendisk structure also holds the size of the disk, in sectors. As part of the initialization process, the driver should set that size with:</p>
<p>    void set_capacity(struct gendisk *disk, sector_t size);</p>
<p>The size value should be in 512-byte sectors, even if the hardware sector size used by your device is different. For removable disks, setting its capacity to zero indicates to the block subsystem that there is currently no media present in the device. Once you have your gendisk structure set up, you have to add it to the list of active disks; that is done with:</p>
<p>    void add_disk(struct gendisk *disk);</p>
<p>After this call, your device is live.</p>
<p>There are a few things worth keeping in mind about add_disk():</p>
<p> &#8211;&gt;add_disk() can create I/O to the device (to read partition tables and such). You should not call add_disk() until your driver is sufficiently initialized to handle requests.</p>
<p>&#8211;&gt; If you are calling add_disk() in your driver initialization routine, you should not fail the initialization process after the first call.</p>
<p>&#8211;&gt; The call to add_disk() increments the disk&#8217;s reference count; if the disk structure is ever to be released, the driver is responsible for decrementing that count (with put_disk()). </p>
<p>To remove a disk from the system, that is accomplished with:</p>
<p>    void del_gendisk(struct gendisk *disk);</p>
<p>This function cleans up all of the information associated with the given disk, and generally removes it from the system. After a call to del_gendisk(), no more operations will be sent to the given device. Your driver&#8217;s reference to the gendisk object remains, though; you must explicitly release it with:</p>
<p>    void put_disk(struct gendisk *disk);<br />
That call will cause the gendisk structure to be freed, as long as no other part of the kernel retains a reference to it. </p>
<p>Note&#8211;&gt;sbd_request() uses the blk_fetch_request(), blk_rq_pos(), blk_rq_cur_sectors() and __blk_end_request_cur() functions rather than elv_next_request(), req-&gt;sector, req-&gt;current_nr_sectors and end_request() respectively. The structure of the loop also changes so we handle each sector from the request individually.</p>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/02/the-gendisk-interface-in-block-driver/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>cvs server:cannot open /root/.cvsignore:  Permission denied OR cvs [server aborted]: can&#8217;t chdir(/root):Permission denied</title>
		<link>https://www.emblogic.com/blog/01/cvs-servercannot-open-root-cvsignore-permission-denied-or-cvs-server-aborted-cant-chdirrootpermission-denied/</link>
		<comments>https://www.emblogic.com/blog/01/cvs-servercannot-open-root-cvsignore-permission-denied-or-cvs-server-aborted-cant-chdirrootpermission-denied/#comments</comments>
		<pubDate>Sat, 14 Jan 2012 06:28:27 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=1634</guid>
		<description><![CDATA[&#8211;&#62;then you probably haven&#8217;t specified ‘-f’ in ‘inetd.conf’. &#8211;&#62;In releases prior to CVS 1.11.1, this problem can be caused by your system setting the $HOME environment variable for programs being run by xinetd. In this case, you can either have &#8230; <a href="https://www.emblogic.com/blog/01/cvs-servercannot-open-root-cvsignore-permission-denied-or-cvs-server-aborted-cant-chdirrootpermission-denied/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>&#8211;&gt;then you probably haven&#8217;t specified ‘-f’ in ‘inetd.conf’.<br />
&#8211;&gt;In releases prior to CVS 1.11.1, this problem can be caused by your system setting the $HOME environment variable for programs being run by xinetd. In this case, you can either have xinetd run a shell script that unsets $HOME and then runs CVS, or you can use env to run CVS with a pristine environment.<br />
 <img src="https://www.emblogic.com/blog/wp-includes/images/smilies/icon_biggrin.gif" alt=":D" class="wp-smiley" /> </p>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/01/cvs-servercannot-open-root-cvsignore-permission-denied-or-cvs-server-aborted-cant-chdirrootpermission-denied/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What are init 0, init 1, init 2 ,init 3, init 4, init 5, init 6, init s, init S</title>
		<link>https://www.emblogic.com/blog/11/what-are-init-0-init-1-init-2-init-3-init-4-init-5-init-6-init-s-init-s/</link>
		<comments>https://www.emblogic.com/blog/11/what-are-init-0-init-1-init-2-init-3-init-4-init-5-init-6-init-s-init-s/#comments</comments>
		<pubDate>Thu, 17 Nov 2011 08:28:54 +0000</pubDate>
		<dc:creator><![CDATA[John McArthur]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://emblogic.org/blog/?p=1257</guid>
		<description><![CDATA[There are basically 8 runlevels in unix. Run Level: At any given time, the system is in one of eight possible run levels. A run level is a software configuration under which only a selected group of processes exists. Processes &#8230; <a href="https://www.emblogic.com/blog/11/what-are-init-0-init-1-init-2-init-3-init-4-init-5-init-6-init-s-init-s/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>There are basically 8 runlevels in unix.<br />
Run Level:  At any given time, the system is in one  of  eight  possible run  levels.  A  run level is a software configuration under which only a selected group of processes  exists.  Processes spawned  by init for each of these run levels are defined in /etc/inittab. init can be in one of eight  run  levels,  0-6 and  S  or  s (S and s are identical). The run level changes when a privileged user runs /sbin/init.</p>
<p>init 0 :  Shutdown (goes thru the /etc/rc0.d/* scripts then halts)<br />
init 1  :  Single user mode or emergency mode means no network no multitasking is present in this mode only root has access in this runlevel<br />
init 2  :  No network but multitasking support is present .<br />
init 3  :  Network is present multitasking is present but with out GUI .<br />
init 4  :  It is similar to runlevel 3; It is reserved for other purposes in research.<br />
init 5  :  Network is present multitasking and GUI is present with sound etc.<br />
init 6  :  This runlevel is defined to system restart.<br />
init s   : Tells the init command to enter the maintenance mode. When the<br />
system enters maintenance mode from another run level, only the system console<br />
is used as the terminal.<br />
init S  : Same as init s.<br />
init m : Same as init s and init S.<br />
init M : Same as init s or init S or init m.</p>
]]></content:encoded>
			<wfw:commentRss>https://www.emblogic.com/blog/11/what-are-init-0-init-1-init-2-init-3-init-4-init-5-init-6-init-s-init-s/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
