You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'linux-2.6'
This commit is contained in:
@@ -1745,8 +1745,9 @@ S: D-64295
|
|||||||
S: Germany
|
S: Germany
|
||||||
|
|
||||||
N: Andi Kleen
|
N: Andi Kleen
|
||||||
E: ak@muc.de
|
E: andi@firstfloor.org
|
||||||
D: network hacker, syncookies
|
U: http://www.halobates.de
|
||||||
|
D: network, x86, NUMA, various hacks
|
||||||
S: Schwalbenstr. 96
|
S: Schwalbenstr. 96
|
||||||
S: 85551 Ottobrunn
|
S: 85551 Ottobrunn
|
||||||
S: Germany
|
S: Germany
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ psdocs: $(PS)
|
|||||||
PDF := $(patsubst %.xml, %.pdf, $(BOOKS))
|
PDF := $(patsubst %.xml, %.pdf, $(BOOKS))
|
||||||
pdfdocs: $(PDF)
|
pdfdocs: $(PDF)
|
||||||
|
|
||||||
HTML := $(patsubst %.xml, %.html, $(BOOKS))
|
HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS)))
|
||||||
htmldocs: $(HTML)
|
htmldocs: $(HTML)
|
||||||
|
|
||||||
MAN := $(patsubst %.xml, %.9, $(BOOKS))
|
MAN := $(patsubst %.xml, %.9, $(BOOKS))
|
||||||
@@ -152,6 +152,7 @@ quiet_cmd_db2man = MAN $@
|
|||||||
@(which xmlto > /dev/null 2>&1) || \
|
@(which xmlto > /dev/null 2>&1) || \
|
||||||
(echo "*** You need to install xmlto ***"; \
|
(echo "*** You need to install xmlto ***"; \
|
||||||
exit 1)
|
exit 1)
|
||||||
|
$(Q)mkdir -p $(obj)/man
|
||||||
$(call cmd,db2man)
|
$(call cmd,db2man)
|
||||||
@touch $@
|
@touch $@
|
||||||
|
|
||||||
@@ -212,11 +213,7 @@ clean-files := $(DOCBOOKS) \
|
|||||||
$(patsubst %.xml, %.9, $(DOCBOOKS)) \
|
$(patsubst %.xml, %.9, $(DOCBOOKS)) \
|
||||||
$(C-procfs-example)
|
$(C-procfs-example)
|
||||||
|
|
||||||
clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS))
|
clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
|
||||||
|
|
||||||
#man put files in man subdir - traverse down
|
|
||||||
subdir- := man/
|
|
||||||
|
|
||||||
|
|
||||||
# Declare the contents of the .PHONY variable as phony. We keep that
|
# Declare the contents of the .PHONY variable as phony. We keep that
|
||||||
# information in a variable se we can use it in if_changed and friends.
|
# information in a variable se we can use it in if_changed and friends.
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
# Rules are put in Documentation/DocBook
|
|
||||||
|
|
||||||
clean-files := *.9.gz *.sgml manpage.links manpage.refs
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
00-INDEX
|
||||||
|
- This file
|
||||||
|
|
||||||
|
cache-lock.txt
|
||||||
|
- HOWTO for blackfin cache locking.
|
||||||
|
|
||||||
|
cachefeatures.txt
|
||||||
|
- Supported cache features.
|
||||||
|
|
||||||
|
Filesystems
|
||||||
|
- Requirements for mounting the root file system.
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* File: Documentation/blackfin/Filesystems
|
||||||
|
* Based on:
|
||||||
|
* Author:
|
||||||
|
*
|
||||||
|
* Created:
|
||||||
|
* Description: This file contains the simple DMA Implementation for Blackfin
|
||||||
|
*
|
||||||
|
* Rev: $Id: Filesystems 2384 2006-11-01 04:12:43Z magicyang $
|
||||||
|
*
|
||||||
|
* Modified:
|
||||||
|
* Copyright 2004-2006 Analog Devices Inc.
|
||||||
|
*
|
||||||
|
* Bugs: Enter bugs at http://blackfin.uclinux.org/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
How to mount the root file system in uClinux/Blackfin
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
1 Mounting EXT3 File system.
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
Creating an EXT3 File system for uClinux/Blackfin:
|
||||||
|
|
||||||
|
|
||||||
|
Please follow the steps to form the EXT3 File system and mount the same as root
|
||||||
|
file system.
|
||||||
|
|
||||||
|
a Make an ext3 file system as large as you want the final root file
|
||||||
|
system.
|
||||||
|
|
||||||
|
mkfs.ext3 /dev/ram0 <your-rootfs-size-in-1k-blocks>
|
||||||
|
|
||||||
|
b Mount this Empty file system on a free directory as:
|
||||||
|
|
||||||
|
mount -t ext3 /dev/ram0 ./test
|
||||||
|
where ./test is the empty directory.
|
||||||
|
|
||||||
|
c Copy your root fs directory that you have so carefully made over.
|
||||||
|
|
||||||
|
cp -af /tmp/my_final_rootfs_files/* ./test
|
||||||
|
|
||||||
|
(For ex: cp -af uClinux-dist/romfs/* ./test)
|
||||||
|
|
||||||
|
d If you have done everything right till now you should be able to see
|
||||||
|
the required "root" dir's (that's etc, root, bin, lib, sbin...)
|
||||||
|
|
||||||
|
e Now unmount the file system
|
||||||
|
|
||||||
|
umount ./test
|
||||||
|
|
||||||
|
f Create the root file system image.
|
||||||
|
|
||||||
|
dd if=/dev/ram0 bs=1k count=<your-rootfs-size-in-1k-blocks> \
|
||||||
|
> ext3fs.img
|
||||||
|
|
||||||
|
|
||||||
|
Now you have to tell the kernel that will be mounting this file system as
|
||||||
|
rootfs.
|
||||||
|
So do a make menuconfig under kernel and select the Ext3 journaling file system
|
||||||
|
support under File system --> submenu.
|
||||||
|
|
||||||
|
|
||||||
|
2. Mounting EXT2 File system.
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
By default the ext2 file system image will be created if you invoke make from
|
||||||
|
the top uClinux-dist directory.
|
||||||
|
|
||||||
|
|
||||||
|
3. Mounting CRAMFS File System
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
To create a CRAMFS file system image execute the command
|
||||||
|
|
||||||
|
mkfs.cramfs ./test cramfs.img
|
||||||
|
|
||||||
|
where ./test is the target directory.
|
||||||
|
|
||||||
|
|
||||||
|
4. Mounting ROMFS File System
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
To create a ROMFS file system image execute the command
|
||||||
|
|
||||||
|
genromfs -v -V "ROMdisk" -f romfs.img -d ./test
|
||||||
|
|
||||||
|
where ./test is the target directory
|
||||||
|
|
||||||
|
|
||||||
|
5. Mounting the JFFS2 Filesystem
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
To create a compressed JFFS filesystem (JFFS2), please execute the command
|
||||||
|
|
||||||
|
mkfs.jffs2 -d ./test -o jffs2.img
|
||||||
|
|
||||||
|
where ./test is the target directory.
|
||||||
|
|
||||||
|
However, please make sure the following is in your kernel config.
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RAM/ROM/Flash chip drivers
|
||||||
|
*/
|
||||||
|
#define CONFIG_MTD_CFI 1
|
||||||
|
#define CONFIG_MTD_ROM 1
|
||||||
|
/*
|
||||||
|
* Mapping drivers for chip access
|
||||||
|
*/
|
||||||
|
#define CONFIG_MTD_COMPLEX_MAPPINGS 1
|
||||||
|
#define CONFIG_MTD_BF533 1
|
||||||
|
#undef CONFIG_MTD_UCLINUX
|
||||||
|
|
||||||
|
Through the u-boot boot loader, use the jffs2.img in the corresponding
|
||||||
|
partition made in linux-2.6.x/drivers/mtd/maps/bf533_flash.c.
|
||||||
|
|
||||||
|
NOTE - Currently the Flash driver is available only for EZKIT. Watch out for a
|
||||||
|
STAMP driver soon.
|
||||||
|
|
||||||
|
|
||||||
|
6. Mounting the NFS File system
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
For mounting the NFS please do the following in the kernel config.
|
||||||
|
|
||||||
|
In Networking Support --> Networking options --> TCP/IP networking -->
|
||||||
|
IP: kernel level autoconfiguration
|
||||||
|
|
||||||
|
Enable BOOTP Support.
|
||||||
|
|
||||||
|
In Kernel hacking --> Compiled-in kernel boot parameter add the following
|
||||||
|
|
||||||
|
root=/dev/nfs rw ip=bootp
|
||||||
|
|
||||||
|
In File system --> Network File system, Enable
|
||||||
|
|
||||||
|
NFS file system support --> NFSv3 client support
|
||||||
|
Root File system on NFS
|
||||||
|
|
||||||
|
in uClibc menuconfig, do the following
|
||||||
|
In Networking Support
|
||||||
|
enable Remote Procedure Call (RPC) support
|
||||||
|
Full RPC Support
|
||||||
|
|
||||||
|
On the Host side, ensure that /etc/dhcpd.conf looks something like this
|
||||||
|
|
||||||
|
ddns-update-style ad-hoc;
|
||||||
|
allow bootp;
|
||||||
|
subnet 10.100.4.0 netmask 255.255.255.0 {
|
||||||
|
default-lease-time 122209600;
|
||||||
|
max-lease-time 31557600;
|
||||||
|
group {
|
||||||
|
host bf533 {
|
||||||
|
hardware ethernet 00:CF:52:49:C3:01;
|
||||||
|
fixed-address 10.100.4.50;
|
||||||
|
option root-path "/home/nfsmount";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure that /etc/exports looks something like this
|
||||||
|
/home/nfsmount *(rw,no_root_squash,no_all_squash)
|
||||||
|
|
||||||
|
run the following commands as root (may differ depending on your
|
||||||
|
distribution) :
|
||||||
|
- service nfs start
|
||||||
|
- service portmap start
|
||||||
|
- service dhcpd start
|
||||||
|
- /usr/sbin/exportfs
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* File: Documentation/blackfin/cache-lock.txt
|
||||||
|
* Based on:
|
||||||
|
* Author:
|
||||||
|
*
|
||||||
|
* Created:
|
||||||
|
* Description: This file contains the simple DMA Implementation for Blackfin
|
||||||
|
*
|
||||||
|
* Rev: $Id: cache-lock.txt 2384 2006-11-01 04:12:43Z magicyang $
|
||||||
|
*
|
||||||
|
* Modified:
|
||||||
|
* Copyright 2004-2006 Analog Devices Inc.
|
||||||
|
*
|
||||||
|
* Bugs: Enter bugs at http://blackfin.uclinux.org/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
How to lock your code in cache in uClinux/blackfin
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
There are only a few steps required to lock your code into the cache.
|
||||||
|
Currently you can lock the code by Way.
|
||||||
|
|
||||||
|
Below are the interface provided for locking the cache.
|
||||||
|
|
||||||
|
|
||||||
|
1. cache_grab_lock(int Ways);
|
||||||
|
|
||||||
|
This function grab the lock for locking your code into the cache specified
|
||||||
|
by Ways.
|
||||||
|
|
||||||
|
|
||||||
|
2. cache_lock(int Ways);
|
||||||
|
|
||||||
|
This function should be called after your critical code has been executed.
|
||||||
|
Once the critical code exits, the code is now loaded into the cache. This
|
||||||
|
function locks the code into the cache.
|
||||||
|
|
||||||
|
|
||||||
|
So, the example sequence will be:
|
||||||
|
|
||||||
|
cache_grab_lock(WAY0_L); /* Grab the lock */
|
||||||
|
|
||||||
|
critical_code(); /* Execute the code of interest */
|
||||||
|
|
||||||
|
cache_lock(WAY0_L); /* Lock the cache */
|
||||||
|
|
||||||
|
Where WAY0_L signifies WAY0 locking.
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* File: Documentation/blackfin/cachefeatures.txt
|
||||||
|
* Based on:
|
||||||
|
* Author:
|
||||||
|
*
|
||||||
|
* Created:
|
||||||
|
* Description: This file contains the simple DMA Implementation for Blackfin
|
||||||
|
*
|
||||||
|
* Rev: $Id: cachefeatures.txt 2384 2006-11-01 04:12:43Z magicyang $
|
||||||
|
*
|
||||||
|
* Modified:
|
||||||
|
* Copyright 2004-2006 Analog Devices Inc.
|
||||||
|
*
|
||||||
|
* Bugs: Enter bugs at http://blackfin.uclinux.org/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
- Instruction and Data cache initialization.
|
||||||
|
icache_init();
|
||||||
|
dcache_init();
|
||||||
|
|
||||||
|
- Instruction and Data cache Invalidation Routines, when flushing the
|
||||||
|
same is not required.
|
||||||
|
_icache_invalidate();
|
||||||
|
_dcache_invalidate();
|
||||||
|
|
||||||
|
Also, for invalidating the entire instruction and data cache, the below
|
||||||
|
routines are provided (another method for invalidation, refer page no 267 and 287 of
|
||||||
|
ADSP-BF533 Hardware Reference manual)
|
||||||
|
|
||||||
|
invalidate_entire_dcache();
|
||||||
|
invalidate_entire_icache();
|
||||||
|
|
||||||
|
-External Flushing of Instruction and data cache routines.
|
||||||
|
|
||||||
|
flush_instruction_cache();
|
||||||
|
flush_data_cache();
|
||||||
|
|
||||||
|
- Internal Flushing of Instruction and Data Cache.
|
||||||
|
|
||||||
|
icplb_flush();
|
||||||
|
dcplb_flush();
|
||||||
|
|
||||||
|
- Locking the cache.
|
||||||
|
|
||||||
|
cache_grab_lock();
|
||||||
|
cache_lock();
|
||||||
|
|
||||||
|
Please refer linux-2.6.x/Documentation/blackfin/cache-lock.txt for how to
|
||||||
|
lock the cache.
|
||||||
|
|
||||||
|
Locking the cache is optional feature.
|
||||||
|
|
||||||
|
- Miscellaneous cache functions.
|
||||||
|
|
||||||
|
flush_cache_all();
|
||||||
|
flush_cache_mm();
|
||||||
|
invalidate_dcache_range();
|
||||||
|
flush_dcache_range();
|
||||||
|
flush_dcache_page();
|
||||||
|
flush_cache_range();
|
||||||
|
flush_cache_page();
|
||||||
|
invalidate_dcache_range();
|
||||||
|
flush_page_to_ram();
|
||||||
|
|
||||||
@@ -55,8 +55,8 @@ aic7*seq.h*
|
|||||||
aicasm
|
aicasm
|
||||||
aicdb.h*
|
aicdb.h*
|
||||||
asm
|
asm
|
||||||
asm-offsets.*
|
asm-offsets.h
|
||||||
asm_offsets.*
|
asm_offsets.h
|
||||||
autoconf.h*
|
autoconf.h*
|
||||||
bbootsect
|
bbootsect
|
||||||
bin2c
|
bin2c
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ For example, you can do something like the following.
|
|||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
devres_close_group(dev, my_midlayer_something);
|
devres_close_group(dev, my_midlayer_create_something);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,13 +117,6 @@ Who: Adrian Bunk <bunk@stusta.de>
|
|||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
What: pci_module_init(driver)
|
|
||||||
When: January 2007
|
|
||||||
Why: Is replaced by pci_register_driver(pci_driver).
|
|
||||||
Who: Richard Knutsson <ricknu-0@student.ltu.se> and Greg Kroah-Hartman <gregkh@suse.de>
|
|
||||||
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
What: Usage of invalid timevals in setitimer
|
What: Usage of invalid timevals in setitimer
|
||||||
When: March 2007
|
When: March 2007
|
||||||
Why: POSIX requires to validate timevals in the setitimer call. This
|
Why: POSIX requires to validate timevals in the setitimer call. This
|
||||||
@@ -190,18 +183,10 @@ Who: Jean Delvare <khali@linux-fr.org>
|
|||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
What: i2c_adapter.dev
|
What: i2c_adapter.list
|
||||||
i2c_adapter.list
|
|
||||||
When: July 2007
|
When: July 2007
|
||||||
Why: Superfluous, given i2c_adapter.class_dev:
|
Why: Superfluous, this list duplicates the one maintained by the driver
|
||||||
* The "dev" was a stand-in for the physical device node that legacy
|
core.
|
||||||
drivers would not have; but now it's almost always present. Any
|
|
||||||
remaining legacy drivers must upgrade (they now trigger warnings).
|
|
||||||
* The "list" duplicates class device children.
|
|
||||||
The delay in removing this is so upgraded lm_sensors and libsensors
|
|
||||||
can get deployed. (Removal causes minor changes in the sysfs layout,
|
|
||||||
notably the location of the adapter type name and parenting the i2c
|
|
||||||
client hardware directly from their controller.)
|
|
||||||
Who: Jean Delvare <khali@linux-fr.org>,
|
Who: Jean Delvare <khali@linux-fr.org>,
|
||||||
David Brownell <dbrownell@users.sourceforge.net>
|
David Brownell <dbrownell@users.sourceforge.net>
|
||||||
|
|
||||||
@@ -314,3 +299,27 @@ Why: Code was merged, then submitter immediately disappeared leaving
|
|||||||
Who: David S. Miller <davem@davemloft.net>
|
Who: David S. Miller <davem@davemloft.net>
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
What: read_dev_chars(), read_conf_data{,_lpm}() (s390 common I/O layer)
|
||||||
|
When: December 2007
|
||||||
|
Why: These functions are a leftover from 2.4 times. They have several
|
||||||
|
problems:
|
||||||
|
- Duplication of checks that are done in the device driver's
|
||||||
|
interrupt handler
|
||||||
|
- common I/O layer can't do device specific error recovery
|
||||||
|
- device driver can't be notified for conditions happening during
|
||||||
|
execution of the function
|
||||||
|
Device drivers should issue the read device characteristics and read
|
||||||
|
configuration data ccws and do the appropriate error handling
|
||||||
|
themselves.
|
||||||
|
Who: Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
What: i2c-ixp2000, i2c-ixp4xx and scx200_i2c drivers
|
||||||
|
When: September 2007
|
||||||
|
Why: Obsolete. The new i2c-gpio driver replaces all hardware-specific
|
||||||
|
I2C-over-GPIO drivers.
|
||||||
|
Who: Jean Delvare <khali@linux-fr.org>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|||||||
@@ -122,21 +122,22 @@ subdirectory has the entries listed in Table 1-1.
|
|||||||
|
|
||||||
Table 1-1: Process specific entries in /proc
|
Table 1-1: Process specific entries in /proc
|
||||||
..............................................................................
|
..............................................................................
|
||||||
File Content
|
File Content
|
||||||
cmdline Command line arguments
|
clear_refs Clears page referenced bits shown in smaps output
|
||||||
cpu Current and last cpu in which it was executed (2.4)(smp)
|
cmdline Command line arguments
|
||||||
cwd Link to the current working directory
|
cpu Current and last cpu in which it was executed (2.4)(smp)
|
||||||
environ Values of environment variables
|
cwd Link to the current working directory
|
||||||
exe Link to the executable of this process
|
environ Values of environment variables
|
||||||
fd Directory, which contains all file descriptors
|
exe Link to the executable of this process
|
||||||
maps Memory maps to executables and library files (2.4)
|
fd Directory, which contains all file descriptors
|
||||||
mem Memory held by this process
|
maps Memory maps to executables and library files (2.4)
|
||||||
root Link to the root directory of this process
|
mem Memory held by this process
|
||||||
stat Process status
|
root Link to the root directory of this process
|
||||||
statm Process memory status information
|
stat Process status
|
||||||
status Process status in human readable form
|
statm Process memory status information
|
||||||
wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan
|
status Process status in human readable form
|
||||||
smaps Extension based on maps, presenting the rss size for each mapped file
|
wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan
|
||||||
|
smaps Extension based on maps, the rss size for each mapped file
|
||||||
..............................................................................
|
..............................................................................
|
||||||
|
|
||||||
For example, to get the status information of a process, all you have to do is
|
For example, to get the status information of a process, all you have to do is
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ Supported adapters:
|
|||||||
* nForce4 MCP-04 10de:0034
|
* nForce4 MCP-04 10de:0034
|
||||||
* nForce4 MCP51 10de:0264
|
* nForce4 MCP51 10de:0264
|
||||||
* nForce4 MCP55 10de:0368
|
* nForce4 MCP55 10de:0368
|
||||||
|
* nForce4 MCP61 10de:03EB
|
||||||
|
* nForce4 MCP65 10de:0446
|
||||||
|
|
||||||
Datasheet: not publicly available, but seems to be similar to the
|
Datasheet: not publicly available, but seems to be similar to the
|
||||||
AMD-8111 SMBus 2.0 adapter.
|
AMD-8111 SMBus 2.0 adapter.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Revision 6, 2005-11-20
|
Revision 7, 2007-04-19
|
||||||
Jean Delvare <khali@linux-fr.org>
|
Jean Delvare <khali@linux-fr.org>
|
||||||
Greg KH <greg@kroah.com>
|
Greg KH <greg@kroah.com>
|
||||||
|
|
||||||
@@ -20,6 +20,10 @@ yours for best results.
|
|||||||
|
|
||||||
Technical changes:
|
Technical changes:
|
||||||
|
|
||||||
|
* [Driver type] Any driver that was relying on i2c-isa has to be
|
||||||
|
converted to a proper isa, platform or pci driver. This is not
|
||||||
|
covered by this guide.
|
||||||
|
|
||||||
* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
|
* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
|
||||||
Includes typically look like that:
|
Includes typically look like that:
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
@@ -27,12 +31,10 @@ Technical changes:
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/i2c-isa.h> /* for ISA drivers */
|
|
||||||
#include <linux/hwmon.h> /* for hardware monitoring drivers */
|
#include <linux/hwmon.h> /* for hardware monitoring drivers */
|
||||||
#include <linux/hwmon-sysfs.h>
|
#include <linux/hwmon-sysfs.h>
|
||||||
#include <linux/hwmon-vid.h> /* if you need VRM support */
|
#include <linux/hwmon-vid.h> /* if you need VRM support */
|
||||||
#include <linux/err.h> /* for class registration */
|
#include <linux/err.h> /* for class registration */
|
||||||
#include <asm/io.h> /* if you have I/O operations */
|
|
||||||
Please respect this inclusion order. Some extra headers may be
|
Please respect this inclusion order. Some extra headers may be
|
||||||
required for a given driver (e.g. "lm75.h").
|
required for a given driver (e.g. "lm75.h").
|
||||||
|
|
||||||
@@ -69,20 +71,16 @@ Technical changes:
|
|||||||
sensors mailing list <lm-sensors@lm-sensors.org> by providing a
|
sensors mailing list <lm-sensors@lm-sensors.org> by providing a
|
||||||
patch to the Documentation/hwmon/sysfs-interface file.
|
patch to the Documentation/hwmon/sysfs-interface file.
|
||||||
|
|
||||||
* [Attach] For I2C drivers, the attach function should make sure
|
* [Attach] The attach function should make sure that the adapter's
|
||||||
that the adapter's class has I2C_CLASS_HWMON (or whatever class is
|
class has I2C_CLASS_HWMON (or whatever class is suitable for your
|
||||||
suitable for your driver), using the following construct:
|
driver), using the following construct:
|
||||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||||
return 0;
|
return 0;
|
||||||
ISA-only drivers of course don't need this.
|
|
||||||
Call i2c_probe() instead of i2c_detect().
|
Call i2c_probe() instead of i2c_detect().
|
||||||
|
|
||||||
* [Detect] As mentioned earlier, the flags parameter is gone.
|
* [Detect] As mentioned earlier, the flags parameter is gone.
|
||||||
The type_name and client_name strings are replaced by a single
|
The type_name and client_name strings are replaced by a single
|
||||||
name string, which will be filled with a lowercase, short string.
|
name string, which will be filled with a lowercase, short string.
|
||||||
In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
|
|
||||||
useless. Same for isa-only drivers, as the test would always be
|
|
||||||
true. Only hybrid drivers (which are quite rare) still need it.
|
|
||||||
The labels used for error paths are reduced to the number needed.
|
The labels used for error paths are reduced to the number needed.
|
||||||
It is advised that the labels are given descriptive names such as
|
It is advised that the labels are given descriptive names such as
|
||||||
exit and exit_free. Don't forget to properly set err before
|
exit and exit_free. Don't forget to properly set err before
|
||||||
|
|||||||
@@ -4,17 +4,23 @@ I2C and SMBus
|
|||||||
=============
|
=============
|
||||||
|
|
||||||
I2C (pronounce: I squared C) is a protocol developed by Philips. It is a
|
I2C (pronounce: I squared C) is a protocol developed by Philips. It is a
|
||||||
slow two-wire protocol (10-400 kHz), but it suffices for many types of
|
slow two-wire protocol (variable speed, up to 400 kHz), with a high speed
|
||||||
devices.
|
extension (3.4 MHz). It provides an inexpensive bus for connecting many
|
||||||
|
types of devices with infrequent or low bandwidth communications needs.
|
||||||
|
I2C is widely used with embedded systems. Some systems use variants that
|
||||||
|
don't meet branding requirements, and so are not advertised as being I2C.
|
||||||
|
|
||||||
SMBus (System Management Bus) is a subset of the I2C protocol. Many
|
SMBus (System Management Bus) is based on the I2C protocol, and is mostly
|
||||||
modern mainboards have a System Management Bus. There are a lot of
|
a subset of I2C protocols and signaling. Many I2C devices will work on an
|
||||||
devices which can be connected to a SMBus; the most notable are modern
|
SMBus, but some SMBus protocols add semantics beyond what is required to
|
||||||
memory chips with EEPROM memories and chips for hardware monitoring.
|
achieve I2C branding. Modern PC mainboards rely on SMBus. The most common
|
||||||
|
devices connected through SMBus are RAM modules configured using I2C EEPROMs,
|
||||||
|
and hardware monitoring chips.
|
||||||
|
|
||||||
Because the SMBus is just a special case of the generalized I2C bus, we
|
Because the SMBus is mostly a subset of the generalized I2C bus, we can
|
||||||
can simulate the SMBus protocol on plain I2C busses. The reverse is
|
use its protocols on many I2C systems. However, there are systems that don't
|
||||||
regretfully impossible.
|
meet both SMBus and I2C electrical constraints; and others which can't
|
||||||
|
implement all the common SMBus protocol semantics or messages.
|
||||||
|
|
||||||
|
|
||||||
Terminology
|
Terminology
|
||||||
@@ -29,6 +35,7 @@ When we talk about I2C, we use the following terms:
|
|||||||
An Algorithm driver contains general code that can be used for a whole class
|
An Algorithm driver contains general code that can be used for a whole class
|
||||||
of I2C adapters. Each specific adapter driver depends on one algorithm
|
of I2C adapters. Each specific adapter driver depends on one algorithm
|
||||||
driver.
|
driver.
|
||||||
|
|
||||||
A Driver driver (yes, this sounds ridiculous, sorry) contains the general
|
A Driver driver (yes, this sounds ridiculous, sorry) contains the general
|
||||||
code to access some type of device. Each detected device gets its own
|
code to access some type of device. Each detected device gets its own
|
||||||
data in the Client structure. Usually, Driver and Client are more closely
|
data in the Client structure. Usually, Driver and Client are more closely
|
||||||
@@ -40,6 +47,10 @@ a separate Adapter and Algorithm driver), and drivers for your I2C devices
|
|||||||
in this package. See the lm_sensors project http://www.lm-sensors.nu
|
in this package. See the lm_sensors project http://www.lm-sensors.nu
|
||||||
for device drivers.
|
for device drivers.
|
||||||
|
|
||||||
|
At this time, Linux only operates I2C (or SMBus) in master mode; you can't
|
||||||
|
use these APIs to make a Linux system behave as a slave/device, either to
|
||||||
|
speak a custom protocol or to emulate some other device.
|
||||||
|
|
||||||
|
|
||||||
Included Bus Drivers
|
Included Bus Drivers
|
||||||
====================
|
====================
|
||||||
|
|||||||
+141
-274
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
|||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
H. Peter Anvin <hpa@zytor.com>
|
H. Peter Anvin <hpa@zytor.com>
|
||||||
Last update 2007-01-26
|
Last update 2007-03-06
|
||||||
|
|
||||||
On the i386 platform, the Linux kernel uses a rather complicated boot
|
On the i386 platform, the Linux kernel uses a rather complicated boot
|
||||||
convention. This has evolved partially due to historical aspects, as
|
convention. This has evolved partially due to historical aspects, as
|
||||||
@@ -35,9 +35,13 @@ Protocol 2.03: (Kernel 2.4.18-pre1) Explicitly makes the highest possible
|
|||||||
initrd address available to the bootloader.
|
initrd address available to the bootloader.
|
||||||
|
|
||||||
Protocol 2.04: (Kernel 2.6.14) Extend the syssize field to four bytes.
|
Protocol 2.04: (Kernel 2.6.14) Extend the syssize field to four bytes.
|
||||||
|
|
||||||
Protocol 2.05: (Kernel 2.6.20) Make protected mode kernel relocatable.
|
Protocol 2.05: (Kernel 2.6.20) Make protected mode kernel relocatable.
|
||||||
Introduce relocatable_kernel and kernel_alignment fields.
|
Introduce relocatable_kernel and kernel_alignment fields.
|
||||||
|
|
||||||
|
Protocol 2.06: (Kernel 2.6.22) Added a field that contains the size of
|
||||||
|
the boot command line
|
||||||
|
|
||||||
|
|
||||||
**** MEMORY LAYOUT
|
**** MEMORY LAYOUT
|
||||||
|
|
||||||
@@ -133,6 +137,8 @@ Offset Proto Name Meaning
|
|||||||
022C/4 2.03+ initrd_addr_max Highest legal initrd address
|
022C/4 2.03+ initrd_addr_max Highest legal initrd address
|
||||||
0230/4 2.05+ kernel_alignment Physical addr alignment required for kernel
|
0230/4 2.05+ kernel_alignment Physical addr alignment required for kernel
|
||||||
0234/1 2.05+ relocatable_kernel Whether kernel is relocatable or not
|
0234/1 2.05+ relocatable_kernel Whether kernel is relocatable or not
|
||||||
|
0235/3 N/A pad2 Unused
|
||||||
|
0238/4 2.06+ cmdline_size Maximum size of the kernel command line
|
||||||
|
|
||||||
(1) For backwards compatibility, if the setup_sects field contains 0, the
|
(1) For backwards compatibility, if the setup_sects field contains 0, the
|
||||||
real value is 4.
|
real value is 4.
|
||||||
@@ -233,6 +239,12 @@ filled out, however:
|
|||||||
if your ramdisk is exactly 131072 bytes long and this field is
|
if your ramdisk is exactly 131072 bytes long and this field is
|
||||||
0x37FFFFFF, you can start your ramdisk at 0x37FE0000.)
|
0x37FFFFFF, you can start your ramdisk at 0x37FE0000.)
|
||||||
|
|
||||||
|
cmdline_size:
|
||||||
|
The maximum size of the command line without the terminating
|
||||||
|
zero. This means that the command line can contain at most
|
||||||
|
cmdline_size characters. With protocol version 2.05 and
|
||||||
|
earlier, the maximum size was 255.
|
||||||
|
|
||||||
|
|
||||||
**** THE KERNEL COMMAND LINE
|
**** THE KERNEL COMMAND LINE
|
||||||
|
|
||||||
@@ -241,11 +253,10 @@ loader to communicate with the kernel. Some of its options are also
|
|||||||
relevant to the boot loader itself, see "special command line options"
|
relevant to the boot loader itself, see "special command line options"
|
||||||
below.
|
below.
|
||||||
|
|
||||||
The kernel command line is a null-terminated string currently up to
|
The kernel command line is a null-terminated string. The maximum
|
||||||
255 characters long, plus the final null. A string that is too long
|
length can be retrieved from the field cmdline_size. Before protocol
|
||||||
will be automatically truncated by the kernel, a boot loader may allow
|
version 2.06, the maximum was 255 characters. A string that is too
|
||||||
a longer command line to be passed to permit future kernels to extend
|
long will be automatically truncated by the kernel.
|
||||||
this limit.
|
|
||||||
|
|
||||||
If the boot protocol version is 2.02 or later, the address of the
|
If the boot protocol version is 2.02 or later, the address of the
|
||||||
kernel command line is given by the header field cmd_line_ptr (see
|
kernel command line is given by the header field cmd_line_ptr (see
|
||||||
|
|||||||
@@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* Exercise /dev/mem mmap cases that have been troublesome in the past
|
||||||
|
*
|
||||||
|
* (c) Copyright 2007 Hewlett-Packard Development Company, L.P.
|
||||||
|
* Bjorn Helgaas <bjorn.helgaas@hp.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int sum;
|
||||||
|
|
||||||
|
int map_mem(char *path, off_t offset, size_t length, int touch)
|
||||||
|
{
|
||||||
|
int fd, rc;
|
||||||
|
void *addr;
|
||||||
|
int *c;
|
||||||
|
|
||||||
|
fd = open(path, O_RDWR);
|
||||||
|
if (fd == -1) {
|
||||||
|
perror(path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
|
||||||
|
if (addr == MAP_FAILED)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (touch) {
|
||||||
|
c = (int *) addr;
|
||||||
|
while (c < (int *) (offset + length))
|
||||||
|
sum += *c++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = munmap(addr, length);
|
||||||
|
if (rc == -1) {
|
||||||
|
perror("munmap");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int scan_sysfs(char *path, char *file, off_t offset, size_t length, int touch)
|
||||||
|
{
|
||||||
|
struct dirent **namelist;
|
||||||
|
char *name, *path2;
|
||||||
|
int i, n, r, rc, result = 0;
|
||||||
|
struct stat buf;
|
||||||
|
|
||||||
|
n = scandir(path, &namelist, 0, alphasort);
|
||||||
|
if (n < 0) {
|
||||||
|
perror("scandir");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
name = namelist[i]->d_name;
|
||||||
|
|
||||||
|
if (fnmatch(".", name, 0) == 0)
|
||||||
|
goto skip;
|
||||||
|
if (fnmatch("..", name, 0) == 0)
|
||||||
|
goto skip;
|
||||||
|
|
||||||
|
path2 = malloc(strlen(path) + strlen(name) + 3);
|
||||||
|
strcpy(path2, path);
|
||||||
|
strcat(path2, "/");
|
||||||
|
strcat(path2, name);
|
||||||
|
|
||||||
|
if (fnmatch(file, name, 0) == 0) {
|
||||||
|
rc = map_mem(path2, offset, length, touch);
|
||||||
|
if (rc == 0)
|
||||||
|
fprintf(stderr, "PASS: %s 0x%lx-0x%lx is %s\n", path2, offset, offset + length, touch ? "readable" : "mappable");
|
||||||
|
else if (rc > 0)
|
||||||
|
fprintf(stderr, "PASS: %s 0x%lx-0x%lx not mappable\n", path2, offset, offset + length);
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "FAIL: %s 0x%lx-0x%lx not accessible\n", path2, offset, offset + length);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r = lstat(path2, &buf);
|
||||||
|
if (r == 0 && S_ISDIR(buf.st_mode)) {
|
||||||
|
rc = scan_sysfs(path2, file, offset, length, touch);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result |= rc;
|
||||||
|
free(path2);
|
||||||
|
|
||||||
|
skip:
|
||||||
|
free(namelist[i]);
|
||||||
|
}
|
||||||
|
free(namelist);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
int read_rom(char *path)
|
||||||
|
{
|
||||||
|
int fd, rc;
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
|
fd = open(path, O_RDWR);
|
||||||
|
if (fd == -1) {
|
||||||
|
perror(path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = write(fd, "1", 2);
|
||||||
|
if (rc <= 0) {
|
||||||
|
perror("write");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
rc = read(fd, buf, sizeof(buf));
|
||||||
|
if (rc > 0)
|
||||||
|
size += rc;
|
||||||
|
} while (rc > 0);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int scan_rom(char *path, char *file)
|
||||||
|
{
|
||||||
|
struct dirent **namelist;
|
||||||
|
char *name, *path2;
|
||||||
|
int i, n, r, rc, result = 0;
|
||||||
|
struct stat buf;
|
||||||
|
|
||||||
|
n = scandir(path, &namelist, 0, alphasort);
|
||||||
|
if (n < 0) {
|
||||||
|
perror("scandir");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
name = namelist[i]->d_name;
|
||||||
|
|
||||||
|
if (fnmatch(".", name, 0) == 0)
|
||||||
|
goto skip;
|
||||||
|
if (fnmatch("..", name, 0) == 0)
|
||||||
|
goto skip;
|
||||||
|
|
||||||
|
path2 = malloc(strlen(path) + strlen(name) + 3);
|
||||||
|
strcpy(path2, path);
|
||||||
|
strcat(path2, "/");
|
||||||
|
strcat(path2, name);
|
||||||
|
|
||||||
|
if (fnmatch(file, name, 0) == 0) {
|
||||||
|
rc = read_rom(path2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It's OK if the ROM is unreadable. Maybe there
|
||||||
|
* is no ROM, or some other error ocurred. The
|
||||||
|
* important thing is that no MCA happened.
|
||||||
|
*/
|
||||||
|
if (rc > 0)
|
||||||
|
fprintf(stderr, "PASS: %s read %ld bytes\n", path2, rc);
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "PASS: %s not readable\n", path2);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r = lstat(path2, &buf);
|
||||||
|
if (r == 0 && S_ISDIR(buf.st_mode)) {
|
||||||
|
rc = scan_rom(path2, file);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result |= rc;
|
||||||
|
free(path2);
|
||||||
|
|
||||||
|
skip:
|
||||||
|
free(namelist[i]);
|
||||||
|
}
|
||||||
|
free(namelist);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (map_mem("/dev/mem", 0, 0xA0000, 1) == 0)
|
||||||
|
fprintf(stderr, "PASS: /dev/mem 0x0-0xa0000 is readable\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "FAIL: /dev/mem 0x0-0xa0000 not accessible\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It's not safe to blindly read the VGA frame buffer. If you know
|
||||||
|
* how to poke the card the right way, it should respond, but it's
|
||||||
|
* not safe in general. Many machines, e.g., Intel chipsets, cover
|
||||||
|
* up a non-responding card by just returning -1, but others will
|
||||||
|
* report the failure as a machine check.
|
||||||
|
*/
|
||||||
|
if (map_mem("/dev/mem", 0xA0000, 0x20000, 0) == 0)
|
||||||
|
fprintf(stderr, "PASS: /dev/mem 0xa0000-0xc0000 is mappable\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "FAIL: /dev/mem 0xa0000-0xc0000 not accessible\n");
|
||||||
|
|
||||||
|
if (map_mem("/dev/mem", 0xC0000, 0x40000, 1) == 0)
|
||||||
|
fprintf(stderr, "PASS: /dev/mem 0xc0000-0x100000 is readable\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "FAIL: /dev/mem 0xc0000-0x100000 not accessible\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Often you can map all the individual pieces above (0-0xA0000,
|
||||||
|
* 0xA0000-0xC0000, and 0xC0000-0x100000), but can't map the whole
|
||||||
|
* thing at once. This is because the individual pieces use different
|
||||||
|
* attributes, and there's no single attribute supported over the
|
||||||
|
* whole region.
|
||||||
|
*/
|
||||||
|
rc = map_mem("/dev/mem", 0, 1024*1024, 0);
|
||||||
|
if (rc == 0)
|
||||||
|
fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 is mappable\n");
|
||||||
|
else if (rc > 0)
|
||||||
|
fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 not mappable\n");
|
||||||
|
else
|
||||||
|
fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n");
|
||||||
|
|
||||||
|
scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
|
||||||
|
scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
|
||||||
|
scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
|
||||||
|
scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
|
||||||
|
|
||||||
|
scan_rom("/sys/devices", "rom");
|
||||||
|
}
|
||||||
@@ -112,16 +112,6 @@ POTENTIAL ATTRIBUTE ALIASING CASES
|
|||||||
|
|
||||||
The /dev/mem mmap constraints apply.
|
The /dev/mem mmap constraints apply.
|
||||||
|
|
||||||
However, since this is for mapping legacy MMIO space, WB access
|
|
||||||
does not make sense. This matters on machines without legacy
|
|
||||||
VGA support: these machines may have WB memory for the entire
|
|
||||||
first megabyte (or even the entire first granule).
|
|
||||||
|
|
||||||
On these machines, we could mmap legacy_mem as WB, which would
|
|
||||||
be safe in terms of attribute aliasing, but X has no way of
|
|
||||||
knowing that it is accessing regular memory, not a frame buffer,
|
|
||||||
so the kernel should fail the mmap rather than doing it with WB.
|
|
||||||
|
|
||||||
read/write of /dev/mem
|
read/write of /dev/mem
|
||||||
|
|
||||||
This uses copy_from_user(), which implicitly uses a kernel
|
This uses copy_from_user(), which implicitly uses a kernel
|
||||||
@@ -138,14 +128,20 @@ POTENTIAL ATTRIBUTE ALIASING CASES
|
|||||||
|
|
||||||
ioremap()
|
ioremap()
|
||||||
|
|
||||||
This returns a kernel identity mapping for use inside the
|
This returns a mapping for use inside the kernel.
|
||||||
kernel.
|
|
||||||
|
|
||||||
If the region is in kern_memmap, we should use the attribute
|
If the region is in kern_memmap, we should use the attribute
|
||||||
specified there. Otherwise, if the EFI memory map reports that
|
specified there.
|
||||||
the entire granule supports WB, we should use that (granules
|
|
||||||
that are partially reserved or occupied by firmware do not appear
|
If the EFI memory map reports that the entire granule supports
|
||||||
in kern_memmap). Otherwise, we should use a UC mapping.
|
WB, we should use that (granules that are partially reserved
|
||||||
|
or occupied by firmware do not appear in kern_memmap).
|
||||||
|
|
||||||
|
If the granule contains non-WB memory, but we can cover the
|
||||||
|
region safely with kernel page table mappings, we can use
|
||||||
|
ioremap_page_range() as most other architectures do.
|
||||||
|
|
||||||
|
Failing all of the above, we have to fall back to a UC mapping.
|
||||||
|
|
||||||
PAST PROBLEM CASES
|
PAST PROBLEM CASES
|
||||||
|
|
||||||
@@ -158,7 +154,7 @@ PAST PROBLEM CASES
|
|||||||
succeed. It may create either WB or UC user mappings, depending
|
succeed. It may create either WB or UC user mappings, depending
|
||||||
on whether the region is in kern_memmap or the EFI memory map.
|
on whether the region is in kern_memmap or the EFI memory map.
|
||||||
|
|
||||||
mmap of 0x0-0xA0000 /dev/mem by "hwinfo" on HP sx1000 with VGA enabled
|
mmap of 0x0-0x9FFFF /dev/mem by "hwinfo" on HP sx1000 with VGA enabled
|
||||||
|
|
||||||
See https://bugzilla.novell.com/show_bug.cgi?id=140858.
|
See https://bugzilla.novell.com/show_bug.cgi?id=140858.
|
||||||
|
|
||||||
@@ -171,28 +167,25 @@ PAST PROBLEM CASES
|
|||||||
so it is safe to use WB mappings.
|
so it is safe to use WB mappings.
|
||||||
|
|
||||||
The kernel VGA driver may ioremap the VGA frame buffer at 0xA0000,
|
The kernel VGA driver may ioremap the VGA frame buffer at 0xA0000,
|
||||||
which will use a granule-sized UC mapping covering 0-0xFFFFF. This
|
which uses a granule-sized UC mapping. This granule will cover some
|
||||||
granule covers some WB-only memory, but since UC is non-speculative,
|
WB-only memory, but since UC is non-speculative, the processor will
|
||||||
the processor will never generate an uncacheable reference to the
|
never generate an uncacheable reference to the WB-only areas unless
|
||||||
WB-only areas unless the driver explicitly touches them.
|
the driver explicitly touches them.
|
||||||
|
|
||||||
mmap of 0x0-0xFFFFF legacy_mem by "X"
|
mmap of 0x0-0xFFFFF legacy_mem by "X"
|
||||||
|
|
||||||
If the EFI memory map reports this entire range as WB, there
|
If the EFI memory map reports that the entire range supports the
|
||||||
is no VGA MMIO hole, and the mmap should fail or be done with
|
same attributes, we can allow the mmap (and we will prefer WB if
|
||||||
a WB mapping.
|
supported, as is the case with HP sx[12]000 machines with VGA
|
||||||
|
disabled).
|
||||||
|
|
||||||
There's no easy way for X to determine whether the 0xA0000-0xBFFFF
|
If EFI reports the range as partly WB and partly UC (as on sx[12]000
|
||||||
region is a frame buffer or just memory, so I think it's best to
|
machines with VGA enabled), we must fail the mmap because there's no
|
||||||
just fail this mmap request rather than using a WB mapping. As
|
safe attribute to use.
|
||||||
far as I know, there's no need to map legacy_mem with WB
|
|
||||||
mappings.
|
|
||||||
|
|
||||||
Otherwise, a UC mapping of the entire region is probably safe.
|
If EFI reports some of the range but not all (as on Intel firmware
|
||||||
The VGA hole means the region will not be in kern_memmap. The
|
that doesn't report the VGA frame buffer at all), we should fail the
|
||||||
HP sx1000 chipset doesn't support UC access to the memory surrounding
|
mmap and force the user to map just the specific region of interest.
|
||||||
the VGA hole, but X doesn't need that area anyway and should not
|
|
||||||
reference it.
|
|
||||||
|
|
||||||
mmap of 0xA0000-0xBFFFF legacy_mem by "X" on HP sx1000 with VGA disabled
|
mmap of 0xA0000-0xBFFFF legacy_mem by "X" on HP sx1000 with VGA disabled
|
||||||
|
|
||||||
@@ -202,6 +195,16 @@ PAST PROBLEM CASES
|
|||||||
This is a special case of the previous case, and the mmap should
|
This is a special case of the previous case, and the mmap should
|
||||||
fail for the same reason as above.
|
fail for the same reason as above.
|
||||||
|
|
||||||
|
read of /sys/devices/.../rom
|
||||||
|
|
||||||
|
For VGA devices, this may cause an ioremap() of 0xC0000. This
|
||||||
|
used to be done with a UC mapping, because the VGA frame buffer
|
||||||
|
at 0xA0000 prevents use of a WB granule. The UC mapping causes
|
||||||
|
an MCA on HP sx[12]000 chipsets.
|
||||||
|
|
||||||
|
We should use WB page table mappings to avoid covering the VGA
|
||||||
|
frame buffer.
|
||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
|
|
||||||
[1] SDM rev 2.2, vol 2, sec 4.4.1.
|
[1] SDM rev 2.2, vol 2, sec 4.4.1.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,3 @@
|
|||||||
$Id: input-programming.txt,v 1.4 2001/05/04 09:47:14 vojtech Exp $
|
|
||||||
|
|
||||||
Programming input drivers
|
Programming input drivers
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@@ -20,28 +18,51 @@ pressed or released a BUTTON_IRQ happens. The driver could look like:
|
|||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
static struct input_dev *button_dev;
|
||||||
|
|
||||||
static void button_interrupt(int irq, void *dummy, struct pt_regs *fp)
|
static void button_interrupt(int irq, void *dummy, struct pt_regs *fp)
|
||||||
{
|
{
|
||||||
input_report_key(&button_dev, BTN_1, inb(BUTTON_PORT) & 1);
|
input_report_key(button_dev, BTN_1, inb(BUTTON_PORT) & 1);
|
||||||
input_sync(&button_dev);
|
input_sync(button_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init button_init(void)
|
static int __init button_init(void)
|
||||||
{
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
|
if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
|
||||||
printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
|
printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
button_dev.evbit[0] = BIT(EV_KEY);
|
button_dev = input_allocate_device();
|
||||||
button_dev.keybit[LONG(BTN_0)] = BIT(BTN_0);
|
if (!button_dev) {
|
||||||
|
printk(KERN_ERR "button.c: Not enough memory\n");
|
||||||
input_register_device(&button_dev);
|
error = -ENOMEM;
|
||||||
|
goto err_free_irq;
|
||||||
|
}
|
||||||
|
|
||||||
|
button_dev->evbit[0] = BIT(EV_KEY);
|
||||||
|
button_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
|
||||||
|
|
||||||
|
error = input_register_device(button_dev);
|
||||||
|
if (error) {
|
||||||
|
printk(KERN_ERR "button.c: Failed to register device\n");
|
||||||
|
goto err_free_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_free_dev:
|
||||||
|
input_free_device(button_dev);
|
||||||
|
err_free_irq:
|
||||||
|
free_irq(BUTTON_IRQ, button_interrupt);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit button_exit(void)
|
static void __exit button_exit(void)
|
||||||
{
|
{
|
||||||
input_unregister_device(&button_dev);
|
input_unregister_device(button_dev);
|
||||||
free_irq(BUTTON_IRQ, button_interrupt);
|
free_irq(BUTTON_IRQ, button_interrupt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,17 +79,18 @@ In the _init function, which is called either upon module load or when
|
|||||||
booting the kernel, it grabs the required resources (it should also check
|
booting the kernel, it grabs the required resources (it should also check
|
||||||
for the presence of the device).
|
for the presence of the device).
|
||||||
|
|
||||||
Then it sets the input bitfields. This way the device driver tells the other
|
Then it allocates a new input device structure with input_aloocate_device()
|
||||||
|
and sets up input bitfields. This way the device driver tells the other
|
||||||
parts of the input systems what it is - what events can be generated or
|
parts of the input systems what it is - what events can be generated or
|
||||||
accepted by this input device. Our example device can only generate EV_KEY type
|
accepted by this input device. Our example device can only generate EV_KEY
|
||||||
events, and from those only BTN_0 event code. Thus we only set these two
|
type events, and from those only BTN_0 event code. Thus we only set these
|
||||||
bits. We could have used
|
two bits. We could have used
|
||||||
|
|
||||||
set_bit(EV_KEY, button_dev.evbit);
|
set_bit(EV_KEY, button_dev.evbit);
|
||||||
set_bit(BTN_0, button_dev.keybit);
|
set_bit(BTN_0, button_dev.keybit);
|
||||||
|
|
||||||
as well, but with more than single bits the first approach tends to be
|
as well, but with more than single bits the first approach tends to be
|
||||||
shorter.
|
shorter.
|
||||||
|
|
||||||
Then the example driver registers the input device structure by calling
|
Then the example driver registers the input device structure by calling
|
||||||
|
|
||||||
@@ -76,16 +98,15 @@ Then the example driver registers the input device structure by calling
|
|||||||
|
|
||||||
This adds the button_dev structure to linked lists of the input driver and
|
This adds the button_dev structure to linked lists of the input driver and
|
||||||
calls device handler modules _connect functions to tell them a new input
|
calls device handler modules _connect functions to tell them a new input
|
||||||
device has appeared. Because the _connect functions may call kmalloc(,
|
device has appeared. input_register_device() may sleep and therefore must
|
||||||
GFP_KERNEL), which can sleep, input_register_device() must not be called
|
not be called from an interrupt or with a spinlock held.
|
||||||
from an interrupt or with a spinlock held.
|
|
||||||
|
|
||||||
While in use, the only used function of the driver is
|
While in use, the only used function of the driver is
|
||||||
|
|
||||||
button_interrupt()
|
button_interrupt()
|
||||||
|
|
||||||
which upon every interrupt from the button checks its state and reports it
|
which upon every interrupt from the button checks its state and reports it
|
||||||
via the
|
via the
|
||||||
|
|
||||||
input_report_key()
|
input_report_key()
|
||||||
|
|
||||||
@@ -113,16 +134,10 @@ can use the open and close callback to know when it can stop polling or
|
|||||||
release the interrupt and when it must resume polling or grab the interrupt
|
release the interrupt and when it must resume polling or grab the interrupt
|
||||||
again. To do that, we would add this to our example driver:
|
again. To do that, we would add this to our example driver:
|
||||||
|
|
||||||
int button_used = 0;
|
|
||||||
|
|
||||||
static int button_open(struct input_dev *dev)
|
static int button_open(struct input_dev *dev)
|
||||||
{
|
{
|
||||||
if (button_used++)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
|
if (request_irq(BUTTON_IRQ, button_interrupt, 0, "button", NULL)) {
|
||||||
printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
|
printk(KERN_ERR "button.c: Can't allocate irq %d\n", button_irq);
|
||||||
button_used--;
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,20 +146,21 @@ static int button_open(struct input_dev *dev)
|
|||||||
|
|
||||||
static void button_close(struct input_dev *dev)
|
static void button_close(struct input_dev *dev)
|
||||||
{
|
{
|
||||||
if (!--button_used)
|
free_irq(IRQ_AMIGA_VERTB, button_interrupt);
|
||||||
free_irq(IRQ_AMIGA_VERTB, button_interrupt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init button_init(void)
|
static int __init button_init(void)
|
||||||
{
|
{
|
||||||
...
|
...
|
||||||
button_dev.open = button_open;
|
button_dev->open = button_open;
|
||||||
button_dev.close = button_close;
|
button_dev->close = button_close;
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
Note the button_used variable - we have to track how many times the open
|
Note that input core keeps track of number of users for the device and
|
||||||
function was called to know when exactly our device stops being used.
|
makes sure that dev->open() is called only when the first user connects
|
||||||
|
to the device and that dev->close() is called when the very last user
|
||||||
|
disconnects. Calls to both callbacks are serialized.
|
||||||
|
|
||||||
The open() callback should return a 0 in case of success or any nonzero value
|
The open() callback should return a 0 in case of success or any nonzero value
|
||||||
in case of failure. The close() callback (which is void) must always succeed.
|
in case of failure. The close() callback (which is void) must always succeed.
|
||||||
@@ -175,7 +191,7 @@ set the corresponding bits and call the
|
|||||||
|
|
||||||
input_report_rel(struct input_dev *dev, int code, int value)
|
input_report_rel(struct input_dev *dev, int code, int value)
|
||||||
|
|
||||||
function. Events are generated only for nonzero value.
|
function. Events are generated only for nonzero value.
|
||||||
|
|
||||||
However EV_ABS requires a little special care. Before calling
|
However EV_ABS requires a little special care. Before calling
|
||||||
input_register_device, you have to fill additional fields in the input_dev
|
input_register_device, you have to fill additional fields in the input_dev
|
||||||
@@ -187,6 +203,10 @@ the ABS_X axis:
|
|||||||
button_dev.absfuzz[ABS_X] = 4;
|
button_dev.absfuzz[ABS_X] = 4;
|
||||||
button_dev.absflat[ABS_X] = 8;
|
button_dev.absflat[ABS_X] = 8;
|
||||||
|
|
||||||
|
Or, you can just say:
|
||||||
|
|
||||||
|
input_set_abs_params(button_dev, ABS_X, 0, 255, 4, 8);
|
||||||
|
|
||||||
This setting would be appropriate for a joystick X axis, with the minimum of
|
This setting would be appropriate for a joystick X axis, with the minimum of
|
||||||
0, maximum of 255 (which the joystick *must* be able to reach, no problem if
|
0, maximum of 255 (which the joystick *must* be able to reach, no problem if
|
||||||
it sometimes reports more, but it must be able to always reach the min and
|
it sometimes reports more, but it must be able to always reach the min and
|
||||||
@@ -197,14 +217,7 @@ If you don't need absfuzz and absflat, you can set them to zero, which mean
|
|||||||
that the thing is precise and always returns to exactly the center position
|
that the thing is precise and always returns to exactly the center position
|
||||||
(if it has any).
|
(if it has any).
|
||||||
|
|
||||||
1.4 The void *private field
|
1.4 NBITS(), LONG(), BIT()
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This field in the input structure can be used to point to any private data
|
|
||||||
structures in the input device driver, in case the driver handles more than
|
|
||||||
one device. You'll need it in the open and close callbacks.
|
|
||||||
|
|
||||||
1.5 NBITS(), LONG(), BIT()
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
These three macros from input.h help some bitfield computations:
|
These three macros from input.h help some bitfield computations:
|
||||||
@@ -213,13 +226,9 @@ These three macros from input.h help some bitfield computations:
|
|||||||
LONG(x) - returns the index in the array in longs for bit x
|
LONG(x) - returns the index in the array in longs for bit x
|
||||||
BIT(x) - returns the index in a long for bit x
|
BIT(x) - returns the index in a long for bit x
|
||||||
|
|
||||||
1.6 The number, id* and name fields
|
1.5 The id* and name fields
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The dev->number is assigned by the input system to the input device when it
|
|
||||||
is registered. It has no use except for identifying the device to the user
|
|
||||||
in system messages.
|
|
||||||
|
|
||||||
The dev->name should be set before registering the input device by the input
|
The dev->name should be set before registering the input device by the input
|
||||||
device driver. It's a string like 'Generic button device' containing a
|
device driver. It's a string like 'Generic button device' containing a
|
||||||
user friendly name of the device.
|
user friendly name of the device.
|
||||||
@@ -234,15 +243,25 @@ driver.
|
|||||||
|
|
||||||
The id and name fields can be passed to userland via the evdev interface.
|
The id and name fields can be passed to userland via the evdev interface.
|
||||||
|
|
||||||
1.7 The keycode, keycodemax, keycodesize fields
|
1.6 The keycode, keycodemax, keycodesize fields
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
These two fields will be used for any input devices that report their data
|
These three fields should be used by input devices that have dense keymaps.
|
||||||
as scancodes. If not all scancodes can be known by autodetection, they may
|
The keycode is an array used to map from scancodes to input system keycodes.
|
||||||
need to be set by userland utilities. The keycode array then is an array
|
The keycode max should contain the size of the array and keycodesize the
|
||||||
used to map from scancodes to input system keycodes. The keycode max will
|
size of each entry in it (in bytes).
|
||||||
contain the size of the array and keycodesize the size of each entry in it
|
|
||||||
(in bytes).
|
Userspace can query and alter current scancode to keycode mappings using
|
||||||
|
EVIOCGKEYCODE and EVIOCSKEYCODE ioctls on corresponding evdev interface.
|
||||||
|
When a device has all 3 aforementioned fields filled in, the driver may
|
||||||
|
rely on kernel's default implementation of setting and querying keycode
|
||||||
|
mappings.
|
||||||
|
|
||||||
|
1.7 dev->getkeycode() and dev->setkeycode()
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
getkeycode() and setkeycode() callbacks allow drivers to override default
|
||||||
|
keycode/keycodesize/keycodemax mapping mechanism provided by input core
|
||||||
|
and implement sparse keycode maps.
|
||||||
|
|
||||||
1.8 Key autorepeat
|
1.8 Key autorepeat
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
@@ -266,7 +285,7 @@ direction - from the system to the input device driver. If your input device
|
|||||||
driver can handle these events, it has to set the respective bits in evbit,
|
driver can handle these events, it has to set the respective bits in evbit,
|
||||||
*and* also the callback routine:
|
*and* also the callback routine:
|
||||||
|
|
||||||
button_dev.event = button_event;
|
button_dev->event = button_event;
|
||||||
|
|
||||||
int button_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
|
int button_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
|
||||||
{
|
{
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user