Ignore:
Timestamp:
Dec 11, 2005, 5:57:39 PM (20 years ago)
Author:
vladest
Message:

Latest update from ALSA. some intial > 15 interrupts support

File:
1 edited

Legend:

Unmodified
Added
Removed
  • GPL/trunk/alsa-kernel/drivers/mpu401/mpu401_uart.c

    r33 r34  
    2929 */
    3030
    31 #define SNDRV_MAIN_OBJECT_FILE
    3231#include <sound/driver.h>
     32#include <asm/io.h>
     33#include <linux/delay.h>
     34#include <linux/init.h>
     35#include <linux/slab.h>
     36#include <linux/ioport.h>
     37#include <linux/interrupt.h>
     38#include <linux/errno.h>
     39#include <sound/core.h>
    3340#include <sound/mpu401.h>
    3441
     
    3744MODULE_LICENSE("GPL");
    3845
    39 static void snd_mpu401_uart_input_read(mpu401_t * mpu);
    40 static void snd_mpu401_uart_output_write(mpu401_t * mpu);
    41 
    42 /*
    43 
    44 */
     46static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu);
     47static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu);
     48
     49/*
     50
     51 */
    4552
    4653#define snd_mpu401_input_avail(mpu)     (!(mpu->read(mpu, MPU401C(mpu)) & 0x80))
     
    5259
    5360/* Build in lowlevel io */
    54 static void mpu401_write_port(mpu401_t *mpu, unsigned char data, unsigned long addr)
    55 {
    56     outb(data, addr);
    57 }
    58 
    59 static unsigned char mpu401_read_port(mpu401_t *mpu, unsigned long addr)
    60 {
    61     return inb(addr);
    62 }
    63 
    64 static void mpu401_write_mmio(mpu401_t *mpu, unsigned char data, unsigned long addr)
    65 {
    66     writeb(data, (unsigned long*)addr);
    67 }
    68 
    69 static unsigned char mpu401_read_mmio(mpu401_t *mpu, unsigned long addr)
    70 {
    71     return readb((unsigned long*)addr);
     61static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data, unsigned long addr)
     62{
     63        outb(data, addr);
     64}
     65
     66static unsigned char mpu401_read_port(struct snd_mpu401 *mpu, unsigned long addr)
     67{
     68        return inb(addr);
     69}
     70
     71static void mpu401_write_mmio(struct snd_mpu401 *mpu, unsigned char data, unsigned long addr)
     72{
     73        writeb(data, (void __iomem *)addr);
     74}
     75
     76static unsigned char mpu401_read_mmio(struct snd_mpu401 *mpu, unsigned long addr)
     77{
     78        return readb((void __iomem *)addr);
    7279}
    7380/*  */
    7481
    75 static void snd_mpu401_uart_clear_rx(mpu401_t *mpu)
    76 {
    77     int timeout = 100000;
    78     for (; timeout > 0 && snd_mpu401_input_avail(mpu); timeout--)
    79         mpu->read(mpu, MPU401D(mpu));
     82static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu)
     83{
     84        int timeout = 100000;
     85        for (; timeout > 0 && snd_mpu401_input_avail(mpu); timeout--)
     86                mpu->read(mpu, MPU401D(mpu));
    8087#ifdef CONFIG_SND_DEBUG
    81     if (timeout <= 0)
    82         snd_printk("cmd: clear rx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu)));
     88        if (timeout <= 0)
     89                snd_printk("cmd: clear rx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu)));
    8390#endif
    8491}
    8592
    86 static void _snd_mpu401_uart_interrupt(mpu401_t *mpu)
    87 {
    88     spin_lock(&mpu->input_lock);
    89     if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
    90         atomic_dec(&mpu->rx_loop);
    91         snd_mpu401_uart_input_read(mpu);
    92         atomic_inc(&mpu->rx_loop);
    93     } else {
    94         snd_mpu401_uart_clear_rx(mpu);
    95     }
    96     spin_unlock(&mpu->input_lock);
    97     /* ok. for better Tx performance try do some output when input is done */
    98     if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) &&
    99         test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) {
    100         if (spin_trylock(&mpu->output_lock)) {
    101             atomic_dec(&mpu->tx_loop);
    102             snd_mpu401_uart_output_write(mpu);
    103             atomic_inc(&mpu->tx_loop);
    104             spin_unlock(&mpu->output_lock);
    105         }
    106     }
    107 
     93static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
     94{
     95        spin_lock(&mpu->input_lock);
     96        if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
     97                snd_mpu401_uart_input_read(mpu);
     98        } else {
     99                snd_mpu401_uart_clear_rx(mpu);
     100        }
     101        spin_unlock(&mpu->input_lock);
     102        /* ok. for better Tx performance try do some output when input is done */
     103        if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) &&
     104            test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) {
     105                spin_lock(&mpu->output_lock);
     106                snd_mpu401_uart_output_write(mpu);
     107                spin_unlock(&mpu->output_lock);
     108        }
    108109}
    109110
     
    118119irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    119120{
    120     mpu401_t *mpu = dev_id;
    121 
    122     if (mpu == NULL)
    123         return IRQ_NONE;
    124     _snd_mpu401_uart_interrupt(mpu);
    125     return IRQ_HANDLED;
     121        struct snd_mpu401 *mpu = dev_id;
     122       
     123        if (mpu == NULL)
     124                return IRQ_NONE;
     125        _snd_mpu401_uart_interrupt(mpu);
     126        return IRQ_HANDLED;
    126127}
    127128
     
    132133static void snd_mpu401_uart_timer(unsigned long data)
    133134{
    134     mpu401_t *mpu = (mpu401_t *)data;
    135 
    136     spin_lock(&mpu->timer_lock);
    137     /*mpu->mode |= MPU401_MODE_TIMER;*/
    138     mpu->timer.expires = 1 + jiffies;
    139     add_timer(&mpu->timer);
    140     spin_unlock(&mpu->timer_lock);
    141     if (mpu->rmidi)
    142         _snd_mpu401_uart_interrupt(mpu);
     135        struct snd_mpu401 *mpu = (struct snd_mpu401 *)data;
     136
     137        spin_lock(&mpu->timer_lock);
     138        /*mpu->mode |= MPU401_MODE_TIMER;*/
     139        mpu->timer.expires = 1 + jiffies;
     140        add_timer(&mpu->timer);
     141        spin_unlock(&mpu->timer_lock);
     142        if (mpu->rmidi)
     143                _snd_mpu401_uart_interrupt(mpu);
    143144}
    144145
     
    146147 * initialize the timer callback if not programmed yet
    147148 */
    148 static void snd_mpu401_uart_add_timer (mpu401_t *mpu, int input)
    149 {
    150     unsigned long flags;
    151 
    152     spin_lock_irqsave (&mpu->timer_lock, flags);
    153     if (mpu->timer_invoked == 0) {
    154         init_timer(&mpu->timer);
    155         mpu->timer.data = (unsigned long)mpu;
    156         mpu->timer.function = snd_mpu401_uart_timer;
    157         mpu->timer.expires = 1 + jiffies;
    158         add_timer(&mpu->timer);
    159     }
    160     mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : MPU401_MODE_OUTPUT_TIMER;
    161     spin_unlock_irqrestore (&mpu->timer_lock, flags);
     149static void snd_mpu401_uart_add_timer (struct snd_mpu401 *mpu, int input)
     150{
     151        unsigned long flags;
     152
     153        spin_lock_irqsave (&mpu->timer_lock, flags);
     154        if (mpu->timer_invoked == 0) {
     155                init_timer(&mpu->timer);
     156                mpu->timer.data = (unsigned long)mpu;
     157                mpu->timer.function = snd_mpu401_uart_timer;
     158                mpu->timer.expires = 1 + jiffies;
     159                add_timer(&mpu->timer);
     160        }
     161        mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : MPU401_MODE_OUTPUT_TIMER;
     162        spin_unlock_irqrestore (&mpu->timer_lock, flags);
    162163}
    163164
     
    165166 * remove the timer callback if still active
    166167 */
    167 static void snd_mpu401_uart_remove_timer (mpu401_t *mpu, int input)
    168 {
    169     unsigned long flags;
    170 
    171     spin_lock_irqsave (&mpu->timer_lock, flags);
    172     if (mpu->timer_invoked) {
    173         mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : ~MPU401_MODE_OUTPUT_TIMER;
    174         if (! mpu->timer_invoked)
    175             del_timer(&mpu->timer);
    176     }
    177     spin_unlock_irqrestore (&mpu->timer_lock, flags);
    178 }
    179 
    180 /*
    181 
    182 */
    183 
    184 static void snd_mpu401_uart_cmd(mpu401_t * mpu, unsigned char cmd, int ack)
    185 {
    186     unsigned long flags;
    187     int timeout, ok;
    188 
    189     spin_lock_irqsave(&mpu->input_lock, flags);
    190     if (mpu->hardware != MPU401_HW_TRID4DWAVE) {
    191         mpu->write(mpu, 0x00, MPU401D(mpu));
    192         /*snd_mpu401_uart_clear_rx(mpu);*/
    193     }
    194     /* ok. standard MPU-401 initialization */
    195     if (mpu->hardware != MPU401_HW_SB) {
    196         for (timeout = 1000; timeout > 0 && !snd_mpu401_output_ready(mpu); timeout--)
    197             udelay(10);
     168static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input)
     169{
     170        unsigned long flags;
     171
     172        spin_lock_irqsave (&mpu->timer_lock, flags);
     173        if (mpu->timer_invoked) {
     174                mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : ~MPU401_MODE_OUTPUT_TIMER;
     175                if (! mpu->timer_invoked)
     176                        del_timer(&mpu->timer);
     177        }
     178        spin_unlock_irqrestore (&mpu->timer_lock, flags);
     179}
     180
     181/*
     182
     183 */
     184
     185static void snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, int ack)
     186{
     187        unsigned long flags;
     188        int timeout, ok;
     189
     190        spin_lock_irqsave(&mpu->input_lock, flags);
     191        if (mpu->hardware != MPU401_HW_TRID4DWAVE) {
     192                mpu->write(mpu, 0x00, MPU401D(mpu));
     193                /*snd_mpu401_uart_clear_rx(mpu);*/
     194        }
     195        /* ok. standard MPU-401 initialization */
     196        if (mpu->hardware != MPU401_HW_SB) {
     197                for (timeout = 1000; timeout > 0 && !snd_mpu401_output_ready(mpu); timeout--)
     198                        udelay(10);
    198199#ifdef CONFIG_SND_DEBUG
    199         if (!timeout)
    200             snd_printk("cmd: tx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu)));
     200                if (!timeout)
     201                        snd_printk("cmd: tx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu)));
    201202#endif
    202     }
    203     mpu->write(mpu, cmd, MPU401C(mpu));
    204     if (ack) {
    205         ok = 0;
    206         timeout = 10000;
    207         while (!ok && timeout-- > 0) {
    208             if (snd_mpu401_input_avail(mpu)) {
    209                 if (mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
    210                     ok = 1;
    211             }
    212         }
    213         if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
    214             ok = 1;
    215     } else {
    216         ok = 1;
    217     }
    218     spin_unlock_irqrestore(&mpu->input_lock, flags);
    219     if (! ok)
    220         snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
    221     // snd_printk("cmd: 0x%x at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
     203        }
     204        mpu->write(mpu, cmd, MPU401C(mpu));
     205        if (ack) {
     206                ok = 0;
     207                timeout = 10000;
     208                while (!ok && timeout-- > 0) {
     209                        if (snd_mpu401_input_avail(mpu)) {
     210                                if (mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
     211                                        ok = 1;
     212                        }
     213                }
     214                if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
     215                        ok = 1;
     216        } else {
     217                ok = 1;
     218        }
     219        spin_unlock_irqrestore(&mpu->input_lock, flags);
     220        if (! ok)
     221                snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
     222        // snd_printk("cmd: 0x%x at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
    222223}
    223224
     
    225226 * input/output open/close - protected by open_mutex in rawmidi.c
    226227 */
    227 static int snd_mpu401_uart_input_open(snd_rawmidi_substream_t * substream)
    228 {
    229     mpu401_t *mpu;
    230     int err;
    231 
    232     mpu = substream->rmidi->private_data;
    233     if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
    234         return err;
    235     if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
    236         snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
    237         snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
    238     }
    239     mpu->substream_input = substream;
    240     atomic_set(&mpu->rx_loop, 1);
    241     set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
    242     return 0;
    243 }
    244 
    245 static int snd_mpu401_uart_output_open(snd_rawmidi_substream_t * substream)
    246 {
    247     mpu401_t *mpu;
    248     int err;
    249 
    250     mpu = substream->rmidi->private_data;
    251     if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
    252         return err;
    253     if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
    254         snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
    255         snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
    256     }
    257     mpu->substream_output = substream;
    258     atomic_set(&mpu->tx_loop, 1);
    259     set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
    260     return 0;
    261 }
    262 
    263 static int snd_mpu401_uart_input_close(snd_rawmidi_substream_t * substream)
    264 {
    265     mpu401_t *mpu;
    266 
    267     mpu = substream->rmidi->private_data;
    268     clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
    269     mpu->substream_input = NULL;
    270     if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode))
    271         snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
    272     if (mpu->close_input)
    273         mpu->close_input(mpu);
    274     return 0;
    275 }
    276 
    277 static int snd_mpu401_uart_output_close(snd_rawmidi_substream_t * substream)
    278 {
    279     mpu401_t *mpu;
    280 
    281     mpu = substream->rmidi->private_data;
    282     clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
    283     mpu->substream_output = NULL;
    284     if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
    285         snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
    286     if (mpu->close_output)
    287         mpu->close_output(mpu);
    288     return 0;
     228static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream)
     229{
     230        struct snd_mpu401 *mpu;
     231        int err;
     232
     233        mpu = substream->rmidi->private_data;
     234        if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
     235                return err;
     236        if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
     237                snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
     238                snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
     239        }
     240        mpu->substream_input = substream;
     241        set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
     242        return 0;
     243}
     244
     245static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
     246{
     247        struct snd_mpu401 *mpu;
     248        int err;
     249
     250        mpu = substream->rmidi->private_data;
     251        if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
     252                return err;
     253        if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
     254                snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
     255                snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
     256        }
     257        mpu->substream_output = substream;
     258        set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
     259        return 0;
     260}
     261
     262static int snd_mpu401_uart_input_close(struct snd_rawmidi_substream *substream)
     263{
     264        struct snd_mpu401 *mpu;
     265
     266        mpu = substream->rmidi->private_data;
     267        clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
     268        mpu->substream_input = NULL;
     269        if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode))
     270                snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
     271        if (mpu->close_input)
     272                mpu->close_input(mpu);
     273        return 0;
     274}
     275
     276static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream)
     277{
     278        struct snd_mpu401 *mpu;
     279
     280        mpu = substream->rmidi->private_data;
     281        clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
     282        mpu->substream_output = NULL;
     283        if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
     284                snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
     285        if (mpu->close_output)
     286                mpu->close_output(mpu);
     287        return 0;
    289288}
    290289
     
    292291 * trigger input callback
    293292 */
    294 static void snd_mpu401_uart_input_trigger(snd_rawmidi_substream_t * substream, int up)
    295 {
    296     u32 flags;
    297     mpu401_t *mpu;
    298     int max = 64;
    299 
    300     mpu = substream->rmidi->private_data;
    301     if (up) {
    302         if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) {
    303             /* first time - flush FIFO */
    304             while (max-- > 0)
    305                 mpu->read(mpu, MPU401D(mpu));
    306             if (mpu->irq < 0)
    307                 snd_mpu401_uart_add_timer(mpu, 1);
    308         }
    309 
    310         /* read data in advance */
    311         /* prevent double enter via rawmidi->event callback */
    312         if (atomic_dec_and_test(&mpu->rx_loop)) {
    313             //                  local_irq_save(flags);
    314             printk("uart inp. trigger\n");
    315             save_flags(&flags);
    316             cli();
    317             if (spin_trylock(&mpu->input_lock)) {
    318                 snd_mpu401_uart_input_read(mpu);
    319                 spin_unlock(&mpu->input_lock);
    320             }
    321             restore_flags(flags);
    322         }
    323         atomic_inc(&mpu->rx_loop);
    324     } else {
    325         if (mpu->irq < 0)
    326             snd_mpu401_uart_remove_timer(mpu, 1);
    327         clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
    328     }
     293static void snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
     294{
     295        unsigned long flags;
     296        struct snd_mpu401 *mpu;
     297        int max = 64;
     298
     299        mpu = substream->rmidi->private_data;
     300        if (up) {
     301                if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) {
     302                        /* first time - flush FIFO */
     303                        while (max-- > 0)
     304                                mpu->read(mpu, MPU401D(mpu));
     305                        if (mpu->irq < 0)
     306                                snd_mpu401_uart_add_timer(mpu, 1);
     307                }
     308               
     309                /* read data in advance */
     310                spin_lock_irqsave(&mpu->input_lock, flags);
     311                snd_mpu401_uart_input_read(mpu);
     312                spin_unlock_irqrestore(&mpu->input_lock, flags);
     313        } else {
     314                if (mpu->irq < 0)
     315                        snd_mpu401_uart_remove_timer(mpu, 1);
     316                clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
     317        }
    329318}
    330319
     
    333322 * call with input_lock spinlock held
    334323 */
    335 static void snd_mpu401_uart_input_read(mpu401_t * mpu)
    336 {
    337     int max = 128;
    338     unsigned char byte;
    339 
    340     while (max-- > 0) {
    341         if (snd_mpu401_input_avail(mpu)) {
    342             byte = mpu->read(mpu, MPU401D(mpu));
    343             printk("mpu uart: %x\n",byte);
    344             //vladest                    if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
    345             snd_rawmidi_receive(mpu->substream_input, &byte, 1);
    346         } else {
    347             break; /* input not available */
    348         }
    349     }
     324static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu)
     325{
     326        int max = 128;
     327        unsigned char byte;
     328
     329        while (max-- > 0) {
     330                if (snd_mpu401_input_avail(mpu)) {
     331                        byte = mpu->read(mpu, MPU401D(mpu));
     332                        if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
     333                                snd_rawmidi_receive(mpu->substream_input, &byte, 1);
     334                } else {
     335                        break; /* input not available */
     336                }
     337        }
    350338}
    351339
     
    362350 * call with output_lock spinlock held
    363351 */
    364 static void snd_mpu401_uart_output_write(mpu401_t * mpu)
    365 {
    366     unsigned char byte;
    367     int max = 256, timeout;
    368 
    369     do {
    370         if (snd_rawmidi_transmit_peek(mpu->substream_output, &byte, 1) == 1) {
    371             for (timeout = 100; timeout > 0; timeout--) {
    372                 if (snd_mpu401_output_ready(mpu)) {
    373                     mpu->write(mpu, byte, MPU401D(mpu));
    374                     snd_rawmidi_transmit_ack(mpu->substream_output, 1);
    375                     break;
    376                 }
    377             }
    378             if (timeout == 0)
    379                 break;  /* Tx FIFO full - try again later */
    380         } else {
    381             snd_mpu401_uart_remove_timer (mpu, 0);
    382             break;      /* no other data - leave the tx loop */
     352static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu)
     353{
     354        unsigned char byte;
     355        int max = 256, timeout;
     356
     357        do {
     358                if (snd_rawmidi_transmit_peek(mpu->substream_output, &byte, 1) == 1) {
     359                        for (timeout = 100; timeout > 0; timeout--) {
     360                                if (snd_mpu401_output_ready(mpu)) {
     361                                        mpu->write(mpu, byte, MPU401D(mpu));
     362                                        snd_rawmidi_transmit_ack(mpu->substream_output, 1);
     363                                        break;
     364                                }
     365                        }
     366                        if (timeout == 0)
     367                                break;  /* Tx FIFO full - try again later */
     368                } else {
     369                        snd_mpu401_uart_remove_timer (mpu, 0);
     370                        break;  /* no other data - leave the tx loop */
     371                }
     372        } while (--max > 0);
     373}
     374
     375/*
     376 * output trigger callback
     377 */
     378static void snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up)
     379{
     380        unsigned long flags;
     381        struct snd_mpu401 *mpu;
     382
     383        mpu = substream->rmidi->private_data;
     384        if (up) {
     385                set_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
     386
     387                /* try to add the timer at each output trigger,
     388                 * since the output timer might have been removed in
     389                 * snd_mpu401_uart_output_write().
     390                 */
     391                snd_mpu401_uart_add_timer(mpu, 0);
     392
     393                /* output pending data */
     394                spin_lock_irqsave(&mpu->output_lock, flags);
     395                snd_mpu401_uart_output_write(mpu);
     396                spin_unlock_irqrestore(&mpu->output_lock, flags);
     397        } else {
     398                snd_mpu401_uart_remove_timer(mpu, 0);
     399                clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
     400        }
     401}
     402
     403/*
     404
     405 */
     406
     407static struct snd_rawmidi_ops snd_mpu401_uart_output =
     408{
     409        .open =         snd_mpu401_uart_output_open,
     410        .close =        snd_mpu401_uart_output_close,
     411        .trigger =      snd_mpu401_uart_output_trigger,
     412};
     413
     414static struct snd_rawmidi_ops snd_mpu401_uart_input =
     415{
     416        .open =         snd_mpu401_uart_input_open,
     417        .close =        snd_mpu401_uart_input_close,
     418        .trigger =      snd_mpu401_uart_input_trigger,
     419};
     420
     421static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
     422{
     423        struct snd_mpu401 *mpu = rmidi->private_data;
     424        if (mpu->irq_flags && mpu->irq >= 0)
     425            free_irq(mpu->irq, (void *) mpu);
     426        if (mpu->res) {
     427            release_resource(mpu->res);
     428            kfree_nocheck(mpu->res);
    383429        }
    384     } while (--max > 0);
    385 }
    386 
    387 /*
    388  * output trigger callback
    389  */
    390 static void snd_mpu401_uart_output_trigger(snd_rawmidi_substream_t * substream, int up)
    391 {
    392     u32 flags;
    393     mpu401_t *mpu;
    394 
    395     mpu = substream->rmidi->private_data;
    396     if (up) {
    397         set_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
    398 
    399         /* try to add the timer at each output trigger,
    400          * since the output timer might have been removed in
    401          * snd_mpu401_uart_output_write().
    402          */
    403         snd_mpu401_uart_add_timer(mpu, 0);
    404 
    405         /* output pending data */
    406         /* prevent double enter via rawmidi->event callback */
    407         if (atomic_dec_and_test(&mpu->tx_loop)) {
    408             save_flags(&flags);
    409             cli();
    410             if (spin_trylock(&mpu->output_lock)) {
    411                 snd_mpu401_uart_output_write(mpu);
    412                 spin_unlock(&mpu->output_lock);
    413             }
    414             restore_flags(flags);
    415         }
    416         atomic_inc(&mpu->tx_loop);
    417     } else {
    418         snd_mpu401_uart_remove_timer(mpu, 0);
    419         clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
    420     }
    421 }
    422 
    423 /*
    424 
    425 */
    426 
    427 #ifdef TARGET_OS2
    428 static snd_rawmidi_ops_t snd_mpu401_uart_output =
    429 {
    430     snd_mpu401_uart_output_open,
    431     snd_mpu401_uart_output_close,
    432     snd_mpu401_uart_output_trigger,0
    433 };
    434 
    435 static snd_rawmidi_ops_t snd_mpu401_uart_input =
    436 {
    437     snd_mpu401_uart_input_open,
    438     snd_mpu401_uart_input_close,
    439     snd_mpu401_uart_input_trigger,0
    440 };
    441 #else
    442 static snd_rawmidi_ops_t snd_mpu401_uart_output =
    443 {
    444 open:           snd_mpu401_uart_output_open,
    445     close:              snd_mpu401_uart_output_close,
    446     trigger:    snd_mpu401_uart_output_trigger,
    447 };
    448 
    449 static snd_rawmidi_ops_t snd_mpu401_uart_input =
    450 {
    451 open:           snd_mpu401_uart_input_open,
    452     close:              snd_mpu401_uart_input_close,
    453     trigger:    snd_mpu401_uart_input_trigger,
    454 };
    455 #endif
    456 
    457 static void snd_mpu401_uart_free(snd_rawmidi_t *rmidi)
    458 {
    459     mpu401_t *mpu = rmidi->private_data;
    460     if (mpu->irq_flags && mpu->irq >= 0)
    461         free_irq(mpu->irq, (void *) mpu);
    462     if (mpu->res) {
    463         release_resource(mpu->res);
    464         kfree_nocheck(mpu->res);
    465     }
    466     kfree(mpu);
     430        kfree(mpu);
    467431}
    468432
     
    482446 * Note that the rawmidi instance is returned on the rrawmidi argument,
    483447 * not the mpu401 instance itself.  To access to the mpu401 instance,
    484  * cast from rawmidi->private_data (with mpu401_t magic-cast).
     448 * cast from rawmidi->private_data (with struct snd_mpu401 magic-cast).
    485449 *
    486450 * Returns zero if successful, or a negative error code.
    487451 */
    488 int snd_mpu401_uart_new(snd_card_t * card, int device,
    489                         unsigned short hardware,
    490                         unsigned long port, int integrated,
    491                         int irq, int irq_flags,
    492                         snd_rawmidi_t ** rrawmidi)
    493 {
    494     mpu401_t *mpu;
    495     snd_rawmidi_t *rmidi;
    496     int err;
    497 
    498     printk("snd_mpu401_uart_new on irq: %i, port: %i\n",irq,port);
    499     if (rrawmidi)
    500         *rrawmidi = NULL;
    501     if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0)
    502         return err;
    503     mpu = kcalloc(1, sizeof(*mpu), GFP_KERNEL);
    504     if (mpu == NULL) {
    505         snd_device_free(card, rmidi);
    506         return -ENOMEM;
    507     }
    508     rmidi->private_data = mpu;
    509     rmidi->private_free = snd_mpu401_uart_free;
    510     spin_lock_init(&mpu->input_lock);
    511     spin_lock_init(&mpu->output_lock);
    512     spin_lock_init(&mpu->timer_lock);
    513     mpu->hardware = hardware;
    514     if (!integrated) {
    515         int res_size = hardware == MPU401_HW_PC98II ? 4 : 2;
    516         if ((mpu->res = request_region(port, res_size, "MPU401 UART")) == NULL) {
    517             snd_device_free(card, rmidi);
    518             return -EBUSY;
    519         }
    520     }
    521     switch (hardware) {
    522     case MPU401_HW_AUREAL:
    523         mpu->write = mpu401_write_mmio;
    524         mpu->read = mpu401_read_mmio;
    525         break;
    526     default:
    527         mpu->write = mpu401_write_port;
    528         mpu->read = mpu401_read_port;
    529         break;
    530     }
    531     mpu->port = port;
    532     if (hardware == MPU401_HW_PC98II)
    533         mpu->cport = port + 2;
    534     else
    535         mpu->cport = port + 1;
    536     if (irq >= 0 && irq_flags) {
    537         if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags, "MPU401 UART", (void *) mpu)) {
    538             snd_printk("unable to grab IRQ %d\n", irq);
    539             snd_device_free(card, rmidi);
    540             return -EBUSY;
    541         }
    542     }
    543     mpu->irq = irq;
    544     mpu->irq_flags = irq_flags;
    545     if (card->shortname[0])
    546         sprintf(rmidi->name, "%s MPU-401", card->shortname);
    547     else
    548         sprintf(rmidi->name, "MPU-401 (UART) %d-%d", card->number, device);
    549     snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mpu401_uart_output);
    550     snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mpu401_uart_input);
    551     rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
    552         SNDRV_RAWMIDI_INFO_INPUT |
    553         SNDRV_RAWMIDI_INFO_DUPLEX;
    554     mpu->rmidi = rmidi;
    555     if (rrawmidi)
    556         *rrawmidi = rmidi;
    557     printk("Created MPU\n");
    558     return 0;
     452int snd_mpu401_uart_new(struct snd_card *card, int device,
     453                        unsigned short hardware,
     454                        unsigned long port, int integrated,
     455                        int irq, int irq_flags,
     456                        struct snd_rawmidi ** rrawmidi)
     457{
     458        struct snd_mpu401 *mpu;
     459        struct snd_rawmidi *rmidi;
     460        int err;
     461
     462        if (rrawmidi)
     463                *rrawmidi = NULL;
     464        if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0)
     465                return err;
     466        mpu = (struct snd_mpu401 *)kzalloc(sizeof(*mpu), GFP_KERNEL);
     467        if (mpu == NULL) {
     468                snd_printk(KERN_ERR "mpu401_uart: cannot allocate\n");
     469                snd_device_free(card, rmidi);
     470                return -ENOMEM;
     471        }
     472        rmidi->private_data = mpu;
     473        rmidi->private_free = snd_mpu401_uart_free;
     474        spin_lock_init(&mpu->input_lock);
     475        spin_lock_init(&mpu->output_lock);
     476        spin_lock_init(&mpu->timer_lock);
     477        mpu->hardware = hardware;
     478        if (!integrated) {
     479                int res_size = hardware == MPU401_HW_PC98II ? 4 : 2;
     480                if ((mpu->res = request_region(port, res_size, "MPU401 UART")) == NULL) {
     481                        snd_printk(KERN_ERR "mpu401_uart: unable to grab port 0x%lx size %d\n", port, res_size);
     482                        snd_device_free(card, rmidi);
     483                        return -EBUSY;
     484                }
     485        }
     486        switch (hardware) {
     487        case MPU401_HW_AUREAL:
     488                mpu->write = mpu401_write_mmio;
     489                mpu->read = mpu401_read_mmio;
     490                break;
     491        default:
     492                mpu->write = mpu401_write_port;
     493                mpu->read = mpu401_read_port;
     494                break;
     495        }
     496        mpu->port = port;
     497        if (hardware == MPU401_HW_PC98II)
     498                mpu->cport = port + 2;
     499        else
     500                mpu->cport = port + 1;
     501        if (irq >= 0 && irq_flags) {
     502                if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags, "MPU401 UART", (void *) mpu)) {
     503                        snd_printk(KERN_ERR "mpu401_uart: unable to grab IRQ %d\n", irq);
     504                        snd_device_free(card, rmidi);
     505                        return -EBUSY;
     506                }
     507        }
     508        mpu->irq = irq;
     509        mpu->irq_flags = irq_flags;
     510        if (card->shortname[0])
     511                sprintf(rmidi->name, "%s MIDI", card->shortname);
     512        else
     513                sprintf(rmidi->name, "MPU-401 MIDI %d-%d", card->number, device);
     514        snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mpu401_uart_output);
     515        snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mpu401_uart_input);
     516        rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
     517                             SNDRV_RAWMIDI_INFO_INPUT |
     518                             SNDRV_RAWMIDI_INFO_DUPLEX;
     519        mpu->rmidi = rmidi;
     520        if (rrawmidi)
     521                *rrawmidi = rmidi;
     522        return 0;
    559523}
    560524
     
    568532static int __init alsa_mpu401_uart_init(void)
    569533{
    570     return 0;
     534        return 0;
    571535}
    572536
Note: See TracChangeset for help on using the changeset viewer.