patch-2.3.43 linux/drivers/sound/es1370.c

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

diff -u --recursive --new-file v2.3.42/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
@@ -116,6 +116,7 @@
  *    28.10.1999   0.31  More waitqueue races fixed
  *    08.01.2000   0.32  Prevent some ioctl's from returning bad count values on underrun/overrun;
  *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
+ *    07.02.2000   0.33  Use pci_alloc_consistent and pci_register_driver
  *
  * some important things missing in Ensoniq documentation:
  *
@@ -307,8 +308,11 @@
 	/* magic */
 	unsigned int magic;
 
-	/* we keep sb cards in a linked list */
-	struct es1370_state *next;
+	/* list of es1370 devices */
+	struct list_head devs;
+
+	/* the corresponding pci_dev structure */
+	struct pci_dev *dev;
 
 	/* soundcore stuff */
 	int dev_audio;
@@ -340,6 +344,7 @@
 
 	struct dmabuf {
 		void *rawbuf;
+		dma_addr_t dmaaddr;
 		unsigned buforder;
 		unsigned numfrag;
 		unsigned fragshift;
@@ -374,7 +379,7 @@
 
 /* --------------------------------------------------------------------- */
 
-static struct es1370_state *devs = NULL;
+static LIST_HEAD(devs);
 
 /*
  * The following buffer is used to point the phantom write channel to,
@@ -532,7 +537,7 @@
 #define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
 #define DMABUF_MINORDER 1
 
-extern inline void dealloc_dmabuf(struct dmabuf *db)
+extern inline void dealloc_dmabuf(struct es1370_state *s, struct dmabuf *db)
 {
 	unsigned long map, mapend;
 
@@ -541,7 +546,7 @@
 		mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
 		for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
 			clear_bit(PG_reserved, &mem_map[map].flags);	
-		free_pages((unsigned long)db->rawbuf, db->buforder);
+		pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, db->rawbuf, db->dmaaddr);
 	}
 	db->rawbuf = NULL;
 	db->mapped = db->ready = 0;
@@ -558,7 +563,7 @@
 	if (!db->rawbuf) {
 		db->ready = db->mapped = 0;
 		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
-			if ((db->rawbuf = (void *)__get_free_pages(GFP_KERNEL, order)))
+			if ((db->rawbuf = pci_alloc_consistent(s->dev, PAGE_SIZE << order, &db->dmaaddr)))
 				break;
 		if (!db->rawbuf)
 			return -ENOMEM;
@@ -593,7 +598,7 @@
 	db->dmasize = db->numfrag << db->fragshift;
 	memset(db->rawbuf, (fmt & ES1370_FMT_S16) ? 0 : 0x80, db->dmasize);
 	outl((reg >> 8) & 15, s->io+ES1370_REG_MEMPAGE);
-	outl(virt_to_bus(db->rawbuf), s->io+(reg & 0xff));
+	outl(db->dmaaddr, s->io+(reg & 0xff));
 	outl((db->dmasize >> 2)-1, s->io+((reg + 4) & 0xff));
 	db->ready = 1;
 	return 0;
@@ -1013,12 +1018,16 @@
 static int es1370_open_mixdev(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
-	struct es1370_state *s = devs;
+	struct list_head *list;
+	struct es1370_state *s;
 
-	while (s && s->dev_mixer != minor)
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct es1370_state, devs);
+		if (s->dev_mixer == minor)
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	MOD_INC_USE_COUNT;
@@ -1040,19 +1049,10 @@
 }
 
 static /*const*/ struct file_operations es1370_mixer_fops = {
-	&es1370_llseek,
-	NULL,  /* read */
-	NULL,  /* write */
-	NULL,  /* readdir */
-	NULL,  /* poll */
-	&es1370_ioctl_mixdev,
-	NULL,  /* mmap */
-	&es1370_open_mixdev,
-	NULL,	/* flush */
-	&es1370_release_mixdev,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		es1370_llseek,
+	ioctl:		es1370_ioctl_mixdev,
+	open:		es1370_open_mixdev,
+	release:	es1370_release_mixdev,
 };
 
 /* --------------------------------------------------------------------- */
@@ -1655,13 +1655,17 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct es1370_state *s = devs;
 	unsigned long flags;
+	struct list_head *list;
+	struct es1370_state *s;
 
-	while (s && ((s->dev_audio ^ minor) & ~0xf))
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct es1370_state, devs);
+		if (!((s->dev_audio ^ minor) & ~0xf))
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -1720,11 +1724,11 @@
 	if (file->f_mode & FMODE_WRITE) {
 		stop_dac2(s);
 		synchronize_irq();
-		dealloc_dmabuf(&s->dma_dac2);
+		dealloc_dmabuf(s, &s->dma_dac2);
 	}
 	if (file->f_mode & FMODE_READ) {
 		stop_adc(s);
-		dealloc_dmabuf(&s->dma_adc);
+		dealloc_dmabuf(s, &s->dma_adc);
 	}
 	s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
 	wake_up(&s->open_wait);
