1 /*
2 * PCI sound skeleton example
3 *
4 * (c) 1998 Red Hat Software
5 *
6 * This software may be used and distributed according to the
7 * terms of the GNU General Public License, incorporated herein by
8 * reference.
9 *
10 * This example is designed to be built in the linux/drivers/sound
11 * directory as part of a kernel build. The example is modular only
12 * drop me a note once you have a working modular driver and want
13 * to integrate it with the main code.
14 * -- Alan <alan@redhat.com>
15 *
16 * This is a first draft. Please report any errors, corrections or
17 * improvements to me.
18 */
19
20 #include <linux/module.h>
21 #include <linux/delay.h>
22 #include <linux/errno.h>
23 #include <linux/fs.h>
24 #include <linux/kernel.h>
25 #include <linux/pci.h>
26
27 #include <asm/io.h>
28
29 #include "sound_config.h"
30
31 /*
32 * Define our PCI vendor ID here
33 */
34
35 #ifndef PCI_VENDOR_MYIDENT
36 #define PCI_VENDOR_MYIDENT 0x125D
37
38 /*
39 * PCI identity for the card.
40 */
41
42 #define PCI_DEVICE_ID_MYIDENT_MYCARD1 0x1969
43 #endif
44
45 #define CARD_NAME "ExampleWave 3D Pro Ultra ThingyWotsit"
46
47 #define MAX_CARDS 8
48
49 /*
50 * Each address_info object holds the information about one of
51 * our card resources. In this case the MSS emulation of our
52 * ficticious card. Its used to manage and attach things.
53 */
54
55 static struct address_info mss_data[MAX_CARDS];
56 static int cards = 0;
57
58 /*
59 * Install the actual card. This is an example
60 */
61
mycard_install(struct pci_dev * pcidev)62 static int mycard_install(struct pci_dev *pcidev)
63 {
64 int iobase;
65 int mssbase;
66 int mpubase;
67 u8 x;
68 u16 w;
69 u32 v;
70 int i;
71 int dma;
72
73 /*
74 * Our imaginary code has its I/O on PCI address 0, a
75 * MSS on PCI address 1 and an MPU on address 2
76 *
77 * For the example we will only initialise the MSS
78 */
79
80 iobase = pci_resource_start(pcidev, 0);
81 mssbase = pci_resource_start(pcidev, 1);
82 mpubase = pci_resource_start(pcidev, 2);
83
84 /*
85 * Reset the board
86 */
87
88 /*
89 * Wait for completion. udelay() waits in microseconds
90 */
91
92 udelay(100);
93
94 /*
95 * Ok card ready. Begin setup proper. You might for example
96 * load the firmware here
97 */
98
99 dma = card_specific_magic(ioaddr);
100
101 /*
102 * Turn on legacy mode (example), There are also byte and
103 * dword (32bit) PCI configuration function calls
104 */
105
106 pci_read_config_word(pcidev, 0x40, &w);
107 w&=~(1<<15); /* legacy decode on */
108 w|=(1<<14); /* Reserved write as 1 in this case */
109 w|=(1<<3)|(1<<1)|(1<<0); /* SB on , FM on, MPU on */
110 pci_write_config_word(pcidev, 0x40, w);
111
112 /*
113 * Let the user know we found his toy.
114 */
115
116 printk(KERN_INFO "Programmed "CARD_NAME" at 0x%X to legacy mode.\n",
117 iobase);
118
119 /*
120 * Now set it up the description of the card
121 */
122
123 mss_data[cards].io_base = mssbase;
124 mss_data[cards].irq = pcidev->irq;
125 mss_data[cards].dma = dma;
126
127 /*
128 * Check there is an MSS present
129 */
130
131 if(ad1848_detect(mssbase, NULL, mss_data[cards].osp)==0)
132 return 0;
133
134 /*
135 * Initialize it
136 */
137
138 mss_data[cards].slots[3] = ad1848_init("MyCard MSS 16bit",
139 mssbase,
140 mss_data[cards].irq,
141 mss_data[cards].dma,
142 mss_data[cards].dma,
143 0,
144 0,
145 THIS_MODULE);
146
147 cards++;
148 return 1;
149 }
150
151
152 /*
153 * This loop walks the PCI configuration database and finds where
154 * the sound cards are.
155 */
156
init_mycard(void)157 int init_mycard(void)
158 {
159 struct pci_dev *pcidev=NULL;
160 int count=0;
161
162 if(!pci_present())
163 return -ENODEV;
164
165
166 while((pcidev = pci_find_device(PCI_VENDOR_MYIDENT, PCI_DEVICE_ID_MYIDENT_MYCARD1, pcidev))!=NULL)
167 {
168 if (pci_enable_device(pcidev))
169 continue;
170 count+=mycard_install(pcidev);
171 if(count)
172 return 0;
173 if(count==MAX_CARDS)
174 break;
175 }
176
177 if(count==0)
178 return -ENODEV;
179 return 0;
180 }
181
182 /*
183 * This function is called when the user or kernel loads the
184 * module into memory.
185 */
186
187
init_module(void)188 int init_module(void)
189 {
190 if(init_mycard()<0)
191 {
192 printk(KERN_ERR "No "CARD_NAME" cards found.\n");
193 return -ENODEV;
194 }
195
196 return 0;
197 }
198
199 /*
200 * This is called when it is removed. It will only be removed
201 * when its use count is 0.
202 */
203
cleanup_module(void)204 void cleanup_module(void)
205 {
206 for(i=0;i< cards; i++)
207 {
208 /*
209 * Free attached resources
210 */
211
212 ad1848_unload(mss_data[i].io_base,
213 mss_data[i].irq,
214 mss_data[i].dma,
215 mss_data[i].dma,
216 0);
217 /*
218 * And disconnect the device from the kernel
219 */
220 sound_unload_audiodevice(mss_data[i].slots[3]);
221 }
222 }
223
224