[alsa-devel] [PATCH] sscape: convert to firmware loader framework
krzysztof.h1 at poczta.fm
krzysztof.h1 at poczta.fm
Tue Sep 29 08:15:22 CEST 2009
Please drop this patch. It does not compile because it includes removed sscape_ioctl.h.
I will send updated patch.
Best regards,
Krzysztof
"Krzysztof Helt" <krzysztof.h1 at poczta.fm> pisze:
> The conversion solves the problem that firmware size was set to 64KB
> while non PnP cards have 128KB firmware files.
>
> An additional post firmware initialization code has been moved
> from the OSS driver.
>
> ---
> Now, the MIDI is audible but not correct. It is not played timely.
> The sscape_ctl alsa-tool is not needed any more.
>
>
> Documentation/sound/alsa/ALSA-Configuration.txt | 8 +-
> include/sound/sscape_ioctl.h | 21 --
> sound/isa/Kconfig | 8 +-
> sound/isa/sscape.c | 305
> +++++++----------------
> 4 files changed, 101 insertions(+), 241 deletions(-)
> delete mode 100644 include/sound/sscape_ioctl.h
>
> diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt
> b/Documentation/sound/alsa/ALSA-Configuration.txt
> index 1c8eb45..cf98525 100644
> --- a/Documentation/sound/alsa/ALSA-Configuration.txt
> +++ b/Documentation/sound/alsa/ALSA-Configuration.txt
> @@ -1631,7 +1631,7 @@ Prior to version 0.9.0rc4 options had a 'snd_'
> prefix. This was removed.
> Module snd-sscape
> -----------------
>
> - Module for ENSONIQ SoundScape PnP cards.
> + Module for ENSONIQ SoundScape cards.
>
> port - Port # (PnP setup)
> wss_port - WSS Port # (PnP setup)
> @@ -1640,9 +1640,9 @@ Prior to version 0.9.0rc4 options had a 'snd_'
> prefix. This was removed.
> dma - DMA # (PnP setup)
> dma2 - 2nd DMA # (PnP setup, -1 to disable)
>
> - This module supports multiple cards. ISA PnP must be enabled.
> - You need sscape_ctl tool in alsa-tools package for loading
> - the microcode.
> + This module supports multiple cards.
> +
> + The driver requires the firmware loader support on kernel.
>
> Module snd-sun-amd7930 (on sparc only)
> --------------------------------------
> diff --git a/include/sound/sscape_ioctl.h b/include/sound/sscape_ioctl.h
> deleted file mode 100644
> index 0d88859..0000000
> --- a/include/sound/sscape_ioctl.h
> +++ /dev/null
> @@ -1,21 +0,0 @@
> -#ifndef SSCAPE_IOCTL_H
> -#define SSCAPE_IOCTL_H
> -
> -
> -struct sscape_bootblock
> -{
> - unsigned char code[256];
> - unsigned version;
> -};
> -
> -#define SSCAPE_MICROCODE_SIZE 65536
> -
> -struct sscape_microcode
> -{
> - unsigned char __user *code;
> -};
> -
> -#define SND_SSCAPE_LOAD_BOOTB _IOWR('P', 100, struct sscape_bootblock)
> -#define SND_SSCAPE_LOAD_MCODE _IOW ('P', 101, struct sscape_microcode)
> -
> -#endif
> diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
> index b90fc16..02fe81c 100644
> --- a/sound/isa/Kconfig
> +++ b/sound/isa/Kconfig
> @@ -372,9 +372,9 @@ config SND_SGALAXY
>
> config SND_SSCAPE
> tristate "Ensoniq SoundScape driver"
> - select SND_HWDEP
> select SND_MPU401_UART
> select SND_WSS_LIB
> + select FW_LOADER
> help
> Say Y here to include support for Ensoniq SoundScape
> and Ensoniq OEM soundcards.
> @@ -382,7 +382,11 @@ config SND_SSCAPE
> The PCM audio is supported on SoundScape Classic, Elite, PnP
> and VIVO cards. The supported OEM cards are SPEA Media FX and
> Reveal SC-600.
> - The MIDI support is very experimental.
> + The MIDI support is very experimental and requires binary
> + firmware files called "scope.cod" and "sndscape.co?" where the
> + ? is digit 0, 1, 2, 3 or 4. The firmware files can be found
> + in DOS or Windows driver packages. One has to put the firmware
> + files into the /lib/firmware directory.
>
> To compile this driver as a module, choose M here: the module
> will be called snd-sscape.
> diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
> index b11c35f..08389a2 100644
> --- a/sound/isa/sscape.c
> +++ b/sound/isa/sscape.c
> @@ -1,5 +1,5 @@
> /*
> - * Low-level ALSA driver for the ENSONIQ SoundScape PnP
> + * Low-level ALSA driver for the ENSONIQ SoundScape
> * Copyright (c) by Chris Rankin
> *
> * This driver was written in part using information obtained from
> @@ -25,12 +25,12 @@
> #include <linux/err.h>
> #include <linux/isa.h>
> #include <linux/delay.h>
> +#include <linux/firmware.h>
> #include <linux/pnp.h>
> #include <linux/spinlock.h>
> #include <linux/moduleparam.h>
> #include <asm/dma.h>
> #include <sound/core.h>
> -#include <sound/hwdep.h>
> #include <sound/wss.h>
> #include <sound/mpu401.h>
> #include <sound/initval.h>
> @@ -39,7 +39,7 @@
>
>
> MODULE_AUTHOR("Chris Rankin");
> -MODULE_DESCRIPTION("ENSONIQ SoundScape PnP driver");
> +MODULE_DESCRIPTION("ENSONIQ SoundScape driver");
> MODULE_LICENSE("GPL");
>
> static int index[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IDX;
> @@ -142,14 +142,12 @@ struct soundscape {
> struct resource *wss_res;
> struct snd_wss *chip;
> struct snd_mpu401 *mpu;
> - struct snd_hwdep *hw;
>
> /*
> * The MIDI device won't work until we've loaded
> * its firmware via a hardware-dependent device IOCTL
> */
> spinlock_t fwlock;
> - int hw_in_use;
> unsigned long midi_usage;
> unsigned char midi_vol;
> };
> @@ -167,12 +165,6 @@ static inline struct soundscape
> *get_mpu401_soundscape(struct snd_mpu401 * mpu)
> return (struct soundscape *) (mpu->private_data);
> }
>
> -static inline struct soundscape *get_hwdep_soundscape(struct snd_hwdep *
> hw)
> -{
> - return (struct soundscape *) (hw->private_data);
> -}
> -
> -
> /*
> * Allocates some kernel memory that we can use for DMA.
> * I think this means that the memory has to map to
> @@ -438,14 +430,14 @@ static int host_startup_ack(struct soundscape *s,
> unsigned timeout)
> * Upload a byte-stream into the SoundScape using DMA channel A.
> */
> static int upload_dma_data(struct soundscape *s,
> - const unsigned char __user *data,
> + const unsigned char *data,
> size_t size)
> {
> unsigned long flags;
> struct snd_dma_buffer dma;
> int ret;
>
> - if (!get_dmabuf(&dma, PAGE_ALIGN(size)))
> + if (!get_dmabuf(&dma, PAGE_ALIGN(32 * 1024)))
> return -ENOMEM;
>
> spin_lock_irqsave(&s->lock, flags);
> @@ -468,35 +460,17 @@ static int upload_dma_data(struct soundscape *s,
> sscape_write_unsafe(s->io_base, GA_HMCTL_REG,
> sscape_read_unsafe(s->io_base, GA_HMCTL_REG) | 0x80);
>
> /*
> - * Upload the user's data (firmware?) to the SoundScape
> + * Upload the firmware to the SoundScape
> * board through the DMA channel ...
> */
> while (size != 0) {
> unsigned long len;
>
> - /*
> - * Apparently, copying to/from userspace can sleep.
> - * We are therefore forbidden from holding any
> - * spinlocks while we copy ...
> - */
> - spin_unlock_irqrestore(&s->lock, flags);
> -
> - /*
> - * Remember that the data that we want to DMA
> - * comes from USERSPACE. We have already verified
> - * the userspace pointer ...
> - */
> len = min(size, dma.bytes);
> - len -= __copy_from_user(dma.area, data, len);
> + memcpy(dma.area, data, len);
> data += len;
> size -= len;
>
> - /*
> - * Grab that spinlock again, now that we've
> - * finished copying!
> - */
> - spin_lock_irqsave(&s->lock, flags);
> -
> snd_dma_program(s->chip->dma1, dma.addr, len, DMA_MODE_WRITE);
> sscape_start_dma_unsafe(s->io_base, GA_DMAA_REG);
> if (!sscape_wait_dma_unsafe(s->io_base, GA_DMAA_REG, 5000)) {
> @@ -512,6 +486,7 @@ static int upload_dma_data(struct soundscape *s,
> } /* while */
>
> set_host_mode_unsafe(s->io_base);
> + outb(0x0, s->io_base);
>
> /*
> * Boot the board ... (I think)
> @@ -537,7 +512,7 @@ _release_dma:
> /*
> * NOTE!!! We are NOT holding any spinlocks at this point !!!
> */
> - sscape_write(s, GA_DMAA_REG, (s->ic_type == IC_ODIE ? 0x70 : 0x40));
> + sscape_write(s, GA_DMAA_REG, (s->ic_type == IC_OPUS ? 0x40 : 0x70));
> free_dmabuf(&dma);
>
> return ret;
> @@ -547,162 +522,70 @@ _release_dma:
> * Upload the bootblock(?) into the SoundScape. The only
> * purpose of this block of code seems to be to tell
> * us which version of the microcode we should be using.
> - *
> - * NOTE: The boot-block data resides in USER-SPACE!!!
> - * However, we have already verified its memory
> - * addresses by the time we get here.
> */
> -static int sscape_upload_bootblock(struct soundscape *sscape, struct
> sscape_bootblock __user *bb)
> +static int sscape_upload_bootblock(struct snd_card *card)
> {
> + struct soundscape *sscape = get_card_soundscape(card);
> unsigned long flags;
> + const struct firmware *init_fw = NULL;
> int data = 0;
> int ret;
>
> - ret = upload_dma_data(sscape, bb->code, sizeof(bb->code));
> -
> - spin_lock_irqsave(&sscape->lock, flags);
> - if (ret == 0) {
> - data = host_read_ctrl_unsafe(sscape->io_base, 100);
> - }
> - set_midi_mode_unsafe(sscape->io_base);
> - spin_unlock_irqrestore(&sscape->lock, flags);
> -
> - if (ret == 0) {
> - if (data < 0) {
> - snd_printk(KERN_ERR "sscape: timeout reading firmware versionn");
> - ret = -EAGAIN;
> - }
> - else if (__copy_to_user(&bb->version, &data, sizeof(bb->version))) {
> - ret = -EFAULT;
> - }
> + ret = request_firmware(&init_fw, "scope.cod", card->dev);
> + if (ret < 0) {
> + snd_printk(KERN_ERR "Error loading scope.cod");
> + return ret;
> }
> + ret = upload_dma_data(sscape, init_fw->data, init_fw->size);
>
> - return ret;
> -}
> + release_firmware(init_fw);
>
> -/*
> - * Upload the microcode into the SoundScape. The
> - * microcode is 64K of data, and if we try to copy
> - * it into a local variable then we will SMASH THE
> - * KERNEL'S STACK! We therefore leave it in USER
> - * SPACE, and save ourselves from copying it at all.
> - */
> -static int sscape_upload_microcode(struct soundscape *sscape,
> - const struct sscape_microcode __user
> *mc)
> -{
> - unsigned long flags;
> - char __user *code;
> - int err;
> -
> - /*
> - * We are going to have to copy this data into a special
> - * DMA-able buffer before we can upload it. We shall therefore
> - * just check that the data pointer is valid for now.
> - *
> - * NOTE: This buffer is 64K long! That's WAY too big to
> - * copy into a stack-temporary anyway.
> - */
> - if ( get_user(code, &mc->code) ||
> - !access_ok(VERIFY_READ, code, SSCAPE_MICROCODE_SIZE) )
> - return -EFAULT;
> + spin_lock_irqsave(&sscape->lock, flags);
> + if (ret == 0)
> + data = host_read_ctrl_unsafe(sscape->io_base, 100);
>
> - if ((err = upload_dma_data(sscape, code, SSCAPE_MICROCODE_SIZE)) == 0)
> {
> - snd_printk(KERN_INFO "sscape: MIDI firmware loadedn");
> - }
> + if (data & 0x10)
> + sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2f);
>
> - spin_lock_irqsave(&sscape->lock, flags);
> - set_midi_mode_unsafe(sscape->io_base);
> spin_unlock_irqrestore(&sscape->lock, flags);
>
> - initialise_mpu401(sscape->mpu);
> + data &= 0xf;
> + if (ret == 0 && data > 7) {
> + snd_printk(KERN_ERR
> + "sscape: timeout reading firmware versionn");
> + ret = -EAGAIN;
> + }
>
> - return err;
> + return (ret == 0) ? data : ret;
> }
>
> /*
> - * Hardware-specific device functions, to implement special
> - * IOCTLs for the SoundScape card. This is how we upload
> - * the microcode into the card, for example, and so we
> - * must ensure that no two processes can open this device
> - * simultaneously, and that we can't open it at all if
> - * someone is using the MIDI device.
> + * Upload the microcode into the SoundScape.
> */
> -static int sscape_hw_open(struct snd_hwdep * hw, struct file *file)
> +static int sscape_upload_microcode(struct snd_card *card, int version)
> {
> - register struct soundscape *sscape = get_hwdep_soundscape(hw);
> - unsigned long flags;
> + struct soundscape *sscape = get_card_soundscape(card);
> + const struct firmware *init_fw = NULL;
> + char name[14] = "sndscape.co0";
> int err;
>
> - spin_lock_irqsave(&sscape->fwlock, flags);
> + name[11] = '0' + version;
>
> - if ((sscape->midi_usage != 0) || sscape->hw_in_use) {
> - err = -EBUSY;
> - } else {
> - sscape->hw_in_use = 1;
> - err = 0;
> + err = request_firmware(&init_fw, name, card->dev);
> + if (err < 0) {
> + snd_printk(KERN_ERR "Error loading sndscape.co0");
> + return err;
> }
> + err = upload_dma_data(sscape, init_fw->data, init_fw->size);
> + if (err == 0)
> + snd_printk(KERN_INFO "MIDI firmware loaded %d KBsn",
> + init_fw->size >> 10);
>
> - spin_unlock_irqrestore(&sscape->fwlock, flags);
> - return err;
> -}
> -
> -static int sscape_hw_release(struct snd_hwdep * hw, struct file *file)
> -{
> - register struct soundscape *sscape = get_hwdep_soundscape(hw);
> - unsigned long flags;
> -
> - spin_lock_irqsave(&sscape->fwlock, flags);
> - sscape->hw_in_use = 0;
> - spin_unlock_irqrestore(&sscape->fwlock, flags);
> - return 0;
> -}
> -
> -static int sscape_hw_ioctl(struct snd_hwdep * hw, struct file *file,
> - unsigned int cmd, unsigned long arg)
> -{
> - struct soundscape *sscape = get_hwdep_soundscape(hw);
> - int err = -EBUSY;
> -
> - switch (cmd) {
> - case SND_SSCAPE_LOAD_BOOTB:
> - {
> - register struct sscape_bootblock __user *bb = (struct sscape_bootblock
> __user *) arg;
> -
> - /*
> - * We are going to have to copy this data into a special
> - * DMA-able buffer before we can upload it. We shall therefore
> - * just check that the data pointer is valid for now ...
> - */
> - if ( !access_ok(VERIFY_READ, bb->code, sizeof(bb->code)) )
> - return -EFAULT;
> -
> - /*
> - * Now check that we can write the firmware version number too...
> - */
> - if ( !access_ok(VERIFY_WRITE, &bb->version, sizeof(bb->version)) )
> - return -EFAULT;
> -
> - err = sscape_upload_bootblock(sscape, bb);
> - }
> - break;
> -
> - case SND_SSCAPE_LOAD_MCODE:
> - {
> - register const struct sscape_microcode __user *mc = (const struct
> sscape_microcode __user *) arg;
> -
> - err = sscape_upload_microcode(sscape, mc);
> - }
> - break;
> -
> - default:
> - err = -EINVAL;
> - break;
> - } /* switch */
> + release_firmware(init_fw);
>
> return err;
> }
>
> -
> /*
> * Mixer control for the SoundScape's MIDI device.
> */
> @@ -920,7 +803,7 @@ static int mpu401_open(struct snd_mpu401 * mpu)
>
> spin_lock_irqsave(&sscape->fwlock, flags);
>
> - if (sscape->hw_in_use || (sscape->midi_usage == ULONG_MAX)) {
> + if (sscape->midi_usage == ULONG_MAX) {
> err = -EBUSY;
> } else {
> ++(sscape->midi_usage);
> @@ -1053,13 +936,6 @@ static int __devinit create_ad1845(struct snd_card
> *card, unsigned port,
> }
> }
>
> - strcpy(card->driver, "SoundScape");
> - strcpy(card->shortname, pcm->name);
> - snprintf(card->longname, sizeof(card->longname),
> - "%s at 0x%lx, IRQ %d, DMA1 %d, DMA2 %dn",
> - pcm->name, chip->port, chip->irq,
> - chip->dma1, chip->dma2);
> -
> sscape->chip = chip;
> }
>
> @@ -1162,29 +1038,6 @@ static int __devinit create_sscape(int dev, struct
> snd_card *card)
> return -ENXIO;
> }
>
> - if (sscape->type != SSCAPE_VIVO) {
> - /*
> - * Now create the hardware-specific device so that we can
> - * load the microcode into the on-board processor.
> - * We cannot use the MPU-401 MIDI system until this firmware
> - * has been loaded into the card.
> - */
> - err = snd_hwdep_new(card, "MC68EC000", 0, &(sscape->hw));
> - if (err < 0) {
> - printk(KERN_ERR "sscape: Failed to create "
> - "firmware devicen");
> - goto _release_dma;
> - }
> - strlcpy(sscape->hw->name, "SoundScape M68K",
> - sizeof(sscape->hw->name));
> - sscape->hw->name[sizeof(sscape->hw->name) - 1] = '�';
> - sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE;
> - sscape->hw->ops.open = sscape_hw_open;
> - sscape->hw->ops.release = sscape_hw_release;
> - sscape->hw->ops.ioctl = sscape_hw_ioctl;
> - sscape->hw->private_data = sscape;
> - }
> -
> /*
> * Tell the on-board devices where their resources are (I think -
> * I can't be sure without a datasheet ... So many magic values!)
> @@ -1222,28 +1075,51 @@ static int __devinit create_sscape(int dev, struct
> snd_card *card)
> wss_port[dev], irq[dev]);
> goto _release_dma;
> }
> + strcpy(card->driver, "SoundScape");
> + strcpy(card->shortname, name);
> + snprintf(card->longname, sizeof(card->longname),
> + "%s at 0x%lx, IRQ %d, DMA1 %d, DMA2 %dn",
> + name, sscape->chip->port, sscape->chip->irq,
> + sscape->chip->dma1, sscape->chip->dma2);
> +
> #define MIDI_DEVNUM 0
> if (sscape->type != SSCAPE_VIVO) {
> - err = create_mpu401(card, MIDI_DEVNUM, port[dev], mpu_irq[dev]);
> - if (err < 0) {
> - printk(KERN_ERR "sscape: Failed to create "
> - "MPU-401 device at 0x%lxn",
> - port[dev]);
> - goto _release_dma;
> - }
> + err = sscape_upload_bootblock(card);
> + if (err >= 0)
> + err = sscape_upload_microcode(card, err);
> +
> + if (err == 0) {
> + err = create_mpu401(card, MIDI_DEVNUM, port[dev],
> + mpu_irq[dev]);
> + if (err < 0) {
> + printk(KERN_ERR "sscape: Failed to create "
> + "MPU-401 device at 0x%lxn",
> + port[dev]);
> + goto _release_dma;
> + }
>
> - /*
> - * Enable the master IRQ ...
> - */
> - sscape_write(sscape, GA_INTENA_REG, 0x80);
> -
> - /*
> - * Initialize mixer
> - */
> - sscape->midi_vol = 0;
> - host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100);
> - host_write_ctrl_unsafe(sscape->io_base, 0, 100);
> - host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100);
> + /*
> + * Initialize mixer
> + */
> + spin_lock_irqsave(&sscape->lock, flags);
> + sscape->midi_vol = 0;
> + host_write_ctrl_unsafe(sscape->io_base,
> + CMD_SET_MIDI_VOL, 100);
> + host_write_ctrl_unsafe(sscape->io_base,
> + sscape->midi_vol, 100);
> + host_write_ctrl_unsafe(sscape->io_base,
> + CMD_XXX_MIDI_VOL, 100);
> + host_write_ctrl_unsafe(sscape->io_base,
> + sscape->midi_vol, 100);
> + host_write_ctrl_unsafe(sscape->io_base,
> + CMD_SET_EXTMIDI, 100);
> + host_write_ctrl_unsafe(sscape->io_base,
> + 0, 100);
> + host_write_ctrl_unsafe(sscape->io_base, 80, 1);
> +
> + set_midi_mode_unsafe(sscape->io_base);
> + spin_unlock_irqrestore(&sscape->lock, flags);
> + }
> }
>
> /*
> @@ -1301,11 +1177,12 @@ static int __devinit snd_sscape_probe(struct
> device *pdev, unsigned int dev)
> sscape->type = SSCAPE;
>
> dma[dev] &= 0x03;
> + snd_card_set_dev(card, pdev);
> +
> ret = create_sscape(dev, card);
> if (ret < 0)
> goto _release_card;
>
> - snd_card_set_dev(card, pdev);
> if ((ret = snd_card_register(card)) < 0) {
> printk(KERN_ERR "sscape: Failed to register sound cardn");
> goto _release_card;
> @@ -1426,12 +1303,12 @@ static int __devinit sscape_pnp_detect(struct
> pnp_card_link *pcard,
> wss_port[idx] = pnp_port_start(dev, 1);
> dma2[idx] = pnp_dma(dev, 1);
> }
> + snd_card_set_dev(card, &pcard->card->dev);
>
> ret = create_sscape(idx, card);
> if (ret < 0)
> goto _release_card;
>
> - snd_card_set_dev(card, &pcard->card->dev);
> if ((ret = snd_card_register(card)) < 0) {
> printk(KERN_ERR "sscape: Failed to register sound cardn");
> goto _release_card;
> --
> 1.6.0.3
>
> ----------------------------------------------------------------------
> Co godzine losujemy 15 000 z
----------------------------------------------------------------------
Praca za granic±? Zobacz oferty!
http://link.interia.pl/f2331
More information about the Alsa-devel
mailing list