linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / sound / oss / trident.c
index e5e14cf..a21c663 100644 (file)
 #include <linux/gameport.h>
 #include <linux/kernel.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
 
 #define DRIVER_VERSION "0.14.10j-2.6"
 
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK 1
+#endif
+
 /* magic numbers to protect our data structures */
 #define TRIDENT_CARD_MAGIC     0x5072696E      /* "Prin" */
 #define TRIDENT_STATE_MAGIC    0x63657373      /* "cess" */
@@ -275,16 +278,14 @@ static char *card_names[] = {
 };
 
 static struct pci_device_id trident_pci_tbl[] = {
-       {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_DX},
-       {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_NX},
-       {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018},
-       {PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, ALI_5451},
-       {PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, CYBER5050},
+       {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX),
+               PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TRIDENT_4D_DX},
+       {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX),
+               0, 0, TRIDENT_4D_NX},
+       {PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, SIS_7018},
+       {PCI_DEVICE(PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451), 0, 0, ALI_5451},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050),
+               0, 0, CYBER5050},
        {0,}
 };
 
@@ -442,7 +443,7 @@ struct trident_card {
        struct timer_list timer;
 
        /* Game port support */
-       struct gameport gameport;
+       struct gameport *gameport;
 };
 
 enum dmabuf_mode {
@@ -488,7 +489,7 @@ static struct trident_channel *ali_alloc_rec_pcm_channel(struct trident_card *ca
 static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card);
 static void ali_restore_regs(struct trident_card *card);
 static void ali_save_regs(struct trident_card *card);
-static int trident_suspend(struct pci_dev *dev, u32 unused);
+static int trident_suspend(struct pci_dev *dev, pm_message_t unused);
 static int trident_resume(struct pci_dev *dev);
 static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel);
 static int ali_setup_multi_channels(struct trident_card *card, int chan_nums);
@@ -497,7 +498,8 @@ static void ali_setup_spdif_in(struct trident_card *card);
 static void ali_disable_spdif_in(struct trident_card *card);
 static void ali_disable_special_channel(struct trident_card *card, int ch);
 static void ali_setup_spdif_out(struct trident_card *card, int flag);
