8fea783dd0cba505a8b85969f56727f25bffa941
[pandora-kernel.git] / sound / oss / skeleton.c
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;
57
58 /*
59  *      Install the actual card. This is an example
60  */
61
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  
157 int init_mycard(void)
158 {
159         struct pci_dev *pcidev=NULL;
160         int count=0;
161                 
162         while((pcidev = pci_find_device(PCI_VENDOR_MYIDENT, PCI_DEVICE_ID_MYIDENT_MYCARD1, pcidev))!=NULL)
163         {
164                 if (pci_enable_device(pcidev))
165                         continue;
166                 count+=mycard_install(pcidev);
167                 if(count)
168                         return 0;
169                 if(count==MAX_CARDS)
170                         break;
171         }
172         
173         if(count==0)
174                 return -ENODEV;
175         return 0;
176 }
177
178 /*
179  *      This function is called when the user or kernel loads the 
180  *      module into memory.
181  */
182
183
184 int init_module(void)
185 {
186         if(init_mycard()<0)
187         {
188                 printk(KERN_ERR "No "CARD_NAME" cards found.\n");
189                 return -ENODEV;
190         }
191
192         return 0;
193 }
194
195 /*
196  *      This is called when it is removed. It will only be removed 
197  *      when its use count is 0.
198  */
199  
200 void cleanup_module(void)
201 {
202         for(i=0;i< cards; i++)
203         {
204                 /*
205                  *      Free attached resources
206                  */
207                  
208                 ad1848_unload(mss_data[i].io_base,
209                               mss_data[i].irq,
210                               mss_data[i].dma,
211                               mss_data[i].dma,
212                               0);
213                 /*
214                  *      And disconnect the device from the kernel
215                  */
216                 sound_unload_audiodevice(mss_data[i].slots[3]);
217         }
218 }
219