Ignore:
Timestamp:
Mar 24, 2008, 2:43:42 AM (17 years ago)
Author:
Paul Smedley
Message:

Update source to ALSA 1.0.16 level

File:
1 edited

Legend:

Unmodified
Added
Removed
  • GPL/branches/uniaud-2.0/alsa-kernel/drivers/serial-u16550.c

    r34 r305  
    11/*
    22 *   serial.c
    3  *   Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
     3 *   Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
    44 *                    Isaku Yamahata <yamahata@private.email.ne.jp>,
    55 *                    George Hansper <ghansper@apana.org.au>,
     
    77 *
    88 *   This code is based on the code from ALSA 0.5.9, but heavily rewritten.
    9  *
    10  * Sat Mar 31 17:27:57 PST 2001 tim.mann@compaq.com
    11  *      Added support for the Midiator MS-124T and for the MS-124W in
    12  *      Single Addressed (S/A) or Multiple Burst (M/B) mode, with
    13  *      power derived either parasitically from the serial port or
    14  *      from a separate power supply.
    15  *
    16  *      The new snd_adaptor module parameter allows you to select
    17  *      either the default Roland Soundcanvas support (0), which was
    18  *      previously included in this driver but was not documented,
    19  *      Midiator MS-124T support (1), Midiator MS-124W S/A mode
    20  *      support (2), or MS-124W M/B mode support (3).  For the
    21  *      Midiator MS-124W, you must set the physical M-S and A-B
    22  *      switches on the Midiator to match the driver mode you select.
    23  *
    24  *      - In Roland Soundcanvas mode, multiple ALSA raw MIDI
    25  *      substreams are supported (midiCnD0-midiCnD15).  Whenever you
    26  *      write to a different substream, the driver sends the
    27  *      nonstandard MIDI command sequence F5 NN, where NN is the
    28  *      substream number plus 1.  Roland modules use this command to
    29  *      switch between different "parts", so this feature lets you
    30  *      treat each part as a distinct raw MIDI substream.  The driver
    31  *      provides no way to send F5 00 (no selection) or to not send
    32  *      the F5 NN command sequence at all; perhaps it ought to.
    33  *
    34  *      - In MS-124T mode, one raw MIDI substream is supported
    35  *      (midiCnD0); the snd_outs module parameter is automatically set
    36  *      to 1.  The driver sends the same data to all four MIDI Out
    37  *      connectors.  Set the A-B switch and the snd_speed module
    38  *      parameter to match (A=19200, B=9600).
    39  *
    40  *      Usage example for MS-124T, with A-B switch in A position:
    41  *        setserial /dev/ttyS0 uart none
    42  *        /sbin/modprobe snd-card-serial snd_port=0x3f8 snd_irq=4 \
    43  *            snd_adaptor=1 snd_speed=19200
    44  *
    45  *      - In MS-124W S/A mode, one raw MIDI substream is supported
    46  *      (midiCnD0); the snd_outs module parameter is automatically set
    47  *      to 1.  The driver sends the same data to all four MIDI Out
    48  *      connectors at full MIDI speed.
    49  *
    50  *      Usage example for S/A mode:
    51  *        setserial /dev/ttyS0 uart none
    52  *        /sbin/modprobe snd-card-serial snd_port=0x3f8 snd_irq=4 \
    53  *            snd_adaptor=2
    54  *
    55  *      - In MS-124W M/B mode, the driver supports 16 ALSA raw MIDI
    56  *      substreams; the snd_outs module parameter is automatically set
    57  *      to 16.  The substream number gives a bitmask of which MIDI Out
    58  *      connectors the data should be sent to, with midiCnD1 sending
    59  *      to Out 1, midiCnD2 to Out 2, midiCnD4 to Out 3, and midiCnD8
    60  *      to Out 4.  Thus midiCnD15 sends the data to all 4 ports.  As a
    61  *      special case, midiCnD0 also sends to all ports, since it is
    62  *      not useful to send the data to no ports.  M/B mode has extra
    63  *      overhead to select the MIDI Out for each byte, so the
    64  *      aggregate data rate across all four MIDI Outs is at most one
    65  *      byte every 520 us, as compared with the full MIDI data rate of
    66  *      one byte every 320 us per port.
    67  *
    68  *      Usage example for M/B mode:
    69  *        setserial /dev/ttyS0 uart none
    70  *        /sbin/insmod snd-card-serial snd_port=0x3f8 snd_irq=4 \
    71  *            snd_adaptor=3
    72  *
    73  *      - The MS-124W hardware's M/A mode is currently not supported.
    74  *      This mode allows the MIDI Outs to act independently at double
    75  *      the aggregate throughput of M/B, but does not allow sending
    76  *      the same byte simultaneously to multiple MIDI Outs.  The M/A
    77  *      protocol requires the driver to twiddle the modem control
    78  *      lines under timing constraints, so it would be a bit more
    79  *      complicated to implement than the other modes.
    80  *
    81  *      - Midiator models other than MS-124W and MS-124T are currently
    82  *      not supported.  Note that the suffix letter is significant;
    83  *      the MS-124 and MS-124B are not compatible, nor are the other
    84  *      known models MS-101, MS-101B, MS-103, and MS-114.  I do have
    85  *      documentation that partially covers these models, but no units
    86  *      to experiment with.  The MS-124W support is tested with a real
    87  *      unit.  The MS-124T support is untested, but should work.
    889 *
    8910 *   This program is free software; you can redistribute it and/or modify
     
    9920 *   You should have received a copy of the GNU General Public License
    10021 *   along with this program; if not, write to the Free Software
    101  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     22 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    10223 *
     24 * Sat Mar 31 17:27:57 PST 2001 tim.mann@compaq.com
     25 *      Added support for the Midiator MS-124T and for the MS-124W in
     26 *      Single Addressed (S/A) or Multiple Burst (M/B) mode, with
     27 *      power derived either parasitically from the serial port or
     28 *      from a separate power supply.
     29 *
     30 *      More documentation can be found in serial-u16550.txt.
    10331 */
    10432
    105 
    106 #define SNDRV_MAIN_OBJECT_FILE
    107 
    108 #include <sound/driver.h>
     33#include <linux/init.h>
     34#include <linux/interrupt.h>
     35#include <linux/err.h>
     36#include <linux/platform_device.h>
     37#include <linux/slab.h>
     38#include <linux/ioport.h>
     39#include <linux/moduleparam.h>
     40#include <sound/core.h>
    10941#include <sound/rawmidi.h>
    110 #define SNDRV_GET_ID
    11142#include <sound/initval.h>
    11243
    11344#include <linux/serial_reg.h>
    114 
    115 EXPORT_NO_SYMBOLS;
    116 MODULE_DESCRIPTION("MIDI serial");
    117 MODULE_CLASSES("{sound}");
    118 MODULE_DEVICES("{{ALSA, MIDI serial}}");
     45#include <linux/jiffies.h>
     46
     47#include <asm/io.h>
     48
     49MODULE_DESCRIPTION("MIDI serial u16550");
     50MODULE_LICENSE("GPL");
     51MODULE_SUPPORTED_DEVICE("{{ALSA, MIDI serial u16550}}");
    11952
    12053#define SNDRV_SERIAL_SOUNDCANVAS 0 /* Roland Soundcanvas; F5 NN selects part */
     
    12255#define SNDRV_SERIAL_MS124W_SA 2   /* Midiator MS-124W in S/A mode */
    12356#define SNDRV_SERIAL_MS124W_MB 3   /* Midiator MS-124W in M/B mode */
    124 #define SNDRV_SERIAL_MAX_ADAPTOR SNDRV_SERIAL_MS124W_MB
     57#define SNDRV_SERIAL_GENERIC 4     /* Generic Interface */
     58#define SNDRV_SERIAL_MAX_ADAPTOR SNDRV_SERIAL_GENERIC
    12559static char *adaptor_names[] = {
    126     "Soundcanvas",
    127     "MS-124T",
    128     "MS-124W S/A",
    129     "MS-124W M/B"
     60        "Soundcanvas",
     61        "MS-124T",
     62        "MS-124W S/A",
     63        "MS-124W M/B",
     64        "Generic"
    13065};
    13166
    132 static int snd_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;  /* Index 0-MAX */
    133 static char *snd_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;   /* ID for this card */
    134 static int snd_enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;      /* Enable this card */
    135 static long snd_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;     /* 0x3f8,0x2f8,0x3e8,0x2e8 */
    136 static int snd_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;    /* 3,4,5,7,9,10,11,14,15 */
    137 #ifdef TARGET_OS2
    138 static int snd_speed[SNDRV_CARDS] = {REPEAT_SNDRV(38400)}; /* 9600,19200,38400,57600,115200 */
    139 static int snd_base[SNDRV_CARDS] = {REPEAT_SNDRV(115200)}; /* baud base */
    140 static int snd_outs[SNDRV_CARDS] = {REPEAT_SNDRV(1)};   /* 1 to 16 */
    141 static int snd_adaptor[SNDRV_CARDS] = {REPEAT_SNDRV(SNDRV_SERIAL_SOUNDCANVAS)};
    142 #else
    143 static int snd_speed[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 38400}; /* 9600,19200,38400,57600,115200 */
    144 static int snd_base[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 115200}; /* baud base */
    145 static int snd_outs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};     /* 1 to 16 */
    146 static int snd_adaptor[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = SNDRV_SERIAL_SOUNDCANVAS};
    147 #endif
    148 
    149 MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
    150 MODULE_PARM_DESC(snd_index, "Index value for Serial MIDI.");
    151 MODULE_PARM_SYNTAX(snd_index, SNDRV_INDEX_DESC);
    152 MODULE_PARM(snd_id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
    153 MODULE_PARM_DESC(snd_id, "ID string for Serial MIDI.");
    154 MODULE_PARM_SYNTAX(snd_id, SNDRV_ID_DESC);
    155 MODULE_PARM(snd_enable, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
    156 MODULE_PARM_DESC(snd_enable, "Enable UART16550A chip.");
    157 MODULE_PARM_SYNTAX(snd_enable, SNDRV_ENABLE_DESC);
    158 MODULE_PARM(snd_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
    159 MODULE_PARM_DESC(snd_port, "Port # for UART16550A chip.");
    160 MODULE_PARM_SYNTAX(snd_port, SNDRV_PORT12_DESC);
    161 MODULE_PARM(snd_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
    162 MODULE_PARM_DESC(snd_irq, "IRQ # for UART16550A chip.");
    163 MODULE_PARM_SYNTAX(snd_irq, SNDRV_IRQ_DESC);
    164 MODULE_PARM(snd_speed, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
    165 MODULE_PARM_DESC(snd_speed, "Speed in bauds.");
    166 MODULE_PARM_SYNTAX(snd_speed, SNDRV_ENABLED ",allows:{9600,19200,38400,57600,115200},dialog:list");
    167 MODULE_PARM(snd_base, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
    168 MODULE_PARM_DESC(snd_base, "Base for divisor in bauds.");
    169 MODULE_PARM_SYNTAX(snd_base, SNDRV_ENABLED ",allows:{57600,115200,230400,460800},dialog:list");
    170 MODULE_PARM(snd_outs, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
    171 MODULE_PARM_DESC(snd_outs, "Number of MIDI outputs.");
    172 MODULE_PARM_SYNTAX(snd_outs, SNDRV_ENABLED ",allows:{{1,16}},dialog:list");
    173 MODULE_PARM(snd_adaptor, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
    174 MODULE_PARM_DESC(snd_adaptor, "Type of adaptor.");
    175 MODULE_PARM_SYNTAX(snd_adaptor, SNDRV_ENABLED ",allows:{{0=Soundcanvas,1=MS-124T,2=MS-124W S/A,3=MS-124W M/B}},dialog:list");
     67#define SNDRV_SERIAL_NORMALBUFF 0 /* Normal blocking buffer operation */
     68#define SNDRV_SERIAL_DROPBUFF   1 /* Non-blocking discard operation */
     69
     70static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;      /* Index 0-MAX */
     71static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;       /* ID for this card */
     72static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
     73static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x3f8,0x2f8,0x3e8,0x2e8 */
     74static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;        /* 3,4,5,7,9,10,11,14,15 */
     75static int speed[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 38400}; /* 9600,19200,38400,57600,115200 */
     76static int base[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 115200}; /* baud base */
     77static int outs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};  /* 1 to 16 */
     78static int ins[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};  /* 1 to 16 */
     79static int adaptor[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = SNDRV_SERIAL_SOUNDCANVAS};
     80static int droponfull[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS -1)] = SNDRV_SERIAL_NORMALBUFF };
     81
     82module_param_array(index, int, NULL, 0444);
     83MODULE_PARM_DESC(index, "Index value for Serial MIDI.");
     84module_param_array(id, charp, NULL, 0444);
     85MODULE_PARM_DESC(id, "ID string for Serial MIDI.");
     86module_param_array(enable, bool, NULL, 0444);
     87MODULE_PARM_DESC(enable, "Enable UART16550A chip.");
     88module_param_array(port, long, NULL, 0444);
     89MODULE_PARM_DESC(port, "Port # for UART16550A chip.");
     90module_param_array(irq, int, NULL, 0444);
     91MODULE_PARM_DESC(irq, "IRQ # for UART16550A chip.");
     92module_param_array(speed, int, NULL, 0444);
     93MODULE_PARM_DESC(speed, "Speed in bauds.");
     94module_param_array(base, int, NULL, 0444);
     95MODULE_PARM_DESC(base, "Base for divisor in bauds.");
     96module_param_array(outs, int, NULL, 0444);
     97MODULE_PARM_DESC(outs, "Number of MIDI outputs.");
     98module_param_array(ins, int, NULL, 0444);
     99MODULE_PARM_DESC(ins, "Number of MIDI inputs.");
     100module_param_array(droponfull, bool, NULL, 0444);
     101MODULE_PARM_DESC(droponfull, "Flag to enable drop-on-full buffer mode");
     102
     103module_param_array(adaptor, int, NULL, 0444);
     104MODULE_PARM_DESC(adaptor, "Type of adaptor.");
    176105
    177106/*#define SNDRV_SERIAL_MS124W_MB_NOCOMBO 1*/  /* Address outs as 0-3 instead of bitmap */
    178107
    179108#define SNDRV_SERIAL_MAX_OUTS   16              /* max 64, min 16 */
    180 
    181 #define TX_BUFF_SIZE            (1<<9)          /* Must be 2^n */
     109#define SNDRV_SERIAL_MAX_INS    16              /* max 64, min 16 */
     110
     111#define TX_BUFF_SIZE            (1<<15)         /* Must be 2^n */
    182112#define TX_BUFF_MASK            (TX_BUFF_SIZE - 1)
    183113
     
    188118#define SERIAL_MODE_OUTPUT_TRIGGERED    (1 << 3)
    189119
    190 typedef struct _snd_uart16550 {
    191     snd_card_t *card;
    192     snd_rawmidi_t *rmidi;
    193     snd_rawmidi_substream_t *midi_output[SNDRV_SERIAL_MAX_OUTS];
    194     snd_rawmidi_substream_t *midi_input;
    195 
    196     int filemode;               //open status of file
    197 
    198     spinlock_t open_lock;
    199 
    200     int irq;
    201 
    202     unsigned long base;
    203     struct resource *res_base;
    204 
    205     unsigned int speed;
    206     unsigned int speed_base;
    207     unsigned char divisor;
    208 
    209     unsigned char old_divisor_lsb;
    210     unsigned char old_divisor_msb;
    211     unsigned char old_line_ctrl_reg;
    212 
    213     // parameter for using of write loop
    214     short int fifo_limit;       //used in uart16550
    215     short int fifo_count;       //used in uart16550
    216 
    217     // type of adaptor
    218     int adaptor;
    219 
    220     // outputs
    221     int prev_out;
    222     unsigned char prev_status[SNDRV_SERIAL_MAX_OUTS];
    223 
    224     // write buffer and its writing/reading position
    225     unsigned char tx_buff[TX_BUFF_SIZE];
    226     int buff_in_count;
    227     int buff_in;
    228     int buff_out;
    229 
    230     // wait timer
    231     unsigned int timer_running:1;
    232     struct timer_list buffer_timer;
    233 
    234 } snd_uart16550_t;
    235 
    236 static snd_card_t *snd_serial_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
    237 
    238 inline static void snd_uart16550_add_timer(snd_uart16550_t *uart)
    239 {
    240     if (! uart->timer_running) {
    241         /* timer 38600bps * 10bit * 16byte */
    242         uart->buffer_timer.expires = jiffies + (HZ+255)/256;
    243         uart->timer_running = 1;
    244         add_timer(&uart->buffer_timer);
    245     }
    246 }
    247 
    248 inline static void snd_uart16550_del_timer(snd_uart16550_t *uart)
    249 {
    250     if (uart->timer_running) {
    251         del_timer(&uart->buffer_timer);
    252         uart->timer_running = 0;
    253     }
     120struct snd_uart16550 {
     121        struct snd_card *card;
     122        struct snd_rawmidi *rmidi;
     123        struct snd_rawmidi_substream *midi_output[SNDRV_SERIAL_MAX_OUTS];
     124        struct snd_rawmidi_substream *midi_input[SNDRV_SERIAL_MAX_INS];
     125
     126        int filemode;           /* open status of file */
     127
     128        spinlock_t open_lock;
     129
     130        int irq;
     131
     132        unsigned long base;
     133        struct resource *res_base;
     134
     135        unsigned int speed;
     136        unsigned int speed_base;
     137        unsigned char divisor;
     138
     139        unsigned char old_divisor_lsb;
     140        unsigned char old_divisor_msb;
     141        unsigned char old_line_ctrl_reg;
     142
     143        /* parameter for using of write loop */
     144        short int fifo_limit;   /* used in uart16550 */
     145        short int fifo_count;   /* used in uart16550 */
     146
     147        /* type of adaptor */
     148        int adaptor;
     149
     150        /* inputs */
     151        int prev_in;
     152        unsigned char rstatus;
     153
     154        /* outputs */
     155        int prev_out;
     156        unsigned char prev_status[SNDRV_SERIAL_MAX_OUTS];
     157
     158        /* write buffer and its writing/reading position */
     159        unsigned char tx_buff[TX_BUFF_SIZE];
     160        int buff_in_count;
     161        int buff_in;
     162        int buff_out;
     163        int drop_on_full;
     164
     165        /* wait timer */
     166        unsigned int timer_running:1;
     167        struct timer_list buffer_timer;
     168
     169};
     170
     171static struct platform_device *devices[SNDRV_CARDS];
     172
     173static inline void snd_uart16550_add_timer(struct snd_uart16550 *uart)
     174{
     175        if (!uart->timer_running) {
     176                /* timer 38600bps * 10bit * 16byte */
     177                uart->buffer_timer.expires = jiffies + (HZ+255)/256;
     178                uart->timer_running = 1;
     179                add_timer(&uart->buffer_timer);
     180        }
     181}
     182
     183static inline void snd_uart16550_del_timer(struct snd_uart16550 *uart)
     184{
     185        if (uart->timer_running) {
     186                del_timer(&uart->buffer_timer);
     187                uart->timer_running = 0;
     188        }
    254189}
    255190
    256191/* This macro is only used in snd_uart16550_io_loop */
    257 inline static void snd_uart16550_buffer_output(snd_uart16550_t *uart)
    258 {
    259     unsigned short buff_out = uart->buff_out;
    260     outb(uart->tx_buff[buff_out], uart->base + UART_TX);
    261     uart->fifo_count++;
    262     buff_out++;
    263     buff_out &= TX_BUFF_MASK;
    264     uart->buff_out = buff_out;
    265     uart->buff_in_count--;
     192static inline void snd_uart16550_buffer_output(struct snd_uart16550 *uart)
     193{
     194        unsigned short buff_out = uart->buff_out;
     195        if (uart->buff_in_count > 0) {
     196                outb(uart->tx_buff[buff_out], uart->base + UART_TX);
     197                uart->fifo_count++;
     198                buff_out++;
     199                buff_out &= TX_BUFF_MASK;
     200                uart->buff_out = buff_out;
     201                uart->buff_in_count--;
     202        }
    266203}
    267204
    268205/* This loop should be called with interrupts disabled
    269  * We don't want to interrupt this,
    270  * as we're already handling an interupt
     206 * We don't want to interrupt this, 
     207 * as we're already handling an interrupt
    271208 */
    272 static void snd_uart16550_io_loop(snd_uart16550_t * uart)
    273 {
    274     unsigned char c, status;
    275 
    276     /* Read Loop */
    277     while ((status = inb(uart->base + UART_LSR)) & UART_LSR_DR) {
    278         /* while receive data ready */
    279         c = inb(uart->base + UART_RX);
    280         if (uart->filemode & SERIAL_MODE_INPUT_OPEN) {
    281             snd_rawmidi_receive(uart->midi_input, &c, 1);
    282         }
    283         if (status & UART_LSR_OE)
    284             snd_printk("%s: Overrun on device at 0x%lx\n",
    285                        uart->rmidi->name, uart->base);
    286     }
    287 
    288     /* no need of check SERIAL_MODE_OUTPUT_OPEN because if not,
    289      buffer is never filled. */
    290     /* Check write status */
    291     if (status & UART_LSR_THRE) {
    292         uart->fifo_count = 0;
    293     }
    294     if (uart->adaptor == SNDRV_SERIAL_MS124W_SA) {
    295         /* Can't use FIFO, must send only when CTS is true */
    296         status = inb(uart->base + UART_MSR);
    297         if (uart->fifo_count == 0 && (status & UART_MSR_CTS)
    298             && uart->buff_in_count > 0)
    299             snd_uart16550_buffer_output(uart);
    300     } else {
    301         /* Write loop */
    302         while (uart->fifo_count < uart->fifo_limit      /* Can we write ? */
    303                && uart->buff_in_count > 0)      /* Do we want to? */
    304             snd_uart16550_buffer_output(uart);
    305     }
    306     if (uart->irq < 0 && uart->buff_in_count > 0)
    307         snd_uart16550_add_timer(uart);
     209static void snd_uart16550_io_loop(struct snd_uart16550 * uart)
     210{
     211        unsigned char c, status;
     212        int substream;
     213
     214        /* recall previous stream */
     215        substream = uart->prev_in;
     216
     217        /* Read Loop */
     218        while ((status = inb(uart->base + UART_LSR)) & UART_LSR_DR) {
     219                /* while receive data ready */
     220                c = inb(uart->base + UART_RX);
     221
     222                /* keep track of last status byte */
     223                if (c & 0x80)
     224                        uart->rstatus = c;
     225
     226                /* handle stream switch */
     227                if (uart->adaptor == SNDRV_SERIAL_GENERIC) {
     228                        if (uart->rstatus == 0xf5) {
     229                                if (c <= SNDRV_SERIAL_MAX_INS && c > 0)
     230                                        substream = c - 1;
     231                                if (c != 0xf5)
     232                                        /* prevent future bytes from being
     233                                           interpreted as streams */
     234                                        uart->rstatus = 0;
     235                        } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN)
     236                                   && uart->midi_input[substream])
     237                                snd_rawmidi_receive(uart->midi_input[substream],
     238                                                    &c, 1);
     239                } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) &&
     240                           uart->midi_input[substream])
     241                        snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
     242
     243                if (status & UART_LSR_OE)
     244                        snd_printk("%s: Overrun on device at 0x%lx\n",
     245                               uart->rmidi->name, uart->base);
     246        }
     247
     248        /* remember the last stream */
     249        uart->prev_in = substream;
     250
     251        /* no need of check SERIAL_MODE_OUTPUT_OPEN because if not,
     252           buffer is never filled. */
     253        /* Check write status */
     254        if (status & UART_LSR_THRE)
     255                uart->fifo_count = 0;
     256        if (uart->adaptor == SNDRV_SERIAL_MS124W_SA
     257           || uart->adaptor == SNDRV_SERIAL_GENERIC) {
     258                /* Can't use FIFO, must send only when CTS is true */
     259                status = inb(uart->base + UART_MSR);
     260                while (uart->fifo_count == 0 && (status & UART_MSR_CTS) &&
     261                       uart->buff_in_count > 0) {
     262                       snd_uart16550_buffer_output(uart);
     263                       status = inb(uart->base + UART_MSR);
     264                }
     265        } else {
     266                /* Write loop */
     267                while (uart->fifo_count < uart->fifo_limit /* Can we write ? */
     268                       && uart->buff_in_count > 0)      /* Do we want to? */
     269                        snd_uart16550_buffer_output(uart);
     270        }
     271        if (uart->irq < 0 && uart->buff_in_count > 0)
     272                snd_uart16550_add_timer(uart);
    308273}
    309274
     
    311276 * ---------------------------
    312277 * After receiving a interrupt, it is important to indicate to the UART that
    313  * this has been done.
    314  * For a Rx interupt, this is done by reading the received byte.
    315  * For a Tx interupt this is done by either:
     278 * this has been done. 
     279 * For a Rx interrupt, this is done by reading the received byte.
     280 * For a Tx interrupt this is done by either:
    316281 * a) Writing a byte
    317282 * b) Reading the IIR
    318  * It is particularly important to read the IIR if a Tx interupt is received
     283 * It is particularly important to read the IIR if a Tx interrupt is received
    319284 * when there is no data in tx_buff[], as in this case there no other
    320  * indication that the interupt has been serviced, and it remains outstanding
    321  * indefinitely. This has the curious side effect that and no further interupts
     285 * indication that the interrupt has been serviced, and it remains outstanding
     286 * indefinitely. This has the curious side effect that and no further interrupts
    322287 * will be generated from this device AT ALL!!.
    323  * It is also desirable to clear outstanding interupts when the device is
     288 * It is also desirable to clear outstanding interrupts when the device is
    324289 * opened/closed.
    325290 *
     
    328293 * interrupts at all. (Possibly tied to an internal pull-up on CTS?)
    329294 */
    330 static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    331 {
    332     snd_uart16550_t *uart;
    333 
    334     uart = (snd_uart16550_t *) dev_id;
    335     spin_lock(&uart->open_lock);
    336     if (uart->filemode == SERIAL_MODE_NOT_OPENED) {
    337         spin_unlock(&uart->open_lock);
    338         return IRQ_HANDLED;
    339     }
    340     inb(uart->base + UART_IIR);         /* indicate to the UART that the interupt has been serviced */
    341     snd_uart16550_io_loop(uart);
    342     spin_unlock(&uart->open_lock);
    343     return IRQ_HANDLED;
     295static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id)
     296{
     297        struct snd_uart16550 *uart;
     298
     299        uart = dev_id;
     300        spin_lock(&uart->open_lock);
     301        if (uart->filemode == SERIAL_MODE_NOT_OPENED) {
     302                spin_unlock(&uart->open_lock);
     303                return IRQ_NONE;
     304        }
     305        /* indicate to the UART that the interrupt has been serviced */
     306        inb(uart->base + UART_IIR);
     307        snd_uart16550_io_loop(uart);
     308        spin_unlock(&uart->open_lock);
     309        return IRQ_HANDLED;
    344310}
    345311
     
    347313static void snd_uart16550_buffer_timer(unsigned long data)
    348314{
    349     snd_uart16550_t *uart;
    350 
    351     uart = (snd_uart16550_t *)data;
    352     spin_lock(&uart->open_lock);
    353     snd_uart16550_del_timer(uart);
    354     snd_uart16550_io_loop(uart);
    355     spin_unlock(&uart->open_lock);
     315        unsigned long flags;
     316        struct snd_uart16550 *uart;
     317
     318        uart = (struct snd_uart16550 *)data;
     319        spin_lock_irqsave(&uart->open_lock, flags);
     320        snd_uart16550_del_timer(uart);
     321        snd_uart16550_io_loop(uart);
     322        spin_unlock_irqrestore(&uart->open_lock, flags);
    356323}
    357324
     
    361328 *  return negative error if not found
    362329 */
    363 static int __init snd_uart16550_detect(unsigned int io_base)
    364 {
    365     int ok;
    366     unsigned char c;
    367 
    368     if (check_region(io_base, 8))
    369         return -EBUSY;
    370 
    371     /* Do some vague tests for the presence of the uart */
    372     if (io_base == 0)
    373         return -ENODEV; /* Not configured */
    374 
    375     ok = 1;                     /* uart detected unless one of the following tests should fail */
    376     /* 8 data-bits, 1 stop-bit, parity off, DLAB = 0 */
    377     outb(UART_LCR_WLEN8, io_base + UART_LCR); /* Line Control Register */
    378     c = inb(io_base + UART_IER);
    379     /* The top four bits of the IER should always == 0 */
    380     if ((c & 0xf0) != 0)
    381         ok = 0;         /* failed */
    382 
    383     outb(0xaa, io_base + UART_SCR);
    384     /* Write arbitrary data into the scratch reg */
    385     c = inb(io_base + UART_SCR);
    386     /* If it comes back, it's OK */
    387     if (c != 0xaa)
    388         ok = 0;         /* failed */
    389 
    390     outb(0x55, io_base + UART_SCR);
    391     /* Write arbitrary data into the scratch reg */
    392     c = inb(io_base + UART_SCR);
    393     /* If it comes back, it's OK */
    394     if (c != 0x55)
    395         ok = 0;         /* failed */
    396 
    397     return ok;
    398 }
    399 
    400 static void snd_uart16550_do_open(snd_uart16550_t * uart)
    401 {
    402     char byte;
    403 
    404     /* Initialize basic variables */
    405     uart->buff_in_count = 0;
    406     uart->buff_in = 0;
    407     uart->buff_out = 0;
    408     uart->fifo_limit = 1;
    409     uart->fifo_count = 0;
    410     uart->timer_running = 0;
    411 
    412     outb(UART_FCR_ENABLE_FIFO   /* Enable FIFO's (if available) */
    413          | UART_FCR_CLEAR_RCVR  /* Clear receiver FIFO */
    414          | UART_FCR_CLEAR_XMIT  /* Clear transmitter FIFO */
    415          | UART_FCR_TRIGGER_4   /* Set FIFO trigger at 4-bytes */
    416          /* NOTE: interupt generated after T=(time)4-bytes
    417           * if less than UART_FCR_TRIGGER bytes received
    418           */
    419          ,uart->base + UART_FCR);       /* FIFO Control Register */
    420 
    421     if ((inb(uart->base + UART_IIR) & 0xf0) == 0xc0)
    422         uart->fifo_limit = 16;
    423     if (uart->divisor != 0) {
    424         uart->old_line_ctrl_reg = inb(uart->base + UART_LCR);
    425         outb(UART_LCR_DLAB      /* Divisor latch access bit */
    426              ,uart->base + UART_LCR);   /* Line Control Register */
    427         uart->old_divisor_lsb = inb(uart->base + UART_DLL);
    428         uart->old_divisor_msb = inb(uart->base + UART_DLM);
    429 
    430         outb(uart->divisor
    431              ,uart->base + UART_DLL);   /* Divisor Latch Low */
    432         outb(0
    433              ,uart->base + UART_DLM);   /* Divisor Latch High */
    434         /* DLAB is reset to 0 in next outb() */
    435     }
    436     /* Set serial parameters (parity off, etc) */
    437     outb(UART_LCR_WLEN8 /* 8 data-bits */
    438          | 0            /* 1 stop-bit */
    439          | 0            /* parity off */
    440          | 0            /* DLAB = 0 */
    441          ,uart->base + UART_LCR);       /* Line Control Register */
    442 
    443     switch (uart->adaptor) {
    444     default:
    445         outb(UART_MCR_RTS       /* Set Request-To-Send line active */
    446              | UART_MCR_DTR     /* Set Data-Terminal-Ready line active */
    447              | UART_MCR_OUT2    /* Set OUT2 - not always required, but when
    448              * it is, it is ESSENTIAL for enabling interrupts
    449              */
    450              ,uart->base + UART_MCR);   /* Modem Control Register */
    451         break;
    452     case SNDRV_SERIAL_MS124W_SA:
    453     case SNDRV_SERIAL_MS124W_MB:
    454         /* MS-124W can draw power from RTS and DTR if they
    455          are in opposite states. */
    456         outb(UART_MCR_RTS | (0&UART_MCR_DTR) | UART_MCR_OUT2,
    457              uart->base + UART_MCR);
    458         break;
    459     case SNDRV_SERIAL_MS124T:
    460         /* MS-124T can draw power from RTS and/or DTR (preferably
    461          both) if they are both asserted. */
    462         outb(UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2,
    463              uart->base + UART_MCR);
    464         break;
    465     }
    466 
    467     if (uart->irq < 0) {
    468         byte = (0 & UART_IER_RDI)       /* Disable Receiver data interupt */
    469             |(0 & UART_IER_THRI)        /* Disable Transmitter holding register empty interupt */
    470             ;
    471     } else if (uart->adaptor == SNDRV_SERIAL_MS124W_SA) {
    472         byte = UART_IER_RDI     /* Enable Receiver data interrupt */
    473             | UART_IER_MSI      /* Enable Modem status interrupt */
    474             ;
    475     } else {
    476         byte = UART_IER_RDI     /* Enable Receiver data interupt */
    477             | UART_IER_THRI     /* Enable Transmitter holding register empty interupt */
    478             ;
    479     }
    480     outb(byte, uart->base + UART_IER);  /* Interupt enable Register */
    481 
    482     inb(uart->base + UART_LSR); /* Clear any pre-existing overrun indication */
    483     inb(uart->base + UART_IIR); /* Clear any pre-existing transmit interrupt */
    484     inb(uart->base + UART_RX);  /* Clear any pre-existing receive interrupt */
    485 }
    486 
    487 static void snd_uart16550_do_close(snd_uart16550_t * uart)
    488 {
    489     if (uart->irq < 0)
    490         snd_uart16550_del_timer(uart);
    491 
    492     /* NOTE: may need to disable interrupts before de-registering out handler.
    493      * For now, the consequences are harmless.
    494      */
    495 
    496     outb((0 & UART_IER_RDI)             /* Disable Receiver data interupt */
    497          |(0 & UART_IER_THRI)   /* Disable Transmitter holding register empty interupt */
    498          ,uart->base + UART_IER);       /* Interupt enable Register */
    499 
    500     switch (uart->adaptor) {
    501     default:
    502         outb((0 & UART_MCR_RTS)         /* Deactivate Request-To-Send line  */
    503              |(0 & UART_MCR_DTR)        /* Deactivate Data-Terminal-Ready line */
    504              |(0 & UART_MCR_OUT2)       /* Deactivate OUT2 */
    505              ,uart->base + UART_MCR);   /* Modem Control Register */
    506         break;
    507     case SNDRV_SERIAL_MS124W_SA:
    508     case SNDRV_SERIAL_MS124W_MB:
    509         /* MS-124W can draw power from RTS and DTR if they
    510          are in opposite states; leave it powered. */
    511         outb(UART_MCR_RTS | (0&UART_MCR_DTR) | (0&UART_MCR_OUT2),
    512              uart->base + UART_MCR);
    513         break;
    514     case SNDRV_SERIAL_MS124T:
    515         /* MS-124T can draw power from RTS and/or DTR (preferably
    516          both) if they are both asserted; leave it powered. */
    517         outb(UART_MCR_RTS | UART_MCR_DTR | (0&UART_MCR_OUT2),
    518              uart->base + UART_MCR);
    519         break;
    520     }
    521 
    522     inb(uart->base + UART_IIR); /* Clear any outstanding interupts */
    523 
    524     /* Restore old divisor */
    525     if (uart->divisor != 0) {
    526         outb(UART_LCR_DLAB              /* Divisor latch access bit */
    527              ,uart->base + UART_LCR);   /* Line Control Register */
    528         outb(uart->old_divisor_lsb
    529              ,uart->base + UART_DLL);   /* Divisor Latch Low */
    530         outb(uart->old_divisor_msb
    531              ,uart->base + UART_DLM);   /* Divisor Latch High */
    532         /* Restore old LCR (data bits, stop bits, parity, DLAB) */
    533         outb(uart->old_line_ctrl_reg
    534              ,uart->base + UART_LCR);   /* Line Control Register */
    535     }
    536 }
    537 
    538 static int snd_uart16550_input_open(snd_rawmidi_substream_t * substream)
    539 {
    540     unsigned long flags;
    541     snd_uart16550_t *uart = substream->rmidi->private_data;
    542 
    543     spin_lock_irqsave(&uart->open_lock, flags);
    544     if (uart->filemode == SERIAL_MODE_NOT_OPENED)
    545         snd_uart16550_do_open(uart);
    546     uart->filemode |= SERIAL_MODE_INPUT_OPEN;
    547     uart->midi_input = substream;
    548     spin_unlock_irqrestore(&uart->open_lock, flags);
    549     return 0;
    550 }
    551 
    552 static int snd_uart16550_input_close(snd_rawmidi_substream_t * substream)
    553 {
    554     unsigned long flags;
    555     snd_uart16550_t *uart = substream->rmidi->private_data;
    556 
    557     spin_lock_irqsave(&uart->open_lock, flags);
    558     uart->filemode &= ~SERIAL_MODE_INPUT_OPEN;
    559     uart->midi_input = NULL;
    560     if (uart->filemode == SERIAL_MODE_NOT_OPENED)
    561         snd_uart16550_do_close(uart);
    562     spin_unlock_irqrestore(&uart->open_lock, flags);
    563     return 0;
    564 }
    565 
    566 static void snd_uart16550_input_trigger(snd_rawmidi_substream_t * substream, int up)
    567 {
    568     unsigned long flags;
    569     snd_uart16550_t *uart = substream->rmidi->private_data;
    570 
    571     spin_lock_irqsave(&uart->open_lock, flags);
    572     if (up) {
    573         uart->filemode |= SERIAL_MODE_INPUT_TRIGGERED;
    574     } else {
    575         uart->filemode &= ~SERIAL_MODE_INPUT_TRIGGERED;
    576     }
    577     spin_unlock_irqrestore(&uart->open_lock, flags);
    578 }
    579 
    580 static int snd_uart16550_output_open(snd_rawmidi_substream_t * substream)
    581 {
    582     unsigned long flags;
    583     snd_uart16550_t *uart = substream->rmidi->private_data;
    584 
    585     spin_lock_irqsave(&uart->open_lock, flags);
    586     if (uart->filemode == SERIAL_MODE_NOT_OPENED)
    587         snd_uart16550_do_open(uart);
    588     uart->filemode |= SERIAL_MODE_OUTPUT_OPEN;
    589     uart->midi_output[substream->number] = substream;
    590     spin_unlock_irqrestore(&uart->open_lock, flags);
    591     return 0;
     330static int __devinit snd_uart16550_detect(struct snd_uart16550 *uart)
     331{
     332        unsigned long io_base = uart->base;
     333        int ok;
     334        unsigned char c;
     335
     336        /* Do some vague tests for the presence of the uart */
     337        if (io_base == 0 || io_base == SNDRV_AUTO_PORT) {
     338                return -ENODEV; /* Not configured */
     339        }
     340
     341        uart->res_base = request_region(io_base, 8, "Serial MIDI");
     342        if (uart->res_base == NULL) {
     343                snd_printk(KERN_ERR "u16550: can't grab port 0x%lx\n", io_base);
     344                return -EBUSY;
     345        }
     346
     347        /* uart detected unless one of the following tests should fail */
     348        ok = 1;
     349        /* 8 data-bits, 1 stop-bit, parity off, DLAB = 0 */
     350        outb(UART_LCR_WLEN8, io_base + UART_LCR); /* Line Control Register */
     351        c = inb(io_base + UART_IER);
     352        /* The top four bits of the IER should always == 0 */
     353        if ((c & 0xf0) != 0)
     354                ok = 0;         /* failed */
     355
     356        outb(0xaa, io_base + UART_SCR);
     357        /* Write arbitrary data into the scratch reg */
     358        c = inb(io_base + UART_SCR);
     359        /* If it comes back, it's OK */
     360        if (c != 0xaa)
     361                ok = 0;         /* failed */
     362
     363        outb(0x55, io_base + UART_SCR);
     364        /* Write arbitrary data into the scratch reg */
     365        c = inb(io_base + UART_SCR);
     366        /* If it comes back, it's OK */
     367        if (c != 0x55)
     368                ok = 0;         /* failed */
     369
     370        return ok;
     371}
     372
     373static void snd_uart16550_do_open(struct snd_uart16550 * uart)
     374{
     375        char byte;
     376
     377        /* Initialize basic variables */
     378        uart->buff_in_count = 0;
     379        uart->buff_in = 0;
     380        uart->buff_out = 0;
     381        uart->fifo_limit = 1;
     382        uart->fifo_count = 0;
     383        uart->timer_running = 0;
     384
     385        outb(UART_FCR_ENABLE_FIFO       /* Enable FIFO's (if available) */
     386             | UART_FCR_CLEAR_RCVR      /* Clear receiver FIFO */
     387             | UART_FCR_CLEAR_XMIT      /* Clear transmitter FIFO */
     388             | UART_FCR_TRIGGER_4       /* Set FIFO trigger at 4-bytes */
     389        /* NOTE: interrupt generated after T=(time)4-bytes
     390         * if less than UART_FCR_TRIGGER bytes received
     391         */
     392             ,uart->base + UART_FCR);   /* FIFO Control Register */
     393
     394        if ((inb(uart->base + UART_IIR) & 0xf0) == 0xc0)
     395                uart->fifo_limit = 16;
     396        if (uart->divisor != 0) {
     397                uart->old_line_ctrl_reg = inb(uart->base + UART_LCR);
     398                outb(UART_LCR_DLAB      /* Divisor latch access bit */
     399                     ,uart->base + UART_LCR);   /* Line Control Register */
     400                uart->old_divisor_lsb = inb(uart->base + UART_DLL);
     401                uart->old_divisor_msb = inb(uart->base + UART_DLM);
     402
     403                outb(uart->divisor
     404                     ,uart->base + UART_DLL);   /* Divisor Latch Low */
     405                outb(0
     406                     ,uart->base + UART_DLM);   /* Divisor Latch High */
     407                /* DLAB is reset to 0 in next outb() */
     408        }
     409        /* Set serial parameters (parity off, etc) */
     410        outb(UART_LCR_WLEN8     /* 8 data-bits */
     411             | 0                /* 1 stop-bit */
     412             | 0                /* parity off */
     413             | 0                /* DLAB = 0 */
     414             ,uart->base + UART_LCR);   /* Line Control Register */
     415
     416        switch (uart->adaptor) {
     417        default:
     418                outb(UART_MCR_RTS       /* Set Request-To-Send line active */
     419                     | UART_MCR_DTR     /* Set Data-Terminal-Ready line active */
     420                     | UART_MCR_OUT2    /* Set OUT2 - not always required, but when
     421                                         * it is, it is ESSENTIAL for enabling interrupts
     422                                 */
     423                     ,uart->base + UART_MCR);   /* Modem Control Register */
     424                break;
     425        case SNDRV_SERIAL_MS124W_SA:
     426        case SNDRV_SERIAL_MS124W_MB:
     427                /* MS-124W can draw power from RTS and DTR if they
     428                   are in opposite states. */
     429                outb(UART_MCR_RTS | (0&UART_MCR_DTR) | UART_MCR_OUT2,
     430                     uart->base + UART_MCR);
     431                break;
     432        case SNDRV_SERIAL_MS124T:
     433                /* MS-124T can draw power from RTS and/or DTR (preferably
     434                   both) if they are both asserted. */
     435                outb(UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2,
     436                     uart->base + UART_MCR);
     437                break;
     438        }
     439
     440        if (uart->irq < 0) {
     441                byte = (0 & UART_IER_RDI)       /* Disable Receiver data interrupt */
     442                    |(0 & UART_IER_THRI)        /* Disable Transmitter holding register empty interrupt */
     443                    ;
     444        } else if (uart->adaptor == SNDRV_SERIAL_MS124W_SA) {
     445                byte = UART_IER_RDI     /* Enable Receiver data interrupt */
     446                    | UART_IER_MSI      /* Enable Modem status interrupt */
     447                    ;
     448        } else if (uart->adaptor == SNDRV_SERIAL_GENERIC) {
     449                byte = UART_IER_RDI     /* Enable Receiver data interrupt */
     450                    | UART_IER_MSI      /* Enable Modem status interrupt */
     451                    | UART_IER_THRI     /* Enable Transmitter holding register empty interrupt */
     452                    ;
     453        } else {
     454                byte = UART_IER_RDI     /* Enable Receiver data interrupt */
     455                    | UART_IER_THRI     /* Enable Transmitter holding register empty interrupt */
     456                    ;
     457        }
     458        outb(byte, uart->base + UART_IER);      /* Interrupt enable Register */
     459
     460        inb(uart->base + UART_LSR);     /* Clear any pre-existing overrun indication */
     461        inb(uart->base + UART_IIR);     /* Clear any pre-existing transmit interrupt */
     462        inb(uart->base + UART_RX);      /* Clear any pre-existing receive interrupt */
     463}
     464
     465static void snd_uart16550_do_close(struct snd_uart16550 * uart)
     466{
     467        if (uart->irq < 0)
     468                snd_uart16550_del_timer(uart);
     469
     470        /* NOTE: may need to disable interrupts before de-registering out handler.
     471         * For now, the consequences are harmless.
     472         */
     473
     474        outb((0 & UART_IER_RDI)         /* Disable Receiver data interrupt */
     475             |(0 & UART_IER_THRI)       /* Disable Transmitter holding register empty interrupt */
     476             ,uart->base + UART_IER);   /* Interrupt enable Register */
     477
     478        switch (uart->adaptor) {
     479        default:
     480                outb((0 & UART_MCR_RTS)         /* Deactivate Request-To-Send line  */
     481                     |(0 & UART_MCR_DTR)        /* Deactivate Data-Terminal-Ready line */
     482                     |(0 & UART_MCR_OUT2)       /* Deactivate OUT2 */
     483                     ,uart->base + UART_MCR);   /* Modem Control Register */
     484          break;
     485        case SNDRV_SERIAL_MS124W_SA:
     486        case SNDRV_SERIAL_MS124W_MB:
     487                /* MS-124W can draw power from RTS and DTR if they
     488                   are in opposite states; leave it powered. */
     489                outb(UART_MCR_RTS | (0&UART_MCR_DTR) | (0&UART_MCR_OUT2),
     490                     uart->base + UART_MCR);
     491                break;
     492        case SNDRV_SERIAL_MS124T:
     493                /* MS-124T can draw power from RTS and/or DTR (preferably
     494                   both) if they are both asserted; leave it powered. */
     495                outb(UART_MCR_RTS | UART_MCR_DTR | (0&UART_MCR_OUT2),
     496                     uart->base + UART_MCR);
     497                break;
     498        }
     499
     500        inb(uart->base + UART_IIR);     /* Clear any outstanding interrupts */
     501
     502        /* Restore old divisor */
     503        if (uart->divisor != 0) {
     504                outb(UART_LCR_DLAB              /* Divisor latch access bit */
     505                     ,uart->base + UART_LCR);   /* Line Control Register */
     506                outb(uart->old_divisor_lsb
     507                     ,uart->base + UART_DLL);   /* Divisor Latch Low */
     508                outb(uart->old_divisor_msb
     509                     ,uart->base + UART_DLM);   /* Divisor Latch High */
     510                /* Restore old LCR (data bits, stop bits, parity, DLAB) */
     511                outb(uart->old_line_ctrl_reg
     512                     ,uart->base + UART_LCR);   /* Line Control Register */
     513        }
     514}
     515
     516static int snd_uart16550_input_open(struct snd_rawmidi_substream *substream)
     517{
     518        unsigned long flags;
     519        struct snd_uart16550 *uart = substream->rmidi->private_data;
     520
     521        spin_lock_irqsave(&uart->open_lock, flags);
     522        if (uart->filemode == SERIAL_MODE_NOT_OPENED)
     523                snd_uart16550_do_open(uart);
     524        uart->filemode |= SERIAL_MODE_INPUT_OPEN;
     525        uart->midi_input[substream->number] = substream;
     526        spin_unlock_irqrestore(&uart->open_lock, flags);
     527        return 0;
     528}
     529
     530static int snd_uart16550_input_close(struct snd_rawmidi_substream *substream)
     531{
     532        unsigned long flags;
     533        struct snd_uart16550 *uart = substream->rmidi->private_data;
     534
     535        spin_lock_irqsave(&uart->open_lock, flags);
     536        uart->filemode &= ~SERIAL_MODE_INPUT_OPEN;
     537        uart->midi_input[substream->number] = NULL;
     538        if (uart->filemode == SERIAL_MODE_NOT_OPENED)
     539                snd_uart16550_do_close(uart);
     540        spin_unlock_irqrestore(&uart->open_lock, flags);
     541        return 0;
     542}
     543
     544static void snd_uart16550_input_trigger(struct snd_rawmidi_substream *substream,
     545                                        int up)
     546{
     547        unsigned long flags;
     548        struct snd_uart16550 *uart = substream->rmidi->private_data;
     549
     550        spin_lock_irqsave(&uart->open_lock, flags);
     551        if (up)
     552                uart->filemode |= SERIAL_MODE_INPUT_TRIGGERED;
     553        else
     554                uart->filemode &= ~SERIAL_MODE_INPUT_TRIGGERED;
     555        spin_unlock_irqrestore(&uart->open_lock, flags);
     556}
     557
     558static int snd_uart16550_output_open(struct snd_rawmidi_substream *substream)
     559{
     560        unsigned long flags;
     561        struct snd_uart16550 *uart = substream->rmidi->private_data;
     562
     563        spin_lock_irqsave(&uart->open_lock, flags);
     564        if (uart->filemode == SERIAL_MODE_NOT_OPENED)
     565                snd_uart16550_do_open(uart);
     566        uart->filemode |= SERIAL_MODE_OUTPUT_OPEN;
     567        uart->midi_output[substream->number] = substream;
     568        spin_unlock_irqrestore(&uart->open_lock, flags);
     569        return 0;
    592570};
    593571
    594 static int snd_uart16550_output_close(snd_rawmidi_substream_t * substream)
    595 {
    596     unsigned long flags;
    597     snd_uart16550_t *uart = substream->rmidi->private_data;
    598 
    599     spin_lock_irqsave(&uart->open_lock, flags);
    600     uart->filemode &= ~SERIAL_MODE_OUTPUT_OPEN;
    601     uart->midi_output[substream->number] = NULL;
    602     if (uart->filemode == SERIAL_MODE_NOT_OPENED)
    603         snd_uart16550_do_close(uart);
    604     spin_unlock_irqrestore(&uart->open_lock, flags);
    605     return 0;
     572static int snd_uart16550_output_close(struct snd_rawmidi_substream *substream)
     573{
     574        unsigned long flags;
     575        struct snd_uart16550 *uart = substream->rmidi->private_data;
     576
     577        spin_lock_irqsave(&uart->open_lock, flags);
     578        uart->filemode &= ~SERIAL_MODE_OUTPUT_OPEN;
     579        uart->midi_output[substream->number] = NULL;
     580        if (uart->filemode == SERIAL_MODE_NOT_OPENED)
     581                snd_uart16550_do_close(uart);
     582        spin_unlock_irqrestore(&uart->open_lock, flags);
     583        return 0;
    606584};
    607585
    608 inline static void snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned char byte)
    609 {
    610     unsigned short buff_in = uart->buff_in;
    611     uart->tx_buff[buff_in] = byte;
    612     buff_in++;
    613     buff_in &= TX_BUFF_MASK;
    614     uart->buff_in = buff_in;
    615     uart->buff_in_count++;
    616     if (uart->irq < 0) /* polling mode */
    617         snd_uart16550_add_timer(uart);
    618 }
    619 
    620 static void snd_uart16550_output_byte(snd_uart16550_t *uart, snd_rawmidi_substream_t * substream, unsigned char midi_byte)
    621 {
    622     if (uart->buff_in_count == 0                            /* Buffer empty? */
    623         && (uart->adaptor != SNDRV_SERIAL_MS124W_SA ||
    624             (uart->fifo_count == 0                               /* FIFO empty? */
    625              && (inb(uart->base + UART_MSR) & UART_MSR_CTS)))) { /* CTS? */
    626 
    627         /* Tx Buffer Empty - try to write immediately */
    628         if ((inb(uart->base + UART_LSR) & UART_LSR_THRE) != 0) {
    629             /* Transmitter holding register (and Tx FIFO) empty */
    630             uart->fifo_count = 1;
    631             outb(midi_byte, uart->base + UART_TX);
    632         } else {
    633             if (uart->fifo_count < uart->fifo_limit) {
    634                 uart->fifo_count++;
    635                 outb(midi_byte, uart->base + UART_TX);
    636             } else {
    637                 /* Cannot write (buffer empty) - put char in buffer */
    638                 snd_uart16550_write_buffer(uart, midi_byte);
    639             }
    640         }
    641     } else {
    642         if (uart->buff_in_count >= TX_BUFF_SIZE) {
    643             snd_printk("%s: Buffer overrun on device at 0x%lx\n",
    644                        uart->rmidi->name, uart->base);
    645             return;
    646         }
    647         snd_uart16550_write_buffer(uart, midi_byte);
    648     }
    649 }
    650 
    651 static void snd_uart16550_output_write(snd_rawmidi_substream_t * substream)
    652 {
    653     unsigned long flags;
    654     unsigned char midi_byte, addr_byte;
    655     snd_uart16550_t *uart = substream->rmidi->private_data;
    656     char first;
    657 
    658     /* Interupts are disabled during the updating of the tx_buff,
    659      * since it is 'bad' to have two processes updating the same
    660      * variables (ie buff_in & buff_out)
    661      */
    662 
    663     spin_lock_irqsave(&uart->open_lock, flags);
    664 
    665     if (uart->irq < 0)  //polling
    666         snd_uart16550_io_loop(uart);
    667 
    668     if (uart->adaptor == SNDRV_SERIAL_MS124W_MB) {
    669         while (1) {
    670             /* buffer full? */
    671             /* in this mode we need two bytes of space */
    672             if (uart->buff_in_count > TX_BUFF_SIZE - 2)
    673                 break;
    674             if (snd_rawmidi_transmit(substream, &midi_byte, 1) != 1)
    675                 break;
    676 #if SNDRV_SERIAL_MS124W_MB_NOCOMBO
    677             /* select exactly one of the four ports */
    678             addr_byte = (1 << (substream->number + 4)) | 0x08;
     586static inline int snd_uart16550_buffer_can_write(struct snd_uart16550 *uart,
     587                                                 int Num)
     588{
     589        if (uart->buff_in_count + Num < TX_BUFF_SIZE)
     590                return 1;
     591        else
     592                return 0;
     593}
     594
     595static inline int snd_uart16550_write_buffer(struct snd_uart16550 *uart,
     596                                             unsigned char byte)
     597{
     598        unsigned short buff_in = uart->buff_in;
     599        if (uart->buff_in_count < TX_BUFF_SIZE) {
     600                uart->tx_buff[buff_in] = byte;
     601                buff_in++;
     602                buff_in &= TX_BUFF_MASK;
     603                uart->buff_in = buff_in;
     604                uart->buff_in_count++;
     605                if (uart->irq < 0) /* polling mode */
     606                        snd_uart16550_add_timer(uart);
     607                return 1;
     608        } else
     609                return 0;
     610}
     611
     612static int snd_uart16550_output_byte(struct snd_uart16550 *uart,
     613                                     struct snd_rawmidi_substream *substream,
     614                                     unsigned char midi_byte)
     615{
     616        if (uart->buff_in_count == 0                    /* Buffer empty? */
     617            && ((uart->adaptor != SNDRV_SERIAL_MS124W_SA &&
     618            uart->adaptor != SNDRV_SERIAL_GENERIC) ||
     619                (uart->fifo_count == 0                  /* FIFO empty? */
     620                 && (inb(uart->base + UART_MSR) & UART_MSR_CTS)))) { /* CTS? */
     621
     622                /* Tx Buffer Empty - try to write immediately */
     623                if ((inb(uart->base + UART_LSR) & UART_LSR_THRE) != 0) {
     624                        /* Transmitter holding register (and Tx FIFO) empty */
     625                        uart->fifo_count = 1;
     626                        outb(midi_byte, uart->base + UART_TX);
     627                } else {
     628                        if (uart->fifo_count < uart->fifo_limit) {
     629                                uart->fifo_count++;
     630                                outb(midi_byte, uart->base + UART_TX);
     631                        } else {
     632                                /* Cannot write (buffer empty) -
     633                                 * put char in buffer */
     634                                snd_uart16550_write_buffer(uart, midi_byte);
     635                        }
     636                }
     637        } else {
     638                if (!snd_uart16550_write_buffer(uart, midi_byte)) {
     639                        snd_printk("%s: Buffer overrun on device at 0x%lx\n",
     640                                   uart->rmidi->name, uart->base);
     641                        return 0;
     642                }
     643        }
     644
     645        return 1;
     646}
     647
     648static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream)
     649{
     650        unsigned long flags;
     651        unsigned char midi_byte, addr_byte;
     652        struct snd_uart16550 *uart = substream->rmidi->private_data;
     653        char first;
     654        static unsigned long lasttime = 0;
     655       
     656        /* Interrupts are disabled during the updating of the tx_buff,
     657         * since it is 'bad' to have two processes updating the same
     658         * variables (ie buff_in & buff_out)
     659         */
     660
     661        spin_lock_irqsave(&uart->open_lock, flags);
     662
     663        if (uart->irq < 0)      /* polling */
     664                snd_uart16550_io_loop(uart);
     665
     666        if (uart->adaptor == SNDRV_SERIAL_MS124W_MB) {
     667                while (1) {
     668                        /* buffer full? */
     669                        /* in this mode we need two bytes of space */
     670                        if (uart->buff_in_count > TX_BUFF_SIZE - 2)
     671                                break;
     672                        if (snd_rawmidi_transmit(substream, &midi_byte, 1) != 1)
     673                                break;
     674#ifdef SNDRV_SERIAL_MS124W_MB_NOCOMBO
     675                        /* select exactly one of the four ports */
     676                        addr_byte = (1 << (substream->number + 4)) | 0x08;
    679677#else
    680             /* select any combination of the four ports */
    681             addr_byte = (substream->number << 4) | 0x08;
    682             /* ...except none */
    683             if (addr_byte == 0x08) addr_byte = 0xf8;
     678                        /* select any combination of the four ports */
     679                        addr_byte = (substream->number << 4) | 0x08;
     680                        /* ...except none */
     681                        if (addr_byte == 0x08)
     682                                addr_byte = 0xf8;
    684683#endif
    685             snd_uart16550_output_byte(uart, substream, addr_byte);
    686             /* send midi byte */
    687             snd_uart16550_output_byte(uart, substream, midi_byte);
    688         }
    689     } else {
    690         first = 0;
    691         while (1) {
    692             /* buffer full? */
    693             if (uart->buff_in_count >= TX_BUFF_SIZE)
    694                 break;
    695             if (snd_rawmidi_transmit(substream, &midi_byte, 1) != 1)
    696                 break;
    697             if (first == 0 && uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS &&
    698                 uart->prev_out != substream->number) {
    699                 /* Roland Soundcanvas part selection */
    700                 /* If this substream of the data is different previous
    701                  substream in this uart, send the change part event */
    702                 uart->prev_out = substream->number;
    703                 /* change part */
    704                 snd_uart16550_output_byte(uart, substream, 0xf5);
    705                 /* data */
    706                 snd_uart16550_output_byte(uart, substream, uart->prev_out + 1);
    707                 /* If midi_byte is a data byte, send the previous status byte */
    708                 if (midi_byte < 0x80)
    709                     snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]);
    710             }
    711             /* send midi byte */
    712             snd_uart16550_output_byte(uart, substream, midi_byte);
    713             if (midi_byte >= 0x80 && midi_byte < 0xf0)
    714                 uart->prev_status[uart->prev_out] = midi_byte;
    715             first = 1;
    716         }
    717     }
    718     spin_unlock_irqrestore(&uart->open_lock, flags);
    719 }
    720 
    721 static void snd_uart16550_output_trigger(snd_rawmidi_substream_t * substream, int up)
    722 {
    723     unsigned long flags;
    724     snd_uart16550_t *uart = substream->rmidi->private_data;
    725 
    726     spin_lock_irqsave(&uart->open_lock, flags);
    727     if (up) {
    728         uart->filemode |= SERIAL_MODE_OUTPUT_TRIGGERED;
    729     } else {
    730         uart->filemode &= ~SERIAL_MODE_OUTPUT_TRIGGERED;
    731     }
    732     spin_unlock_irqrestore(&uart->open_lock, flags);
    733     if (up)
    734         snd_uart16550_output_write(substream);
    735 }
    736 
    737 #ifdef TARGET_OS2
    738 static snd_rawmidi_ops_t snd_uart16550_output =
    739 {
    740     snd_uart16550_output_open,
    741     snd_uart16550_output_close,
    742     snd_uart16550_output_trigger,0
     684                        snd_uart16550_output_byte(uart, substream, addr_byte);
     685                        /* send midi byte */
     686                        snd_uart16550_output_byte(uart, substream, midi_byte);
     687                }
     688        } else {
     689                first = 0;
     690                while (snd_rawmidi_transmit_peek(substream, &midi_byte, 1) == 1) {
     691                        /* Also send F5 after 3 seconds with no data
     692                         * to handle device disconnect */
     693                        if (first == 0 &&
     694                            (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS ||
     695                             uart->adaptor == SNDRV_SERIAL_GENERIC) &&
     696                            (uart->prev_out != substream->number ||
     697                             time_after(jiffies, lasttime + 3*HZ))) {
     698
     699                                if (snd_uart16550_buffer_can_write(uart, 3)) {
     700                                        /* Roland Soundcanvas part selection */
     701                                        /* If this substream of the data is
     702                                         * different previous substream
     703                                         * in this uart, send the change part
     704                                         * event
     705                                         */
     706                                        uart->prev_out = substream->number;
     707                                        /* change part */
     708                                        snd_uart16550_output_byte(uart, substream,
     709                                                                  0xf5);
     710                                        /* data */
     711                                        snd_uart16550_output_byte(uart, substream,
     712                                                                  uart->prev_out + 1);
     713                                        /* If midi_byte is a data byte,
     714                                         * send the previous status byte */
     715                                        if (midi_byte < 0x80 &&
     716                                            uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS)
     717                                                snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]);
     718                                } else if (!uart->drop_on_full)
     719                                        break;
     720
     721                        }
     722
     723                        /* send midi byte */
     724                        if (!snd_uart16550_output_byte(uart, substream, midi_byte) &&
     725                            !uart->drop_on_full )
     726                                break;
     727
     728                        if (midi_byte >= 0x80 && midi_byte < 0xf0)
     729                                uart->prev_status[uart->prev_out] = midi_byte;
     730                        first = 1;
     731
     732                        snd_rawmidi_transmit_ack( substream, 1 );
     733                }
     734                lasttime = jiffies;
     735        }
     736        spin_unlock_irqrestore(&uart->open_lock, flags);
     737}
     738
     739static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream,
     740                                         int up)
     741{
     742        unsigned long flags;
     743        struct snd_uart16550 *uart = substream->rmidi->private_data;
     744
     745        spin_lock_irqsave(&uart->open_lock, flags);
     746        if (up)
     747                uart->filemode |= SERIAL_MODE_OUTPUT_TRIGGERED;
     748        else
     749                uart->filemode &= ~SERIAL_MODE_OUTPUT_TRIGGERED;
     750        spin_unlock_irqrestore(&uart->open_lock, flags);
     751        if (up)
     752                snd_uart16550_output_write(substream);
     753}
     754
     755static struct snd_rawmidi_ops snd_uart16550_output =
     756{
     757        .open =         snd_uart16550_output_open,
     758        .close =        snd_uart16550_output_close,
     759        .trigger =      snd_uart16550_output_trigger,
    743760};
    744761
    745 static snd_rawmidi_ops_t snd_uart16550_input =
    746 {
    747     snd_uart16550_input_open,
    748     snd_uart16550_input_close,
    749     snd_uart16550_input_trigger,0
     762static struct snd_rawmidi_ops snd_uart16550_input =
     763{
     764        .open =         snd_uart16550_input_open,
     765        .close =        snd_uart16550_input_close,
     766        .trigger =      snd_uart16550_input_trigger,
    750767};
    751 #else
    752 static snd_rawmidi_ops_t snd_uart16550_output =
    753 {
    754 open:           snd_uart16550_output_open,
    755     close:              snd_uart16550_output_close,
    756     trigger:    snd_uart16550_output_trigger,
     768
     769static int snd_uart16550_free(struct snd_uart16550 *uart)
     770{
     771        if (uart->irq >= 0)
     772                free_irq(uart->irq, uart);
     773        release_and_free_resource(uart->res_base);
     774        kfree(uart);
     775        return 0;
    757776};
    758777
    759 static snd_rawmidi_ops_t snd_uart16550_input =
    760 {
    761 open:           snd_uart16550_input_open,
    762     close:              snd_uart16550_input_close,
    763     trigger:    snd_uart16550_input_trigger,
     778static int snd_uart16550_dev_free(struct snd_device *device)
     779{
     780        struct snd_uart16550 *uart = device->device_data;
     781        return snd_uart16550_free(uart);
     782}
     783
     784static int __devinit snd_uart16550_create(struct snd_card *card,
     785                                       unsigned long iobase,
     786                                       int irq,
     787                                       unsigned int speed,
     788                                       unsigned int base,
     789                                       int adaptor,
     790                                       int droponfull,
     791                                       struct snd_uart16550 **ruart)
     792{
     793        static struct snd_device_ops ops = {
     794                .dev_free =     snd_uart16550_dev_free,
     795        };
     796        struct snd_uart16550 *uart;
     797        int err;
     798
     799
     800        if ((uart = kzalloc(sizeof(*uart), GFP_KERNEL)) == NULL)
     801                return -ENOMEM;
     802        uart->adaptor = adaptor;
     803        uart->card = card;
     804        spin_lock_init(&uart->open_lock);
     805        uart->irq = -1;
     806        uart->base = iobase;
     807        uart->drop_on_full = droponfull;
     808
     809        if ((err = snd_uart16550_detect(uart)) <= 0) {
     810                printk(KERN_ERR "no UART detected at 0x%lx\n", iobase);
     811                snd_uart16550_free(uart);
     812                return -ENODEV;
     813        }
     814
     815        if (irq >= 0 && irq != SNDRV_AUTO_IRQ) {
     816                if (request_irq(irq, snd_uart16550_interrupt,
     817                                IRQF_DISABLED, "Serial MIDI", uart)) {
     818                        snd_printk("irq %d busy. Using Polling.\n", irq);
     819                } else {
     820                        uart->irq = irq;
     821                }
     822        }
     823        uart->divisor = base / speed;
     824        uart->speed = base / (unsigned int)uart->divisor;
     825        uart->speed_base = base;
     826        uart->prev_out = -1;
     827        uart->prev_in = 0;
     828        uart->rstatus = 0;
     829        memset(uart->prev_status, 0x80, sizeof(unsigned char) * SNDRV_SERIAL_MAX_OUTS);
     830        init_timer(&uart->buffer_timer);
     831        uart->buffer_timer.function = snd_uart16550_buffer_timer;
     832        uart->buffer_timer.data = (unsigned long)uart;
     833        uart->timer_running = 0;
     834
     835        /* Register device */
     836        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, uart, &ops)) < 0) {
     837                snd_uart16550_free(uart);
     838                return err;
     839        }
     840
     841        switch (uart->adaptor) {
     842        case SNDRV_SERIAL_MS124W_SA:
     843        case SNDRV_SERIAL_MS124W_MB:
     844                /* MS-124W can draw power from RTS and DTR if they
     845                   are in opposite states. */
     846                outb(UART_MCR_RTS | (0&UART_MCR_DTR), uart->base + UART_MCR);
     847                break;
     848        case SNDRV_SERIAL_MS124T:
     849                /* MS-124T can draw power from RTS and/or DTR (preferably
     850                   both) if they are asserted. */
     851                outb(UART_MCR_RTS | UART_MCR_DTR, uart->base + UART_MCR);
     852                break;
     853        default:
     854                break;
     855        }
     856
     857        if (ruart)
     858                *ruart = uart;
     859
     860        return 0;
     861}
     862
     863static void __devinit snd_uart16550_substreams(struct snd_rawmidi_str *stream)
     864{
     865        struct snd_rawmidi_substream *substream;
     866
     867        list_for_each_entry(substream, &stream->substreams, list) {
     868                sprintf(substream->name, "Serial MIDI %d", substream->number + 1);
     869        }
     870}
     871
     872static int __devinit snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
     873                                      int outs, int ins,
     874                                      struct snd_rawmidi **rmidi)
     875{
     876        struct snd_rawmidi *rrawmidi;
     877        int err;
     878
     879        err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device,
     880                              outs, ins, &rrawmidi);
     881        if (err < 0)
     882                return err;
     883        snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT,
     884                            &snd_uart16550_input);
     885        snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
     886                            &snd_uart16550_output);
     887        strcpy(rrawmidi->name, "Serial MIDI");
     888        snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]);
     889        snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]);
     890        rrawmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
     891                               SNDRV_RAWMIDI_INFO_INPUT |
     892                               SNDRV_RAWMIDI_INFO_DUPLEX;
     893        rrawmidi->private_data = uart;
     894        if (rmidi)
     895                *rmidi = rrawmidi;
     896        return 0;
     897}
     898
     899static int __devinit snd_serial_probe(struct platform_device *devptr)
     900{
     901        struct snd_card *card;
     902        struct snd_uart16550 *uart;
     903        int err;
     904        int dev = devptr->id;
     905
     906        switch (adaptor[dev]) {
     907        case SNDRV_SERIAL_SOUNDCANVAS:
     908                ins[dev] = 1;
     909                break;
     910        case SNDRV_SERIAL_MS124T:
     911        case SNDRV_SERIAL_MS124W_SA:
     912                outs[dev] = 1;
     913                ins[dev] = 1;
     914                break;
     915        case SNDRV_SERIAL_MS124W_MB:
     916                outs[dev] = 16;
     917                ins[dev] = 1;
     918                break;
     919        case SNDRV_SERIAL_GENERIC:
     920                break;
     921        default:
     922                snd_printk("Adaptor type is out of range 0-%d (%d)\n",
     923                           SNDRV_SERIAL_MAX_ADAPTOR, adaptor[dev]);
     924                return -ENODEV;
     925        }
     926
     927        if (outs[dev] < 1 || outs[dev] > SNDRV_SERIAL_MAX_OUTS) {
     928                snd_printk("Count of outputs is out of range 1-%d (%d)\n",
     929                           SNDRV_SERIAL_MAX_OUTS, outs[dev]);
     930                return -ENODEV;
     931        }
     932
     933        if (ins[dev] < 1 || ins[dev] > SNDRV_SERIAL_MAX_INS) {
     934                snd_printk("Count of inputs is out of range 1-%d (%d)\n",
     935                           SNDRV_SERIAL_MAX_INS, ins[dev]);
     936                return -ENODEV;
     937        }
     938
     939        card  = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
     940        if (card == NULL)
     941                return -ENOMEM;
     942
     943        strcpy(card->driver, "Serial");
     944        strcpy(card->shortname, "Serial MIDI (UART16550A)");
     945
     946        if ((err = snd_uart16550_create(card,
     947                                        port[dev],
     948                                        irq[dev],
     949                                        speed[dev],
     950                                        base[dev],
     951                                        adaptor[dev],
     952                                        droponfull[dev],
     953                                        &uart)) < 0)
     954                goto _err;
     955
     956        err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi);
     957        if (err < 0)
     958                goto _err;
     959
     960        sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s droponfull %d",
     961                card->shortname,
     962                uart->base,
     963                uart->irq,
     964                uart->speed,
     965                (int)uart->divisor,
     966                outs[dev],
     967                ins[dev],
     968                adaptor_names[uart->adaptor],
     969                uart->drop_on_full);
     970
     971        snd_card_set_dev(card, &devptr->dev);
     972
     973        if ((err = snd_card_register(card)) < 0)
     974                goto _err;
     975
     976        platform_set_drvdata(devptr, card);
     977        return 0;
     978
     979 _err:
     980        snd_card_free(card);
     981        return err;
     982}
     983
     984static int __devexit snd_serial_remove(struct platform_device *devptr)
     985{
     986        snd_card_free(platform_get_drvdata(devptr));
     987        platform_set_drvdata(devptr, NULL);
     988        return 0;
     989}
     990
     991#define SND_SERIAL_DRIVER       "snd_serial_u16550"
     992
     993static struct platform_driver snd_serial_driver = {
     994        .probe          = snd_serial_probe,
     995        .remove         = __devexit_p( snd_serial_remove),
     996        .driver         = {
     997                .name   = SND_SERIAL_DRIVER
     998        },
    764999};
     1000
     1001static void snd_serial_unregister_all(void)
     1002{
     1003        int i;
     1004
     1005        for (i = 0; i < ARRAY_SIZE(devices); ++i)
     1006                platform_device_unregister(devices[i]);
     1007        platform_driver_unregister(&snd_serial_driver);
     1008}
     1009
     1010static int __init alsa_card_serial_init(void)
     1011{
     1012        int i, cards, err;
     1013
     1014        if ((err = platform_driver_register(&snd_serial_driver)) < 0)
     1015                return err;
     1016
     1017        cards = 0;
     1018        for (i = 0; i < SNDRV_CARDS; i++) {
     1019                struct platform_device *device;
     1020                if (! enable[i])
     1021                        continue;
     1022                device = platform_device_register_simple(SND_SERIAL_DRIVER,
     1023                                                         i, NULL, 0);
     1024                if (IS_ERR(device))
     1025                        continue;
     1026                if (!platform_get_drvdata(device)) {
     1027                        platform_device_unregister(device);
     1028                        continue;
     1029                }
     1030                devices[i] = device;
     1031                cards++;
     1032        }
     1033        if (! cards) {
     1034#ifdef MODULE
     1035                printk(KERN_ERR "serial midi soundcard not found or device busy\n");
    7651036#endif
    766 
    767 static int snd_uart16550_free(snd_uart16550_t *uart)
    768 {
    769     if (uart->irq >= 0)
    770         free_irq(uart->irq, (void *)uart);
    771     if (uart->res_base)
    772         release_resource(uart->res_base);
    773     kfree(uart);
    774     return 0;
    775 };
    776 
    777 static int snd_uart16550_dev_free(snd_device_t *device)
    778 {
    779     snd_uart16550_t *uart = device->device_data;
    780     return snd_uart16550_free(uart);
    781 }
    782 
    783 static int __init snd_uart16550_create(snd_card_t * card,
    784                                        unsigned long iobase,
    785                                        int irq,
    786                                        unsigned int speed,
    787                                        unsigned int base,
    788                                        int adaptor,
    789                                        snd_uart16550_t **ruart)
    790 {
    791 #ifdef TARGET_OS2
    792     static snd_device_ops_t ops = {
    793         snd_uart16550_dev_free,0,0,0
    794     };
    795 #else
    796     static snd_device_ops_t ops = {
    797     dev_free:       snd_uart16550_dev_free,
    798     };
    799 #endif
    800     snd_uart16550_t *uart;
    801     int err;
    802 
    803 
    804     if ((uart = kcalloc(1, sizeof(*uart), GFP_KERNEL)) == NULL)
    805         return -ENOMEM;
    806     uart->adaptor = adaptor;
    807     uart->card = card;
    808     spin_lock_init(&uart->open_lock);
    809     uart->irq = -1;
    810     if ((uart->res_base = request_region(iobase, 8, "Serial MIDI")) == NULL) {
    811         snd_printk("unable to grab ports 0x%lx-0x%lx\n", iobase, iobase + 8 - 1);
    812         return -EBUSY;
    813     }
    814     uart->base = iobase;
    815     if (irq >= 0) {
    816         if (request_irq(irq, snd_uart16550_interrupt,
    817                         SA_INTERRUPT, "Serial MIDI", (void *) uart)) {
    818             uart->irq = -1;
    819             snd_printk("irq %d busy. Using Polling.\n", irq);
    820         } else {
    821             uart->irq = irq;
    822         }
    823     }
    824     uart->divisor = base / speed;
    825     uart->speed = base / (unsigned int)uart->divisor;
    826     uart->speed_base = base;
    827     uart->prev_out = -1;
    828     memset(uart->prev_status, 0x80, sizeof(unsigned char) * SNDRV_SERIAL_MAX_OUTS);
    829     uart->buffer_timer.function = snd_uart16550_buffer_timer;
    830     uart->buffer_timer.data = (unsigned long)uart;
    831     uart->timer_running = 0;
    832 
    833     /* Register device */
    834     if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, uart, &ops)) < 0) {
    835         snd_uart16550_free(uart);
    836         return err;
    837     }
    838 
    839     switch (uart->adaptor) {
    840     case SNDRV_SERIAL_MS124W_SA:
    841     case SNDRV_SERIAL_MS124W_MB:
    842         /* MS-124W can draw power from RTS and DTR if they
    843          are in opposite states. */
    844         outb(UART_MCR_RTS | (0&UART_MCR_DTR), uart->base + UART_MCR);
    845         break;
    846     case SNDRV_SERIAL_MS124T:
    847         /* MS-124T can draw power from RTS and/or DTR (preferably
    848          both) if they are asserted. */
    849         outb(UART_MCR_RTS | UART_MCR_DTR, uart->base + UART_MCR);
    850         break;
    851     default:
    852         break;
    853     }
    854 
    855     if (ruart)
    856         *ruart = uart;
    857 
    858     return 0;
    859 }
    860 
    861 static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int outs, snd_rawmidi_t **rmidi)
    862 {
    863     snd_rawmidi_t *rrawmidi;
    864     int err;
    865 
    866     if ((err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device, outs, 1, &rrawmidi)) < 0)
    867         return err;
    868     snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_uart16550_input);
    869     snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_uart16550_output);
    870     sprintf(rrawmidi->name, "uart16550 MIDI #%d", device);
    871     rrawmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
    872         SNDRV_RAWMIDI_INFO_INPUT |
    873         SNDRV_RAWMIDI_INFO_DUPLEX;
    874     rrawmidi->private_data = uart;
    875     if (rmidi)
    876         *rmidi = rrawmidi;
    877     return 0;
    878 }
    879 
    880 static int __init snd_serial_probe(int dev)
    881 {
    882     snd_card_t *card;
    883     snd_uart16550_t *uart;
    884     int err;
    885 
    886     if (!snd_enable[dev])
    887         return -ENOENT;
    888 
    889     switch (snd_adaptor[dev]) {
    890     case SNDRV_SERIAL_SOUNDCANVAS:
    891         break;
    892     case SNDRV_SERIAL_MS124T:
    893     case SNDRV_SERIAL_MS124W_SA:
    894         snd_outs[dev] = 1;
    895         break;
    896     case SNDRV_SERIAL_MS124W_MB:
    897         snd_outs[dev] = 16;
    898         break;
    899     default:
    900         snd_printk("Adaptor type is out of range 0-%d (%d)\n",
    901                    SNDRV_SERIAL_MAX_ADAPTOR, snd_adaptor[dev]);
    902         return -ENODEV;
    903     }
    904 
    905     if (snd_outs[dev] < 1 || snd_outs[dev] > SNDRV_SERIAL_MAX_OUTS) {
    906         snd_printk("Count of outputs is out of range 1-%d (%d)\n",
    907                    SNDRV_SERIAL_MAX_OUTS, snd_outs[dev]);
    908         return -ENODEV;
    909     }
    910 
    911     card  = snd_card_new(snd_index[dev], snd_id[dev], THIS_MODULE, 0);
    912     if (card == NULL)
    913         return -ENOMEM;
    914 
    915     strcpy(card->driver, "Serial");
    916     strcpy(card->shortname, "Serial midi (uart16550A)");
    917 
    918     if ((err = snd_uart16550_detect(snd_port[dev])) <= 0) {
    919         snd_card_free(card);
    920         snd_printk("no UART detected at 0x%lx\n", (long)snd_port[dev]);
    921         return err;
    922     }
    923 
    924     if ((err = snd_uart16550_create(card,
    925                                     snd_port[dev],
    926                                     snd_irq[dev],
    927                                     snd_speed[dev],
    928                                     snd_base[dev],
    929                                     snd_adaptor[dev],
    930                                     &uart)) < 0) {
    931         snd_card_free(card);
    932         return err;
    933     }
    934 
    935     if ((err = snd_uart16550_rmidi(uart, 0, snd_outs[dev], &uart->rmidi)) < 0) {
    936         snd_card_free(card);
    937         return err;
    938     }
    939 
    940     sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d adaptor %s",
    941             card->shortname,
    942             uart->base,
    943             uart->irq,
    944             uart->speed,
    945             (int)uart->divisor,
    946             snd_outs[dev],
    947             adaptor_names[uart->adaptor]);
    948 
    949     if ((err = snd_card_register(card)) < 0) {
    950         snd_card_free(card);
    951         return err;
    952     }
    953     snd_serial_cards[dev] = card;
    954     return 0;
    955 }
    956 
    957 static int __init alsa_card_serial_init(void)
    958 {
    959     int dev = 0;
    960     int cards = 0;
    961 
    962     for (dev = 0; dev < SNDRV_CARDS; dev++) {
    963         if (snd_serial_probe(dev) == 0)
    964             cards++;
    965     }
    966 
    967     if (cards == 0) {
    968 #ifdef MODULE
    969         snd_printk("serial midi soundcard not found or device busy\n");
    970 #endif
    971         return -ENODEV;
    972     }
    973     return 0;
     1037                snd_serial_unregister_all();
     1038                return -ENODEV;
     1039        }
     1040        return 0;
    9741041}
    9751042
    9761043static void __exit alsa_card_serial_exit(void)
    9771044{
    978     int dev;
    979 
    980     for (dev = 0; dev < SNDRV_CARDS; dev++) {
    981         if (snd_serial_cards[dev] != NULL)
    982             snd_card_free(snd_serial_cards[dev]);
    983     }
     1045        snd_serial_unregister_all();
    9841046}
    9851047
    9861048module_init(alsa_card_serial_init)
    9871049module_exit(alsa_card_serial_exit)
    988 
    989 #ifndef MODULE
    990 
    991 /* format is: snd-card-serial=snd_enable,snd_index,snd_id,
    992  snd_port,snd_irq,snd_speed,snd_base,snd_outs */
    993 
    994 static int __init alsa_card_serial_setup(char *str)
    995 {
    996     static unsigned __initdata nr_dev = 0;
    997 
    998     if (nr_dev >= SNDRV_CARDS)
    999         return 0;
    1000     (void)(get_option(&str,&snd_enable[nr_dev]) == 2 &&
    1001            get_option(&str,&snd_index[nr_dev]) == 2 &&
    1002            get_id(&str,&snd_id[nr_dev]) == 2 &&
    1003            get_option(&str,(int *)&snd_port[nr_dev]) == 2 &&
    1004            get_option(&str,&snd_irq[nr_dev]) == 2 &&
    1005            get_option(&str,&snd_speed[nr_dev]) == 2 &&
    1006            get_option(&str,&snd_base[nr_dev]) == 2 &&
    1007            get_option(&str,&snd_outs[nr_dev]) == 2 &&
    1008            get_option(&str,&snd_adaptor[nr_dev]) == 2);
    1009     nr_dev++;
    1010     return 1;
    1011 }
    1012 
    1013 __setup("snd-card-serial=", alsa_card_serial_setup);
    1014 
    1015 #endif /* ifndef MODULE */
Note: See TracChangeset for help on using the changeset viewer.