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