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 4. 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> </td><th width="60%" align="center">Chapter 4. PCI Resource Management</th><td width="20%" align="right"> <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 < 0) { 38 kfree(chip); 39 pci_disable_device(pci); 40 return err; 41 } 42 chip->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->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->irq, snd_mychip_interrupt, 59 IRQF_SHARED, KBUILD_MODNAME, chip)) { 60 printk(KERN_ERR "cannot grab irq %d\n", pci->irq); 61 snd_mychip_free(chip); 62 return -EBUSY; 63 } 64 chip->irq = pci->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->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">“<span class="quote">check-and-release</span>”</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->irq >= 0) 108 free_irq(chip->irq, chip); 109 110 </pre></div><p> 111 112 Since the irq number can start from 0, you should initialize 113 chip->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->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->res_port, the release procedure looks like: 134 135 </p><div class="informalexample"><pre class="programlisting"> 136 137 release_and_free_resource(chip->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")) < 0) { 185 kfree(chip); 186 return err; 187 } 188 chip->iobase_phys = pci_resource_start(pci, 0); 189 chip->iobase_virt = ioremap_nocache(chip->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->iobase_virt) 202 iounmap(chip->iobase_virt); 203 .... 204 pci_release_regions(chip->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> </td><td width="20%" align="center"><a accesskey="u" href="pci-resource.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="pci-resource-entries.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Some Hafta's </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> PCI Entries</td></tr></table></div></body></html> 210