﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-所谓技术</title><link>http://www.cnitblog.com/vsolo/</link><description>－－－－－simple,sometimes naive!</description><language>zh-cn</language><lastBuildDate>Mon, 13 Apr 2026 07:11:42 GMT</lastBuildDate><pubDate>Mon, 13 Apr 2026 07:11:42 GMT</pubDate><ttl>60</ttl><item><title>输入子系统的实现</title><link>http://www.cnitblog.com/vsolo/archive/2008/05/28/44497.html</link><dc:creator>vsolo</dc:creator><author>vsolo</author><pubDate>Wed, 28 May 2008 13:28:00 GMT</pubDate><guid>http://www.cnitblog.com/vsolo/archive/2008/05/28/44497.html</guid><wfw:comment>http://www.cnitblog.com/vsolo/comments/44497.html</wfw:comment><comments>http://www.cnitblog.com/vsolo/archive/2008/05/28/44497.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/vsolo/comments/commentRss/44497.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/vsolo/services/trackbacks/44497.html</trackback:ping><description><![CDATA[<p>这是2.6.15以前某个版本，2.6.15已经略有不同，但总体思想还是差不多<br><br>输入子系统大致实现方法：</p>
<p>&nbsp;&nbsp; 底层驱动层（input_dev）-----&lt;通过结构体input_handle关联&gt;-----输入事件处理层类接口（input_handler）-----&lt;输入核心层input.c&gt;-----应用层<br><br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br><span style="COLOR: #3366ff">struct input_handle {&nbsp;//用于关联底层驱动层input_dev和事件处理层input_handler</span></p>
<p style="COLOR: #3366ff">&nbsp;void *private;</p>
<p style="COLOR: #3366ff">&nbsp;int open;</p>
<p style="COLOR: #3366ff">&nbsp;struct input_dev *dev;<br>&nbsp;struct input_handler *handler;</p>
<p><span style="COLOR: #3366ff">&nbsp;struct input_handle *dnext;<br>&nbsp;struct input_handle *hnext;<br></span><span style="COLOR: #3366ff">};<br></span>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>void input_register_device(struct input_dev *dev)<br>{<br>&nbsp;struct input_handler *handler = input_handler;<br>&nbsp;struct input_handle *handle;</p>
<p>/*<br>&nbsp;* Initialize repeat timer to default values.<br>&nbsp;*/</p>
<p>&nbsp;init_timer(&amp;dev-&gt;timer);<br>&nbsp;dev-&gt;timer.data = (long) dev;<br>&nbsp;dev-&gt;timer.function = input_repeat_key;<br>&nbsp;dev-&gt;rep[REP_DELAY] = HZ/4;<br>&nbsp;dev-&gt;rep[REP_PERIOD] = HZ/33;</p>
<p>/*<br>&nbsp;* Add the device.<br>&nbsp;*/</p>
<p>&nbsp;if (input_number &gt;= INPUT_DEVICES) {<br>&nbsp;&nbsp;printk(KERN_WARNING "input: ran out of input device numbers!\n");<br>&nbsp;&nbsp;dev-&gt;number = input_number;<br>&nbsp;} else {<br>&nbsp;&nbsp;dev-&gt;number = find_first_zero_bit(input_devices, INPUT_DEVICES);<br>&nbsp;&nbsp;set_bit(dev-&gt;number, input_devices);&nbsp;&nbsp;&nbsp;&nbsp; //编号此输入设备<br>&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//input_devices[8],8*32(BITS_PER_LONG)=256b,256 minor for each major<br>&nbsp;&nbsp;<br>&nbsp;dev-&gt;next = input_dev;&nbsp;&nbsp;&nbsp;&nbsp;//插入到单链表首&nbsp;<br>&nbsp;input_dev = dev;<br>&nbsp;input_number++;</p>
<p>/*<br>&nbsp;* Notify handlers.<br>&nbsp;*/</p>
<p>&nbsp;while (handler) {&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #3366ff">&nbsp;//故应先通过input_register_handler注册handler到单链表中，即输入子系统的第二层：事件处理层<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//事件处理层是类通用的，如endev，tsdev，mousedev等<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//且某个具体的驱动层设备可以关联多个事件处理层接口，生成多个节点<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//用户程序根据打开的节点判断调用某一类事件处理层接口，进而关联驱动层<br></span>&nbsp;&nbsp;if ((handle = handler-&gt;connect(handler, dev)))<br>&nbsp;&nbsp;&nbsp;input_link_handle(handle);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; －－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void input_link_handle(struct input_handle *handle)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handle-&gt;dnext = handle-&gt;dev-&gt;handle;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handle-&gt;hnext = handle-&gt;handler-&gt;handle;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handle-&gt;dev-&gt;handle = handle;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handle-&gt;handler-&gt;handle = handle;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; －－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>&nbsp;&nbsp;handler = handler-&gt;next;<br>&nbsp;}<br>}</p>
<p><br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>以endev为例：</p>
<p><br>static struct input_handler evdev_handler = {<br>&nbsp;event:&nbsp;&nbsp;evdev_event,<br>&nbsp;connect:&nbsp;evdev_connect,<br>&nbsp;disconnect:&nbsp;evdev_disconnect,<br>&nbsp;fops:&nbsp;&nbsp;&amp;evdev_fops,<br>&nbsp;minor:&nbsp;&nbsp;EVDEV_MINOR_BASE,<br>};</p>
<p>static struct file_operations evdev_fops = {<br>&nbsp;owner:&nbsp;&nbsp;THIS_MODULE,<br>&nbsp;read:&nbsp;&nbsp;evdev_read,<br>&nbsp;write:&nbsp;&nbsp;evdev_write,<br>&nbsp;poll:&nbsp;&nbsp;evdev_poll,<br>&nbsp;open:&nbsp;&nbsp;evdev_open,<br>&nbsp;release:&nbsp;evdev_release,<br>&nbsp;ioctl:&nbsp;&nbsp;evdev_ioctl,<br>&nbsp;fasync:&nbsp;&nbsp;evdev_fasync,<br>};</p>
<p><br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</p>
<p>void input_register_handler(struct input_handler *handler)<br>{<br>&nbsp;struct input_dev *dev = input_dev;<br>&nbsp;struct input_handle *handle;</p>
<p>/*<br>&nbsp;* Add minors if needed.<br>&nbsp;*/</p>
<p>&nbsp;if (handler-&gt;fops != NULL)<br>&nbsp;&nbsp;input_table[handler-&gt;minor &gt;&gt; 5] = handler;</p>
<p>/*<br>&nbsp;* Add the handler.<br>&nbsp;*/</p>
<p>&nbsp;handler-&gt;next = input_handler;&nbsp;&nbsp;&nbsp;//插入到单链表首<br>&nbsp;input_handler = handler;<br>&nbsp;<br>/*<br>&nbsp;* Notify it about all existing devices.<br>&nbsp;*/</p>
<p>&nbsp;while (dev) {<br>&nbsp;&nbsp;if ((handle = handler-&gt;connect(handler, dev)))&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;input_link_handle(handle);<br>&nbsp;&nbsp;dev = dev-&gt;next;<br>&nbsp;}<br>}</p>
<p><br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev)<br>{<br>&nbsp;struct evdev *evdev;<br>&nbsp;int minor;</p>
<p>&nbsp;for (minor = 0; minor &lt; EVDEV_MINORS &amp;&amp; evdev_table[minor]; minor++); <span style="COLOR: #3366ff">//evdev_table记录endev的个数<br></span>&nbsp;if (minor == EVDEV_MINORS) {<br>&nbsp;&nbsp;printk(KERN_ERR "evdev: no more free evdev devices\n");<br>&nbsp;&nbsp;return NULL;<br>&nbsp;}</p>
<p>&nbsp;if (!(evdev = kmalloc(sizeof(struct evdev), GFP_KERNEL)))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //申请一个新的endev<br>&nbsp;&nbsp;return NULL;<br>&nbsp;memset(evdev, 0, sizeof(struct evdev));</p>
<p>&nbsp;init_waitqueue_head(&amp;evdev-&gt;wait);</p>
<p>&nbsp;evdev-&gt;minor = minor;<br>&nbsp;evdev_table[minor] = evdev;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//添加到evdev_table</p>
<p>&nbsp;evdev-&gt;handle.dev = dev;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #3366ff">//实现驱动层和事件处理层的关联<br></span>&nbsp;evdev-&gt;handle.handler = handler;<br>&nbsp;evdev-&gt;handle.private = evdev;</p>
<p>&nbsp;evdev-&gt;exist = 1;</p>
<p>&nbsp;evdev-&gt;devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE);</p>
<p>//&nbsp;printk(KERN_INFO "event%d: Event device for input%d\n", minor, dev-&gt;number);</p>
<p>&nbsp;return &amp;evdev-&gt;handle;<br>}<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>devfs_handle_t input_register_minor(char *name, int minor, int minor_base)<br>{<br>&nbsp;char devfs_name[16];<br>&nbsp;sprintf(devfs_name, name, minor);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #3366ff">//创建设备节点：INPUT_MAJOR＝13，<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//minor_base+minor:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EVDEV_MINOR_BASE(64)+(0-31);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOUSEDEV_MINOR_BASE(32)+(0-31);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JOYDEV_MINOR_BASE(0)+(0-31);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TSDEV_MINOR_BASE(128)+(0-31);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//input_devfs_handle=devfs_mk_dir(NULL, "input", NULL);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//在/dev/input/下可看到相关的input设备节点</span><br>&nbsp;return devfs_register(input_devfs_handle, devfs_name, DEVFS_FL_DEFAULT, INPUT_MAJOR, minor + minor_base,<br>&nbsp;&nbsp;S_IFCHR | S_IRUGO | S_IWUSR, &amp;input_fops, NULL);<br>}<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>static int __init input_init(void)<br>{<br>&nbsp;if (devfs_register_chrdev(INPUT_MAJOR, "input", &amp;input_fops)) {<br>&nbsp;&nbsp;printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);<br>&nbsp;&nbsp;return -EBUSY;<br>&nbsp;}<br>&nbsp;input_devfs_handle = devfs_mk_dir(NULL, "input", NULL);<br>&nbsp;return 0;<br>}</p>
<p><br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)<br>{<br>&nbsp;struct input_handle *handle = dev-&gt;handle;</p>
<p>/*<br>&nbsp;* Filter non-events, and bad input values out.<br>&nbsp;*/</p>
<p>&nbsp;if (type &gt; EV_MAX || !test_bit(type, dev-&gt;evbit))<br>&nbsp;&nbsp;return;</p>
<p>&nbsp;switch (type) {</p>
<p>&nbsp;&nbsp;case EV_KEY:</p>
<p>&nbsp;&nbsp;&nbsp;if (code &gt; KEY_MAX || !test_bit(code, dev-&gt;keybit) || !!test_bit(code, dev-&gt;key) == value)<br>&nbsp;&nbsp;&nbsp;&nbsp;return;</p>
<p>&nbsp;&nbsp;&nbsp;if (value == 2) break;</p>
<p>&nbsp;&nbsp;&nbsp;change_bit(code, dev-&gt;key);</p>
<p>&nbsp;&nbsp;&nbsp;if (test_bit(EV_REP, dev-&gt;evbit) &amp;&amp; dev-&gt;timer.function) {<br>&nbsp;&nbsp;&nbsp;&nbsp;if (value) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mod_timer(&amp;dev-&gt;timer, jiffies + dev-&gt;rep[REP_DELAY]);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dev-&gt;repeat_key = code;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;if (dev-&gt;repeat_key == code)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;del_timer(&amp;dev-&gt;timer);<br>&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;break;<br>&nbsp;&nbsp;<br>&nbsp;&nbsp;case EV_ABS:</p>
<p>&nbsp;&nbsp;&nbsp;if (code &gt; ABS_MAX || !test_bit(code, dev-&gt;absbit))<br>&nbsp;&nbsp;&nbsp;&nbsp;return;</p>
<p>&nbsp;&nbsp;&nbsp;if (dev-&gt;absfuzz[code]) {<br>&nbsp;&nbsp;&nbsp;&nbsp;if ((value &gt; dev-&gt;abs[code] - (dev-&gt;absfuzz[code] &gt;&gt; 1)) &amp;&amp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (value &lt; dev-&gt;abs[code] + (dev-&gt;absfuzz[code] &gt;&gt; 1)))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;if ((value &gt; dev-&gt;abs[code] - dev-&gt;absfuzz[code]) &amp;&amp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (value &lt; dev-&gt;abs[code] + dev-&gt;absfuzz[code]))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value = (dev-&gt;abs[code] * 3 + value) &gt;&gt; 2;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;if ((value &gt; dev-&gt;abs[code] - (dev-&gt;absfuzz[code] &lt;&lt; 1)) &amp;&amp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (value &lt; dev-&gt;abs[code] + (dev-&gt;absfuzz[code] &lt;&lt; 1)))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value = (dev-&gt;abs[code] + value) &gt;&gt; 1;<br>&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;if (dev-&gt;abs[code] == value)<br>&nbsp;&nbsp;&nbsp;&nbsp;return;</p>
<p>&nbsp;&nbsp;&nbsp;dev-&gt;abs[code] = value;<br>&nbsp;&nbsp;&nbsp;break;</p>
<p>&nbsp;&nbsp;case EV_REL:</p>
<p>&nbsp;&nbsp;&nbsp;if (code &gt; REL_MAX || !test_bit(code, dev-&gt;relbit) || (value == 0))<br>&nbsp;&nbsp;&nbsp;&nbsp;return;</p>
<p>&nbsp;&nbsp;&nbsp;break;</p>
<p>&nbsp;&nbsp;case EV_MSC:</p>
<p>&nbsp;&nbsp;&nbsp;if (code &gt; MSC_MAX || !test_bit(code, dev-&gt;mscbit))<br>&nbsp;&nbsp;&nbsp;&nbsp;return;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;break;</p>
<p>&nbsp;&nbsp;case EV_LED:<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;if (code &gt; LED_MAX || !test_bit(code, dev-&gt;ledbit) || !!test_bit(code, dev-&gt;led) == value)<br>&nbsp;&nbsp;&nbsp;&nbsp;return;</p>
<p>&nbsp;&nbsp;&nbsp;change_bit(code, dev-&gt;led);<br>&nbsp;&nbsp;&nbsp;if (dev-&gt;event) dev-&gt;event(dev, type, code, value);&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;break;</p>
<p>&nbsp;&nbsp;case EV_SND:<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;if (code &gt; SND_MAX || !test_bit(code, dev-&gt;sndbit) || !!test_bit(code, dev-&gt;snd) == value)<br>&nbsp;&nbsp;&nbsp;&nbsp;return;</p>
<p>&nbsp;&nbsp;&nbsp;change_bit(code, dev-&gt;snd);<br>&nbsp;&nbsp;&nbsp;if (dev-&gt;event) dev-&gt;event(dev, type, code, value);&nbsp;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;break;</p>
<p>&nbsp;&nbsp;case EV_REP:</p>
<p>&nbsp;&nbsp;&nbsp;if (code &gt; REP_MAX || dev-&gt;rep[code] == value) return;</p>
<p>&nbsp;&nbsp;&nbsp;dev-&gt;rep[code] = value;<br>&nbsp;&nbsp;&nbsp;if (dev-&gt;event) dev-&gt;event(dev, type, code, value);</p>
<p>&nbsp;&nbsp;&nbsp;break;</p>
<p>&nbsp;&nbsp;case EV_FF:<br>&nbsp;&nbsp;&nbsp;if (dev-&gt;event) dev-&gt;event(dev, type, code, value);<br>&nbsp;&nbsp;&nbsp;break;<br>&nbsp;}</p>
<p>/*<br>&nbsp;* Distribute the event to handler modules.<br>&nbsp;*/</p>
<p>&nbsp;while (handle) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //遍历每个打开的handle<br>&nbsp;&nbsp;if (handle-&gt;open)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //when open a input device,record it once time <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //in function input_open_device,handle-&gt;open++;&nbsp; <br>&nbsp;&nbsp;&nbsp;handle-&gt;handler-&gt;event(handle, type, code, value);<br>&nbsp;&nbsp;handle = handle-&gt;dnext;<br>&nbsp;}<br>}<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>static void evdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)<br>{<br>&nbsp;struct evdev *evdev = handle-&gt;private;<br>&nbsp;struct evdev_list *list = evdev-&gt;list;</p>
<p>&nbsp;while (list) {</p>
<p>&nbsp;&nbsp;do_gettimeofday(&amp;list-&gt;buffer[list-&gt;head].time);<br>&nbsp;&nbsp;list-&gt;buffer[list-&gt;head].type = type;<br>&nbsp;&nbsp;list-&gt;buffer[list-&gt;head].code = code;<br>&nbsp;&nbsp;list-&gt;buffer[list-&gt;head].value = value;<br>&nbsp;&nbsp;list-&gt;head = (list-&gt;head + 1) &amp; (EVDEV_BUFFER_SIZE - 1);</p>
<p>&nbsp;&nbsp;kill_fasync(&amp;list-&gt;fasync, SIGIO, POLL_IN);</p>
<p>&nbsp;&nbsp;list = list-&gt;next;<br>&nbsp;}</p>
<p>&nbsp;wake_up_interruptible(&amp;evdev-&gt;wait);&nbsp;&nbsp;&nbsp;//填充数据结构，并唤醒相关的等待进程。<br>}<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</p>
<p>&nbsp;</p>
<p><span style="COLOR: #3366ff">至于何时打开：<br></span>static struct file_operations input_fops = {<br>&nbsp;owner: THIS_MODULE,<br>&nbsp;open: input_open_file,<br>};<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>static int input_open_file(struct inode *inode, struct file *file)<br>{<br>&nbsp;struct input_handler *handler = input_table[MINOR(inode-&gt;i_rdev) &gt;&gt; 5];&nbsp; <span style="COLOR: #3366ff">//LINUX最多8类事件处理层接口，各32个节点<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //打开某个设备时，根据节点大小选择事件处理层接口<br></span>&nbsp;struct file_operations *old_fops, *new_fops = NULL;<br>&nbsp;int err;</p>
<p>&nbsp;/* No load-on-demand here? */<br>&nbsp;if (!handler || !(new_fops = fops_get(handler-&gt;fops)))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //得到相应的事件处理层接口的操作接口<br>&nbsp;&nbsp;return -ENODEV;</p>
<p>&nbsp;/*<br>&nbsp; * That's _really_ odd. Usually NULL -&gt;open means "nothing special",<br>&nbsp; * not "no device". Oh, well...<br>&nbsp; */<br>&nbsp;if (!new_fops-&gt;open) {<br>&nbsp;&nbsp;fops_put(new_fops);<br>&nbsp;&nbsp;return -ENODEV;<br>&nbsp;}<br>&nbsp;old_fops = file-&gt;f_op;<br>&nbsp;file-&gt;f_op = new_fops;</p>
<p>&nbsp;lock_kernel();<br>&nbsp;err = new_fops-&gt;open(inode, file);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //进一步调用<br>&nbsp;unlock_kernel();</p>
<p>&nbsp;if (err) {<br>&nbsp;&nbsp;fops_put(file-&gt;f_op);<br>&nbsp;&nbsp;file-&gt;f_op = fops_get(old_fops);<br>&nbsp;}<br>&nbsp;fops_put(old_fops);<br>&nbsp;return err;<br>}<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>static int evdev_open(struct inode * inode, struct file * file)<br>{<br>&nbsp;struct evdev_list *list;<br>&nbsp;int i = MINOR(inode-&gt;i_rdev) - EVDEV_MINOR_BASE;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;if (i &gt;= EVDEV_MINORS || !evdev_table[i])<br>&nbsp;&nbsp;return -ENODEV;</p>
<p>&nbsp;if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))<br>&nbsp;&nbsp;return -ENOMEM;<br>&nbsp;memset(list, 0, sizeof(struct evdev_list));</p>
<p>&nbsp;list-&gt;evdev = evdev_table[i];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //得到底层驱动层<br>&nbsp;list-&gt;next = evdev_table[i]-&gt;list;<br>&nbsp;evdev_table[i]-&gt;list = list;</p>
<p>&nbsp;file-&gt;private_data = list;</p>
<p>&nbsp;if (!list-&gt;evdev-&gt;open++)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//若未打开，则调用input_open_device并标识为打开<br>&nbsp;&nbsp;if (list-&gt;evdev-&gt;exist)<br>&nbsp;&nbsp;&nbsp;input_open_device(&amp;list-&gt;evdev-&gt;handle);</p>
<p>&nbsp;return 0;<br>}<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>int input_open_device(struct input_handle *handle)<br>{<br>&nbsp;handle-&gt;open++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//打开handle实现<br>&nbsp;if (handle-&gt;dev-&gt;open)<br>&nbsp;&nbsp;return handle-&gt;dev-&gt;open(handle-&gt;dev);&nbsp;&nbsp;//驱动层若有open，进一步实现<br>&nbsp;return 0;<br>}<br></p>
<img src ="http://www.cnitblog.com/vsolo/aggbug/44497.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/vsolo/" target="_blank">vsolo</a> 2008-05-28 21:28 <a href="http://www.cnitblog.com/vsolo/archive/2008/05/28/44497.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AT91SAM9261的ROMBoot启动片段</title><link>http://www.cnitblog.com/vsolo/archive/2008/05/20/43983.html</link><dc:creator>vsolo</dc:creator><author>vsolo</author><pubDate>Tue, 20 May 2008 14:24:00 GMT</pubDate><guid>http://www.cnitblog.com/vsolo/archive/2008/05/20/43983.html</guid><wfw:comment>http://www.cnitblog.com/vsolo/comments/43983.html</wfw:comment><comments>http://www.cnitblog.com/vsolo/archive/2008/05/20/43983.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/vsolo/comments/commentRss/43983.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/vsolo/services/trackbacks/43983.html</trackback:ping><description><![CDATA[<p>AT91SAM9261中内部ROM有32K，可惜启动代码只用了不到8K的空间，目前看来还是有浪费之嫌的（想想当年51就寒碜）<br>上电启动代码的反汇编，只走了第一个S文件：</p>
<p>ROM:00400000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AREA ROM, CODE, READWRITE, ALIGN=0<br>ROM:00400000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ; ORG 0x400000<br>ROM:00400000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CODE32<br>ROM:00400000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; loc_400020&nbsp;&nbsp;&nbsp;&nbsp;//Reset<br>ROM:00400000 ; --------------------------------------------------------------------------------<br>ROM:00400004&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFE ;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;//Other Exception vectors<br>ROM:00400005&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFF<br>ROM:00400006&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFF<br>ROM:00400007&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xEA ; <br>ROM:00400008&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0x2F ; <br>ROM:00400009&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB&nbsp;&nbsp;&nbsp; 0<br>ROM:0040000A&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB&nbsp;&nbsp;&nbsp; 0<br>ROM:0040000B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xEA ; <br>ROM:0040000C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFE ; <br>ROM:0040000D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFF<br>ROM:0040000E&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFF<br>ROM:0040000F&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xEA ; <br>ROM:00400010&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFE ; <br>ROM:00400011&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFF<br>ROM:00400012&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFF<br>ROM:00400013&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xEA ; <br>ROM:00400014&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFE ; <br>ROM:00400015&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFF<br>ROM:00400016&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFF<br>ROM:00400017&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xEA ; <br>ROM:00400018&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFE ; <br>ROM:00400019&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFF<br>ROM:0040001A&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFF<br>ROM:0040001B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xEA ; <br>ROM:0040001C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFE ; <br>ROM:0040001D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFF<br>ROM:0040001E&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xFF<br>ROM:0040001F&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0xEA ; <br>ROM:00400020 ; --------------------------------------------------------------------------------<br>ROM:00400020<br>ROM:00400020 loc_400020&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>ROM:00400020&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; SP, #0x328000&nbsp;&nbsp;&nbsp;//stack setup<br>ROM:00400024&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDR&nbsp;&nbsp;&nbsp;&nbsp; R1, =0xFFFFFC00&nbsp;&nbsp;&nbsp;//即LDR&nbsp; R1, =AT91C_PMC_SCER ；(PMC) System Clock Enable Register<br>ROM:00400028&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDR&nbsp;&nbsp;&nbsp;&nbsp; R0, =0x4001<br>ROM:0040002C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; STR&nbsp;&nbsp;&nbsp;&nbsp; R0, [R1,#0x20]&nbsp;&nbsp;&nbsp;//即STR&nbsp; R0, [R1,#MOR] ；(PMC) Main Oscillator Register<br>ROM:00400030&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; R4, #1<br>ROM:00400034<br>ROM:00400034 loc_400034&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>ROM:00400034&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDR&nbsp;&nbsp;&nbsp;&nbsp; R3, [R1,#0x68]&nbsp;&nbsp;&nbsp;//即LDR&nbsp;&nbsp; R3, [R1,#SR] ；(PMC) Status Register<br>ROM:00400038&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AND&nbsp;&nbsp;&nbsp;&nbsp; R3, R4, R3<br>ROM:0040003C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CMP&nbsp;&nbsp;&nbsp;&nbsp; R3, #1<br>ROM:00400040&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BNE&nbsp;&nbsp;&nbsp;&nbsp; loc_400034&nbsp;&nbsp;&nbsp;&nbsp;//等待主时钟振荡器稳定<br>ROM:00400044&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; R0, #1<br>ROM:00400048&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; STR&nbsp;&nbsp;&nbsp;&nbsp; R0, [R1,#0x30]&nbsp;&nbsp;&nbsp;//即STR&nbsp;&nbsp; R0, [R1,#MCKR] ；(PMC) Master Clock Register<br>ROM:0040004C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; R4, #8<br>ROM:00400050<br>ROM:00400050 loc_400050&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>ROM:00400050&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDR&nbsp;&nbsp;&nbsp;&nbsp; R3, [R1,#0x68]&nbsp;&nbsp;&nbsp;//读取PMC状态<br>ROM:00400054&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AND&nbsp;&nbsp;&nbsp;&nbsp; R3, R4, R3<br>ROM:00400058&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CMP&nbsp;&nbsp;&nbsp;&nbsp; R3, #8<br>ROM:0040005C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BNE&nbsp;&nbsp;&nbsp;&nbsp; loc_400050<br>ROM:00400060&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ADR&nbsp;&nbsp;&nbsp;&nbsp; R2, off_400094&nbsp;&nbsp;&nbsp;//等待芯片时钟稳定<br>ROM:00400064&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDMIA&nbsp;&nbsp; R2, {R0,R1,R3,R4}<br>ROM:00400068&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CMP&nbsp;&nbsp;&nbsp;&nbsp; R0, R1<br>ROM:0040006C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BEQ&nbsp;&nbsp;&nbsp;&nbsp; loc_400080<br>ROM:00400070<br>ROM:00400070 loc_400070&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>ROM:00400070&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CMP&nbsp;&nbsp;&nbsp;&nbsp; R1, R3&nbsp;&nbsp;&nbsp;&nbsp;//copy RW section to IRAM<br>ROM:00400074&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDRCC&nbsp;&nbsp; R2, [R0],#4<br>ROM:00400078&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; STRCC&nbsp;&nbsp; R2, [R1],#4<br>ROM:0040007C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BCC&nbsp;&nbsp;&nbsp;&nbsp; loc_400070<br>ROM:00400080<br>ROM:00400080 loc_400080&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>ROM:00400080&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; R2, #0<br>ROM:00400084<br>ROM:00400084 loc_400084&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>ROM:00400084&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CMP&nbsp;&nbsp;&nbsp;&nbsp; R3, R4&nbsp;&nbsp;&nbsp;&nbsp;//copy ZI section to IRAM and Zero init<br>ROM:00400088&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; STRCC&nbsp;&nbsp; R2, [R3],#4<br>ROM:0040008C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BCC&nbsp;&nbsp;&nbsp;&nbsp; loc_400084<br>ROM:00400090&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; loc_4000A4<br>ROM:00400090 ; --------------------------------------------------------------------------------<br>ROM:00400094 off_400094&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCD 0x401E9C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//|Image$$RO$$Limit| <br>ROM:00400098&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//|Image$$RW$$Base|<br>ROM:00400099&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0x70 ; p&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>ROM:0040009A&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0x32 ; 2<br>ROM:0040009B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>ROM:0040009C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0x10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//|Image$$ZI$$Base|<br>ROM:0040009D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0x70 ; p<br>ROM:0040009E&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0x32 ; 2<br>ROM:0040009F&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>ROM:004000A0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0x88 ; ?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//|Image$$ZI$$Limit|<br>ROM:004000A1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0x70 ; p<br>ROM:004000A2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB 0x32 ; 2<br>ROM:004000A3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DCB&nbsp;&nbsp;&nbsp; 0<br>ROM:004000A4 ; --------------------------------------------------------------------------------<br>ROM:004000A4<br>ROM:004000A4 loc_4000A4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>ROM:004000A4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDR&nbsp;&nbsp;&nbsp;&nbsp; R0, =sub_401690<br>ROM:004000A8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; LR, PC<br>ROM:004000AC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; R0<br>ROM:004000B0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDR&nbsp;&nbsp;&nbsp;&nbsp; R0, =sub_40066C<br>ROM:004000B4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; LR, PC<br>ROM:004000B8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; R0<br>ROM:004000BC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MRC&nbsp;&nbsp;&nbsp;&nbsp; p15, 0, R5,c1,c0<br>ROM:004000C0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; R6, #0x1000<br>ROM:004000C4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ORR&nbsp;&nbsp;&nbsp;&nbsp; R5, R5, R6<br>ROM:004000C8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MCR&nbsp;&nbsp;&nbsp;&nbsp; p15, 0, R5,c1,c0<br>ROM:004000CC<br>ROM:004000CC loc_4000CC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>ROM:004000CC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LDR&nbsp;&nbsp;&nbsp;&nbsp; R0, =sub_401338<br>ROM:004000D0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MOV&nbsp;&nbsp;&nbsp;&nbsp; LR, PC<br>ROM:004000D4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BX&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; R0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//Jump to main Function<br>ROM:004000D8<br>ROM:004000D8 loc_4000D8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>ROM:004000D8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; loc_4000D8&nbsp;&nbsp;&nbsp;&nbsp;//Normally, never occur.<br></p>
<img src ="http://www.cnitblog.com/vsolo/aggbug/43983.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/vsolo/" target="_blank">vsolo</a> 2008-05-20 22:24 <a href="http://www.cnitblog.com/vsolo/archive/2008/05/20/43983.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>I/O资源如何映射到内核虚拟空间</title><link>http://www.cnitblog.com/vsolo/archive/2008/04/26/42786.html</link><dc:creator>vsolo</dc:creator><author>vsolo</author><pubDate>Sat, 26 Apr 2008 08:02:00 GMT</pubDate><guid>http://www.cnitblog.com/vsolo/archive/2008/04/26/42786.html</guid><wfw:comment>http://www.cnitblog.com/vsolo/comments/42786.html</wfw:comment><comments>http://www.cnitblog.com/vsolo/archive/2008/04/26/42786.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/vsolo/comments/commentRss/42786.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/vsolo/services/trackbacks/42786.html</trackback:ping><description><![CDATA[<p><span style="COLOR: #0000ff"><strong>(1)&nbsp; 系统启动初始化时iotable_init()</strong></span><br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>MACHINE_START(AT91SAM9261EK, "ATMEL AT91SAM9261")<br>&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .map_io&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = <span style="COLOR: #0000ff">at91sam9261_map_io</span>,<br>&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;<br>MACHINE_END<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>void __init <span style="COLOR: #0000ff">at91sam9261_map_io</span>(void)<br>{<br>&nbsp;iotable_init(<span style="COLOR: #0000ff">at91sam9261_io_desc</span>, ARRAY_SIZE(at91sam9261_io_desc));<br>}<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>/*<br>&nbsp;* System peripheral registers mapped at virtual address.<br>&nbsp;*/</p>
<p>static struct map_desc <span style="COLOR: #0000ff">at91sam9261_io_desc</span>[] __initdata = {<br>&nbsp;{ <br>&nbsp;&nbsp;.virtual = AT91C_VA_BASE_SYS,<br>&nbsp;&nbsp;.pfn = __phys_to_pfn(AT91C_BASE_AIC),<br>&nbsp;&nbsp;.length = SZ_4K,<br>&nbsp;&nbsp;.type = MT_DEVICE<br>&nbsp;},<br>&nbsp;{ <br>&nbsp;&nbsp;.virtual = AT91C_VA_BASE_EBI,<br>&nbsp;&nbsp;.pfn = __phys_to_pfn(AT91C_BASE_EBI),<br>&nbsp;&nbsp;.length = SZ_4K,<br>&nbsp;&nbsp;.type = MT_DEVICE<br>&nbsp;},<br>&nbsp;&nbsp;&nbsp;&nbsp; &#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;<br>};</p>
<p>&lt;./linux/include/asm-arm/map.h&gt;－－－－－－－－－－－－－－－－－－－－－－－<br>struct map_desc {<br>&nbsp;unsigned long virtual;<br>&nbsp;unsigned long pfn;<br>&nbsp;unsigned long length;<br>&nbsp;unsigned int type;&nbsp;&nbsp; //标志位：domain、read、write、cache、buffer<br>};</p>
<p>#define&nbsp;__phys_to_pfn(paddr)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((paddr) &gt;&gt; PAGE_SHIFT)<br>#define&nbsp;__pfn_to_phys(pfn)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((pfn) &lt;&lt; PAGE_SHIFT)<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>&nbsp;&nbsp;<span style="COLOR: #0000ff">&nbsp; iotable_init()函数&lt;./arch/arm/mm/mm-armv.c&gt;循环调用create_mapping()函数完成IO的虚拟地址到物理地址的映射。</span></p>
<p><br><span style="COLOR: #0000ff"><strong>(2)&nbsp; 系统启动后，在驱动中ioremap()</strong></span><br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>static struct platform_device *smdk2410_devices[] __initdata = {<br>&amp;s3c_device_usb,&nbsp;&nbsp;&nbsp; //片上的各个设备<br>&amp;<span style="COLOR: #0000ff">s3c_device_lcd</span>,&nbsp;&nbsp;&nbsp; //下面以s3c_device_lcd为例<br>&amp;s3c_device_wdt,<br>&amp;s3c_device_i2c,<br>&amp;s3c_device_iis,<br>};<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>struct platform_device <span style="COLOR: #0000ff">s3c_device_lcd</span> = {<br>.name = "s3c2410-lcd",&nbsp; //此处设备的命名应和相应驱动程序命名一致以实现driver bind<br>.id = -1,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //-1表示不支持同类多个设备<br>.num_resources = ARRAY_SIZE(s3c_lcd_resource),<br>.<span style="COLOR: #0000ff">resource = s3c_lcd_resource</span>,<br>.dev = {<br>.dma_mask = &amp;s3c_device_lcd_dmamask,<br>.coherent_dma_mask = 0xffffffffUL<br>}<br>};</p>
<p>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>/* LCD Controller */<br>static struct resource <span style="COLOR: #0000ff">s3c_lcd_resource</span>[] = {&nbsp;&nbsp; //LCD的两个资源<br><span style="COLOR: #0000ff">[0] = {<br>.start = S3C2410_PA_LCD, <br>.end = S3C2410_PA_LCD + S3C2410_SZ_LCD,<br>.flags = IORESOURCE_MEM,<br>},<br>[1] = {<br>.start = IRQ_LCD,<br>.end = IRQ_LCD,<br>.flags = IORESOURCE_IRQ,<br>}</span></p>
<p>};<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>/* －－－－－－－Resource type －－－－－－－－ */<br>#define IORESOURCE_IO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;0x00000100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>#define IORESOURCE_MEM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;0x00000200<br>#define IORESOURCE_IRQ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;0x00000400<br>#define IORESOURCE_DMA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;0x00000800<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</p>
<p>－－－－－<span style="COLOR: #0000ff">s3c_device_lcd的resource中硬件地址</span>－－－－－－－－－－－－－－－</p>
<p>#define S3C2410_LCDREG(x)&nbsp;(x)</p>
<p>/* LCD control registers */<br>#define S3C2410_LCDCON1&nbsp;&nbsp;&nbsp;&nbsp; S3C2410_LCDREG(0x00)<br>#define S3C2410_LCDCON2&nbsp;&nbsp;&nbsp;&nbsp; S3C2410_LCDREG(0x04)<br>#define S3C2410_LCDCON3&nbsp;&nbsp;&nbsp;&nbsp; S3C2410_LCDREG(0x08)<br>#define S3C2410_LCDCON4&nbsp;&nbsp;&nbsp;&nbsp; S3C2410_LCDREG(0x0C)<br>#define S3C2410_LCDCON5&nbsp;&nbsp;&nbsp;&nbsp; S3C2410_LCDREG(0x10)</p>
<p>/* LCD controller */<br>#define S3C2410_PA_LCD&nbsp;&nbsp;&nbsp; (0x4D000000)<br>#define S3C24XX_SZ_LCD&nbsp;&nbsp;&nbsp; SZ_1M<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>/**<br>* platform_device_register - add a platform-level device<br>* @pdev: platform device we're adding<br>*<br>*/<br>int <span style="COLOR: #0000ff">platform_device_register</span>(struct platform_device * pdev)<br>{<br>device_initialize(&amp;pdev-&gt;dev);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //初始化设备结构<br>return <span style="COLOR: #0000ff">platform_device_add</span>(pdev); //添加一个片上的设备到设备层<br>}<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>/**<br>&nbsp;*&nbsp;platform_device_add - add a platform device to device hierarchy<br>&nbsp;*&nbsp;@pdev:&nbsp;platform device we're adding<br>&nbsp;*<br>&nbsp;*&nbsp;This is part 2 of platform_device_register(), though may be called<br>&nbsp;*&nbsp;separately _iff_ pdev was allocated by platform_device_alloc().<br>&nbsp;*/<br>int <span style="COLOR: #0000ff">platform_device_add</span>(struct platform_device *pdev)<br>{<br>&nbsp;int i, ret = 0;<br>&nbsp;if (!pdev)<br>&nbsp;&nbsp;return -EINVAL;</p>
<p>&nbsp;if (!pdev-&gt;dev.parent)<br>&nbsp;&nbsp;pdev-&gt;dev.parent = &amp;platform_bus;<br>&nbsp;pdev-&gt;dev.bus = &amp;platform_bus_type;</p>
<p>&nbsp;if (pdev-&gt;id != -1)<br>&nbsp;&nbsp;snprintf(pdev-&gt;dev.bus_id, BUS_ID_SIZE, "%s.%u", pdev-&gt;name, pdev-&gt;id);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* <span style="COLOR: #0000ff">若支持同类多个设备，则用pdev-&gt;name和pdev-&gt;id在总线上标识该设备</span>&nbsp; */<br>&nbsp;else<br>&nbsp;&nbsp;strlcpy(pdev-&gt;dev.bus_id, pdev-&gt;name, BUS_ID_SIZE);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">否则，用pdev-&gt;name(即"s3c2410-lcd")在总线上标识该设备</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */</p>
<p>&nbsp;for (i = 0; i &lt; pdev-&gt;num_resources; i++) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 遍历资源数，并为各自在总线地址空间请求分配&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;struct resource *p, *r = &amp;pdev-&gt;resource[i];</p>
<p>&nbsp;&nbsp;if (r-&gt;name == NULL)<br>&nbsp;&nbsp;&nbsp;r-&gt;name = pdev-&gt;dev.bus_id;</p>
<p>&nbsp;&nbsp;p = r-&gt;parent;<br>&nbsp;&nbsp;if (!p) {<br>&nbsp;&nbsp;&nbsp;if (r-&gt;flags &amp; IORESOURCE_MEM)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff"> p = &amp;iomem_resource;</span>&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp;&nbsp;&nbsp; LCD寄存器地址作为IO内存资源分配&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; －－－－－－－－－－－－－－－－<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct resource iomem_resource = {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .name&nbsp;&nbsp; = "PCI mem",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .start&nbsp; = 0UL,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .end&nbsp;&nbsp;&nbsp; = ~0UL,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .flags&nbsp; = IORESOURCE_MEM,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; －－－－－－－－－－－－－－－－<br>&nbsp;&nbsp;&nbsp;else if (r-&gt;flags &amp; IORESOURCE_IO)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p = &amp;ioport_resource;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;if (p &amp;&amp; <span style="COLOR: #0000ff">insert_resource(p, r))</span> {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp;&nbsp; 将LCD寄存器地址插入到IO内存空间&nbsp; */<br>&nbsp;&nbsp;&nbsp;printk(KERN_ERR<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "%s: failed to claim resource %d\n",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pdev-&gt;dev.bus_id, i);<br>&nbsp;&nbsp;&nbsp;ret = -EBUSY;<br>&nbsp;&nbsp;&nbsp;goto failed;<br>&nbsp;&nbsp;}<br>&nbsp;}</p>
<p>&nbsp;pr_debug("Registering platform device '%s'. Parent at %s\n",<br>&nbsp;&nbsp; pdev-&gt;dev.bus_id, pdev-&gt;dev.parent-&gt;bus_id);</p>
<p>&nbsp;ret = device_add(&amp;pdev-&gt;dev);<br>&nbsp;if (ret == 0)<br>&nbsp;&nbsp;return ret;</p>
<p>&nbsp;failed:<br>&nbsp;while (--i &gt;= 0)<br>&nbsp;&nbsp;if (pdev-&gt;resource[i].flags &amp; (IORESOURCE_MEM|IORESOURCE_IO))<br>&nbsp;&nbsp;&nbsp;release_resource(&amp;pdev-&gt;resource[i]);<br>&nbsp;return ret;<br>}<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</p>
<p><br>static struct platform_driver <span style="COLOR: #0000ff">s3c2410fb_driver</span> = {<br>&nbsp;.probe&nbsp;&nbsp;= s3c2410fb_probe,<br>&nbsp;.remove&nbsp;&nbsp;= s3c2410fb_remove,<br>&nbsp;.suspend&nbsp;= s3c2410fb_suspend,<br>&nbsp;.resume&nbsp;&nbsp;= s3c2410fb_resume,<br>&nbsp;.driver&nbsp;&nbsp;= {<br>&nbsp;&nbsp;.name&nbsp;= "s3c2410-lcd",<br>&nbsp;&nbsp;.owner&nbsp;= THIS_MODULE,<br>&nbsp;},<br>};</p>
<p><span style="COLOR: #0000ff">platform_driver_register(&amp;s3c2410fb_driver)-----&gt; <br>driver_register(&amp;drv-&gt;driver)-----&gt; <br>bus_add_driver(drv)-----&gt; <br>driver_attach(drv)-----&gt; <br>bus_for_each_dev(drv-&gt;bus, NULL, drv, __driver_attach)-----&gt; <br>__driver_attach(struct device * dev, void * data)-----&gt; <br>driver_probe_device(drv, dev)-----&gt; <br>really_probe(dev, drv)-----&gt;</span> </p>
<p><span style="COLOR: #0000ff">在really_probe()中：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为设备指派管理该设备的驱动：dev-&gt;driver = drv<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 调用s3c2410fb_probe()初始化设备：drv-&gt;probe(dev)</span><br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>static int __init s3c2410fb_probe(struct platform_device *pdev)<br>{<br>&nbsp;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; res = platform_get_resource(pdev, IORESOURCE_MEM, 0);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 取得LCD控制寄存器的物理地址&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */</p>
<p>&nbsp;size = (res-&gt;end - res-&gt;start)+1;<br>&nbsp;<span style="COLOR: #0000ff">info-&gt;mem = request_mem_region(res-&gt;start, size, pdev-&gt;name);</span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 个人理解:设备注册时已经分配区域，驱动这里应该不是必须的*/</p>
<p>&nbsp;<span style="COLOR: #0000ff"><strong>info-&gt;io = ioremap(res-&gt;start, size);</strong></span><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 此时驱动便可以用指针info-&gt;io&nbsp; 读写LCD控制寄存器了&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eg： readl(info-&gt;io + S3C2410_LCDCON1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;<br>}</p>
<p>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>以下是AT91SAM9261EK的IOMEM：</p>
<p><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#114;&#111;&#111;&#116;&#64;&#101;&#98;&#100;&#57;&#50;&#54;&#49;">root@ebd9261</a>:~# cat /proc/iomem<br>00500000-005fffff : usb-ohci.0<br>&nbsp; 00500000-005fffff : ohci_hcd<br>00600000-00600fff : sidsa-lcdc.0&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">//支持同类多个设备，在驱动中未分配I/O内存区域<br></span>20000000-23ffffff : System RAM<br>&nbsp; 20022000-20225e47 : Kernel text<br>&nbsp; 20226000-2028da23 : Kernel data<br>30000000-30000003 : dm9000.0&nbsp;&nbsp;&nbsp; <br>&nbsp; 30000000-30000003 : dm9000&nbsp;&nbsp;&nbsp; <br>30000044-300000ff : dm9000.0<br>&nbsp; 30000044-300000ff : dm9000<br>fffa4000-fffa7fff : at91_udc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">//不支持同类多个设备，在驱动中也分配I/O内存区域</span><br>&nbsp; fffa4000-fffa7fff : at91_udc<br>fffb0000-fffb3fff : usart.1<br>fffb4000-fffb7fff : usart.2<br>fffc8000-fffcbfff : spi.0<br>fffff200-fffff3ff : usart.0</p>
<img src ="http://www.cnitblog.com/vsolo/aggbug/42786.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/vsolo/" target="_blank">vsolo</a> 2008-04-26 16:02 <a href="http://www.cnitblog.com/vsolo/archive/2008/04/26/42786.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>内核中断的注册与申请</title><link>http://www.cnitblog.com/vsolo/archive/2008/04/25/42733.html</link><dc:creator>vsolo</dc:creator><author>vsolo</author><pubDate>Fri, 25 Apr 2008 08:42:00 GMT</pubDate><guid>http://www.cnitblog.com/vsolo/archive/2008/04/25/42733.html</guid><wfw:comment>http://www.cnitblog.com/vsolo/comments/42733.html</wfw:comment><comments>http://www.cnitblog.com/vsolo/archive/2008/04/25/42733.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/vsolo/comments/commentRss/42733.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/vsolo/services/trackbacks/42733.html</trackback:ping><description><![CDATA[<p><span style="COLOR: #0000ff"><strong>(1)系统启动时注册中断：<br></strong></span>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>#define IRQ_BATT_FLT&#160;&#160; S3C2410_IRQ(7)<br>&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;<br>#define IRQ_LCD&#160;&#160;&#160;&#160;&#160;&#160;&#160; S3C2410_IRQ(16)&#160;&#160;&#160;&#160; /* 32 */<br>&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;<br>#define IRQ_ADCPARENT&#160; S3C2410_IRQ(31)</p>
<p>/* interrupts generated from the external interrupts sources */<br>#define IRQ_EINT4&#160;&#160;&#160;&#160;&#160; S3C2410_IRQ(32)&#160;&#160;&#160; /* 48 */<br>#define IRQ_EINT5&#160;&#160;&#160;&#160;&#160; S3C2410_IRQ(33)</p>
<p><br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>MACHINE_START(SMDK2410, "SMDK2410") <br>&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;<br>&#160;.init_irq&#160;= <span style="COLOR: #0000ff">smdk2410_init_irq</span>,&#160;&#160; //中断初始化函数<br>&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;<br>MACHINE_END<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>/*<br>&#160;* Set of macros to define architecture features.&#160; This is built into<br>&#160;* a table by the linker.<br>&#160;*/<br>#define MACHINE_START(_type,_name)&#160;&#160;&#160;\<br>static const struct machine_desc __mach_desc_##_type&#160;\<br>&#160;__attribute_used__&#160;&#160;&#160;&#160;&#160;\<br>&#160;__attribute__((__section__(".arch.info.init"))) = {&#160;\<br>&#160;.nr&#160;&#160;= MACH_TYPE_##_type,&#160;&#160;\<br>&#160;.name&#160;&#160;= _name,</p>
<p>#define MACHINE_END&#160;&#160;&#160;&#160;\<br>};</p>
<p>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</p>
<p><span style="COLOR: #0000ff"><strong>函数smdk2410_init_irq()的调用过程</strong></span>：<br><./linux/arch/arm/kernel/head.S>－－－－－－－－－－－－－－－－－－－－－<br>/*<br>&#160;* Lookup machine architecture in the linker-build list of architectures.<br>&#160;* Note that we can't use the absolute addresses for the __arch_info<br>&#160;* lists since we aren't running with the MMU on (and therefore, we are<br>&#160;* not in the correct address space).&#160; We have to calculate the offset.<br>&#160;*<br>&#160;*&#160; r1 = machine architecture number<br>&#160;* Returns:<br>&#160;*&#160; r3, r4, r6 corrupted<br>&#160;*&#160; r5 = mach_info pointer in physical address space<br>&#160;*/<br>&#160;.type&#160;__lookup_machine_type, %function<br><span style="COLOR: #0000ff">__lookup_machine_type</span>:<br>&#160;adr&#160;r3, 3b<br>&#160;ldmia&#160;r3, {r4, r5, r6}<br>&#160;sub&#160;r3, r3, r4&#160;&#160;&#160;@ get offset between virt&phys<br>&#160;add&#160;r5, r5, r3&#160;&#160;&#160;@ convert virt addresses to<br>&#160;add&#160;r6, r6, r3&#160;&#160;&#160;@ physical address space<br>1:&#160;ldr&#160;r3, [r5, #MACHINFO_TYPE]&#160;@ get machine type<br>&#160;teq&#160;r3, r1&#160;&#160;&#160;&#160;@ matches loader number?<br>&#160;beq&#160;2f&#160;&#160;&#160;&#160;@ found<br>&#160;add&#160;r5, r5, #SIZEOF_MACHINE_DESC&#160;@ next machine_desc<br>&#160;cmp&#160;r5, r6<br>&#160;blo&#160;1b<br>&#160;mov&#160;r5, #0&#160;&#160;&#160;&#160;@ unknown machine<br>2:&#160;mov&#160;pc, lr</p>
<p>/*<br>&#160;* This provides a C-API version of the above function.<br>&#160;*/<br><span style="COLOR: #0000ff">ENTRY(lookup_machine_type)<br></span>&#160;stmfd&#160;sp!, {r4 - r6, lr}<br>&#160;mov&#160;r1, r0<br>&#160;bl&#160;<span style="COLOR: #0000ff">__lookup_machine_type<br></span>&#160;mov&#160;r0, r5<br>&#160;ldmfd&#160;sp!, {r4 - r6, pc}<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</p>
<p><span style="COLOR: #0000ff">在start_kernel()中：<br><br>&#160;&#160;&#160;&#160;&#160;&#160;&#160; setup_arch(&command_line)：<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; mdesc = setup_machine(machine_arch_type);<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 此函数将调用head.S中的lookup_machine_type得到对应<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // machine_arch_type的machine_desc<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; init_arch_irq = mdesc->init_irq;&#160; //指向<strong style="COLOR: #ff0000">smdk2410_init_irq<br></strong><br>&#160;&#160;&#160;&#160;&#160;&#160;&#160; init_IRQ()：<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <strong>init_arch_irq();</strong> //执行smdk2410_init_irq()<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //完成中断初始化</span><br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>static void __init <span style="COLOR: #0000ff">smdk2410_init_irq</span>(void)<br>{<br>&#160;<span style="COLOR: #0000ff">s3c24xx_init_irq</span>();<br>}<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>void __init <span style="COLOR: #0000ff">s3c24xx_init_irq</span>(void)<br>{<br>&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;<br>&#160;/* register the main interrupts */</p>
<p>&#160;irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");</p>
<p>&#160;for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) {<br>&#160;&#160;/* set all the s3c2410 internal irqs */</p>
<p>&#160;&#160;switch (irqno) {<br>&#160;&#160;&#160;/* deal with the special IRQs (cascaded) */</p>
<p>&#160;&#160;case IRQ_UART0:<br>&#160;&#160;case IRQ_UART1:<br>&#160;&#160;case IRQ_UART2:<br>&#160;&#160;case IRQ_ADCPARENT:<br>&#160;&#160;&#160;set_irq_chip(irqno, &s3c_irq_level_chip);<br>&#160;&#160;&#160;set_irq_handler(irqno, do_level_IRQ);<br>&#160;&#160;&#160;break;</p>
<p>&#160;&#160;case IRQ_RESERVED6:<br>&#160;&#160;case IRQ_RESERVED24:<br>&#160;&#160;&#160;/* no IRQ here */<br>&#160;&#160;&#160;break;</p>
<p>&#160;&#160;default:/*&#160;&#160;&#160;&#160;&#160;&#160;&#160; 非级联中断的中断例程相同&#160;&#160;&#160;&#160;&#160;&#160;&#160; */<br>&#160;&#160;&#160;//irqdbf("registering irq %d (s3c irq)\n", irqno);<br>&#160;&#160;&#160;set_irq_chip(irqno, &s3c_irq_chip);<br>&#160;&#160;&#160;set_irq_handler(irqno, <span style="COLOR: #0000ff"><strong>do_edge_IRQ</strong></span>);<br>&#160;&#160;&#160;set_irq_flags(irqno, IRQF_VALID);<br>&#160;&#160;}<br>&#160;}</p>
<p>&#160;/* setup the cascade irq handlers */<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; /*&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 级联中断有各自的中断例程&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; */<br>&#160;set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);<br>&#160;set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);<br>&#160;set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);<br>&#160;set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);</p>
<p><br>&#160;/* external interrupts */</p>
<p>&#160;for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {<br>&#160;&#160;irqdbf("registering irq %d (ext int)\n", irqno);<br>&#160;&#160;set_irq_chip(irqno, &s3c_irq_eint0t4);<br>&#160;&#160;set_irq_handler(irqno, do_edge_IRQ);<br>&#160;&#160;set_irq_flags(irqno, IRQF_VALID);<br>&#160;}</p>
<p>&#160;for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {<br>&#160;&#160;irqdbf("registering irq %d (extended s3c irq)\n", irqno);<br>&#160;&#160;set_irq_chip(irqno, &s3c_irqext_chip);<br>&#160;&#160;set_irq_handler(irqno, do_edge_IRQ);<br>&#160;&#160;set_irq_flags(irqno, IRQF_VALID);<br>&#160;}<br>&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;</p>
<p>}<br><span style="COLOR: #0000ff">&#160;&#160;&#160;&#160;&#160;&#160;&#160; 其中中断例程do_edge_IRQ()&#160; ->&#160; __do_irq() 中ret = action->handler(irq, action->dev_id, regs)<br>完成驱动中的中断处理例程<strong>s3c2410fb_irq</strong>的调用。<br></span>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</p>
<p><span style="COLOR: #0000ff"><strong>(2)驱动申请中断：</strong></span><br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;ret = request_irq(irq, <span style="COLOR: #0000ff">s3c2410fb_irq</span>, IRQF_DISABLED, pdev->name, info);<br>其中irq即为IRQ_LCD；</p>
<p>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),<br>&#160;&#160; unsigned long irq_flags, const char * devname, void *dev_id)<br>{<br>&#160;unsigned long retval;<br>&#160;struct irqaction *action;</p>
<p>&#160;if (irq >= NR_IRQS || !irq_desc[irq].valid || !handler ||<br>&#160;&#160;&#160;&#160; (irq_flags & SA_SHIRQ && !dev_id))<br>&#160;&#160;return -EINVAL;<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; /*&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 检查中断号irq是否注册（有效）&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; */</p>
<p>&#160;action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);<br>&#160;if (!action)<br>&#160;&#160;return -ENOMEM;</p>
<p>&#160;action->handler = handler;<br>&#160;action->flags = irq_flags;<br>&#160;cpus_clear(action->mask);<br>&#160;action->name = devname;<br>&#160;action->next = NULL;<br>&#160;action->dev_id = dev_id;</p>
<p><span style="COLOR: #0000ff">&#160;retval = setup_irq(irq, action);<br>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; / * 关联中断处理例程到对应的中断描述结构体irqdesc */</span><br>&#160;if (retval)<br>&#160;&#160;kfree(action);<br>&#160;return retval;<br>}<br><./linux/include/asm-arm/mach/irq.h>－－－－－－－－－－－－－－－－－－－－－－－－<br>struct irqdesc {<br>&#160;irq_handler_t&#160;handle;<br>&#160;struct irqchip&#160;*chip;<br>&#160;struct irqaction *action;<br>&#160;struct list_head pend;<br>&#160;void&#160;&#160;*chipdata;<br>&#160;void&#160;&#160;*data;<br>&#160;unsigned int&#160;disable_depth;</p>
<p>&#160;unsigned int&#160;triggered: 1;&#160;&#160;/* IRQ has occurred&#160;&#160;&#160;&#160;&#160;&#160; */<br>&#160;unsigned int&#160;running&#160; : 1;&#160;&#160;/* IRQ is running&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; */<br>&#160;unsigned int&#160;pending&#160; : 1;&#160;&#160;/* IRQ is pending&#160;&#160;&#160;&#160;&#160;&#160; */<br>&#160;unsigned int&#160;probing&#160; : 1;&#160;&#160;/* IRQ in use for a probe&#160;&#160;&#160;&#160; */<br>&#160;unsigned int&#160;probe_ok : 1;&#160;&#160;/* IRQ can be used for probe&#160; */<br>&#160;unsigned int&#160;valid&#160;&#160;&#160; : 1;&#160;&#160;/* IRQ claimable&#160;&#160;&#160;&#160;&#160;&#160; */<br>&#160;unsigned int&#160;noautoenable : 1;&#160;/* don't automatically enable IRQ */<br>&#160;unsigned int&#160;unused&#160;&#160; :25;</p>
<p>&#160;struct proc_dir_entry *procdir;</p>
<p>#ifdef CONFIG_SMP<br>&#160;cpumask_t&#160;affinity;<br>&#160;unsigned int&#160;cpu;<br>#endif</p>
<p>&#160;/*<br>&#160; * IRQ lock detection<br>&#160; */<br>&#160;unsigned int&#160;lck_cnt;<br>&#160;unsigned int&#160;lck_pc;<br>&#160;unsigned int&#160;lck_jif;<br>};</p>
 <img src ="http://www.cnitblog.com/vsolo/aggbug/42733.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/vsolo/" target="_blank">vsolo</a> 2008-04-25 16:42 <a href="http://www.cnitblog.com/vsolo/archive/2008/04/25/42733.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>内核启动时,设备及驱动初始化的实现</title><link>http://www.cnitblog.com/vsolo/archive/2008/04/21/42592.html</link><dc:creator>vsolo</dc:creator><author>vsolo</author><pubDate>Mon, 21 Apr 2008 13:21:00 GMT</pubDate><guid>http://www.cnitblog.com/vsolo/archive/2008/04/21/42592.html</guid><wfw:comment>http://www.cnitblog.com/vsolo/comments/42592.html</wfw:comment><comments>http://www.cnitblog.com/vsolo/archive/2008/04/21/42592.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/vsolo/comments/commentRss/42592.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/vsolo/services/trackbacks/42592.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Uboot完成系统的引导并将Linux内核拷贝到内存之后，bootm -&gt; do_bootm_linux()跳转到kernel的起始位置；<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 压缩过的kernel入口在arch/arm/boot/compressed/head.S，它将调用函数decompress_kernel()&lt;./arch/arm/boot/compressed/misc.c&gt;解压,打印&#8220;Uncompressing Linux...&#8221;，调用gunzip()，打印"done, booting the kernel."<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 然后call_kernel,执行解压后的kernel,经linux/arch/arm/kernel/head.S调用start_kernel转入体系结构无关的通用C代码，在start_kernel()中完成了一系列系统初始化，设备及驱动的注册即在此时完成：<br><br>&lt;./init/main.c&gt;－－－－－－－－－－－－－－－－－－－－－－－－－</p>
<p>asmlinkage void __init <span style="COLOR: #0000ff"><strong>start_kernel</strong></span>(void)<br>{<br>&nbsp;char * command_line;<br>&nbsp;extern struct kernel_param __start___param[], __stop___param[];</p>
<p>&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;<br>&nbsp;printk(KERN_NOTICE "Kernel command line: %s\n", saved_command_line);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //打印内核命令行<br>&nbsp;parse_early_param();<br>&nbsp;parse_args("Booting kernel", command_line, __start___param,<br>&nbsp;&nbsp;&nbsp;&nbsp; __stop___param - __start___param,<br>&nbsp;&nbsp;&nbsp;&nbsp; &amp;unknown_bootoption);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //解析由BOOT传递的启动参数<br>&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;</p>
<p>&nbsp;/* Do the rest non-__init'ed, we're now alive */<br>&nbsp;<span style="COLOR: #0000ff">rest_init</span>();<br>}</p>
<p>start_kernel()中的函数rest_init()将创建第一个核心线程kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND)，调用init()函数：</p>
<p>static int <span style="COLOR: #0000ff"><strong>init</strong></span>(void * unused)－－－－－－－－－－－－－－－－－－－<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff">do_basic_setup</span>();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;</p>
<p>&nbsp;/*<br>&nbsp; * We try each of these until one succeeds.<br>&nbsp; *<br>&nbsp; * The Bourne shell can be used instead of init if we are <br>&nbsp; * trying to recover a really broken machine.<br>&nbsp; */<br>&nbsp;if (execute_command) { //判断在启动时是否指定了init参数<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//如果指定则执行用户init进程，成功将不会返回<br>&nbsp;&nbsp;run_init_process(execute_command);<br>&nbsp;&nbsp;printk(KERN_WARNING "Failed to execute %s.&nbsp; Attempting "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"defaults...\n", execute_command);<br>&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp;&nbsp; 如果没有指定init启动参数，则查找下面的目录init进程,成功将不会返回，否则打印出错信息&nbsp;&nbsp; */<br>&nbsp;run_init_process("/sbin/init");<br>&nbsp;run_init_process("/etc/init");<br>&nbsp;run_init_process("/bin/init");<br>&nbsp;run_init_process("/bin/sh");</p>
<p>&nbsp;panic("No init found.&nbsp; Try passing init= option to kernel.");</p>
<p>}</p>
<p>继而调用函数do_basic_setup()（此时与体系结构相关的部分已经初始化完了,现在开始初始化设备了）：</p>
<p>/*<br>&nbsp;* Ok, the machine is now initialized. None of the devices<br>&nbsp;* have been touched yet, but the CPU subsystem is up and<br>&nbsp;* running, and memory and process management works.<br>&nbsp;*<br>&nbsp;* Now we can finally start doing some real work..<br>&nbsp;*/<br>static void __init <span style="COLOR: #0000ff"><strong>do_basic_setup</strong></span>(void)－－－－－－－－－－－－－－－－－<br>{<br>&nbsp;/* drivers will send hotplug events */<br>&nbsp;init_workqueues();<br>&nbsp;usermodehelper_init();<br>&nbsp;<span style="COLOR: #0000ff">driver_init</span>();&nbsp;&nbsp;&nbsp;&nbsp; //建立设备模型子系统</p>
<p>#ifdef CONFIG_SYSCTL<br>&nbsp;sysctl_init();<br>#endif</p>
<p>&nbsp;/* Networking initialization needs a process context */ <br>&nbsp;sock_init();</p>
<p>&nbsp;<span style="COLOR: #0000ff">do_initcalls</span>();&nbsp;&nbsp; //系统初始化(包括设备，文件系统，内核模块等)<br>}<br>&lt;./drivers/base/init.c&gt;－－－－－－－－－－－－－－－－－－－－－－－－－<br>/**<br>&nbsp;*&nbsp;driver_init - initialize driver model.<br>&nbsp;*<br>&nbsp;*&nbsp;Call the driver model init functions to initialize their<br>&nbsp;*&nbsp;subsystems. Called early from init/main.c.<br>&nbsp;*/</p>
<p>void __init <span style="COLOR: #0000ff"><strong>driver_init</strong></span>(void)<br>{<br>&nbsp;/* These are the core pieces */<br>&nbsp;devices_init();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;./drivers/base/core.c&gt;－－－－－－－－－－－－－<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int __init devices_init(void)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return subsystem_register(&amp;devices_subsys);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; －－－－－－－－－－－－－－－－－－－－－－－<br>&nbsp;buses_init();<br>&nbsp;classes_init();<br>&nbsp;firmware_init();</p>
<p>&nbsp;/* These are also core pieces, but must come after the<br>&nbsp; * core core pieces.<br>&nbsp; */<br>&nbsp;platform_bus_init();<br>&nbsp;system_bus_init();<br>&nbsp;cpu_dev_init();<br>&nbsp;memory_dev_init();<br>&nbsp;attribute_container_init();<br>}<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－<br><span style="COLOR: #0000ff">extern initcall_t __initcall_start[], __initcall_end[];</span></p>
<p>static void __init <span style="COLOR: #0000ff"><strong>do_initcalls</strong></span>(void)<br>{<br>&nbsp;initcall_t *call;<br>&nbsp;int count = preempt_count();</p>
<p>&nbsp;for (call = __initcall_start; call &lt; __initcall_end; call++) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (*call)();&nbsp;&nbsp;&nbsp;&nbsp; //调用一系列初始化函数<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;<br>}<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __initcall_start和__initcall_end界定了存放初始化函数指针区域的起始地址，即从__initcall_start开始到__initcall_end结束的区域中存放了指向各个初始化函数的函数指针。&nbsp;由 (*call)()完成各个部分的初始化工作，且便于扩充。具体实现如下：<br>&lt;./arch/arm/kernel/vmlinux.lds.S&gt;－－－－－－－－－－－－－－－－－<br>&nbsp;&nbsp;__initcall_start = .;<br>&nbsp;&nbsp;&nbsp;*(.initcall1.init)<br>&nbsp;&nbsp;&nbsp;*(.initcall2.init)<br>&nbsp;&nbsp;&nbsp;*(.initcall3.init)<br>&nbsp;&nbsp;&nbsp;*(.initcall4.init)<br>&nbsp;&nbsp;&nbsp;*(.initcall5.init)<br>&nbsp;&nbsp;&nbsp;*(.initcall6.init)<br>&nbsp;&nbsp;&nbsp;*(.initcall7.init)<br>&nbsp;&nbsp;__initcall_end = .;</p>
<p>&nbsp;&lt;./include/linux/init.h&gt;－－－－－－－－－－－－－－－－－－－－－</p>
<p>#ifndef MODULE&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp;&nbsp;&nbsp; 如果驱动模块静态编译进内核&nbsp;&nbsp; */</p>
<p>&nbsp; &#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;</p>
<p>/* initcalls are now grouped by functionality into separate <br>&nbsp;* subsections. Ordering inside the subsections is determined<br>&nbsp;* by link order. <br>&nbsp;* For backwards compatibility, initcall() puts the call in <br>&nbsp;* the device init subsection.<br>&nbsp;*/</p>
<p>#define __define_initcall(level,fn) \<br>&nbsp;static initcall_t __initcall_##fn __attribute_used__ \<br>&nbsp;__attribute__((__section__(".initcall" level ".init"))) = fn</p>
<p>#define core_initcall(fn)&nbsp;&nbsp;__define_initcall("1",fn)<br>#define postcore_initcall(fn)&nbsp;&nbsp;__define_initcall("2",fn)<br>#define arch_initcall(fn)&nbsp;&nbsp;__define_initcall("3",fn)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: #0000ff"><strong> //此处初始化了设备<br></strong></span><span style="COLOR: #0000ff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*－－－－eg：arch_initcall(at91sam9261_device_init)－－－<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static int __init at91sam9261_device_init(void)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at91_add_device_udc();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;at91_add_device_dm9000();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; armebs3_add_input_buttons();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return platform_add_devices(at91sam9261_devices, ARRAY_SIZE(at91sam9261_devices));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; －－－－－－－－－－－－－－－－－－－－－－－－*/</span><br>#define subsys_initcall(fn)&nbsp;&nbsp;__define_initcall("4",fn)<br>#define fs_initcall(fn)&nbsp;&nbsp;__define_initcall("5",fn)<br>#define device_initcall(fn)&nbsp;&nbsp;__define_initcall("6",fn)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="COLOR: #0000ff"><strong>//此处初始化了静态编译的驱动模块</strong></span><br>#define late_initcall(fn)&nbsp;&nbsp;__define_initcall("7",fn)</p>
<p><span style="COLOR: #0000ff">#define __initcall(fn) device_initcall(fn)</span></p>
<p><br>&nbsp; /**<br>&nbsp;* module_init() - driver initialization entry point<br>&nbsp;* @x: function to be run at kernel boot time or module insertion<br>&nbsp;* <br>&nbsp;* module_init() will either be called during do_initcalls (if<br>&nbsp;* builtin) or at module insertion time (if a module).&nbsp; There can only<br>&nbsp;* be one per module.<br>&nbsp;*/<br><span style="COLOR: #0000ff">#define module_init(x)&nbsp;__initcall(x);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;//静态编译的驱动模块作为device_initcall在内核启动就被do_initcalls</span><br>/**<br>&nbsp;* module_exit() - driver exit entry point<br>&nbsp;* @x: function to be run when driver is removed<br>&nbsp;* <br>&nbsp;* module_exit() will wrap the driver clean-up code<br>&nbsp;* with cleanup_module() when used with rmmod when<br>&nbsp;* the driver is a module.&nbsp; If the driver is statically<br>&nbsp;* compiled into the kernel, module_exit() has no effect.<br>&nbsp;* There can only be one per module.<br>&nbsp;*/<br>#define module_exit(x)&nbsp;__exitcall(x);</p>
<p>#else /* MODULE&nbsp;&nbsp;&nbsp; 如果驱动模块动态加载入内核&nbsp;&nbsp; */</p>
<p>&nbsp; &#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;&#183;</p>
<p>/* Each module must use one module_init(), or one no_module_init */<br>#define module_init(initfn)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>&nbsp;static inline initcall_t __inittest(void)&nbsp;&nbsp;\<br>&nbsp;{ return initfn; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>&nbsp;int init_module(void) __attribute__((alias(#initfn)));<br>&nbsp;&nbsp;&nbsp;&nbsp; //insmod 是通过系统调用sys_init_module(const char *name_user, struct module *mod_user)<br>&nbsp;&nbsp;&nbsp;&nbsp; //将动态驱动模块载入到内核空间</p>
<p>/* This is only required if you want to be unloadable. */<br>#define module_exit(exitfn)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>&nbsp;static inline exitcall_t __exittest(void)&nbsp;&nbsp;\<br>&nbsp;{ return exitfn; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<br>&nbsp;void cleanup_module(void) __attribute__((alias(#exitfn)));</p>
<p>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</p>
<img src ="http://www.cnitblog.com/vsolo/aggbug/42592.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/vsolo/" target="_blank">vsolo</a> 2008-04-21 21:21 <a href="http://www.cnitblog.com/vsolo/archive/2008/04/21/42592.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>