@@ -1734,19 +1738,14 @@
 }
 
 static /*const*/ struct file_operations es1370_audio_fops = {
-	&es1370_llseek,
-	&es1370_read,
-	&es1370_write,
-	NULL,  /* readdir */
-	&es1370_poll,
-	&es1370_ioctl,
-	&es1370_mmap,
-	&es1370_open,
-	NULL,	/* flush */
-	&es1370_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		es1370_llseek,
+	read:		es1370_read,
+	write:		es1370_write,
+	poll:		es1370_poll,
+	ioctl:		es1370_ioctl,
+	mmap:		es1370_mmap,
+	open:		es1370_open,
+	release:	es1370_release,
 };
 
 /* --------------------------------------------------------------------- */
@@ -2065,13 +2064,17 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct es1370_state *s = devs;
 	unsigned long flags;
+	struct list_head *list;
+	struct es1370_state *s;
 
-	while (s && ((s->dev_dac ^ minor) & ~0xf))
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct es1370_state, devs);
+		if (!((s->dev_dac ^ minor) & ~0xf))
+			break;
+	}
        	VALIDATE_STATE(s);
        	/* we allow opening with O_RDWR, most programs do it although they will only write */
 #if 0
@@ -2123,7 +2126,7 @@
 	drain_dac1(s, file->f_flags & O_NONBLOCK);
 	down(&s->open_sem);
 	stop_dac1(s);
-	dealloc_dmabuf(&s->dma_dac1);
+	dealloc_dmabuf(s, &s->dma_dac1);
 	s->open_mode &= ~FMODE_DAC;
 	wake_up(&s->open_wait);
 	up(&s->open_sem);
@@ -2132,19 +2135,13 @@
 }
 
 static /*const*/ struct file_operations es1370_dac_fops = {
-	&es1370_llseek,
-	NULL,  /* read */
-	&es1370_write_dac,
-	NULL,  /* readdir */
-	&es1370_poll_dac,
-	&es1370_ioctl_dac,
-	&es1370_mmap_dac,
-	&es1370_open_dac,
-	NULL,	/* flush */
-	&es1370_release_dac,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		es1370_llseek,
+	write:		es1370_write_dac,
+	poll:		es1370_poll_dac,
+	ioctl:		es1370_ioctl_dac,
+	mmap:		es1370_mmap_dac,
+	open:		es1370_open_dac,
+	release:	es1370_release_dac,
 };
 
 /* --------------------------------------------------------------------- */
@@ -2307,13 +2304,17 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct es1370_state *s = devs;
 	unsigned long flags;
+	struct list_head *list;
+	struct es1370_state *s;
 
-	while (s && s->dev_midi != minor)
-		s = s->next;
-	if (!s)
-		return -ENODEV;
+	for (list = devs.next; ; list = list->next) {
+		if (list == &devs)
+			return -ENODEV;
+		s = list_entry(list, struct es1370_state, devs);
+		if (s->dev_midi == minor)
+			break;
+	}
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -2404,30 +2405,25 @@
 }
 
 static /*const*/ struct file_operations es1370_midi_fops = {
-	&es1370_llseek,
-	&es1370_midi_read,
-	&es1370_midi_write,
-	NULL,  /* readdir */
-	&es1370_midi_poll,
-	NULL,  /* ioctl */
-	NULL,  /* mmap */
-	&es1370_midi_open,
-	NULL,	/* flush */
-	&es1370_midi_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL,  /* lock */
+	llseek:		es1370_llseek,
+	read:		es1370_midi_read,
+	write:		es1370_midi_write,
+	poll:		es1370_midi_poll,
+	open:		es1370_midi_open,
+	release:	es1370_midi_release,
 };
 
 /* --------------------------------------------------------------------- */
 
-/* maximum number of devices */
+/* maximum number of devices; only used for command line params */
 #define NR_DEVICE 5
 
 static int joystick[NR_DEVICE] = { 0, };
 static int lineout[NR_DEVICE] = { 0, };
 static int micbias[NR_DEVICE] = { 0, };
 
+static unsigned int devindex = 0;
+
 MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i");
 MODULE_PARM_DESC(joystick, "if 1 enables joystick interface (still need separate driver)");
 MODULE_PARM(lineout, "1-" __MODULE_STRING(NR_DEVICE) "i");
@@ -2460,142 +2456,168 @@
 				 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
 #define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
 
-
-static int __init init_es1370(void)
+static int es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
 {
 	struct es1370_state *s;
-	struct pci_dev *pcidev = NULL;
 	mm_segment_t fs;
-	int i, val, index = 0;
+	int i, val;
+
+	if (!RSRCISIOREGION(pcidev, 0))
+		return -1;
+	if (pcidev->irq == 0) 
+		return -1;
+	if (!(s = kmalloc(sizeof(struct es1370_state), GFP_KERNEL))) {
+		printk(KERN_WARNING "es1370: out of memory\n");
+		return -1;
+	}
+	memset(s, 0, sizeof(struct es1370_state));
+	init_waitqueue_head(&s->dma_adc.wait);
+	init_waitqueue_head(&s->dma_dac1.wait);
+	init_waitqueue_head(&s->dma_dac2.wait);
+	init_waitqueue_head(&s->open_wait);
+	init_waitqueue_head(&s->midi.iwait);
+	init_waitqueue_head(&s->midi.owait);
+	init_MUTEX(&s->open_sem);
+	spin_lock_init(&s->lock);
+	s->magic = ES1370_MAGIC;
+	s->dev = pcidev;
+	s->io = RSRCADDRESS(pcidev, 0);
+	s->irq = pcidev->irq;
+	if (!request_region(s->io, ES1370_EXTENT, "es1370")) {
+		printk(KERN_ERR "es1370: io ports %#lx-%#lx in use\n", s->io, s->io+ES1370_EXTENT-1);
+		goto err_region;
+	}
+	if (request_irq(s->irq, es1370_interrupt, SA_SHIRQ, "es1370", s)) {
+		printk(KERN_ERR "es1370: irq %u in use\n", s->irq);
+		goto err_irq;
+	}
+	pci_enable_device(pcidev);
+	/* initialize codec registers */
+	/* note: setting CTRL_SERR_DIS is reported to break
+	 * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */
+	s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL);
+	if (joystick[devindex]) {
+		if (check_region(0x200, JOY_EXTENT))
+			printk(KERN_ERR "es1370: io port 0x200 in use\n");
+		else
+			s->ctrl |= CTRL_JYSTK_EN;
+	}
+	if (lineout[devindex])
+		s->ctrl |= CTRL_XCTL0;
+	if (micbias[devindex])
+		s->ctrl |= CTRL_XCTL1;
+	s->sctrl = 0;
+	printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n"
+	       KERN_INFO "es1370: features: joystick %s, line %s, mic impedance %s\n",
+	       s->io, s->irq, (s->ctrl & CTRL_JYSTK_EN) ? "on" : "off",
+	       (s->ctrl & CTRL_XCTL0) ? "out" : "in",
+		       (s->ctrl & CTRL_XCTL1) ? "1" : "0");
+	/* register devices */
+	if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0)
+		goto err_dev1;
+	if ((s->dev_mixer = register_sound_mixer(&es1370_mixer_fops, -1)) < 0)
+		goto err_dev2;
+	if ((s->dev_dac = register_sound_dsp(&es1370_dac_fops, -1)) < 0)
+		goto err_dev3;
+	if ((s->dev_midi = register_sound_midi(&es1370_midi_fops, -1)) < 0)
+		goto err_dev4;
+	/* initialize the chips */
+	outl(s->ctrl, s->io+ES1370_REG_CONTROL);
+	outl(s->sctrl, s->io+ES1370_REG_SERIAL_CONTROL);
+	/* point phantom write channel to "bugbuf" */
+	outl((ES1370_REG_PHANTOM_FRAMEADR >> 8) & 15, s->io+ES1370_REG_MEMPAGE);
+	outl(virt_to_bus(bugbuf), s->io+(ES1370_REG_PHANTOM_FRAMEADR & 0xff));
+	outl(0, s->io+(ES1370_REG_PHANTOM_FRAMECNT & 0xff));
+	pci_set_master(pcidev);  /* enable bus mastering */
+	wrcodec(s, 0x16, 3); /* no RST, PD */
+	wrcodec(s, 0x17, 0); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off the LRCLK2 PLL; program DAC_SYNC=0!!  */
+	wrcodec(s, 0x18, 0); /* recording source is mixer */
+	wrcodec(s, 0x19, s->mix.micpreamp = 1); /* turn on MIC preamp */
+	s->mix.imix = 1;
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	val = SOUND_MASK_LINE|SOUND_MASK_SYNTH|SOUND_MASK_CD;
+	mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
+	for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
+		val = initvol[i].vol;
+		mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
+	}
+	set_fs(fs);
+	/* store it in the driver field */
+	pcidev->driver_data = s;
+	pcidev->dma_mask = 0xffffffff;
+	/* put it into driver list */
+	list_add_tail(&s->devs, &devs);
+	/* increment devindex */
+	if (devindex < NR_DEVICE-1)
+		devindex++;
+	return 0;
+
+ err_dev4:
+	unregister_sound_dsp(s->dev_dac);
+ err_dev3:
+	unregister_sound_mixer(s->dev_mixer);
+ err_dev2:
+	unregister_sound_dsp(s->dev_audio);
+ err_dev1:
+	printk(KERN_ERR "es1370: cannot register misc device\n");
+	free_irq(s->irq, s);
+ err_irq:
+	release_region(s->io, ES1370_EXTENT);
+ err_region:
+	kfree_s(s, sizeof(struct es1370_state));
+	return -1;
+}
+
+static void es1370_remove(struct pci_dev *dev)
+{
+       struct es1370_state *s = (struct es1370_state *)dev->driver_data;
+
+       if (!s)
+               return;
+       list_del(&s->devs);
+       outl(CTRL_SERR_DIS | (1 << CTRL_SH_WTSRSEL), s->io+ES1370_REG_CONTROL); /* switch everything off */
+       outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */
+       synchronize_irq();
+       free_irq(s->irq, s);
+       release_region(s->io, ES1370_EXTENT);
+       unregister_sound_dsp(s->dev_audio);
+       unregister_sound_mixer(s->dev_mixer);
+       unregister_sound_dsp(s->dev_dac);
+       unregister_sound_midi(s->dev_midi);
+       kfree_s(s, sizeof(struct es1370_state));
+       dev->driver_data = NULL;
+}
+
+static const struct pci_device_id id_table[] = {
+	{ PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
+	{ 0, 0, 0, 0, 0, 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, id_table);
+
+static struct pci_driver es1370_driver = {
+	name: "es1370",
+	id_table: id_table,
+	probe: es1370_probe,
+	remove: es1370_remove
+};
 
+static int __init init_es1370(void)
+{
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1370: version v0.32 time " __TIME__ " " __DATE__ "\n");
-	while (index < NR_DEVICE && 
-	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
-		if (!RSRCISIOREGION(pcidev, 0))
-			continue;
-		if (pcidev->irq == 0) 
-			continue;
-		if (!(s = kmalloc(sizeof(struct es1370_state), GFP_KERNEL))) {
-			printk(KERN_WARNING "es1370: out of memory\n");
-			continue;
-		}
-		memset(s, 0, sizeof(struct es1370_state));
-		init_waitqueue_head(&s->dma_adc.wait);
-		init_waitqueue_head(&s->dma_dac1.wait);
-		init_waitqueue_head(&s->dma_dac2.wait);
-		init_waitqueue_head(&s->open_wait);
-		init_waitqueue_head(&s->midi.iwait);
-		init_waitqueue_head(&s->midi.owait);
-		init_MUTEX(&s->open_sem);
-		spin_lock_init(&s->lock);
-		s->magic = ES1370_MAGIC;
-		s->io = RSRCADDRESS(pcidev, 0);
-		s->irq = pcidev->irq;
-		if (check_region(s->io, ES1370_EXTENT)) {
-			printk(KERN_ERR "es1370: io ports %#lx-%#lx in use\n", s->io, s->io+ES1370_EXTENT-1);
-			goto err_region;
-		}
-		request_region(s->io, ES1370_EXTENT, "es1370");
-		if (request_irq(s->irq, es1370_interrupt, SA_SHIRQ, "es1370", s)) {
-			printk(KERN_ERR "es1370: irq %u in use\n", s->irq);
-			goto err_irq;
-		}
-		/* initialize codec registers */
-		/* note: setting CTRL_SERR_DIS is reported to break
-		 * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */
-	        s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL);
-	        if (joystick[index]) {
-			if (check_region(0x200, JOY_EXTENT))
-				printk(KERN_ERR "es1370: io port 0x200 in use\n");
-			else
-				s->ctrl |= CTRL_JYSTK_EN;
-		}
-		if (lineout[index])
-			s->ctrl |= CTRL_XCTL0;
-		if (micbias[index])
-			s->ctrl |= CTRL_XCTL1;
-		s->sctrl = 0;
-		printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n"
-		       KERN_INFO "es1370: features: joystick %s, line %s, mic impedance %s\n",
-		       s->io, s->irq, (s->ctrl & CTRL_JYSTK_EN) ? "on" : "off",
-		       (s->ctrl & CTRL_XCTL0) ? "out" : "in",
-		       (s->ctrl & CTRL_XCTL1) ? "1" : "0");
-		/* register devices */
-		if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0)
-			goto err_dev1;
-		if ((s->dev_mixer = register_sound_mixer(&es1370_mixer_fops, -1)) < 0)
-			goto err_dev2;
-		if ((s->dev_dac = register_sound_dsp(&es1370_dac_fops, -1)) < 0)
-			goto err_dev3;
-		if ((s->dev_midi = register_sound_midi(&es1370_midi_fops, -1)) < 0)
-			goto err_dev4;
-		/* initialize the chips */
-		outl(s->ctrl, s->io+ES1370_REG_CONTROL);
-		outl(s->sctrl, s->io+ES1370_REG_SERIAL_CONTROL);
-		/* point phantom write channel to "bugbuf" */
-		outl((ES1370_REG_PHANTOM_FRAMEADR >> 8) & 15, s->io+ES1370_REG_MEMPAGE);
-		outl(virt_to_bus(bugbuf), s->io+(ES1370_REG_PHANTOM_FRAMEADR & 0xff));
-		outl(0, s->io+(ES1370_REG_PHANTOM_FRAMECNT & 0xff));
-		pci_set_master(pcidev);  /* enable bus mastering */
-		wrcodec(s, 0x16, 3); /* no RST, PD */
-		wrcodec(s, 0x17, 0); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off the LRCLK2 PLL; program DAC_SYNC=0!!  */
-		wrcodec(s, 0x18, 0); /* recording source is mixer */
-		wrcodec(s, 0x19, s->mix.micpreamp = 1); /* turn on MIC preamp */
-		s->mix.imix = 1;
-		fs = get_fs();
-		set_fs(KERNEL_DS);
-		val = SOUND_MASK_LINE|SOUND_MASK_SYNTH|SOUND_MASK_CD;
-		mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
-		for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
-			val = initvol[i].vol;
-			mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
-		}
-		set_fs(fs);
-		/* queue it for later freeing */
-		s->next = devs;
-		devs = s;
-		index++;
-		continue;
-
-	err_dev4:
-		unregister_sound_dsp(s->dev_dac);
-	err_dev3:
-		unregister_sound_mixer(s->dev_mixer);
-	err_dev2:
-		unregister_sound_dsp(s->dev_audio);
-	err_dev1:
-		printk(KERN_ERR "es1370: cannot register misc device\n");
-		free_irq(s->irq, s);
-	err_irq:
-		release_region(s->io, ES1370_EXTENT);
-	err_region:
-		kfree_s(s, sizeof(struct es1370_state));
-	}
-	if (!devs)
+	printk(KERN_INFO "es1370: version v0.33 time " __TIME__ " " __DATE__ "\n");
+	if (!pci_register_driver(&es1370_driver))
 		return -ENODEV;
-	return 0;
+        return 0;
+
 }
 
 static void __exit cleanup_es1370(void)
 {
-	struct es1370_state *s;
-
-	while ((s = devs)) {
-		devs = devs->next;
-		outl(CTRL_SERR_DIS | (1 << CTRL_SH_WTSRSEL), s->io+ES1370_REG_CONTROL); /* switch everything off */
-		outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */
-		synchronize_irq();
-		free_irq(s->irq, s);
-		release_region(s->io, ES1370_EXTENT);
-		unregister_sound_dsp(s->dev_audio);
-		unregister_sound_mixer(s->dev_mixer);
-		unregister_sound_dsp(s->dev_dac);
-		unregister_sound_midi(s->dev_midi);
-		kfree_s(s, sizeof(struct es1370_state));
-	}
 	printk(KERN_INFO "es1370: unloading\n");
+	pci_unregister_driver(&es1370_driver);
 }
 
 module_init(init_es1370);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)