Based on kernel version 2.6.24. Page generated on 2008-01-28 12:56 EST.
<span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#1" name="1">1</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#2" name="2">2</a> </span>Device Drivers<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#3" name="3">3</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#4" name="4">4</a> </span>struct device_driver {<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#5" name="5">5</a> </span> char * name;<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#6" name="6">6</a> </span> struct bus_type * bus;<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#7" name="7">7</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#8" name="8">8</a> </span> struct completion unloaded;<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#9" name="9">9</a> </span> struct kobject kobj;<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#10" name="10">10</a> </span> list_t devices;<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#11" name="11">11</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#12" name="12">12</a> </span> struct module *owner;<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#13" name="13">13</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#14" name="14">14</a> </span> int (*probe) (struct device * dev);<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#15" name="15">15</a> </span> int (*remove) (struct device * dev);<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#16" name="16">16</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#17" name="17">17</a> </span> int (*suspend) (struct device * dev, pm_message_t state);<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#18" name="18">18</a> </span> int (*resume) (struct device * dev);<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#19" name="19">19</a> </span>};<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#20" name="20">20</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#21" name="21">21</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#22" name="22">22</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#23" name="23">23</a> </span>Allocation<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#24" name="24">24</a> </span>~~~~~~~~~~<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#25" name="25">25</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#26" name="26">26</a> </span>Device drivers are statically allocated structures. Though there may<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#27" name="27">27</a> </span>be multiple devices in a system that a driver supports, struct<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#28" name="28">28</a> </span>device_driver represents the driver as a whole (not a particular<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#29" name="29">29</a> </span>device instance).<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#30" name="30">30</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#31" name="31">31</a> </span>Initialization<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#32" name="32">32</a> </span>~~~~~~~~~~~~~~<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#33" name="33">33</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#34" name="34">34</a> </span>The driver must initialize at least the name and bus fields. It should<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#35" name="35">35</a> </span>also initialize the devclass field (when it arrives), so it may obtain<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#36" name="36">36</a> </span>the proper linkage internally. It should also initialize as many of<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#37" name="37">37</a> </span>the callbacks as possible, though each is optional.<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#38" name="38">38</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#39" name="39">39</a> </span>Declaration<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#40" name="40">40</a> </span>~~~~~~~~~~~<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#41" name="41">41</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#42" name="42">42</a> </span>As stated above, struct device_driver objects are statically<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#43" name="43">43</a> </span>allocated. Below is an example declaration of the eepro100<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#44" name="44">44</a> </span>driver. This declaration is hypothetical only; it relies on the driver<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#45" name="45">45</a> </span>being converted completely to the new model. <br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#46" name="46">46</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#47" name="47">47</a> </span>static struct device_driver eepro100_driver = {<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#48" name="48">48</a> </span> .name = "eepro100",<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#49" name="49">49</a> </span> .bus = &pci_bus_type,<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#50" name="50">50</a> </span> <br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#51" name="51">51</a> </span> .probe = eepro100_probe,<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#52" name="52">52</a> </span> .remove = eepro100_remove,<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#53" name="53">53</a> </span> .suspend = eepro100_suspend,<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#54" name="54">54</a> </span> .resume = eepro100_resume,<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#55" name="55">55</a> </span>};<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#56" name="56">56</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#57" name="57">57</a> </span>Most drivers will not be able to be converted completely to the new<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#58" name="58">58</a> </span>model because the bus they belong to has a bus-specific structure with<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#59" name="59">59</a> </span>bus-specific fields that cannot be generalized. <br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#60" name="60">60</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#61" name="61">61</a> </span>The most common example of this are device ID structures. A driver<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#62" name="62">62</a> </span>typically defines an array of device IDs that it supports. The format<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#63" name="63">63</a> </span>of these structures and the semantics for comparing device IDs are<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#64" name="64">64</a> </span>completely bus-specific. Defining them as bus-specific entities would<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#65" name="65">65</a> </span>sacrifice type-safety, so we keep bus-specific structures around. <br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#66" name="66">66</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#67" name="67">67</a> </span>Bus-specific drivers should include a generic struct device_driver in<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#68" name="68">68</a> </span>the definition of the bus-specific driver. Like this:<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#69" name="69">69</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#70" name="70">70</a> </span>struct pci_driver {<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#71" name="71">71</a> </span> const struct pci_device_id *id_table;<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#72" name="72">72</a> </span> struct device_driver driver;<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#73" name="73">73</a> </span>};<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#74" name="74">74</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#75" name="75">75</a> </span>A definition that included bus-specific fields would look like<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#76" name="76">76</a> </span>(using the eepro100 driver again):<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#77" name="77">77</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#78" name="78">78</a> </span>static struct pci_driver eepro100_driver = {<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#79" name="79">79</a> </span> .id_table = eepro100_pci_tbl,<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#80" name="80">80</a> </span> .driver = {<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#81" name="81">81</a> </span> .name = "eepro100",<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#82" name="82">82</a> </span> .bus = &pci_bus_type,<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#83" name="83">83</a> </span> .probe = eepro100_probe,<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#84" name="84">84</a> </span> .remove = eepro100_remove,<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#85" name="85">85</a> </span> .suspend = eepro100_suspend,<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#86" name="86">86</a> </span> .resume = eepro100_resume,<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#87" name="87">87</a> </span> },<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#88" name="88">88</a> </span>};<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#89" name="89">89</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#90" name="90">90</a> </span>Some may find the syntax of embedded struct initialization awkward or<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#91" name="91">91</a> </span>even a bit ugly. So far, it's the best way we've found to do what we want...<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#92" name="92">92</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#93" name="93">93</a> </span>Registration<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#94" name="94">94</a> </span>~~~~~~~~~~~~<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#95" name="95">95</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#96" name="96">96</a> </span>int driver_register(struct device_driver * drv);<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#97" name="97">97</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#98" name="98">98</a> </span>The driver registers the structure on startup. For drivers that have<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#99" name="99">99</a> </span>no bus-specific fields (i.e. don't have a bus-specific driver<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#100" name="100">100</a> </span>structure), they would use driver_register and pass a pointer to their<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#101" name="101">101</a> </span>struct device_driver object. <br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#102" name="102">102</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#103" name="103">103</a> </span>Most drivers, however, will have a bus-specific structure and will<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#104" name="104">104</a> </span>need to register with the bus using something like pci_driver_register.<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#105" name="105">105</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#106" name="106">106</a> </span>It is important that drivers register their driver structure as early as<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#107" name="107">107</a> </span>possible. Registration with the core initializes several fields in the<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#108" name="108">108</a> </span>struct device_driver object, including the reference count and the<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#109" name="109">109</a> </span>lock. These fields are assumed to be valid at all times and may be<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#110" name="110">110</a> </span>used by the device model core or the bus driver.<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#111" name="111">111</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#112" name="112">112</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#113" name="113">113</a> </span>Transition Bus Drivers<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#114" name="114">114</a> </span>~~~~~~~~~~~~~~~~~~~~~~<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#115" name="115">115</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#116" name="116">116</a> </span>By defining wrapper functions, the transition to the new model can be<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#117" name="117">117</a> </span>made easier. Drivers can ignore the generic structure altogether and<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#118" name="118">118</a> </span>let the bus wrapper fill in the fields. For the callbacks, the bus can<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#119" name="119">119</a> </span>define generic callbacks that forward the call to the bus-specific<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#120" name="120">120</a> </span>callbacks of the drivers. <br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#121" name="121">121</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#122" name="122">122</a> </span>This solution is intended to be only temporary. In order to get class<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#123" name="123">123</a> </span>information in the driver, the drivers must be modified anyway. Since<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#124" name="124">124</a> </span>converting drivers to the new model should reduce some infrastructural<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#125" name="125">125</a> </span>complexity and code size, it is recommended that they are converted as<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#126" name="126">126</a> </span>class information is added.<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#127" name="127">127</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#128" name="128">128</a> </span>Access<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#129" name="129">129</a> </span>~~~~~~<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#130" name="130">130</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#131" name="131">131</a> </span>Once the object has been registered, it may access the common fields of<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#132" name="132">132</a> </span>the object, like the lock and the list of devices. <br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#133" name="133">133</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#134" name="134">134</a> </span>int driver_for_each_dev(struct device_driver * drv, void * data, <br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#135" name="135">135</a> </span> int (*callback)(struct device * dev, void * data));<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#136" name="136">136</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#137" name="137">137</a> </span>The devices field is a list of all the devices that have been bound to<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#138" name="138">138</a> </span>the driver. The LDM core provides a helper function to operate on all<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#139" name="139">139</a> </span>the devices a driver controls. This helper locks the driver on each<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#140" name="140">140</a> </span>node access, and does proper reference counting on each device as it<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#141" name="141">141</a> </span>accesses it. <br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#142" name="142">142</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#143" name="143">143</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#144" name="144">144</a> </span>sysfs<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#145" name="145">145</a> </span>~~~~~<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#146" name="146">146</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#147" name="147">147</a> </span>When a driver is registered, a sysfs directory is created in its<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#148" name="148">148</a> </span>bus's directory. In this directory, the driver can export an interface<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#149" name="149">149</a> </span>to userspace to control operation of the driver on a global basis;<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#150" name="150">150</a> </span>e.g. toggling debugging output in the driver.<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#151" name="151">151</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#152" name="152">152</a> </span>A future feature of this directory will be a 'devices' directory. This<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#153" name="153">153</a> </span>directory will contain symlinks to the directories of devices it<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#154" name="154">154</a> </span>supports.<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#155" name="155">155</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#156" name="156">156</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#157" name="157">157</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#158" name="158">158</a> </span>Callbacks<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#159" name="159">159</a> </span>~~~~~~~~~<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#160" name="160">160</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#161" name="161">161</a> </span> int (*probe) (struct device * dev);<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#162" name="162">162</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#163" name="163">163</a> </span>The probe() entry is called in task context, with the bus's rwsem locked<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#164" name="164">164</a> </span>and the driver partially bound to the device. Drivers commonly use<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#165" name="165">165</a> </span>container_of() to convert "dev" to a bus-specific type, both in probe()<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#166" name="166">166</a> </span>and other routines. That type often provides device resource data, such<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#167" name="167">167</a> </span>as pci_dev.resource[] or platform_device.resources, which is used in<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#168" name="168">168</a> </span>addition to dev->platform_data to initialize the driver.<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#169" name="169">169</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#170" name="170">170</a> </span>This callback holds the driver-specific logic to bind the driver to a<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#171" name="171">171</a> </span>given device. That includes verifying that the device is present, that<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#172" name="172">172</a> </span>it's a version the driver can handle, that driver data structures can<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#173" name="173">173</a> </span>be allocated and initialized, and that any hardware can be initialized.<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#174" name="174">174</a> </span>Drivers often store a pointer to their state with dev_set_drvdata().<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#175" name="175">175</a> </span>When the driver has successfully bound itself to that device, then probe()<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#176" name="176">176</a> </span>returns zero and the driver model code will finish its part of binding<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#177" name="177">177</a> </span>the driver to that device.<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#178" name="178">178</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#179" name="179">179</a> </span>A driver's probe() may return a negative errno value to indicate that<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#180" name="180">180</a> </span>the driver did not bind to this device, in which case it should have<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#181" name="181">181</a> </span>released all resources it allocated.<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#182" name="182">182</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#183" name="183">183</a> </span> int (*remove) (struct device * dev);<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#184" name="184">184</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#185" name="185">185</a> </span>remove is called to unbind a driver from a device. This may be<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#186" name="186">186</a> </span>called if a device is physically removed from the system, if the<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#187" name="187">187</a> </span>driver module is being unloaded, during a reboot sequence, or<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#188" name="188">188</a> </span>in other cases.<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#189" name="189">189</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#190" name="190">190</a> </span>It is up to the driver to determine if the device is present or<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#191" name="191">191</a> </span>not. It should free any resources allocated specifically for the<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#192" name="192">192</a> </span>device; i.e. anything in the device's driver_data field. <br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#193" name="193">193</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#194" name="194">194</a> </span>If the device is still present, it should quiesce the device and place<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#195" name="195">195</a> </span>it into a supported low-power state.<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#196" name="196">196</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#197" name="197">197</a> </span> int (*suspend) (struct device * dev, pm_message_t state);<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#198" name="198">198</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#199" name="199">199</a> </span>suspend is called to put the device in a low power state.<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#200" name="200">200</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#201" name="201">201</a> </span> int (*resume) (struct device * dev);<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#202" name="202">202</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#203" name="203">203</a> </span>Resume is used to bring a device back from a low power state.<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#204" name="204">204</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#205" name="205">205</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#206" name="206">206</a> </span>Attributes<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#207" name="207">207</a> </span>~~~~~~~~~~<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#208" name="208">208</a> </span>struct driver_attribute {<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#209" name="209">209</a> </span> struct attribute attr;<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#210" name="210">210</a> </span> ssize_t (*show)(struct device_driver *, char * buf, size_t count, loff_t off);<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#211" name="211">211</a> </span> ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off);<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#212" name="212">212</a> </span>};<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#213" name="213">213</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#214" name="214">214</a> </span>Device drivers can export attributes via their sysfs directories. <br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#215" name="215">215</a> </span>Drivers can declare attributes using a DRIVER_ATTR macro that works<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#216" name="216">216</a> </span>identically to the DEVICE_ATTR macro. <br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#217" name="217">217</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#218" name="218">218</a> </span>Example:<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#219" name="219">219</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#220" name="220">220</a> </span>DRIVER_ATTR(debug,0644,show_debug,store_debug);<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#221" name="221">221</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#222" name="222">222</a> </span>This is equivalent to declaring:<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#223" name="223">223</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#224" name="224">224</a> </span>struct driver_attribute driver_attr_debug;<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#225" name="225">225</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#226" name="226">226</a> </span>This can then be used to add and remove the attribute from the<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#227" name="227">227</a> </span>driver's directory using:<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#228" name="228">228</a> </span><br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#229" name="229">229</a> </span>int driver_create_file(struct device_driver *, struct driver_attribute *);<br /><span class="l"><a href="http://www.mjmwired.net/kernel/Documentation/driver-model/driver.txt#230" name="230">230</a> </span>void driver_remove_file(struct device_driver *, struct driver_attribute *);
转载请注明:在路上 » Linux Driver Model