patch-2.2.0-pre8 linux/drivers/sound/skeleton.c

Next file: linux/drivers/sound/sound_core.c
Previous file: linux/drivers/sound/sequencer.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.0-pre7/linux/drivers/sound/skeleton.c linux/drivers/sound/skeleton.c
@@ -0,0 +1,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;
+}
+

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov