1<html><head><meta http-equiv="Content-Type" content="text/html; charset=ANSI_X3.4-1968"><title>Resource Allocation</title><meta name="generator" content="DocBook XSL Stylesheets V1.78.1"><link rel="home" href="index.html" title="Writing an ALSA Driver"><link rel="up" href="pci-resource.html" title="Chapter&#160;4.&#160;PCI Resource Management"><link rel="prev" href="pci-resource-some-haftas.html" title="Some Hafta's"><link rel="next" href="pci-resource-entries.html" title="PCI Entries"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Resource Allocation</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="pci-resource-some-haftas.html">Prev</a>&#160;</td><th width="60%" align="center">Chapter&#160;4.&#160;PCI Resource Management</th><td width="20%" align="right">&#160;<a accesskey="n" href="pci-resource-entries.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="pci-resource-resource-allocation"></a>Resource Allocation</h2></div></div></div><p>
2        The allocation of I/O ports and irqs is done via standard kernel
3      functions. Unlike ALSA ver.0.5.x., there are no helpers for
4      that. And these resources must be released in the destructor
5      function (see below). Also, on ALSA 0.9.x, you don't need to
6      allocate (pseudo-)DMA for PCI like in ALSA 0.5.x.
7      </p><p>
8        Now assume that the PCI device has an I/O port with 8 bytes
9        and an interrupt. Then struct <span class="structname">mychip</span> will have the
10        following fields:
11
12        </p><div class="informalexample"><pre class="programlisting">
13
14  struct mychip {
15          struct snd_card *card;
16
17          unsigned long port;
18          int irq;
19  };
20
21          </pre></div><p>
22      </p><p>
23        For an I/O port (and also a memory region), you need to have
24      the resource pointer for the standard resource management. For
25      an irq, you have to keep only the irq number (integer). But you
26      need to initialize this number as -1 before actual allocation,
27      since irq 0 is valid. The port address and its resource pointer
28      can be initialized as null by
29      <code class="function">kzalloc()</code> automatically, so you
30      don't have to take care of resetting them. 
31      </p><p>
32        The allocation of an I/O port is done like this:
33
34        </p><div class="informalexample"><pre class="programlisting">
35
36  err = pci_request_regions(pci, "My Chip");
37  if (err &lt; 0) { 
38          kfree(chip);
39          pci_disable_device(pci);
40          return err;
41  }
42  chip-&gt;port = pci_resource_start(pci, 0);
43
44          </pre></div><p>
45      </p><p>
46        
47        It will reserve the I/O port region of 8 bytes of the given
48      PCI device. The returned value, chip-&gt;res_port, is allocated
49      via <code class="function">kmalloc()</code> by
50      <code class="function">request_region()</code>. The pointer must be
51      released via <code class="function">kfree()</code>, but there is a
52      problem with this. This issue will be explained later.
53      </p><p>
54        The allocation of an interrupt source is done like this:
55
56        </p><div class="informalexample"><pre class="programlisting">
57
58  if (request_irq(pci-&gt;irq, snd_mychip_interrupt,
59                  IRQF_SHARED, KBUILD_MODNAME, chip)) {
60          printk(KERN_ERR "cannot grab irq %d\n", pci-&gt;irq);
61          snd_mychip_free(chip);
62          return -EBUSY;
63  }
64  chip-&gt;irq = pci-&gt;irq;
65
66          </pre></div><p>
67
68        where <code class="function">snd_mychip_interrupt()</code> is the
69      interrupt handler defined <a class="link" href="pcm-interface-interrupt-handler.html" title="Interrupt Handler"><em class="citetitle">later</em></a>.
70      Note that chip-&gt;irq should be defined
71      only when <code class="function">request_irq()</code> succeeded.
72      </p><p>
73      On the PCI bus, interrupts can be shared. Thus,
74      <code class="constant">IRQF_SHARED</code> is used as the interrupt flag of
75      <code class="function">request_irq()</code>. 
76      </p><p>
77        The last argument of <code class="function">request_irq()</code> is the
78      data pointer passed to the interrupt handler. Usually, the
79      chip-specific record is used for that, but you can use what you
80      like, too. 
81      </p><p>
82        I won't give details about the interrupt handler at this
83        point, but at least its appearance can be explained now. The
84        interrupt handler looks usually like the following: 
85
86        </p><div class="informalexample"><pre class="programlisting">
87
88  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
89  {
90          struct mychip *chip = dev_id;
91          ....
92          return IRQ_HANDLED;
93  }
94
95          </pre></div><p>
96      </p><p>
97        Now let's write the corresponding destructor for the resources
98      above. The role of destructor is simple: disable the hardware
99      (if already activated) and release the resources. So far, we
100      have no hardware part, so the disabling code is not written here. 
101      </p><p>
102        To release the resources, the <span class="quote">&#8220;<span class="quote">check-and-release</span>&#8221;</span>
103        method is a safer way. For the interrupt, do like this: 
104
105        </p><div class="informalexample"><pre class="programlisting">
106
107  if (chip-&gt;irq &gt;= 0)
108          free_irq(chip-&gt;irq, chip);
109
110          </pre></div><p>
111
112        Since the irq number can start from 0, you should initialize
113        chip-&gt;irq with a negative value (e.g. -1), so that you can
114        check the validity of the irq number as above.
115      </p><p>
116        When you requested I/O ports or memory regions via
117	<code class="function">pci_request_region()</code> or
118	<code class="function">pci_request_regions()</code> like in this example,
119	release the resource(s) using the corresponding function,
120	<code class="function">pci_release_region()</code> or
121	<code class="function">pci_release_regions()</code>.
122
123        </p><div class="informalexample"><pre class="programlisting">
124
125  pci_release_regions(chip-&gt;pci);
126
127          </pre></div><p>
128      </p><p>
129	When you requested manually via <code class="function">request_region()</code>
130	or <code class="function">request_mem_region</code>, you can release it via
131	<code class="function">release_resource()</code>.  Suppose that you keep
132	the resource pointer returned from <code class="function">request_region()</code>
133	in chip-&gt;res_port, the release procedure looks like:
134
135        </p><div class="informalexample"><pre class="programlisting">
136
137  release_and_free_resource(chip-&gt;res_port);
138
139          </pre></div><p>
140      </p><p>
141      Don't forget to call <code class="function">pci_disable_device()</code>
142      before the end.
143      </p><p>
144        And finally, release the chip-specific record.
145
146        </p><div class="informalexample"><pre class="programlisting">
147
148  kfree(chip);
149
150          </pre></div><p>
151      </p><p>
152      We didn't implement the hardware disabling part in the above.
153      If you need to do this, please note that the destructor may be
154      called even before the initialization of the chip is completed.
155      It would be better to have a flag to skip hardware disabling
156      if the hardware was not initialized yet.
157      </p><p>
158      When the chip-data is assigned to the card using
159      <code class="function">snd_device_new()</code> with
160      <code class="constant">SNDRV_DEV_LOWLELVEL</code> , its destructor is 
161      called at the last.  That is, it is assured that all other
162      components like PCMs and controls have already been released.
163      You don't have to stop PCMs, etc. explicitly, but just
164      call low-level hardware stopping.
165      </p><p>
166        The management of a memory-mapped region is almost as same as
167        the management of an I/O port. You'll need three fields like
168        the following: 
169
170        </p><div class="informalexample"><pre class="programlisting">
171
172  struct mychip {
173          ....
174          unsigned long iobase_phys;
175          void __iomem *iobase_virt;
176  };
177
178          </pre></div><p>
179
180        and the allocation would be like below:
181
182        </p><div class="informalexample"><pre class="programlisting">
183
184  if ((err = pci_request_regions(pci, "My Chip")) &lt; 0) {
185          kfree(chip);
186          return err;
187  }
188  chip-&gt;iobase_phys = pci_resource_start(pci, 0);
189  chip-&gt;iobase_virt = ioremap_nocache(chip-&gt;iobase_phys,
190                                      pci_resource_len(pci, 0));
191
192          </pre></div><p>
193        
194        and the corresponding destructor would be:
195
196        </p><div class="informalexample"><pre class="programlisting">
197
198  static int snd_mychip_free(struct mychip *chip)
199  {
200          ....
201          if (chip-&gt;iobase_virt)
202                  iounmap(chip-&gt;iobase_virt);
203          ....
204          pci_release_regions(chip-&gt;pci);
205          ....
206  }
207
208          </pre></div><p>
209      </p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="pci-resource-some-haftas.html">Prev</a>&#160;</td><td width="20%" align="center"><a accesskey="u" href="pci-resource.html">Up</a></td><td width="40%" align="right">&#160;<a accesskey="n" href="pci-resource-entries.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Some Hafta's&#160;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&#160;PCI Entries</td></tr></table></div></body></html>
210