-static int ali_write_5_1(struct trident_state *state, const char *buffer, 
+static int ali_write_5_1(struct trident_state *state,
+                        const char __user *buffer, 
                         int cnt_for_multi_channel, unsigned int *copy_count, 
                         unsigned int *state_cnt);
 static int ali_allocate_other_states_resources(struct trident_state *state, 
@@ -1281,7 +1283,7 @@ alloc_dmabuf(struct dmabuf *dmabuf, struct pci_dev *pci_dev, int order)
        dmabuf->buforder = order;
 
        /* now mark the pages as reserved; otherwise */ 
-       /* remap_page_range doesn't do what we want */
+       /* remap_pfn_range doesn't do what we want */
        pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1);
        for (page = virt_to_page(rawbuf); page <= pend; page++)
                SetPageReserved(page);
@@ -1861,7 +1863,7 @@ trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 /* to be copied to the user's buffer.  it is filled by the dma machine and */ 
 /* drained by this loop. */
 static ssize_t
-trident_read(struct file *file, char *buffer, size_t count, loff_t * ppos)
+trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos)
 {
        struct trident_state *state = (struct trident_state *)file->private_data;
        struct dmabuf *dmabuf = &state->dmabuf;
@@ -1873,8 +1875,6 @@ trident_read(struct file *file, char *buffer, size_t count, loff_t * ppos)
        pr_debug("trident: trident_read called, count = %d\n", count);
 
        VALIDATE_STATE(state);
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
 
        if (dmabuf->mapped)
                return -ENXIO;
@@ -1976,7 +1976,7 @@ out:
    the soundcard.  it is drained by the dma machine and filled by this loop. */
 
 static ssize_t
-trident_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
+trident_write(struct file *file, const char __user *buffer, size_t count, loff_t * ppos)
 {
        struct trident_state *state = (struct trident_state *)file->private_data;
        struct dmabuf *dmabuf = &state->dmabuf;
@@ -1991,8 +1991,6 @@ trident_write(struct file *file, const char *buffer, size_t count, loff_t * ppos
        pr_debug("trident: trident_write called, count = %d\n", count);
 
        VALIDATE_STATE(state);
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
 
        /*
         *      Guard against an mmap or ioctl while writing
@@ -2227,7 +2225,8 @@ trident_mmap(struct file *file, struct vm_area_struct *vma)
        if (size > (PAGE_SIZE << dmabuf->buforder))
                goto out;
        ret = -EAGAIN;
-       if (remap_page_range(vma, vma->vm_start, virt_to_phys(dmabuf->rawbuf), 
+       if (remap_pfn_range(vma, vma->vm_start,
+                            virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT,
                             size, vma->vm_page_prot))
                goto out;
        dmabuf->mapped = 1;
@@ -2247,8 +2246,9 @@ trident_ioctl(struct inode *inode, struct file *file,
        audio_buf_info abinfo;
        count_info cinfo;
        int val, mapped, ret = 0;
-
        struct trident_card *card = state->card;
+       void __user *argp = (void __user *)arg;
+       int __user *p = argp;
 
        VALIDATE_STATE(state);
 
@@ -2256,11 +2256,11 @@ trident_ioctl(struct inode *inode, struct file *file,
        mapped = ((file->f_mode & (FMODE_WRITE | FMODE_READ)) && dmabuf->mapped);
 
        pr_debug("trident: trident_ioctl, command = %2d, arg = 0x%08x\n",
-                _IOC_NR(cmd), arg ? *(int *) arg : 0);
+                _IOC_NR(cmd), arg ? *p : 0);
 
        switch (cmd) {
        case OSS_GETVERSION:
-               ret = put_user(SOUND_VERSION, (int *) arg);
+               ret = put_user(SOUND_VERSION, p);
                break;
 
        case SNDCTL_DSP_RESET:
@@ -2287,7 +2287,7 @@ trident_ioctl(struct inode *inode, struct file *file,
                break;
 
        case SNDCTL_DSP_SPEED:  /* set smaple rate */
-               if (get_user(val, (int *) arg)) {
+               if (get_user(val, p)) {
                        ret = -EFAULT;
                        break;
                }
@@ -2307,11 +2307,11 @@ trident_ioctl(struct inode *inode, struct file *file,
                                spin_unlock_irqrestore(&state->card->lock, flags);
                        }
                }
-               ret = put_user(dmabuf->rate, (int *) arg);
+               ret = put_user(dmabuf->rate, p);
                break;
 
        case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
-               if (get_user(val, (int *) arg)) {
+               if (get_user(val, p)) {
                        ret = -EFAULT;
                        break;
                }
@@ -2342,14 +2342,14 @@ trident_ioctl(struct inode *inode, struct file *file,
                        if ((val = prog_dmabuf_playback(state)))
                                ret = val;
                        else
-                               ret = put_user(dmabuf->fragsize, (int *) arg);
+                               ret = put_user(dmabuf->fragsize, p);
                        break;
                }
                if (file->f_mode & FMODE_READ) {
                        if ((val = prog_dmabuf_record(state)))
                                ret = val;
                        else
-                               ret = put_user(dmabuf->fragsize, (int *) arg);
+                               ret = put_user(dmabuf->fragsize, p);
                        break;
                }
                /* neither READ nor WRITE? is this even possible? */
@@ -2359,11 +2359,11 @@ trident_ioctl(struct inode *inode, struct file *file,
 
        case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format */
                ret = put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 | 
-                              AFMT_U8, (int *) arg);
+                              AFMT_U8, p);
                break;
 
        case SNDCTL_DSP_SETFMT: /* Select sample format */
-               if (get_user(val, (int *) arg)) {
+               if (get_user(val, p)) {
                        ret = -EFAULT;
                        break;
                }
@@ -2390,11 +2390,11 @@ trident_ioctl(struct inode *inode, struct file *file,
                }
                unlock_set_fmt(state);
                ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE : 
-                              AFMT_U8, (int *) arg);
+                              AFMT_U8, p);
                break;
 
        case SNDCTL_DSP_CHANNELS:
-               if (get_user(val, (int *) arg)) {
+               if (get_user(val, p)) {
                        ret = -EFAULT;
                        break;
                }
@@ -2458,7 +2458,7 @@ trident_ioctl(struct inode *inode, struct file *file,
                        }
                        unlock_set_fmt(state);
                }
-               ret = put_user(val, (int *) arg);
+               ret = put_user(val, p);
                break;
 
        case SNDCTL_DSP_POST:
@@ -2470,7 +2470,7 @@ trident_ioctl(struct inode *inode, struct file *file,
                        ret = -EINVAL;
                        break;
                }
-               if (get_user(val, (int *) arg)) {
+               if (get_user(val, p)) {
                        ret = -EFAULT;
                        break;
                }
@@ -2482,7 +2482,7 @@ trident_ioctl(struct inode *inode, struct file *file,
                break;
 
        case SNDCTL_DSP_SETFRAGMENT:
-               if (get_user(val, (int *) arg)) {
+               if (get_user(val, p)) {
                        ret = -EFAULT;
                        break;
                }
@@ -2514,7 +2514,7 @@ trident_ioctl(struct inode *inode, struct file *file,
                abinfo.fragstotal = dmabuf->numfrag;
                abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
                spin_unlock_irqrestore(&state->card->lock, flags);
-               ret = copy_to_user((void *) arg, &abinfo, sizeof (abinfo)) ? 
+               ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ? 
                        -EFAULT : 0;
                break;
 
@@ -2534,7 +2534,7 @@ trident_ioctl(struct inode *inode, struct file *file,
                abinfo.fragstotal = dmabuf->numfrag;
                abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
                spin_unlock_irqrestore(&state->card->lock, flags);
-               ret = copy_to_user((void *) arg, &abinfo, sizeof (abinfo)) ? 
+               ret = copy_to_user(argp, &abinfo, sizeof (abinfo)) ? 
                        -EFAULT : 0;
                break;
 
@@ -2544,7 +2544,7 @@ trident_ioctl(struct inode *inode, struct file *file,
 
        case SNDCTL_DSP_GETCAPS:
                ret = put_user(DSP_CAP_REALTIME | DSP_CAP_TRIGGER | 
-                              DSP_CAP_MMAP | DSP_CAP_BIND, (int *) arg);
+                              DSP_CAP_MMAP | DSP_CAP_BIND, p);
                break;
 
        case SNDCTL_DSP_GETTRIGGER:
@@ -2553,11 +2553,11 @@ trident_ioctl(struct inode *inode, struct file *file,
                        val |= PCM_ENABLE_INPUT;
                if ((file->f_mode & FMODE_WRITE) && dmabuf->enable)
                        val |= PCM_ENABLE_OUTPUT;
-               ret = put_user(val, (int *) arg);
+               ret = put_user(val, p);
                break;
 
        case SNDCTL_DSP_SETTRIGGER:
-               if (get_user(val, (int *) arg)) {
+               if (get_user(val, p)) {
                        ret = -EFAULT;
                        break;
                }
@@ -2599,7 +2599,7 @@ trident_ioctl(struct inode *inode, struct file *file,
                if (dmabuf->mapped)
                        dmabuf->count &= dmabuf->fragsize - 1;
                spin_unlock_irqrestore(&state->card->lock, flags);
-               ret = copy_to_user((void *) arg, &cinfo, sizeof (cinfo)) ? 
+               ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ? 
                        -EFAULT : 0;
                break;
 
@@ -2622,7 +2622,7 @@ trident_ioctl(struct inode *inode, struct file *file,
                if (dmabuf->mapped)
                        dmabuf->count &= dmabuf->fragsize - 1;
                spin_unlock_irqrestore(&state->card->lock, flags);
-               ret = copy_to_user((void *) arg, &cinfo, sizeof (cinfo)) ? 
+               ret = copy_to_user(argp, &cinfo, sizeof (cinfo)) ? 
                        -EFAULT : 0;
                break;
 
@@ -2643,26 +2643,26 @@ trident_ioctl(struct inode *inode, struct file *file,
                trident_update_ptr(state);
                val = dmabuf->count;
                spin_unlock_irqrestore(&state->card->lock, flags);
-               ret = put_user(val, (int *) arg);
+               ret = put_user(val, p);
                break;
 
        case SOUND_PCM_READ_RATE:
-               ret = put_user(dmabuf->rate, (int *) arg);
+               ret = put_user(dmabuf->rate, p);
                break;
 
        case SOUND_PCM_READ_CHANNELS:
                ret = put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1, 
-                              (int *) arg);
+                              p);
                break;
 
        case SOUND_PCM_READ_BITS:
                ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE : 
-                              AFMT_U8, (int *) arg);
+                              AFMT_U8, p);
                break;
 
        case SNDCTL_DSP_GETCHANNELMASK:
                ret = put_user(DSP_BIND_FRONT | DSP_BIND_SURR | 
-                              DSP_BIND_CENTER_LFE,  (int *) arg);
+                              DSP_BIND_CENTER_LFE,  p);
                break;
 
        case SNDCTL_DSP_BIND_CHANNEL:
@@ -2671,7 +2671,7 @@ trident_ioctl(struct inode *inode, struct file *file,
                        break;
                }
 
-               if (get_user(val, (int *) arg)) {
+               if (get_user(val, p)) {
                        ret = -EFAULT;
                        break;
                }
@@ -2688,7 +2688,7 @@ trident_ioctl(struct inode *inode, struct file *file,
                                                              SRC_ENABLE);
                        dmabuf->channel->attribute |= mask2attr[ffs(val)];
                }
-               ret = put_user(val, (int *) arg);
+               ret = put_user(val, p);
                break;
 
        case SNDCTL_DSP_MAPINBUF:
@@ -2821,7 +2821,7 @@ trident_open(struct inode *inode, struct file *file)
        pr_debug("trident: open virtual channel %d, hard channel %d\n",
                 state->virt, dmabuf->channel->num);
 
-       return 0;
+       return nonseekable_open(inode, file);
 }
 
 static int
@@ -3725,7 +3725,7 @@ ali_restore_regs(struct trident_card *card)
 }
 
 static int
-trident_suspend(struct pci_dev *dev, u32 unused)
+trident_suspend(struct pci_dev *dev, pm_message_t unused)
 {
        struct trident_card *card = pci_get_drvdata(dev);
 
@@ -3878,14 +3878,14 @@ depend on a master state's DMA, and changing the counters of the master
 state DMA is protected by a spinlock.
 */
 static int
-ali_write_5_1(struct trident_state *state, const char *buf, 
+ali_write_5_1(struct trident_state *state, const char __user *buf, 
              int cnt_for_multi_channel, unsigned int *copy_count, 
              unsigned int *state_cnt)
 {
 
        struct dmabuf *dmabuf = &state->dmabuf;
        struct dmabuf *dmabuf_temp;
-       const char *buffer = buf;
+       const char __user *buffer = buf;
        unsigned swptr, other_dma_nums, sample_s;
        unsigned int i, loop;
 
@@ -4016,9 +4016,10 @@ ali_free_other_states_resources(struct trident_state *state)
        }
 }
 
-struct proc_dir_entry *res;
+static struct proc_dir_entry *res;
+
 static int
-ali_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
+ali_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data)
 {
        struct trident_card *card = (struct trident_card *) data;
        unsigned long flags;
@@ -4077,7 +4078,7 @@ trident_open_mixdev(struct inode *inode, struct file *file)
       match:
        file->private_data = card->ac97_codec[i];
 
-       return 0;
+       return nonseekable_open(inode, file);
 }
 
 static int
@@ -4253,26 +4254,27 @@ trident_ac97_init(struct trident_card *card)
        return num_ac97 + 1;
 }
 
+#ifdef SUPPORT_JOYSTICK
 /* Gameport functions for the cards ADC gameport */
 
-static unsigned char
-trident_game_read(struct gameport *gameport)
+static unsigned char trident_game_read(struct gameport *gameport)
 {
-       struct trident_card *card = gameport->driver;
+       struct trident_card *card = gameport->port_data;
+
        return inb(TRID_REG(card, T4D_GAME_LEG));
 }
 
-static void
-trident_game_trigger(struct gameport *gameport)
+static void trident_game_trigger(struct gameport *gameport)
 {
-       struct trident_card *card = gameport->driver;
+       struct trident_card *card = gameport->port_data;
+
        outb(0xff, TRID_REG(card, T4D_GAME_LEG));
 }
 
-static int
-trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+static int trident_game_cooked_read(struct gameport *gameport,
+                                   int *axes, int *buttons)
 {
-       struct trident_card *card = gameport->driver;
+       struct trident_card *card = gameport->port_data;
        int i;
 
        *buttons = (~inb(TRID_REG(card, T4D_GAME_LEG)) >> 4) & 0xf;
@@ -4286,10 +4288,9 @@ trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
        return 0;
 }
 
-static int
-trident_game_open(struct gameport *gameport, int mode)
+static int trident_game_open(struct gameport *gameport, int mode)
 {
-       struct trident_card *card = gameport->driver;
+       struct trident_card *card = gameport->port_data;
 
        switch (mode) {
        case GAMEPORT_MODE_COOKED:
@@ -4306,6 +4307,41 @@ trident_game_open(struct gameport *gameport, int mode)
        return 0;
 }
 
+static int __devinit trident_register_gameport(struct trident_card *card)
+{
+       struct gameport *gp;
+
+       card->gameport = gp = gameport_allocate_port();
+       if (!gp) {
+               printk(KERN_ERR "trident: can not allocate memory for gameport\n");
+               return -ENOMEM;
+       }
+
+       gameport_set_name(gp, "Trident 4DWave");
+       gameport_set_phys(gp, "pci%s/gameport0", pci_name(card->pci_dev));
+       gp->read = trident_game_read;
+       gp->trigger = trident_game_trigger;
+       gp->cooked_read = trident_game_cooked_read;
+       gp->open = trident_game_open;
+       gp->fuzz = 64;
+       gp->port_data = card;
+
+       gameport_register_port(gp);
+
+       return 0;
+}
+
+static inline void trident_unregister_gameport(struct trident_card *card)
+{
+       if (card->gameport)
+               gameport_unregister_port(card->gameport);
+}
+
+#else
+static inline int trident_register_gameport(struct trident_card *card) { return -ENOSYS; }
+static inline void trident_unregister_gameport(struct trident_card *card) { }
+#endif /* SUPPORT_JOYSTICK */
+
 /* install the driver, we do not allocate hardware channel nor DMA buffer */ 
 /* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ 
 /* open/read/write/ioctl/mmap) */
@@ -4369,13 +4405,6 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
        card->banks[BANK_B].addresses = &bank_b_addrs;
        card->banks[BANK_B].bitmap = 0UL;
 
-       card->gameport.driver = card;
-       card->gameport.fuzz = 64;
-       card->gameport.read = trident_game_read;
-       card->gameport.trigger = trident_game_trigger;
-       card->gameport.cooked_read = trident_game_cooked_read;
-       card->gameport.open = trident_game_open;
-
        init_MUTEX(&card->open_sem);
        spin_lock_init(&card->lock);
        init_timer(&card->timer);
@@ -4509,7 +4538,7 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
        trident_enable_loop_interrupts(card);
 
        /* Register gameport */
-       gameport_register_port(&card->gameport);
+       trident_register_gameport(card);
 
 out:
        return rc;
@@ -4552,7 +4581,7 @@ trident_remove(struct pci_dev *pci_dev)
        }
 
        /* Unregister gameport */
-       gameport_unregister_port(&card->gameport);
+       trident_unregister_gameport(card);
 
        /* Kill interrupts, and SP/DIF */
        trident_disable_loop_interrupts(card);
@@ -4597,11 +4626,7 @@ trident_init_module(void)
               "5050 PCI Audio, version " DRIVER_VERSION ", " __TIME__ " " 
               __DATE__ "\n");
 
-       if (!pci_register_driver(&trident_pci_driver)) {
-               pci_unregister_driver(&trident_pci_driver);
-               return -ENODEV;
-       }
-       return 0;
+       return pci_register_driver(&trident_pci_driver);
 }
 
 static void __exit